1、概述
二叉树是由n(n>= 0)个节点组成的有序集合。它要么是空树,要么是非空树。对于非空树:
- 有且仅有一个称之为根的节点。
- 当n>1时,其余节点可分为两个互不相交的有限集T1、T2,其中每个集合本身又是一颗树,分别称为根节点的左子树和右子树。
因为每个节点最多有两个子节点,所以称为二叉树。相应的,我们也可以定义三叉树、四叉树、…、八叉树等。
1.1、树的几个概念
路径:顺着连接点从一个节点走向另一个节点,所经过的节点的顺序排列称为路径。
根:树的顶端称为根节点,一棵树只有一个根节点,从根到其它任何一个节点都必须有且仅有一条路径。
深度:从根到所在节点路径所经过的节点个数。
父节点:每个节点(除了根)向上连接的节点,为当前节点的父节点。
子节点:每个节点都有可能有一条或者多条向下连接的节点,这些下面的节点称为当前节点的子节点。
叶节点:没有子节点的节点称为叶节点。
度数:当前节点拥有子节点的个数,称为当前节点的度数。
高度:树中所有节点深度的最大值,称为该树的高度。
层数:从根开始,根为第一层,根的子节点为第二层,以此类推。
1.2、二叉树的性质
1、在二叉树的第i层上最多有
个节点。( i >= 1 )
2、二叉树如果高度为k,那么最多有
-1个节点。( k >= 1 )
3、N0 = N2 + 1 N0表示度数为0的节点数,N2表示度数为2的节点数。
4、若对含 n 个节点的完全二叉树从上到下且从左至右进行 1 至 n 的编号,则对完全二叉树中任意一个编号为 i 的结点有如下特性:
- 若 i = 1,则该节点是二叉树的根。
- 若2i > n, 则该节点无左子节点,否则,编号为 2i 的节点为其左子节点。
- 若 2i+1 > n, 则该节点无右子节点,否则,编号为 2i+1 的节点为其右子节点。
1.3、二叉树的遍历
二叉树分为三种遍历方法:
前序遍历:D L R 先自身数据,然后左子节点,最后右子节点
中序遍历:L D R 先左子节点,在自身数据,最后右子节点
后序遍历:L R D 先左子节点,在右子节点,最后是自身数据
通过上面我们可以总结:
1、左子节点总是在右子节点的前面
2、所说的前序、中序、后序是自身数据所在的位置
1.4、二叉树的分类
根据二叉树的状态可以把二叉树分为好几类。
满二叉树:所有层的节点都是满的。
完全二叉树:前面n-1层是满的,最后一层可以不满,但是要从左向右连续排列。
平衡二叉树:一棵树的左右两个子树的高度差不超过1,又称AVL树。
线索二叉树、霍夫曼树、红黑树、B树等,若后面有时间在慢慢整理。
二叉树也是一个逻辑上的概念,我们可以使用顺序结构或者链式结构实现。
2、顺序结构二叉树
顺序二叉树只能还原完全二叉树,所以不是完全二叉树的需要变成完全二叉树,需要用空位补成完全二叉树。
因为顺序结构的大小是固定的,所以对于存储是有数量限制的。而且如果二叉树离完全二叉树标准特别远,即需要补很多的空位,则会造成内存的大量浪费,所以很少有使用顺序结构实现二叉树。
顺序存储就是使用一组数组存储二叉树中的结点,并且结点的存储位置,就是数组的下标索引。如下图所示:
在数组中的存储为:
头结点在位置1的地方,左子节点位于1*2的地方,右子节点位于1*2+1的地方。以此类推节点n的左子节点位于2*n的位置,右子节点位于2*n+1的位置。
3、链式结构二叉树
对于链式二叉树,每一个节点由三部分组成:当前数据、左子节点、右子节点。
节点定义为:
struct TreeNode
{
int data;
TreeNode* pLeft;
TreeNode* pright;
}
仔细一看,这就是一个双向链表的结构。
具体的实现就不写了,网上有太多的资源,上网一查就得到了。
感谢大家,我是假装很努力的YoungYangD(小羊)。
参考资料:
https://www.jianshu.com/p/bf73c8d50dc2
https://www.cnblogs.com/lustar/p/7139176.html
https://www.cnblogs.com/polly333/p/4740355.html