要认识二叉树,首先要先了解,二叉树是树的一种特殊的结构


目录

一、树

1.1树的概念和结构

1.2树的相关专业名词

1.3树和非树

二、二叉树

2.1二叉树的概念的结构

三、二叉树的功能实现

3.1二叉树节点的设计

3.2创建二叉树的新节点

3.3二叉树链式结构的遍历

3.3.1二叉树前序遍历的实现

3.3.1二叉树中序遍历的实现

3.3.1二叉树后序遍历的实现  ​

3.4求二叉树的数据个数(节点个数)的实现

3.5求二叉树的叶子节点个数的实现

3.6销毁二叉树申请的空间的实现

四、二叉树的层序遍历(用的多)

五、总代码

六、代码运行实例


一、树

1.1树的概念和结构

树是一种非线性的数据结构,它是由n(n>=0)个有限节点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。结构如下图所示。

1、空树也是一种树,就是没有节点,可以理解为本来有一棵树,结果被连根挖走了,原来这里的树,就变成了空树。(了解即可)

2、一个节点也能称为树,可以想象成 只有根的树,此时节点A就叫做根节点。

3、一颗普通的树:节点A可以叫做节点B、C、D的根节点,节点B可以叫做节点E、F的根节点,节点E可以叫做节点J的根节点,其他类似;节点A作为 根节点不同于其他根节点,它的上面没有节点,为了区分,我叫做节点A叫做 主根节点。(但是实际上是没有主根节点这个的概念的,只是为了方便理解


1.2树的相关专业名词

1、树的节点:如上图一棵树,由有限个节点组成,A、B、C ...... Q都叫做树的节点,后面我们称为节点A、节点B ...... 。

2、节点的子树:由某个节点 往下直接相连的节点 叫做 某个节点的子树,如节点A的子树是 节点B、C、D、E、F、G;节点D的子树是 节点H;节点E的子树是 节点I、J;节点J的子树是 节点P、Q;其他类似。

3、节点的度:一个节点含有的 子树的个数 称为该节点的度,如节点A的度是6,因为节点A有6个子树;节点B的度是0,因为节点B没有子树;节点D的度是1,因为节点D有1个子树;其他类似。

4、叶节点(也叫终端节点):度为0的节点称为叶节点;如节点B、C、H、I、P、Q、K、L、M、N都是叶节点(终端节点)。

5、分支节点(也叫非终端节点):度不为0的节点;除了叶节点,其他的都可以叫分支节点。

6、父节点(也叫双亲节点):若一个节点含有子节点,则这个节点称为其子节点的父节点; 如节点A是节点B的父节点。

7、子节点(也叫孩子节点):一个节点含有的子树的根节点称为该节点的子节点; 如节点B是节点A的孩子节点。

8、兄弟节点:具有相同父节点的节点互称为兄弟节点;如节点B、C、D、E、F、G互称为兄弟节点。

9、树的度:一棵树中 ,最大的某个节点的度称为树的度;如上图的树,树的度为6。

10、节点的层次:从主根节点开始定义为第1层,后面以此类推。

11、树的高度(也叫树的深度):树的最大层次;如上图,树的高度为4。


1.3树和非树

树:1、子树是不相交的

2、除了主根节点外,每个节点有且仅有一个父节点

3、一颗N个节点的树有N-1条边


二、二叉树

2.1二叉树的概念的结构

一棵二叉树是节点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成,即二叉树 就是 树的每个节点最多只有两个子树 的树。

二叉树的特点:

1、每个节点最多有两个子树,即二叉树不存在度大于2的节点。

2、二叉树的子树有左右之分,其子树的次序不能颠倒,即在左边的就是左子树,右边的就是右子树,不能改变。

结构图如下:


三、二叉树的功能实现

二叉树的存储方式有顺序存储和链式存储,用的多的是链式存储,我们这里讲链式存储。二叉树的链式存储结构是指 用链表来表示一棵二叉树,只不过是非线性链表,即用链来指示元素的逻辑关系。 通常的方法是链表中每个节点由三个域组成,数据域和左右指针域,左右指针分别指向该节点左子树和右子树。


3.1二叉树节点的设计

二叉树储存数据的方式是链式存储的话,即用链表。那么二叉树的节点还是由结构体表示:一个数据,一个指向 这个节点左子树的 指针left,一个指向 这个节点右子树的 指针right。

typedef char BTDataType;//类型重名名typedef struct BinaryTreeNode
{struct BinaryTreeNode* left;//节点里的指针left指向这个节点的左子树struct BinaryTreeNode* right;//节点里的指针right指向这个节点的右子树BTDataType data;//这个节点存放的数据
}BTNode;

3.2创建二叉树的新节点

//创建新节点
BTNode* BinaryTreeNode(BTDataType x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));//动态开辟内存空间,大小是一个结构体类型BTnodeif (newnode == NULL){perror("the mistake");}newnode->data = x;//将想存放的数据放入节点里newnode->left = NULL;//创建的新节点里的指针left和right要先置为NULL,方便后面的修改newnode->right = NULL;//也是因为当这个节点作为根的时候,其左子树和右子树都为NULLreturn newnode; //用返回值返回创建的新节点,这样形参就不用创建二级指针了
}

