数据结构与算法(第四版)-廖明宏,郭福顺,张岩,李秀坤-高等教育出版社.pdf
计算机科学中的树
一、代码的编写艺术(如何思考)
1、程序设计方法:
1)逐步求精:
2)程序的逻辑结构只有顺序,选择,循环。
2、写程序时只需要想想如何组合,即在写自然语言为主,计算机高级语言为辅的伪代码时,就要表示出如何组合
3、画流程图
1)break,continue
2)for,whlie
for(表达式1;表达式2;表达式3)
{循环体}
循环嵌套;for(i=1;i<=n;i++); //循环变量;判断条件;循环变量增值
{ for(j=1;j<=i;j++); //循环变量;判断条件;变循环量增值
{m=m*j;} //循环体乘
sum=sum+m; //循环体加
}
while(表达式)
{循环体}
3)if
4)递归
int fact(int n)
{
if(n<=1)
return 1;
else
return (n*fact(n-1))
}
不精确的大致的过程如下两图:
二、抽象问题,转化成图像,达到形象解决的效果(如何转化)(凑齐一百个)
1、遍历二叉树(当然特殊存储方式下会有特殊的遍历方法)
(1)从某中角度描述二叉树的样子
(2)顺序一般默认是从左子树到右子树
(3)遍历的三种方式:
遍历的三种路径(路径是红色,圆圈是头和两子树):
(4)两子树中若有内含二叉树的,就以遍历二叉树的方式走过这个特殊的子树,即以遍历树的方式走过特殊子树。
如图是三种不同的遍历方法:
2、对数(树的复杂度会用)
时间复杂度:①顺序的是取最大的。②循环的是取循环体与循环次数的乘积,(实际是一种循环体自乘的感觉)
1)以10为底数,记作lgx
2)以e为底数,记作lnx
3)以2为底的数,记作logx
3、深度优先遍历(搜索)和广度优先遍历(搜索)
深度优先遍历(搜索)
起点任意
访问相邻未且访问过的结点
广度优先遍历(搜索)
起点任意
依照次序访问相邻未且访问过的结点
4、普里姆prim算法- -加顶点
得到最小生成树(所有顶点都连通了,且无环路的图)
深度优先遍历
起点为权值最小的边的尾巴+找最小权值+回退
边权值常常定义为路径长度
5、克鲁斯卡尔Kruskal算法- -加边
得到最小生成树(所有顶点都连通了,且无环路的图)
6、迪杰斯特拉 Dijkstra 算法
贪心算法+每次选择最短路径距离
如何搜索最短路径?
从1开始如图:
二到三更新1到4的最短路径距离由无穷成30,进一步影响到三的S(1到5)和S(1到3);
三到四更新1到3的最短路径距离由无穷成50,进一步影响到四的S(1到5);
7、(罗伯特·弗洛伊德)Floyd算法
动态规划算法+每次选择最短路径距离
添加中间结点
for(k=1;k<=n;k++)//此for的循环体是跟每对结点添加一个中间结点k,循环几次添加几个
for(i=1;i<=n;i++)//此for的循环体是跟每行的结点对添加一个中间结点k,循环几次添加几行
for(j=1;j<=n;j++)//此for的循环体是跟每个结点对添加一个中间结点k,循环几次添加几对
if(D[i][k]+D[k][j]<D[i][j])//<小于时是求最短,>大于时是求最长
{
D[i][j]=D[i][k]+D[k][j];//从i到j的距离改为,从i经过k后到j的距离
P[i][j]=k;//记录结点i到结点j,要经过的中间结点k
}
代码图解释为:
8、(史蒂芬·沃舍尔)Warshall算法
改Floyd算法,不再存距离,改为存0与1.0代表没边,1代表有边
代码
#include<stdio.h>
int main()
{
int k,n,j,i;
n=5;
int D[5][5]={1,1,0,1,1,
0,1,1,0,0,
0,0,1,1,1,
0,0,1,1,1,
1,0,0,0,1};//.0代表没边,1代表有边
for(k=1;k<=n;k++)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
D[i-1][j-1]=D[i-1][j-1]||(D[i-1][k-1]&&D[k-1][j-1]);
printf("k=%d i=%d j=%d D[%d][%d] ",k,i,j,i,j); //k=1 i=1 j=1 D[1][1]
printf("= D[%d][%d] || (D[%d][%d] && D[%d][%d])",i-1,j-1,i-1,k-1,k-1,j-1); //= D[0][0] || (D[0][0] && D[0][0])
printf("= %d || (%d && %d)\n",D[i-1][j-1],D[i-1][k-1],D[k-1][j-1]); //= 1 || (1 && 1)
}
printf("j层for循环,执行了%d次循环体后,结束循环\n",j-1);
}
printf("i层for循环,执行了%d次循环体后,结束循环\n",i-1);
}
printf("k层for循环,执行了%d次循环体后,结束循环\n",k-1);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
printf("D[%d][%d]=%d ",i,j, D[i-1][j-1]);
}
printf("\n");
}
return 0;
}
输出结果
[Running] cd "c:\Users\李杰\Desktop\画图\Warshall\" && gcc hello.c -o hello && "c:\Users\李杰\Desktop\画图\Warshall\"hello
k=1 i=1 j=1 D[1][1] = D[0][0] || (D[0][0] && D[0][0])= 1 || (1 && 1)
k=1 i=1 j=2 D[1][2] = D[0][1] || (D[0][0] && D[0][1])= 1 || (1 && 1)
k=1 i=1 j=3 D[1][3] = D[0][2] || (D[0][0] && D[0][2])= 0 || (1 && 0)
k=1 i=1 j=4 D[1][4] = D[0][3] || (D[0][0] && D[0][3])= 1 || (1 && 1)
k=1 i=1 j=5 D[1][5] = D[0][4] || (D[0][0] && D[0][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=1 i=2 j=1 D[2][1] = D[1][0] || (D[1][0] && D[0][0])= 0 || (0 && 1)
k=1 i=2 j=2 D[2][2] = D[1][1] || (D[1][0] && D[0][1])= 1 || (0 && 1)
k=1 i=2 j=3 D[2][3] = D[1][2] || (D[1][0] && D[0][2])= 1 || (0 && 0)
k=1 i=2 j=4 D[2][4] = D[1][3] || (D[1][0] && D[0][3])= 0 || (0 && 1)
k=1 i=2 j=5 D[2][5] = D[1][4] || (D[1][0] && D[0][4])= 0 || (0 && 1)
j层for循环,执行了5次循环体后,结束循环
k=1 i=3 j=1 D[3][1] = D[2][0] || (D[2][0] && D[0][0])= 0 || (0 && 1)
k=1 i=3 j=2 D[3][2] = D[2][1] || (D[2][0] && D[0][1])= 0 || (0 && 1)
k=1 i=3 j=3 D[3][3] = D[2][2] || (D[2][0] && D[0][2])= 1 || (0 && 0)
k=1 i=3 j=4 D[3][4] = D[2][3] || (D[2][0] && D[0][3])= 1 || (0 && 1)
k=1 i=3 j=5 D[3][5] = D[2][4] || (D[2][0] && D[0][4])= 1 || (0 && 1)
j层for循环,执行了5次循环体后,结束循环
k=1 i=4 j=1 D[4][1] = D[3][0] || (D[3][0] && D[0][0])= 0 || (0 && 1)
k=1 i=4 j=2 D[4][2] = D[3][1] || (D[3][0] && D[0][1])= 0 || (0 && 1)
k=1 i=4 j=3 D[4][3] = D[3][2] || (D[3][0] && D[0][2])= 1 || (0 && 0)
k=1 i=4 j=4 D[4][4] = D[3][3] || (D[3][0] && D[0][3])= 1 || (0 && 1)
k=1 i=4 j=5 D[4][5] = D[3][4] || (D[3][0] && D[0][4])= 1 || (0 && 1)
j层for循环,执行了5次循环体后,结束循环
k=1 i=5 j=1 D[5][1] = D[4][0] || (D[4][0] && D[0][0])= 1 || (1 && 1)
k=1 i=5 j=2 D[5][2] = D[4][1] || (D[4][0] && D[0][1])= 1 || (1 && 1)
k=1 i=5 j=3 D[5][3] = D[4][2] || (D[4][0] && D[0][2])= 0 || (1 && 0)
k=1 i=5 j=4 D[5][4] = D[4][3] || (D[4][0] && D[0][3])= 1 || (1 && 1)
k=1 i=5 j=5 D[5][5] = D[4][4] || (D[4][0] && D[0][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
i层for循环,执行了5次循环体后,结束循环
k=2 i=1 j=1 D[1][1] = D[0][0] || (D[0][1] && D[1][0])= 1 || (1 && 0)
k=2 i=1 j=2 D[1][2] = D[0][1] || (D[0][1] && D[1][1])= 1 || (1 && 1)
k=2 i=1 j=3 D[1][3] = D[0][2] || (D[0][1] && D[1][2])= 1 || (1 && 1)
k=2 i=1 j=4 D[1][4] = D[0][3] || (D[0][1] && D[1][3])= 1 || (1 && 0)
k=2 i=1 j=5 D[1][5] = D[0][4] || (D[0][1] && D[1][4])= 1 || (1 && 0)
j层for循环,执行了5次循环体后,结束循环
k=2 i=2 j=1 D[2][1] = D[1][0] || (D[1][1] && D[1][0])= 0 || (1 && 0)
k=2 i=2 j=2 D[2][2] = D[1][1] || (D[1][1] && D[1][1])= 1 || (1 && 1)
k=2 i=2 j=3 D[2][3] = D[1][2] || (D[1][1] && D[1][2])= 1 || (1 && 1)
k=2 i=2 j=4 D[2][4] = D[1][3] || (D[1][1] && D[1][3])= 0 || (1 && 0)
k=2 i=2 j=5 D[2][5] = D[1][4] || (D[1][1] && D[1][4])= 0 || (1 && 0)
j层for循环,执行了5次循环体后,结束循环
k=2 i=3 j=1 D[3][1] = D[2][0] || (D[2][1] && D[1][0])= 0 || (0 && 0)
k=2 i=3 j=2 D[3][2] = D[2][1] || (D[2][1] && D[1][1])= 0 || (0 && 1)
k=2 i=3 j=3 D[3][3] = D[2][2] || (D[2][1] && D[1][2])= 1 || (0 && 1)
k=2 i=3 j=4 D[3][4] = D[2][3] || (D[2][1] && D[1][3])= 1 || (0 && 0)
k=2 i=3 j=5 D[3][5] = D[2][4] || (D[2][1] && D[1][4])= 1 || (0 && 0)
j层for循环,执行了5次循环体后,结束循环
k=2 i=4 j=1 D[4][1] = D[3][0] || (D[3][1] && D[1][0])= 0 || (0 && 0)
k=2 i=4 j=2 D[4][2] = D[3][1] || (D[3][1] && D[1][1])= 0 || (0 && 1)
k=2 i=4 j=3 D[4][3] = D[3][2] || (D[3][1] && D[1][2])= 1 || (0 && 1)
k=2 i=4 j=4 D[4][4] = D[3][3] || (D[3][1] && D[1][3])= 1 || (0 && 0)
k=2 i=4 j=5 D[4][5] = D[3][4] || (D[3][1] && D[1][4])= 1 || (0 && 0)
j层for循环,执行了5次循环体后,结束循环
k=2 i=5 j=1 D[5][1] = D[4][0] || (D[4][1] && D[1][0])= 1 || (1 && 0)
k=2 i=5 j=2 D[5][2] = D[4][1] || (D[4][1] && D[1][1])= 1 || (1 && 1)
k=2 i=5 j=3 D[5][3] = D[4][2] || (D[4][1] && D[1][2])= 1 || (1 && 1)
k=2 i=5 j=4 D[5][4] = D[4][3] || (D[4][1] && D[1][3])= 1 || (1 && 0)
k=2 i=5 j=5 D[5][5] = D[4][4] || (D[4][1] && D[1][4])= 1 || (1 && 0)
j层for循环,执行了5次循环体后,结束循环
i层for循环,执行了5次循环体后,结束循环
k=3 i=1 j=1 D[1][1] = D[0][0] || (D[0][2] && D[2][0])= 1 || (1 && 0)
k=3 i=1 j=2 D[1][2] = D[0][1] || (D[0][2] && D[2][1])= 1 || (1 && 0)
k=3 i=1 j=3 D[1][3] = D[0][2] || (D[0][2] && D[2][2])= 1 || (1 && 1)
k=3 i=1 j=4 D[1][4] = D[0][3] || (D[0][2] && D[2][3])= 1 || (1 && 1)
k=3 i=1 j=5 D[1][5] = D[0][4] || (D[0][2] && D[2][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=3 i=2 j=1 D[2][1] = D[1][0] || (D[1][2] && D[2][0])= 0 || (1 && 0)
k=3 i=2 j=2 D[2][2] = D[1][1] || (D[1][2] && D[2][1])= 1 || (1 && 0)
k=3 i=2 j=3 D[2][3] = D[1][2] || (D[1][2] && D[2][2])= 1 || (1 && 1)
k=3 i=2 j=4 D[2][4] = D[1][3] || (D[1][2] && D[2][3])= 1 || (1 && 1)
k=3 i=2 j=5 D[2][5] = D[1][4] || (D[1][2] && D[2][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=3 i=3 j=1 D[3][1] = D[2][0] || (D[2][2] && D[2][0])= 0 || (1 && 0)
k=3 i=3 j=2 D[3][2] = D[2][1] || (D[2][2] && D[2][1])= 0 || (1 && 0)
k=3 i=3 j=3 D[3][3] = D[2][2] || (D[2][2] && D[2][2])= 1 || (1 && 1)
k=3 i=3 j=4 D[3][4] = D[2][3] || (D[2][2] && D[2][3])= 1 || (1 && 1)
k=3 i=3 j=5 D[3][5] = D[2][4] || (D[2][2] && D[2][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=3 i=4 j=1 D[4][1] = D[3][0] || (D[3][2] && D[2][0])= 0 || (1 && 0)
k=3 i=4 j=2 D[4][2] = D[3][1] || (D[3][2] && D[2][1])= 0 || (1 && 0)
k=3 i=4 j=3 D[4][3] = D[3][2] || (D[3][2] && D[2][2])= 1 || (1 && 1)
k=3 i=4 j=4 D[4][4] = D[3][3] || (D[3][2] && D[2][3])= 1 || (1 && 1)
k=3 i=4 j=5 D[4][5] = D[3][4] || (D[3][2] && D[2][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=3 i=5 j=1 D[5][1] = D[4][0] || (D[4][2] && D[2][0])= 1 || (1 && 0)
k=3 i=5 j=2 D[5][2] = D[4][1] || (D[4][2] && D[2][1])= 1 || (1 && 0)
k=3 i=5 j=3 D[5][3] = D[4][2] || (D[4][2] && D[2][2])= 1 || (1 && 1)
k=3 i=5 j=4 D[5][4] = D[4][3] || (D[4][2] && D[2][3])= 1 || (1 && 1)
k=3 i=5 j=5 D[5][5] = D[4][4] || (D[4][2] && D[2][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
i层for循环,执行了5次循环体后,结束循环
k=4 i=1 j=1 D[1][1] = D[0][0] || (D[0][3] && D[3][0])= 1 || (1 && 0)
k=4 i=1 j=2 D[1][2] = D[0][1] || (D[0][3] && D[3][1])= 1 || (1 && 0)
k=4 i=1 j=3 D[1][3] = D[0][2] || (D[0][3] && D[3][2])= 1 || (1 && 1)
k=4 i=1 j=4 D[1][4] = D[0][3] || (D[0][3] && D[3][3])= 1 || (1 && 1)
k=4 i=1 j=5 D[1][5] = D[0][4] || (D[0][3] && D[3][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=4 i=2 j=1 D[2][1] = D[1][0] || (D[1][3] && D[3][0])= 0 || (1 && 0)
k=4 i=2 j=2 D[2][2] = D[1][1] || (D[1][3] && D[3][1])= 1 || (1 && 0)
k=4 i=2 j=3 D[2][3] = D[1][2] || (D[1][3] && D[3][2])= 1 || (1 && 1)
k=4 i=2 j=4 D[2][4] = D[1][3] || (D[1][3] && D[3][3])= 1 || (1 && 1)
k=4 i=2 j=5 D[2][5] = D[1][4] || (D[1][3] && D[3][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=4 i=3 j=1 D[3][1] = D[2][0] || (D[2][3] && D[3][0])= 0 || (1 && 0)
k=4 i=3 j=2 D[3][2] = D[2][1] || (D[2][3] && D[3][1])= 0 || (1 && 0)
k=4 i=3 j=3 D[3][3] = D[2][2] || (D[2][3] && D[3][2])= 1 || (1 && 1)
k=4 i=3 j=4 D[3][4] = D[2][3] || (D[2][3] && D[3][3])= 1 || (1 && 1)
k=4 i=3 j=5 D[3][5] = D[2][4] || (D[2][3] && D[3][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=4 i=4 j=1 D[4][1] = D[3][0] || (D[3][3] && D[3][0])= 0 || (1 && 0)
k=4 i=4 j=2 D[4][2] = D[3][1] || (D[3][3] && D[3][1])= 0 || (1 && 0)
k=4 i=4 j=3 D[4][3] = D[3][2] || (D[3][3] && D[3][2])= 1 || (1 && 1)
k=4 i=4 j=4 D[4][4] = D[3][3] || (D[3][3] && D[3][3])= 1 || (1 && 1)
k=4 i=4 j=5 D[4][5] = D[3][4] || (D[3][3] && D[3][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=4 i=5 j=1 D[5][1] = D[4][0] || (D[4][3] && D[3][0])= 1 || (1 && 0)
k=4 i=5 j=2 D[5][2] = D[4][1] || (D[4][3] && D[3][1])= 1 || (1 && 0)
k=4 i=5 j=3 D[5][3] = D[4][2] || (D[4][3] && D[3][2])= 1 || (1 && 1)
k=4 i=5 j=4 D[5][4] = D[4][3] || (D[4][3] && D[3][3])= 1 || (1 && 1)
k=4 i=5 j=5 D[5][5] = D[4][4] || (D[4][3] && D[3][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
i层for循环,执行了5次循环体后,结束循环
k=5 i=1 j=1 D[1][1] = D[0][0] || (D[0][4] && D[4][0])= 1 || (1 && 1)
k=5 i=1 j=2 D[1][2] = D[0][1] || (D[0][4] && D[4][1])= 1 || (1 && 1)
k=5 i=1 j=3 D[1][3] = D[0][2] || (D[0][4] && D[4][2])= 1 || (1 && 1)
k=5 i=1 j=4 D[1][4] = D[0][3] || (D[0][4] && D[4][3])= 1 || (1 && 1)
k=5 i=1 j=5 D[1][5] = D[0][4] || (D[0][4] && D[4][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=5 i=2 j=1 D[2][1] = D[1][0] || (D[1][4] && D[4][0])= 1 || (1 && 1)
k=5 i=2 j=2 D[2][2] = D[1][1] || (D[1][4] && D[4][1])= 1 || (1 && 1)
k=5 i=2 j=3 D[2][3] = D[1][2] || (D[1][4] && D[4][2])= 1 || (1 && 1)
k=5 i=2 j=4 D[2][4] = D[1][3] || (D[1][4] && D[4][3])= 1 || (1 && 1)
k=5 i=2 j=5 D[2][5] = D[1][4] || (D[1][4] && D[4][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=5 i=3 j=1 D[3][1] = D[2][0] || (D[2][4] && D[4][0])= 1 || (1 && 1)
k=5 i=3 j=2 D[3][2] = D[2][1] || (D[2][4] && D[4][1])= 1 || (1 && 1)
k=5 i=3 j=3 D[3][3] = D[2][2] || (D[2][4] && D[4][2])= 1 || (1 && 1)
k=5 i=3 j=4 D[3][4] = D[2][3] || (D[2][4] && D[4][3])= 1 || (1 && 1)
k=5 i=3 j=5 D[3][5] = D[2][4] || (D[2][4] && D[4][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=5 i=4 j=1 D[4][1] = D[3][0] || (D[3][4] && D[4][0])= 1 || (1 && 1)
k=5 i=4 j=2 D[4][2] = D[3][1] || (D[3][4] && D[4][1])= 1 || (1 && 1)
k=5 i=4 j=3 D[4][3] = D[3][2] || (D[3][4] && D[4][2])= 1 || (1 && 1)
k=5 i=4 j=4 D[4][4] = D[3][3] || (D[3][4] && D[4][3])= 1 || (1 && 1)
k=5 i=4 j=5 D[4][5] = D[3][4] || (D[3][4] && D[4][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
k=5 i=5 j=1 D[5][1] = D[4][0] || (D[4][4] && D[4][0])= 1 || (1 && 1)
k=5 i=5 j=2 D[5][2] = D[4][1] || (D[4][4] && D[4][1])= 1 || (1 && 1)
k=5 i=5 j=3 D[5][3] = D[4][2] || (D[4][4] && D[4][2])= 1 || (1 && 1)
k=5 i=5 j=4 D[5][4] = D[4][3] || (D[4][4] && D[4][3])= 1 || (1 && 1)
k=5 i=5 j=5 D[5][5] = D[4][4] || (D[4][4] && D[4][4])= 1 || (1 && 1)
j层for循环,执行了5次循环体后,结束循环
i层for循环,执行了5次循环体后,结束循环
k层for循环,执行了5次循环体后,结束循环
D[1][1]=1 D[1][2]=1 D[1][3]=1 D[1][4]=1 D[1][5]=1
D[2][1]=1 D[2][2]=1 D[2][3]=1 D[2][4]=1 D[2][5]=1
D[3][1]=1 D[3][2]=1 D[3][3]=1 D[3][4]=1 D[3][5]=1
D[4][1]=1 D[4][2]=1 D[4][3]=1 D[4][4]=1 D[4][5]=1
D[5][1]=1 D[5][2]=1 D[5][3]=1 D[5][4]=1 D[5][5]=1
[Done] exited with code=0 in 0.249 seconds
这样想知道有向图中任意两结点间是否存在有向路,可以查看矩阵
9、拓扑排序算法
顶点活动网是一个有向无环图。因“顶点活动”的英语缩写为AOV,故简称“AOV网”。
直观上,偏序指集合上只有部分元素之间可比较,全序是指全体元素均可比较
拓扑序列是顶点活动网中将活动按发生的先后次序进行的一种排列。
拓扑排序,是对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G)(边u到v含于有向无环图G的边集E),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。
简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序
全序T是偏序P的线性扩展,只要x小于等于y在偏序中成立,则x小于等于y在全序中也成立。
在计算机科学中,找到偏序的线性扩展的算法,叫做拓扑排序,即找到全序的算法,叫做拓扑排序
任何无环路的AOV网,其顶点都可以排成一个拓扑序列,并且其拓扑序列不一定是唯一的
基于深度优先遍历(搜索)和广度优先遍历(搜索)都可以得到拓扑序列
10、平衡二叉树
一个结点的左子树与右子树的高度之差,其绝对值不超过1,即允许有一层没有满,但是不能有两层都没有满
平衡化处理
实现能够在O(logn)时间内对具有n个元素的符号表进行查找、插入、删除操作
right 右边;left 左边
11、B-树的删除插入操作
(读B树,不是B减树)
(1)AVL树是在结点高度上采用相对平衡的策略,使其平均性能接近于二叉树的最好情况下的性能。
B-树=AVL树的高度相对平衡+增加树结点的子树个数
下面看看如何创建m-路查找树的概念,再用m-路查找树引出B-树的概念
1)m-路查找树的任意某根结点的子树至多含m棵子树
子树的结构:n,A0,(k1,A1),(K2,A2),(K3,A3)…,(Kn,An) (0≤i≤n<m)
n是结点中的关键字的数量,k是关键字,A是指向子树的指针,由0≤i≤n<m知n的最大值是m-1
2)讨论m-路查找树中的3-路查找树,任意某根结点的子树至多含3棵子树
存有两个关键字的子树的结构:n,A0,(k1,A1),(K2,A2)
3)m-路查找树中的为了方便查找关键字,而需要的特征
①Ki<Ki+1,即左小于右
②子树An中的所有关键字值都大于Kn,子树A0中的所有关键字值都小于K1,即关键字像是出生年下层儿子年大于上层的爸爸年
③每棵子树Ai都是m-路查找树
(2)B-树包含于m-路查找树,满足如下三点的m-路查找树是B-树
①根节点至少包含2个儿子
②除根结点和失败结点以外,所有结点都至少具有m/2个儿子,有余加1
③所有失败结点都在同一层
(2)删除和插入时:保证搜索树结构和B-树结构
1)插入从非失败结点的底层开始插入
2)如果在结点p上插入新关键字使结点p的关键字个数达到m,则需要分裂结点p
3)删除时的不同的4种情况
①删除根节点
②不涉及:除根结点和失败结点以外,所有结点都至少具有m/2个儿子,有余加1
③涉及:除根结点和失败结点以外,所有结点都至少具有m/2个儿子,有余加1
④涉及:除根结点和失败结点以外,所有结点都至少具有m/2个儿子
在③的情况下,增加兄弟也是m/2个,帮不了
合并形成的结点的关键字个数超过m-1了吗?(m路=1路记录关键字个数+m-1路记录关键字值)
删除后结点的关键字个数变化:父亲失去一个关键字,需被删关键字的结点的关键字数量不变,需被删关键字的结点的兄弟的关键字数量不变
m为偶数时,除根结点和失败结点以外,所有结点都至少具有m/2=m/2个指针,指针指向儿子即儿子
m为奇数时,除根结点和失败结点以外,所有结点都至少具有m/2=(m+1)/2-1个指针(因为有余数时,进1,如3/2=(3+1)/2-1=1)
所以合并形成的结点的关键字个数是:
m为偶数时m/2+m/2=m; 此时合并形成的结点的关键字个数=m-1
m为奇数时(m+1)/2-1+(m+1)/2-1=m-2,此时合并形成的结点的关键字个数=m-2-1=m-3
当然若父亲的关键字个数移下去后也不满足m/2个后向上要,肯定能要到,因为在添加时上层肯定是满了才增加层数往下
12、散列技术
Hash 哈希散列散表哈希值
散列技术适用于实际出现的关键字的数目远小于关键字所有可能取值的数量,且关键字所有可能取值在一个范围
冲突处理