8.1 查找的基本概念
查找和排序问题中,通常将数据元素称为记录,类型定义如下:
typedef struct{//查找和排序问题中记录类型定义
ElemType key;//关键字项
InfoType otherinfo;//其他数据项,InfoType依赖于具体应用
}RedType;
查找表:由同一类型的记录构成的集合。
对查找表常进行的操作有:
- 查询某个特定的记录是否在表中;
- 检索某个特定的记录的各种属性;
- 在查找表中插入一个记录;
- 在查找表中删除某个记录。
查找分类:
- 静态查找:不涉及插入和删除操作的查找叫静态查找,静态查找失败时只返回一个不成功标志,查找的结果不改变查找表。
- 动态查找:涉及插入和删除操作的查找叫动态查找,动态查找在查找失败时,需要将被查找的记录插入到查找表中,查找结果可能会改变查找表。
关键字:又称关键码,是记录某个数据项的值,用它可以标识一个记录。如果关键字可以唯一标识一个记录,则称此关键字为主关键字;反之,用于识别若干记录的关键字称为次关键字。
查找:根据给定的某个值,在查找表中确定一个其关键字等于给定值的记录。
查找结构:在某些应用中,查找操作是最主要的操作,为了提高查找效率,需要专门为查找操作设置数据结构。这种面向查找操作的数据结构叫查找结构。主要讨论:静态查找表,动态查找表和哈希表。
平均查找长度(ASL):常以关键字与给定值进行比较的平均次数作为衡量查找效算法效率优劣的标准。为了确定要查找的记录位置,与给定值进行比较的关键字个数的期望值称为查找算法成功时的平均查找长度。
pi是查找第i个记录的概率;若不特别声明,每个记录的概率相等。ci是查找第i个记录所需要的关键字的比较次数。
8.2 静态查找表
静态查找表的特点:表结构在查找之前已生成。
静态查找可以采用:顺序查找技术,折半查找技术,分块查找技术。
8.2.1 静态查找表的类型定义
静态查找表的顺序存储结构:
//静态查找表的顺序存储结构
typedef struct{
RedType *r;//基址,建表时按实际值分配,r[0]空
int length;//表长
}SSTable;
8.2.2 顺序表的查找
从顺序表的一端向另一端逐个关键字与给定值进行比较:如果相等则查找成功,返回记录在表中的位置;如果未找到与给定值相等的关键字,则查找失败,返回0。
哨兵:哨兵就是待查值,将它放在查找方向的尽头处,免去了在查找过程中每一次比较之后都要判断查找位置是否越界。
示例:
算法:
//顺序查找
int Search_Sq(SSTable ST,ElemType k){
ST.r[0].key=k;//置r[0]位置为哨兵
i=ST.length;
while(ST.r[i].key!=k)
--i;//从后往前查找
return i;
}
查找成功时平均查找长度:ASL=(n+1)/2(查找记录概率相等)
查找失败时关键字比较次数:n+1
优点:算法简单且适用面广;对表的解构没有任何要求。
缺点:平均查找长度较大。
8.2.3 有序表的查找
有序表可以采用折半查找技术,也称二分查找技术。
设有序表递增有序。取表中间记录作为比较对象,如果给定值与中间记录的关键字相等,则查找成功,返回该记录在表中所在位置;如果给定值小于中间记录的关键字,则在中间记录的左半区继续查找;如果给定值大于中间记录的关键字,则在中间记录的右半区继续查找。不断重复上述过程,直到查找成功或查找失败。
示例:
算法:
//折半查找
int Search_Bin(SSTable ST,ElemType k){
int low=1;
int high=ST.length;//让low和high分别指向表头和表尾
while(low<=high){
int mid=(low+high)/2;//让mid指向中间位置
if(k==ST.r[mid].key)
return mid;//如果k和mid关键字相等则返回mid
else if(k<ST.r[mid].key)
high=mid-1;//如果k小于mid关键字,则对左半部分进行折半查找
else
low=mid+1;//如果k大于mid关键字,则对右半部分进行查找
}
return 0;//查找失败返回0
}
该查找可以对表中每个记录的查找过程使用二叉树来描述,树中每个结点对应表中一个记录,节点中的值为该记录在表中的位置。这个二叉树称为折半查找判定树。
下图是11个元素折半查找的折半查找判定树:
折半查找判定树的性质:
- 任意两颗折半查找判定树,如果他们的节点数目相同,则他们的结构完全相同;
- 具有n个结点的折半查找判定树的深度为;
- 任意结点的左右子树中结点个数最多相差1;
- 任意结点的左右子树的深度最多相差1;
- 任意两个叶子所处层次最多相差1。
查找成功时,给定值和关键字进行比较的次数恰是从查找判定树的根节点到该结点的路径长度。
无论查找成功与否比较次数不超过。
平均查找长度:;
当n较大(n>50)时平均查找长度近似于;
优点:比顺序查找平均查找长度小且速度快;
缺点:只限于顺序有序表,不适合线性链表。
折半查找适用于:一经建立就很少改动又经常需要查找的线性表;
对于那些查找少又需要改动的线性表,可以采用线性链表进行查找。
*分块查找不在考纲