以上面的二叉树为例子: 因为每个节点都有指向这个节点左子树和右子树的指针left和right,如果这个节点没有左子树和右子树,那么这个节点的指针left和right则指向空指针(注意这个节点的度就为0,因为实际上它是没有子树的),和单链表链表一样,最后节点里的指针则指向空指针。


3.3二叉树链式结构的遍历

所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个节点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础,遍历的思想是递归

前序/中序/后序的递归结构遍历:是根据访问节点操作发生位置命名
1. NLR:前序遍历(Preorder Traversal 亦称先序遍历)——访问根节点的操作发生在遍历其左右子树之前。
2. LNR:中序遍历(Inorder Traversal)——访问根节点的操作发生在遍历其左右子树之中。
3. LRN:后序遍历(Postorder Traversal)——访问根节点的操作发生在遍历其左右子树之后。
由于被访问的节点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又
可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。


3.3.1二叉树前序遍历的实现

//前序遍历( 根 左子树 右子树 )
void PrevOrder(BTNode* root)//指向根的指针进入
{if (root == NULL) //两种情况:1、二叉树无节点,直接打印NULL,并结束函数//2、当递归的作为 根节点 的 左子树 或者 根节点 的 右子树 为空指针NULL的时候,//这个递归结束,返回上一个递归{printf("NULL ");return;//结束函数}printf("%c ", root->data);//打印该节点的存放的数据PrevOrder(root->left);//这个节点的左子树作为根再进入PrevOrder(root->right);//这个节点的右子树作为根再进入
}

解释请看注解和图,非常详细。


3.3.1二叉树中序遍历的实现

//中序遍历( 左子树 根 右子树 )
void InOrder(BTNode* root)//第一个根节点
{if (root == NULL)//两种情况:1、二叉树无节点,直接打印NULL,并结束函数//2、当递归的作为 根节点 的 左子树 或者 根节点 的 右子树 为空指针NULL的时候,//这个递归结束,返回上一个递归{printf("NULL ");return;//结束函数}InOrder(root->left);//这个节点的左子树作为根再进入printf("%c ", root->data);//打印该节点的存放的数据InOrder(root->right);//这个节点的右子树作为根再进入
}

解释请看注解和图,非常详细。


3.3.1二叉树后序遍历的实现  

//后序遍历( 左子树 右子树 根 )
void PostOrder(BTNode* root)//第一个根节点
{if (root == NULL)//两种情况:1、二叉树无节点,直接打印NULL,并结束函数//2、当递归的作为 根节点 的 左子树 或者 根节点 的 右子树 为空指针NULL的时候,//这个递归结束,返回上一个递归{printf("NULL ");return;//结束函数}PostOrder(root->left);//这个节点的左子树作为根再进入PostOrder(root->right);//这个节点的右子树作为根再进入printf("%c ", root->data);//打印该节点的存放的数据
}

解释请看注解和图,非常详细。


3.4求二叉树的数据个数(节点个数)的实现

//求二叉树的数据个数,二叉树每个节点只存放一个数据,
//所以也可以说求二叉树的节点个数(用的遍历后序的思维)
int TreeSize(BTNode* root)
{//三目操作符:exp1?exp2:exp3//如果 表达式exp1 为真,则 整个表达式 的结果为 表达式exp2;如果为假,则 整个表达式 的结果为 表达式exp3return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

解释请看注解,非常详细。


3.5求二叉树的叶子节点个数的实现

//求二叉树叶子节点(度为0的节点)的个数
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);
}

