第七章学习的是查找,分别学习了线性表、树表、散列表的查找。
查找首先要确定是什么数据结构,用的是什么存储方法。
首先是线性表的查找:有顺序查找、折半查找。分块查找的方法。
顺序查找
int Search_Seq(SSTable ST,KeyType key)
{
SR.R[0].key=key;//将第一个元素置空,用于存放待查找的数据
for(i=ST.length;ST.R[i].key!=key;i--);//将数据从后往前查找,当查找成功的时候下标就为i
return i;
}
这个方法的ASL=(1+n)/2
顺序查找对表的结构没有任何要求,适用于链式结构和顺序结构,但当n很大的时候,查找效率比较低
折半查找
类似于二分法
int Search_Seq(SSTable ST,KeyType key)
{//找到,则为该元素的位置,否则为0
low=1;high=ST.length;
while(low<-high)
{
mid = (low+high)/2;
if(key==ST.R[mid].key) return mid;
else if(key
}
return 0;//找不到
}
这个方法的ASL=log2(n+1)
折半查找的方法效率比顺序查找要高,但是它要求表是有序的。如果是无序的话,查找前需要排序
分块查找
分块查找分为两步:先分为字块,再在字块中查找,字块与字块之间是有序的,而字块之后可以是无序的
所以分块查找可以看做是顺序查找和折半查找的合成
若将表分为b块,每块有s个记录,每个记录和每块的查找概率分别相同
则ASL=Lb+Ls=1/2 (n/s + s) + 1
后面是树表的查找
首先学习了二叉排序树
二叉排序树可以是一棵空树,或者是 一颗左子树上任何结点都小于其根结点, 右子树上任何结点都大于其根结点的树
二叉树的递归查找:
BSTree SearchBST(BSTree T,KeyType key)
{//递归查找,利用二叉排序树的特点递归左子树或者右子树
if(!T || key == T->data.key) return T;
else if(key < T->data.key) return SearchBST(T->lchild,key);
else if(key > T->data.key) return SearchBST(T->rchild,key);
}
二叉排序树的插入,删除与创建都是基于查找来实现的
平衡二叉树,AVL树,是指左子树和右子树的深度之差的绝对值不超过1,而且左子树和右子树都是平衡二叉树
平衡因子,是指AVL树左右子树的差
其中还有LL,RR,LR,RL型的树,指的是在 第一位的L/R 子树根结点的 第二位L/R子树 上插入结点,就会使得树失去平衡
然后还有B-树,
m阶的B-树每个结点至多只有m棵子树;
如果根结点不是叶子结点,则至少有两棵子树;
除跟之外的非终端结点至少有 m/2 棵子树;
所有的叶子结点都在同一层,而且不带信息,也被称为失败结点;
B-树的查找,插入、删除都与二叉排序树相似
最后是散列表
散列表是指一个有限连续的地址空间,用以存放散列函数计算所得 的 散列地址 的数据记录
散列表一般都是一个一维数组,散列地址则是这个数组的下标
冲突是指地址相同,但是数据是不同的 , 而地址相同的两个关键字 被称为 同义词
散列函数的构造方法有:数字分析法,平方取中法,折叠法,除留余数法
数字分析法是要已知数字的分布情况,根据数字的特点来得到不同的散列地址
平方取中法是指关键字平方后的数字的几位或者其他的组合作为散列地址
折叠法是将关键字分割成为位数相同的几部分,然后将他们叠加和作为散列地址
除留余数法就是取一个不大于表长的数p,然后关键字除p后的余数作为散列地址
但当地址相同时会出现冲突
冲突产生时可以使用开放地址或者链地址的方法
开放地址中法有
线性探测法:是指地址冲突时,地址加一,当地址最大时则从0开始加一
二次探测法:地址冲突时+1^2,-1^2,+2^2,-2^2…………
伪随机探测法:地址冲突时,产生一个伪随机数,然后将它当做散列地址
链地址法:将相同地址的数据放在同一个单链表中
散列表的查找要根据冲突的处理方法,如果直接找到了则返回key,找不到就根据处理方法来计算下一个散列地址,如果还找不到,就要不断的重复上述操作,最后全部地址都试过后就证明所查的Key不存在
最后还有装填因子的概念,a = 表中的数据个数 / 表长