二叉树
定义:二叉树是一种树型结构,它的特点是每个结点至多只有两棵子树,并且,二叉树的子树有左右之分,次序不能任意颠倒
性质:
①在二叉树的第i层上至多有2^(i-1 )个结点(i≥1)
②深度为k的二叉树至多有2^k-1个结点
③对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n0=n2+1
④具有n个结点的完全二叉树的深度为floor(log2 n)+1
二叉树的存储结构
1.顺序存储结构
1 |
|
将完全二叉树上的编号为i的结点元素存储在如上定义的一位数组中下标为i-1的分量中。
最坏的情况下,一个深度为k且只有k个结点的单支树(树中不存在度为2的结点)却需要长度为2^k-1的一位数组
仅适合用于完全二叉树
2.链式存储结构
1 | typedef struct BiTNode{ |
遍历二叉树
1.先序遍历
1 | Status Bitree::PreOrderTraverse(const BiTree &T) { |
1 | Status PreOrderStack(const BiTree T){ |
2.中序遍历
1 | Status Bitree::InOrderTraverse(const BiTree &T) { |
1 | Status InOrderStack(const BiTree &T) { |
3.后序遍历
1 | Status Bitree::PostOrderTraverse(const BiTree &T) { |
1 | Status PostOrderStack(BiTree T){ |
4.层序遍历
1 | Status Bitree::LevelOrderTraverse(const BiTree &T) { |
线索二叉树
利用n个结点的二叉树必有n+1个空链域存放指向某种遍历次序下的前驱结点或后继结点的指针
图示
数据结构
1 | typedef enum PointTag{Link,Thread}; //Link==0;指针,Thread==1;线索 |
树和森林
相关术语
树的结点:包含一个数据元素及若干指向其子树的分支
度:结点拥有的子树数称为结点的度(Degree)
叶子:度为0的结点
分支结点:度不为0的结点
结点的层次
从根开始定义起,根为第一层,根的孩子为第二层
深度(Depth):树中结点的最大层次
有序树:结点各子树看成从左至右是有次序的(即不能交换的)
*无序树:结点各子树看成从左至右是无次序的(即可以交换的)
*森林(Forest):m(m≥0)棵互不相交的树的集合
存储结构
1.双亲表存储表示
1 |
|
利用每个结点(除根节点外)只有唯一双亲的性质求结点的孩子时需要遍历整个结构
2.孩子链表存储表示
1 | typedef struct CTNode{ |
便于一些涉及孩子的操作,不适用于找双亲
3.二叉链表(孩子-兄弟)存储表示):
1 | typedef structCSNode{ |
便于实现各种树的操作
森林与二叉树的转换
1.树变二叉树
兄弟相连,保留长子的连线
2.二叉树变树
结点的右孩子与其双亲连
3.森林变二叉树
树变而二叉树,各个树的根相连
哈夫曼树
路径长度
路径上的分支数目
树的路径长度
从树根到每个结点的路径长度之和
树的带权路径长度
所有叶子结点的带权路径长度之和
WPL=∑(k=1,n)wk*lk
WPL最小的二叉树称作最优二叉树或哈夫曼树
构造
权值越大,应分配的路径长度越小
故:
将所有带权结点加入集合,每次从结合中选取权值最小的两个结点,生成一个权值为两者权值之和的父节点,父节点加入集合,两个子节点移出集合,重复操作,直至集合只剩下一个结点,即根结点。
应用
前缀编码
数据结构
1 | typedef struct{ |
二叉树代码
1 |
|
哈夫曼树代码
1 |
|