解释请看注解,非常详细。


3.6销毁二叉树申请的空间的实现

void DestroyTree(BTNode* root)
{if (root == NULL){return;}DestroyTree(root->left);//将当前节点的左子树作为根节点递归DestroyTree(root->right);//将当前节点的左子树作为根节点递归free(root);//释放点节点的空间//root = NULL;//这里将root置为空指针没有意义,因为这个函数的参数是 值传递 ,//是将指针root存放的地址拷贝了一份给函数内部创建的指针root,我们是想将函数外的指针root置为空指针,//这里因为是值传递,所以只是将函数内部创建的临时指针root置为空,值传递形参的改变不影响实参,//所以函数外部的指针root依旧存放的是动态开辟的 大小是结构体类型 的空间的地址,并没有变为空指针NULL。//这里如果非要改变,那么就用二级指针,或者不用管,因为整个程序结束后,申请的所有空间都会销毁(返还)
}

解释请看注解,非常详细。


四、二叉树的层序遍历(用的多)

二叉树的层序遍历,用到了线性表的队列,队列是先进先出,用队列的实现二叉树的核心思路是:上一层带下一层。解释请看代码的注解和图片,非常详细。

//层序遍历二叉树的节点的数据(需要用到队列)
void LevelOrder(BTNode* root)//传指向二叉树根节点的指针
{// 核心思路:上一层出的时候带下一层节点进;//队列里的元素是指向二叉树节点的指针Queue q;//创建一个结构体类型Queue的变量,这个结构体里放的是//一个指向第一个节点的指针head和一个指向尾节点的指针tailQueueInit(&q);//初始化这个结构体,地址传递,可以改变实参if (root)//判断二叉树是否有节点QueuePush(&q, root);//将 指向二叉树根节点的指针 作为元素 队尾入队列里//此时队列里 只有 指向二叉树根节点的指针这一个元素while (!QueueEmpty(&q))//队列里非空,就继续;队列空,就跳出循环{BTNode* front = QueueFront(&q);//将对头的元素由临时变量存放QueuePop(&q);//对头出 队列对头的元素printf("%c ", front->data);//打印 对头的元素 里存放的元素//即打印的二叉树节点里存放的数据if (front->left)//该节点的左子树不为空指针,则将左子树队尾入队列里{QueuePush(&q, front->left);}if (front->right)//该节点的右子树不为空指针,则将右子树队尾入队列里{QueuePush(&q, front->right);}}printf("\n");QueueDestory(&q);//销毁队列的空间
}


五、总代码

这是总代码的地址,有需要的可以自取:放代码: 代码 - Gitee.com


六、代码运行实例

前序遍历的顺序:A B D NULL NULL E NULL NULL C NULL NULL
中序遍历的顺序:NULL D NULL B NULL E NULL A NULL C NULL
后序遍历的顺序:NULL NULL D NULL NULL E B NULL NULL C A
节点A作为第一个根节点的二叉树元素个数:5
节点B作为第一个根节点的二叉树元素个数:3
节点A作为第一个根节点的二叉树叶子节点的个数:3
节点B作为第一个根节点的二叉树叶子节点的个数:2

