二叉树链式结构的实现

文章目录

1.前置说明

2.二叉树的遍历


文章内容

1.前置说明

       学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在我们对于二叉树的了解还处于初级阶段,所以我们手动创建一棵简单的二叉树,以便进入二叉树操作学习,等深入了解二叉树之后,我们再来研究二叉树真正建立的方法。

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>#include "Queue.h"typedef int BTDataType;
typedef struct BinaryTreeNode
{struct BinaryTreeNode* left;struct BinaryTreeNode* right;BTDataType data;}BTNode;BTNode* BuyNode(BTDataType x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->data = x;newnode->left = NULL;newnode->right = NULL;return newnode;
}BTNode* CreatBinaryTree()
{BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);
//  BTNode* node7 = BuyNode(7);node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;
//	node5->right = node7;return node1;
}

注意:上述代码并不是创建二叉树的方式

再看二叉树基本操作前,再回顾下二叉树的概念,二叉树是:

 1. 空树
 2. 非空:根节点,根节点的左子树、根节点的右子树组成的。

 从概念中可以看出,二叉树定义是递归式的,因此后序基本操作中基本都是按照该概念实现的。

2.二叉树的遍历

 2.1 前序、中序以及后序遍历

      学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

 按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历

1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。

访问根的时候决定了其到底是什么遍历。

由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。

   递归问题,我们第一个要想的是在哪里展开递归,第二个便是回退的时机,我们想要的得到的结果是什么,这导致我们要施加什么回退的条件来结束递归。回退又可以分为递归的程序结束完回退,以及符合回退条件时回退

每一个节点都可以看成根节点,每一个节点都有其左子树和右子树。

前序遍历递归图解:(先访问根,在遍历)

 

 

     

//前序
void PreOrder(BTNode* root)
{if (root == NULL){printf("# ");return;}printf("%d ", root->data);PreOrder(root->left);PreOrder(root->right);}

中序遍历:(先遍历,在访问根节点)

 


//中序
void InOrder(BTNode* root)
{if (root == NULL){printf("# ");return;}InOrder(root->left);printf("%d ", root->data);InOrder(root->right);}

后序遍历:(最后访问根)

//后序
void PostOrder(BTNode* root)
{if (root == NULL){printf("# ");return;}PostOrder(root->left);PostOrder(root->right);printf("%d ", root->data);}
2.2二叉树节点数量

   在判断当前节点不为空的时候count++

   return在count++之前,所以逻辑上当当前节点为空时候,就返回了,count并不会++。

 

要注意的是,这里我们要定义一个全局变量count ,方便我们计数

int count = 0;
void TreeSize1(BTNode* root)
{if (root == NULL){return;}count++;TreeSize1(root->left);TreeSize1(root->right);}

main函数里 count 要初始化,全局变量谁都能用,避免出现差错。

int main()
{count = 0;TreeSize1(root);printf("TreeSize1:%d\n", count);return 0;
}

 第二种思路:

与第一种思路相似,遇到空就返回,不过使用了三目操作符,更加简单。

int TreeSize2(BTNode* root)
{return root == NULL ? 0 :TreeSize2(root->left) + TreeSize2(root->right) + 1;
}
2.3叶子节点的数量

  叶子节点是左右节点都为空的节点。这个定义就是回退是的条件。

  当 当前节点既不为空,左孩子节点,右孩子节点也都不为空时,继续开展递归,当前节点的左孩子右孩子都为空时(此时为叶子节点),或当前节点为为空,便回退。

//叶子节点数量
//递归往往是回退的时候才带值的
int TreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}if (root->left == NULL && root->right == NULL)//左子树右子树都为空是叶子节点的条件{return 1;}return TreeLeafSize(root->left) + TreeLeafSize(root->right);}
2.4二叉树第k层节点的数量

     要找到确定第k层节点的数量,就要先找到第k层,我们这里从第一层开始,没有第0层。

     函数递归展开后其本身并不知道当前是第几层,这时候我们就需要一个函数变量来告诉函数是第几层。

      求根节点的第k层就是求其左右子树的第k-1层,在把左右子树看成根节点,就是求k-2层......

依次下去当k等于1 时,当前层数的节点就是我们要求的

        

