树
定义
- 树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合
性质
- 树中的结点数=所有结点的度数之和+1
- 度为 m 的树中第 i 层至多有 m i-1个节点(i≥1)
- 高度为 h 的 m 叉树至多有(mh-1)/(m-1)
二叉树
定义
- 本身是有序树;
- 树中包含的各个节点的度不能超过 2
性质
-
二叉树中,第 i 层最多有 2i-1 个结点。
-
如果二叉树的深度为 K,那么此二叉树最多有 2K-1 个结点。
-
二叉树中,终端结点数(叶子结点数)为 n0,度为 2 的结点数为 n2,则 n0=n2+1。
-
包含n个结点的二叉树的高度至少为log2 (n+1)
二叉树的顺序存储结构
- ^ 表示并不存在的空结点(也可以用0表示)
- 空间利用率太低
- 这种存储结构从数组下标1开始存储树中的结点,才能根据性质来计算孩子结点在数组中的位置
二叉树的链式存储结构
二叉链表存储
-
存储结构
-
两种二叉链表
二叉树的遍历
-
序指的是根结点在何时被访问
-
先序、中序、后序指的是父节点被访问的次序
-
先序遍历:遍历顺序规则为【根左右】
-
中序遍历:遍历顺序规则为【左根右】
-
后序遍历:遍历顺序规则为【左右根】
template <typename T> struct BinTreeNode {
T data; //数据域
BinTreeNode * LeftChild; //左孩子节点指针
BinTreeNode * RightChild; //右孩子节点指针
BinTreeNode * parent; //父节点指针
};
先序
- 考察到一个节点后,即刻输出该节点的值,并继续遍历其左右子树
void travPre_R(BinTreeNode<T> * root) {
if (!root) return;
cout << root->data;
travPre_R(root->LeftChild);
travPre_R(root->RightChild);
}
中序
- 考察到一个节点后,将其暂存,遍历完左子树后,再输出该节点的值,然后遍历右子树
void travIn_R(BinTreeNode<T> * root) {
if (!root)
return;
travPre_R(root->LeftChild);
cout << root->data;
travPre_R(root->RightChild);
}
后序
- 考察到一个节点后,将其暂存,遍历完左右子树后,再输出该节点的值
void travPost_R(BinTreeNode<T> * root) {
if (!root)
return;
travPost_R(root->LeftChild);
travPost_R(root->RightChild);
cout << root->data;
}
层次
满二叉树
定义
- 高度为h,并且有2h –1个结点的二叉树,被称为满二叉树
- 如果一棵二叉树的结点要么是叶子结点,要么它有两个子结点,这样的树就是满二叉树
性质
- 满二叉树中第 i 层的节点数为 2n-1 个。
- 深度为 k 的满二叉树必有 2k-1 个节点 ,叶子数为 2k-1。
- 满二叉树中不存在度为 1 的节点,每一个分支点中都两棵深度相同的子树,且叶子节点都在最底层。
- 具有 n 个节点的满二叉树的深度为 log2(n+1)。
完全二叉树
定义
- 一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下一层的叶结点集中在靠左的若干位置上。这样的二叉树称为完全二叉树。
- 如果二叉树中除去最后一层节点为满二叉树,且最后一层的结点依次从左到右分布,则此二叉树被称为完全二叉树。
性质
二叉排序树(BST)
定义
- 又叫二叉查找树
- 左子树所有的关键字小于根结点的关键字
- 右子树所有的关键字大于根节点的关键字
- 左子树和右子树又各是一个二叉排序树
性质
1、若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
2、若它的右子树不空,则右子树上所有节点的值均大于其根节点的值。
3、任何节点的键值一定大于其左子树中的每一个节点的键值,并小于其右子树中的每一个节点的键值。
目的
- 提高查找和插入删除关键字的速度
平衡二叉树(AVL树)
定义
- 也被称为高度平衡树
- 它必须是二叉查找树
- 任何一结点的左子树和右子树的深度之差不超过1
- 若将二叉树节点的平衡因子BF定义为该节点的左子树的深度减去它的右子树的深度,则平衡二叉树上所有节点的平衡因子只可能为-1,0,1
- AVL树的查找平均复杂度是O(log(n))
意义
- 二叉搜索树一定程度上可以提高搜索效率,但是当原序列有序时,例如序列 A = {1,2,3,4,5,6},构造二叉搜索树如图 。依据此序列构造的二叉搜索树为右斜树,同时二叉树退化成单链表,搜索效率降低为 O(n)
平衡因子
- 某节点的左子树与右子树的高度(深度)差即为该节点的平衡因子(BF,Balance Factor),平衡二叉树中不存在平衡因子大于 1 的节点。在一棵平衡二叉树中,节点的平衡因子只能取 0 、1 或者 -1 ,分别对应着左右子树等高,左子树比较高,右子树比较高
转换
- 平衡二叉树的失衡调整主要是通过旋转最小失衡子树来实现的。根据旋转的方向有两种处理方式,左旋 与 右旋
最小不平衡子树
- 距离插入节点最近的,且平衡因子的绝对值大于1的节点为根的子树
LL 型
RR型
LR型
RL型
线索二叉树
定义
- 在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行遍历,使其变为线索二叉树的过程称为对二叉树进行线索化
- 对一棵二叉树中所有节点的空指针域按照某种遍历方式加线索的过程叫作线索化,被线索化了的二叉树称为线索二叉树
原理
- 遍历二叉树的原理其实就是以一定规则将二叉树中的结点排列成一个线性序列,得到二叉树中结点的先序序列、中序序列或后序序列。这些线性序列中的每一个元素都有且仅有一个前驱结点和后继结点。
结点结构
-
LTag为0是指向该结点的左孩子,为1时指向该结点的前驱
-
RTag为0是指向该结点的右孩子,为1时指向该结点的后继
为什么
- 知道了“前驱”和“后继”信息,就可以把二叉树看作一个链表结构,从而可以像遍历链表那样来遍历二叉树,进而提高效率
森林
定义
- 只要没有回路的连通图就是树。森林是指互相不交并树的集合。
- 森林(forest)是m(m≥0)棵互不相交的树的集合。任何一棵树,删除了根结点就变成了森林。
森林跟二叉树的转换
森林转换为二叉树
- 初始
- 将森林中的每棵树变为二叉树
- 将各二叉树的根节点从左到右连在一起,形成二叉树
- 调整位置
二叉树转换为森林
- 初始
- 若结点X是双亲Y的左孩子,则把X的右孩子,右孩子的右孩子…都和 Y用线连起来
- 去掉所有双亲到右孩子间的连线
- 调整位置
哈夫曼树
定义
- 给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
- 路径是指在一棵树中,从一个节点到另一个节点之间的分支构成的通路
- 节点的带权路径长度指的是从根节点到该节点之间的路径长度与该节点权的乘积
- 树的带权路径长度指的是所有叶子节点的带权路径长度之和