目录
- typedef struct{//查找表的数据结构
- ElemType *elem;//元素存储空间基址,建表时按实际长度分配,0号单元留空
- int TableLen;//表的长度
- }SSTable;
- int Search_Seq(SSTable ST,ElemType key){
- ST.elem[0]=key;//哨兵
- for(i=ST.TableLen;ST.elem[i]!=key;--i);//从后往前找
- return i;//若表中不存在关键字key的元素,将查找到i为0时退出for循环
- }
对线性的链表只能进行顺序查找。
,
查找成功的平均查找长度和一般线性表的顺序查找一样。
~比一般顺序查找算法好一些;
可以是链式存储结构。
二分查找,仅适用于有序的顺序表。
- int Binary_Search(SeqList L,ElemType key){
- int low=0,high=L.Tablelen-1,mid;
- while(low
- mid=(low+high)/2;//取中间位置
- if(L.elem[mid]==key)
- return mid;//查找成功,返回所在位置
- else if(L.elem[mid]>key)//从前半部分继续查找
- high=mid-1;
- else low=mid+1; //从后半部分继续查找
- }
- return -1;查找失败,返回-1
- }
判定树是一个平衡二叉树。
![](https://1000bd.com/contentImg/2022/08/09/043441581.png)
圆形节点是查找成功。
![ASL_{success}=\frac{1}{n}\sum_{i=1}^{n}l_{i}=\frac{1}{n}(1\times1+2\times2+...+h\times2^{h-1} )=\frac{n+1}{n}log_{2}(n+1)-1\approx log_{2}(n+1)-1](https://1000bd.com/contentImg/2022/08/09/043442672.gif)
h是树的高度。元素个数为n的时,树高![h=\left \lceil log_{2}(n+1) \right \rceil](https://1000bd.com/contentImg/2022/08/09/043443671.gif)
方形节点是查找失败。
仅适用于顺序存储结构,不适用于链式存储结构,且要求元素按关键字有序。
分块查找
索引顺序查找,既有动态结构,有适于快速查找。块内的元素可以无序,但块之间是有序的。
1 在索引表中确定待查记录所在的块,可以顺序查找或折半查找索引表
2 在块内顺序查找
分别是索引查找和块内查找的平均查找长度,将长度为n的查找表均匀地分为b块,每块有s个记录。
![ASL=L_{I}+L_{S}=\frac{b+1}{2}+\frac{s+1}{2}=\frac{s^{2}+2s+n}{2s}](https://1000bd.com/contentImg/2022/08/09/043446086.gif)
若
,则平均查找长度取最小值
,若对索引表采用折半查找,则
![ASL=L_{I}+L_{S}=\left \lceil log_{2}(b+1) \right \rceil+\frac{s+1}{2}](https://1000bd.com/contentImg/2022/08/09/043449586.gif)
二叉排序树BST
也称二叉查找树。对BST进行中序遍历,得到一个递增的有序序列。
二叉排序树的查找
二叉排序树的非递归查找算法
- BSTnode *BST_Search(BiTree T,ElemType key){
- while(T!=NULL&&key!=T->data){//若树空或等于根结点值,则结束循环
- if(key
lchild;//小于,则在左子树上查找 - else T=T->rchild;//大于,则在右子树上查找
- }
- return T;
- }
二叉排序树的插入
插入的结点一定是一个新添加的叶结点。
- int BST_Insert(BiTree &T,KeyType k){
- if(T==NULL){//原树为空,新插入的记录为根结点
- T=(BiTree)malloc(sizeof(BSTNode));
- t->data=k;
- T->lchild=T->rchild=NULL;
- return 1;//插入成功
- }
- else if(k==T->data)//树中存在相同关键字的结点,插入失败
- return 0;
- else if(k
data) - return BST_Insert(T->lchild,k);//插入到T的左子树
- else
- return BST_Insert(T->lchild,k);//插入到T的右子树
- }
二叉排序树的构造
- void Creat_BST(BiTree &T,KeyType str[],int n){
- T=NULL;//初始T为空
- int i=0;
- while(i
//依次将每个关键字插入到二叉排序树中 - BST_Insert(T,str[i]);
- i++;
- }
- }
二叉排序树的删除
- 若被删除结点z是叶子结点,则直接删除,不会破坏二叉排序树的性质。
- 若z只有一棵左子树或右子树,则让z的子树成为z父结点的子树,替代z的位置。
- 若z右左、右两颗子树,则令z 的直接后继(或直接前驱) 替代z,然后从而差排序树中删除这个直接后继(或直接前驱),这样就转换成了第一或者第二种情况。
![](https://1000bd.com/contentImg/2022/08/09/043449870.png)
二叉排序树的查找效率分析
二分查找的判定树唯一,二叉排序树的查找不唯一,相同关键字其插入顺序不同可能产生不同的二叉排序树
平衡二叉树
平衡二叉树的插入
先找到 插入路径上 离插入结点 最近的平衡因子 的绝对值大于1 的结点A,再对以A为根的子树,调整位置,使重新达到平衡。
LL平衡旋转(右单旋转)
![](https://1000bd.com/contentImg/2022/08/09/043450067.png)
RR平衡旋转(左单旋转)
![](https://1000bd.com/contentImg/2022/08/09/043450372.png)
LR平衡旋转(先左后右双旋转)
RL平衡旋转(先右后左双旋转)
![](https://1000bd.com/contentImg/2022/08/09/043450869.png)
平衡二叉树的删除
与插入操作的调整方式一样,不同之处在于,插入操作仅需要对以z为根的子树进行平衡调整,而删除操作先对以为根的子树进行平衡调整,若调整后子树高度减1,则可能需要对z的祖先结点进行平衡调整,甚至回溯到根结点。
红黑树
基本定义、结论
是满足条件的二叉排序树
左根右,根叶黑
不红红,黑路同
每个结点是红色或黑色的
根结点是黑色的
叶结点是黑色的(虚构的外部结点,NULL结点)
不存在两个相邻的红结点,(即红结点的父结点和孩子结点都是黑色的)
对每个结点,从该结点到任一叶结点的简单路径上,所含黑结点的 数量相同
结论:
- 从根到叶结点的最长路径不大于最短路径的2倍。
- 有n个内部结点的红黑树的高度
红黑树的插入
结论:
- 新插入红黑树中的结点初始着色为红色
用二叉查找树插入法插入,并将结点z着为红色,若结点的父结点时黑色的,无需调整。
如果z是根结点,将z着为红色,树的高度增加1,结束。
若z不是根结点,并且z的父结点z.p是红色,则
1 z的叔结点y是黑色的,且z是一个右孩子(LR)
2 z的叔结点y是黑色的,且z是一个左孩子(LL)
3 z的叔结点y是红色的
![](https://1000bd.com/contentImg/2022/08/09/043452061.png)
![](https://1000bd.com/contentImg/2022/08/09/043452693.png)
红黑树的删除
用二叉查找树删除法,若待删除结点有两个孩子,找到该结点的中序后继(或前驱)填补,即右子树中最小的结点,然后转换为删除该后继结点。
待删除结点没有孩子
若该结点是红色的,直接删除。无需调整。
若该结点是黑色的, 4种情况 图7.23-7.26
1 x的兄弟结点w是红色的
2 x的兄弟结点w是黑色的,w的左孩子是红色的,w的右孩子是黑色的
3 x的兄弟结点w是黑色的,且w的右孩子是红色的
4 x的兄弟结点w是黑色的,且w的两个孩子结点都是黑色的
待删除结点只有右子树或左子树,则只有两种情况
![](https://1000bd.com/contentImg/2022/08/09/043452906.png)
![](https://1000bd.com/contentImg/2022/08/09/043453062.png)
![](https://1000bd.com/contentImg/2022/08/09/043453216.png)
![](https://1000bd.com/contentImg/2022/08/09/043453356.png)
完整例子
![](https://1000bd.com/contentImg/2022/08/09/043453729.png)
待补充
B树
多路平衡查找树
B+树