//k层节点
//通过控制k 来控制递归
int TreeKLevel(BTNode* root, int k)
{assert(k >= 1);if (root == NULL){return 0;}if (k == 1)//通过k控制递归的层数,程序到达这里,首先要root != null 要进去就要符合条件{return 1;}return TreeKLevel(root->left, k - 1) + TreeKLevel(root->right, k - 1);}
 2.5查找值为x的数

        查找x并不需要遍历全部的二叉树,当找到对应的x之后我们要停止遍历二叉树。

        停止遍历二叉之后,我们还要把x值所在节点的地址给带回去。

//查找x
//找到就返回,如在左子树里面找到,直接返回不需要再去右子树里面BTNode* TreeFind(BTNode* root, int x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode* ret1 = TreeFind(root->left, x);if (ret1){return ret1;//假如再次分支找到了,程序不会往下走,直接返回了}BTNode* ret2 = TreeFind(root->right, x);if (ret2){return ret2;}return NULL;
}
2.6二叉树的深度

        当前二叉树的深度可以转化成左子树右子树的中最高的那一颗+1。而左右子树的高度又可以转化为他们子树中最高的那一颗+1......

       从最深的那一层的节点开始找出他们最深的左右子树返回给上一层。

2.7二叉树的销毁 

        二叉树的销毁符合后序遍历,先访问在左右子树,在销毁。free要放到遍历完右子树后,如果先free而不是先遍历的话,就会造成野指针的问题。

        

//销毁
void TreeDestroy(BTNode* root)
{if (root == NULL){return ;}TreeDestroy(root->left);TreeDestroy(root->right);free(root);}

        

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/106663.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

javeee eclipse项目导入idea中

步骤一 复制项目到idea工作空间 步骤二 在idea中导入项目 步骤三 配置classes目录 步骤四 配置lib目录 步骤五 添加tomcat依赖 步骤六 添加artifacts 步骤七 部署到tomcat

电商项目part06 微服务网关整合OAuth2.0授权中心

微服务网关整合 OAuth2.0 思路分析 网关整合 OAuth2.0 有两种思路&#xff0c;一种是授权服务器生成令牌, 所有请求统一在网关层验证&#xff0c;判断权 限等操作&#xff1b;另一种是由各资源服务处理&#xff0c;网关只做请求转发。 比较常用的是第一种&#xff0c;把API网关…

认识Mybatis的关联关系映射,灵活关联表对象之间的关系

目录 一、概述 ( 1 ) 介绍 ( 2 ) 关联关系映射 ( 3 ) 关联讲述 二、一对一关联映射 2.1 数据库创建 2.2 配置文件 2.3 代码生成 2.4 编写测试 三、一对多关联映射 四 、多对多关联映射 给我们带来的收获 一、概述 ( 1 ) 介绍 关联关系映射是指在数据库中&…

RH1288V3 - 初识物理服务器

如果你拥有一台物理服务器(不是云服务器) 个人比较推荐你用物理服务器&#xff0c;虽然性能会比云要来的差&#xff0c;但是不用每月交钱上。云服务固然方便&#xff0c;但是几个核的性能和一点存储&#xff0c;想做一个动漫网站固然要很多mp4这种影视资源&#xff0c;云服务器…

人工智能在现代招聘中的崛起:超越传统筛选的未来

引言 在过去的几十年里,招聘一直是企业的核心活动之一。传统的招聘流程依赖于人力资源专家手工筛选简历、面试候选人并进行背景调查。这种方法不仅耗时,而且可能受到人为偏见的影响。随着技术的进步,特别是人工智能(AI)的发展,招聘的面貌正在发生深刻的变化。人工智能在…

【Ubuntu20.04安装Nvidia驱动、CUDA和CUDNN】

Ubuntu20.04安装Nvidia驱动、CUDA和CUDNN 1 Nvidia驱动安装1.1 安装1.2 安装Nvidia可能会遇到的问题1.2.1 NVIDIA 驱动与 Nouveau 驱动不兼容1.2.2 ERROR: Unable to find the development tool cc 2 CUDA安装2.1 下载和安装2.2 配置CUDA环境 3 安装CUDNN4 切换CUDA版本 1 Nvid…

在 macOS 中安装 TensorFlow 1g

tensorflow 需要多大空间 pip install tensorflow pip install tensorflow Looking in indexes: https://pypi.douban.com/simple/ Collecting tensorflowDownloading https://pypi.doubanio.com/packages/1a/c1/9c14df0625836af8ba6628585c6d3c3bf8f1e1101cafa2435eb28a7764…

在其他python环境中使用jupyter notebook

1、切换到目标python环境 activate 目标python环境 2、安装notebook内核包 pip install ipykernel 3、加环境加入到notebook中 python -m ipykernel install 目标python环境 4、切换到base环境 activate base 5、打开目标项目的对应盘 如果&#xff0c;项目在c盘&…

DEFORMABLE DETR: DEFORMABLE TRANSFORMERS FOR END-TO-END OBJECT DETECTION 论文精度笔记

DEFORMABLE DETR DEFORMABLE DETR: DEFORMABLE TRANSFORMERS FOR END-TO-END OBJECT DETECTION 参考&#xff1a;AI-杂货铺-Transformer跨界CV又一佳作&#xff01;Deformable DETR&#xff1a;超强的小目标检测算法&#xff01; 摘要 摘要部分&#xff0c;作者主要说明了如…

