树的基本性质:
1、树的结点数n等于所有结点的度数之和(分支结点数)+1
2、度为m的树第i层最多有m^(i-1)个结点
3、高度为h的m叉树最多有(m^h-1)/(m-1)个结点,(等比数列求和)
4、度为m,有n个结点的树最小高度为cell(logm(n(m-1))+1),(前h-1层满,h层1个)
5、度为m,n个结点的树最大高度为n-m+1,(至少一层有m个结点)
6、满m叉树第k个结点的第i个孩子的编号为m*(k-1)+i+1 【编号从1开始】,m*k+i【编号从0开始】
额外知识(操作系统):以n位为字长的位示图(管理空闲磁盘块)的第i行第j列所表示的盘块编号为:n*(i-1)+j【行列,盘块编号都从1开始】 n*i+j【行列,盘块都从0开始】
二叉树:
区别于度为2的树的性质:
1、二叉树可以为空,度为2的树至少3个结点
2、二叉树的结点区分左右,普通树的左右只是相对位置
特殊的二叉树:
满二叉树 | 高度为h,且有2^h-1个结点 除最后一层的叶节点其他结点度均为2 若i结点有左右孩子,则左孩子为2i,右孩子为2i+1 |
完全二叉树 | 高度为h的完全二叉树仅第h层不满,叶节点只可能在最深的两层 若有度为1的结点,则至多一个,且该点只有左孩子无右孩子 若i结点只有左孩子若为叶节点,则编号大于i的结点均为叶节点 若树结点数为奇数,则不存在度为1的点,为偶数则有度为1的点 结点i所在的层次为floor(log2(n+1)) 或floor(log2(n))+1 具有n个结点的完全二叉树的高度为cell(log2(n+1))或floor(log2(n))+1 |
二叉排序树 (二叉查找树)(BST) | 左子树<根节点<右子树 |
平衡二叉树(AVL) | 任一结点的左右子树高度差不超过1 |
正则二叉树 | 树中没有度为0的点 |
线索二叉树 | 链式存储,结点无左孩子,左指针指向前驱,无有孩子,右指针指向后继 (第一个和最后一个除外) |
二叉树的性质
1、非空二叉树的叶节点数等于度为2的结点数+1
2、链式存储中有n+1个空指针(n为结点总数)
树的存储结构
1、双亲表示法
采用连续的存储空间存储结点,在每个结点中添加伪指针,指示其双亲结点在数组中的位置
可以很快找到每个结点的双亲结点,但求结点的孩子需要遍历整个结构
2、孩子表示法
3、孩子兄弟表示法(二叉树表示法)
以二叉链表作为树的存储结构,每个结点包含:结点值,指向结点第一个孩子结点的指针,指向结点下一个兄弟结点的指针
树,二叉树,森林转换
树转换为二叉树:每个结点的左指针指向第一个孩子,右指针指向相邻的兄弟结点
森林转二叉树:每棵树先转为二叉树,每科树的根可视为兄弟结点,合并为一个二叉树
二叉树转森林:根及左子树为第一颗树,根的右子树同理将左右子树拆开
遍历关系
树 | 森林 | 二叉树 |
先根遍历 | 先序遍历 | 先序遍历 |
后根遍历 | 中序遍历(后序遍历) | 中序遍历 |
部分教程将森林的中序遍历称为后序遍历,中序遍历是相对其二叉树而言的,后序遍历因为根确实是最后访问的,可理解为一种称谓
哈夫曼树
哈夫曼树只有度为0和2的结点
路径:从树中一个结点到另一个结点之间的分支
路径长度:路径上的分支数目
带权路径长度:从树的根到一个结点的路径长度与该结点的权值的乘积
树的带权路径长度(WPL)=树中全部叶结点的带权路径长度之和=所有非叶结点的权值之和
WPL最小的树称为哈夫曼树(最优二叉树)
哈夫曼编码
若对每个字符用相同长度的二进制表示,称为固定长度编码
允许对不同字符用不同长度的二进制位表示,称为可变长度编码
若没有一个编码是另一个编码的前缀,则为前缀编码(哈夫曼树就是)
各种树的查找,插入,删除,调整
二叉排序树:
查找:平均为O(log2(n))
最坏为O(n)
插入:必为叶节点
删除:
1)为叶节点直接删除
2)不为叶节点 :【1】只有左或右孩子:用子树直接替代
【2】即左又右:用中序直接后继(前驱)替代,并删除替代元素
二叉平衡树
查找:平均为O(log2(n))
插入后调整(插入过程与二叉排序树一致):
LL(右单旋),LR(先左后右),RR(左单旋),RL(先右后左)
插入的是左子树还是右子树不影响后序旋转
删除后(删除过程与二叉排序树一致):
找第一个不平衡结点,与插入同理调整
红黑树
性质:
1、根为黑
2、叶节点(虚构的结点,NULL结点)为黑
3、不存在两个相邻的红结点
4、对每个结点,从该结点到叶节点的黑结点数量相等
结论:
1、从根到叶节点的最长路径不大于最短路径的两倍(最短路径全为黑结点,最长路径红黑交替)
2、有n个内部结点的红黑树高度h<=2(log2(n+1)),( 从根到任一结点至少一半为黑,黑高>=h\2,所以n>=2^(h\2)-1 )
插入(易出现两相邻的红结点):
插入初始为红:1)父结点为黑,无需调整
2)父结点为红,看叔结点:【1】叔为黑 {1}新结点为右孩子(LR)
{2}新结点为左孩子(LL)
调整后换色(原父变黑,原爷变红)
旋转都需要换色,详见删除后的注意
【2】叔为红:叔和父变黑,爷变红,将爷作为新结点继续向上调整
此时将父节点视为爷结点的左孩子,若父结点为右孩子,则调整改为(RR)和(RL)
删除(易破坏黑高):
1)待删点有两个孩子,用中序直接后继(前驱)替代,转为删除直接后继(前驱)
2)待删点有左或右孩子,此时子树只有一个结点,且必为红
用孩子替代,并把孩子变为黑
性质5即前面的性质4
(yr和yl作为子树只有一个结点,即为叶节点,但性质中说叶节点必为黑,不是矛盾了吗?)
注意性质中描述的叶节点是虚构的结点,不是这里通常意义上的叶节点
3)待删结点无孩子(为什么不用叶结点表述,相信大家也已经理解了)
【1】结点为红,直接删除
【2】结点为黑 (此时将替换待删结点的结点加一层额外的黑色,保证性质4)
注意:当待删结点为终端结点时,替换的结点为NULL结点(叶结点),由于出现了双黑结点,下述过程为将双黑结点变为普通结点
{1}兄弟为红,则兄弟的孩子必为黑(性质4),交换父和兄弟的色并左旋(兄弟为右结点),右旋 (兄弟为左结点)
{2}兄弟为黑(兄弟视为右结点,左结点同理,不在赘述)
1、兄弟右孩子为红(RR)
2、兄弟左孩子为红,右孩子为黑(RL)
3、兄弟两孩子均为黑,将双黑结点和兄弟结点去除一层黑色,把他们的父结点添加一层黑色,若父结点变为双黑结点,把父结点作为新结点进行调整
注意:每次旋转时都要交换两个旋转结点的颜色,即RL,LR需要调整两次颜色
调整完后把双黑结点视为普通结点
二叉查找树,二叉平衡树,红黑树三者均为中序有序递增,堆从根结点到任意叶结点都是有序的
B树(常存储在磁盘上)
所谓m阶B树是所有结点的平衡因子均为0的m路平衡查找树
性质:
1、每个结点至多有m颗子树,即至多m-1个关键字
2、若根节点不是叶节点,则至少有2颗子树,即至少一个关键字
3、除根节点外所有非叶结点至少有cell(m/2)颗子树,即cell(m/2)-1个关键字
4、所有“叶结点”都出现在同一层次上,且不带信息(NULL结点)
5、结点中关键字从左到右递增有序,左侧指针所指子树的所有关键字均小于该关键字,右侧指针所指子树的所有关键字均大于该关键字
B树的高度(磁盘存取次数)
1、B树每层至多m-1个关键字,m颗子树
n<=(m-1)(1+m+m^2+....m^(h-1) )=m^h - 1;
h>=logm(n+1)
2、除根节点最少.......
第二层2个,第三层2*cell(m/2),第h+1层2*cell(m/2)^(h-1)
查找不成功的结点数n+1>=2*cell(m/2)^(h-1)
h<=log cell(m/2) ((n+1)/2)+1
插入:
位置一定是最底层的非叶结点(终端结点)
若插入后 1)关键字个数<m,无需调整
2)关键字个数>m-1,进行分裂,cell(m/2)加入父节点,左右拆分,对父节点继续调整
删除:
1)删除非终端结点,用中序直接前驱(后继)替代,转为删除前驱(后继)
2)删除终端结点:【1】所在结点关键字个数>=cell(m/2),直接删除
【2】兄弟够借:所在结点关键字个数=cell(m/2),且相邻的兄弟结点关键字个数 >=cell(m/2)
进行父子换位(父结点的关键字替代删除关键字,兄弟节点中的关键字
替代父节点中的关键字)
【3】兄弟不够借:将关键字删除后与左(或右)兄弟结点及双亲结点中的关键
字合并
B+树
m阶B+树
性质:
1、每个分支结点最多m颗子树
2、非叶根结点至少两颗子树,其他分支结点至少cell(m/2)颗子树
3、结点的子树个数与关键字个数相等
4、所有叶结点包含全部关键字及指向相应记录的指针,叶结点中将关键字按大小顺序排列,并且相邻叶结点按大小顺序相互链接起来(支持顺序查找)。
5、所有分支结点(可视为索引的索引)中仅包含它的各个子结点(即下一级的索引块)中关键字的最大值及指向其子结点的指针。
m阶B+树与m阶B树的主要差异:
1、在B+树中,具有n个关键字的结点只含有n棵子树,即每个关键字对应一棵子树;而在B树中,具有n个关键字的结点含有n+1棵子树。
2、在B+树中,每个结点(非根内部结点)的关键字个数n的范围是\cell(m / 2)≤ n ≤ m(非叶根结点:2≤n≤m);而在B树中,每个结点(非根内部结点)的关键字个数n的范围是cell(m / 2 ) - 1≤n≤m-1(根结点:1≤n≤m-1)。
3、在B+树中,叶结点包含全部的关键字,非叶结点中出现的关键字也会出现在叶结点中
B树中,终端结点包含的关键字和其他结点包含的关键字是不重复的
4、B+树中所有非叶结点仅起索引作用,非叶结点的每个索引项只含有对应子树的最大关键字和指向该子树的指针,不含对应记录的存储地址(使磁盘块存储更多关键字,使磁盘读写次数更少,查找速度更快)
5、B+树中,用一个指针指向关键字最小的叶结点,将所有叶结点串成一个线性链表
查找,插入删除与B树基本类似,但在查找中,必须找到叶节点上的关键字,所以,无论查找成功与否,每次查找都是一条从根结点到叶结点的路径
堆
可将堆视为完全二叉树
大根堆:任一非根结点的值小于其双亲结点值
小根堆:与大根堆相反
创建初始堆:
从n/2-1到1进行调整,
调整过程:看要调整结点的值是否大于左右子结点的值,若不大于,与较大者交换,交换后下面的堆可能出现问题,需要继续往下调整
堆排序(仅适用于顺序存储的线性表)
输出堆顶元素,将堆顶元素与最后一个元素互换,将堆从1开始进行调整(堆元素-1,原堆顶元素不参与调整,后序同理)
建堆时间为O(n),排序时间为O(n*log2(n))
仅采用常数个辅助单元,空间复杂度为O(1)