数据结构——非线性结构 之 二叉树,详细解析相关推荐

  1. 数据结构——非线性结构(树与二叉树)

    文章目录 一. 非线性结构的概述 二. 树的基本概念 1. 树的定义 2. 专业术语 3. 树的性质 三. 树的分类 1. 一般树 2. 二叉树(是有序树) 2.1 概念 2.2 分类 1. 一般二叉 ...

  2. 数据结构 非线性结构 树 介绍及存储方法

    所谓树, 其实跟链表有类似的地方,  就是都是由节点和指针构成的数据结构. 在链表中,  每1个节点(尾节点除外)只有1个指针指向下1个节点. 所以链表各个节点可以由一条线链接起来, 就是一种线性结构 ...

  3. 数据结构——非线性结构(图)

    文章目录 一. 非线性结构的概述 二. 图的基本概念 1. 定义 2. 无向图.有向图 2.1 无向图 2.2 有向图 2.3 简单图 2.4 多重图 3. 顶点的度.出度.入度 3.1 对于无向图 ...

  4. 数据结构——非线性结构

    简单地说,非线性结构就是表中各个结点之间具有多个对应关系.如果从数据结构的语言来描述,非线性结构应该包括如下几点: 1.非线性结构是非空集. 2.非线性结构的一个结点可能有多个直接前趋结点和多个直接后 ...

  5. c 结构体 不允许使用不完整的类型_C语言必学知识点 quot;结构体quot;详细解析!...

    结构体是经常用到的数据类型,使用频率不亚于指针,所以需要重视,不过用法非常简单. 一.什么是结构体 ☀ 在前面的时候已经介绍了C语言中的数组,用法跟其他语言差不多.当一个整体由多个数据构成时,我们可以 ...

  6. 【内卷数据结构】顺序表超详细解析 | 从零开始步步解读 | 画图理解+调试分析 | 菜单制作

    ​​​​ 前言: 本章节将对顺序表的概念进行介绍,着重讲解动态顺序表.对常用的接口函数进行一个个讲解,并进行解析.顺序表讲解部分将从零实现顺序表接口函数,遇到问题我会进行一步步地调试说明,通过对本章的 ...

  7. 《数据结构》邓俊辉 网课习题详细解析(第五章:二叉树)

    文章目录 (a)树 (b)树的表示 (c)二叉树 (e1)先序遍历 (e2)中序遍历 (e4)层次遍历 (e5)重构 (a)树 1.下列那种数据结构可以高效地兼顾静态操作和动态操作(D) A.arra ...

  8. 【数据结构总结】第五章 树和二叉树(非线性结构)

    第五章 树和二叉树(非线性结构) 提示:本文主要是以思维导图的形式概括数据结构第一章的精华内容,基本不会用到文字性的内容,目的是为了给大家梳理每个重要的知识点的相关概念,方便大家在复盘的时候快速阅读和 ...

  9. 二叉树结构与算法思路解析

    二叉树 介绍 主要内容 二叉树的概念和性质 二叉树的存储结构 遍历二叉树 递归遍历 非递归遍历 线索二叉树 哈夫曼树 树和森林 树和森林的存储 树和森林与二叉树的转换 树和森林的遍历 树型结构特点 一 ...

最新文章

  1. java 模拟实现mq,RabbitMQ的5种模式,并使用java进行模拟操作
  2. 客户资产管理(Custom Asset Management)
  3. Python3入门笔记(1) —— windows安装与运行
  4. DL:深度学习(神经网络)的简介、基础知识(神经元/感知机、训练策略、预测原理)、算法分类、经典案例应用之详细攻略
  5. 使用@required注解完成依赖检查
  6. html制作卡通图案代码,CSS画的卡通动画图案
  7. 飞鸽传书下载,还是飞鸽传书下载
  8. vue 前台文本修改触发事件_利用VBA代码禁用触发事件及对工作薄修改的保存方案...
  9. Redis从入门到精通:初级篇(转)
  10. centos8离线安装Apache_疯狂Hive之Hivean安装部署与交互方式(一)
  11. 操作系统--进程管理1--单个CPU情况
  12. hive split 注意事项
  13. 真正解决:gpg --verify sig: 无法检查签名:找不到公钥
  14. chmod命令用法linux,Linux下chmod命令详细介绍及用法举例
  15. 基本知识 100028
  16. 信息安全管理体系--建立
  17. linux的tar命令的exclude,mac 的tar命令--exclude和linux的tar命令--exclude的区别
  18. 娱乐大数据:《小时代》是属于谁的小时代?
  19. 将多个excel表合并到一个excel表
  20. kafka-eagle详细安装配置图文教程

热门文章

  1. 如何画软件软件设计图
  2. 免费企业建站系统哪个好?
  3. wpscan常见的使用方法
  4. 物联网人工智能常用算法
  5. 什么是智能硬件?智能硬件开发对物联网有哪些重要性?
  6. ‘filter()‘ and ‘map()‘ can be swapped
  7. Github 正常显示图片,以及调整图片的大小
  8. 12月微信的新规来了
  9. python batchnorm2d_Python nn.BatchNorm2d方法代碼示例
  10. 批处理实现文件夹同步