Datawhale AI夏令营 - 用户新增预测挑战赛 | 学习笔记

任务1&#xff1a;跑通Baseline # 1. 导入需要用到的相关库 # 导入 pandas 库&#xff0c;用于数据处理和分析 import pandas as pd # 导入 numpy 库&#xff0c;用于科学计算和多维数组操作 import numpy as np # 从 sklearn.tree 模块中导入 DecisionTreeClassifier 类 # De…

开源容灾备份软件,开源cdp备份软件

数据的安全性和完整性面临着硬件问题、黑客攻击、人为错误等各种威胁。在这种环境下&#xff0c;开源容灾备份软件应运而生&#xff0c;通过提供自动数据备份和恢复&#xff0c;有效地保证了公司的数据安全。 一、开源容灾备份软件的定义和作用 开源容灾备份软件是一种基于开源…

全流程R语言Meta分析核心技术教程

详情点击链接&#xff1a;全流程R语言Meta分析核心技术教程 一&#xff0c;Meta分析的选题与检索 1、Meta分析的选题与文献检索 1)什么是Meta分析&#xff1f; 2)Meta分析的选题策略 3)精确检索策略&#xff0c;如何检索全、检索准 4)文献的管理与清洗&#xff0c;如何制定文…

Django基础5——ORM中间程序

文章目录 一、基本了解二、ORM基本操作2.1 连接数据库2.1.1 使用sqlite数据库2.1.2 使用MySQL数据库 2.2 对数据库操作2.2.1 增&#xff08;前端数据——>数据库&#xff09;2.2.2 查&#xff08;数据库——>前端展示&#xff09;2.2.3 改&#xff08;修改数据&#xff0…

C# Winfrom通过COM接口访问和控制Excel应用程序,将Excel数据导入DataGridView

1.首先要创建xlsx文件 2.在Com中添加引用 3. 添加命名空间 using ApExcel Microsoft.Office.Interop.Excel; --这样起个名字方面后面写 4.样例 //点击操作excelDataTable dt new DataTable();string fileName "D:\desktop\tmp\test.xlsx";ApExcel.Application exA…

软件测试知识点总结(一)

文章目录 前言一. 什么是软件测试二. 软件测试和软件调试的区别三. 软件测试和研发的区别四. 优秀的测试人员所应该具备的素质总结 前言 在现实生活中的很多场景下&#xff0c;我们都会进行测试。 比如买件衣服&#xff0c;我们需要看衣服是不是穿着好看&#xff0c;衣服材质如…

pyton\yolov8安装和基础使用,训练和预测

首先到官网下载yolov8&#xff0c;官方的地址&#xff0c;下载好压缩包后&#xff0c;解压到pycharm打开&#xff0c;我个人使用的是pycharm&#xff0c;接下来也是在pycharm里操作的。&#xff08;专业版pycharm&#xff09; yolov8的官方文档有说明&#xff0c;必须要有的环境…

“深度学习”学习日记:Tensorflow实现VGG每一个卷积层的可视化

2023.8.19 深度学习的卷积对于初学者是非常抽象&#xff0c;当时在入门学习的时候直接劝退一大班人&#xff0c;还好我坚持了下来。可视化时用到的图片&#xff08;我们学校的一角&#xff01;&#xff01;&#xff01;&#xff09;以下展示了一个卷积和一次Relu的变化 作者使…

【C51 GPIO的原理和内部结构】

51单片机项目基础篇 中篇&#xff1a;介绍GPIO1、认识GPIO2、GPIO 结构框图与工作原理2.1、P0端口结构框图与工作原理2.1.1、剖析组成 P0 口的每个单元的作用2.1.2、 P0 口做为 I/O 口及地址/数据总线使用时的具体工作过程 2.2、P1 端口结构框图与工作原理2.3、P2 端口结构框图…

Lamda表达式

为什么要使用lamda表达式 避免匿名内部类定义过多可以让你的代码看起来很简洁去掉了一堆没有意义的代码&#xff0c;只留下核心的逻辑 函数式接口 理解Functionalnterface (函数式接口)是学习Java8 lambda表达式的关键所在. 定义: 任何接口&#xff0c;如果只包含唯一一个…

多维时序 | MATLAB实现SABO-CNN-GRU-Attention多变量时间序列预测

多维时序 | MATLAB实现SABO-CNN-GRU-Attention多变量时间序列预测 目录 多维时序 | MATLAB实现SABO-CNN-GRU-Attention多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 多维时序 | MATLAB实现SABO-CNN-GRU-Attention多变量时间序列预测。 模型描…