本节将介绍内部查找即:顺序查找、折半查找、分块查找和二叉排序树查找
- 顺序查找
顺序查找(Sequential Search)的查找过程为:从表的一端开始,依次将记录的关键字和给定值进行比较,若某个记录的关键字和给定值相等,则查找成功;反之,若扫描整个表后,仍未找到关键字和给定值相等的记录,则查找失败。
顺序查找方法既适用于线性表的顺序存储结构,又适用千线性表的链式存储结构。
int Search_Seq(SSTable ST, KeyType key)
{//在顺序表 ST中顺序查找其关键字等千key的数据元素。若找到,则函数值为该元素在表中的位置,否则为0
for(i=ST.length;i>=l;--i)
if(ST.R[i] .key==key)
return i; //从后往前找
return 0;
}
以上算法在查找过程中每步都要检测整个表是否查找完毕,即每步都要有循环变量是否满足 条件i >=1的检测。改进这个程序, 可以免去这个检测过程。改进方法是查找之前先对ST.R[0]的关键字赋值key, 在此,ST.R[0]起到了监视哨的作用。
int Search_Seq(SSTable ST,KeyType key)
{//在顺序表 ST 中顺序查找其关键字等于 key 的数据元素。若找到,则函数值为该元素在表中的位置,否则为0
ST.R[O].key=key; // "哨兵”
for(i=ST.length;ST.R[i] .key!=key;--i); //从后往前找
return i;
}
- 折半查找
折半查找(Binary Searhc )也称二分查找,它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构, 而且表中元素按关键字有序排列。在下面及后续的讨论中, 均假设有序表是递增有序的。
折半查找的查找过程为:从表的中间记录开始,如果给定值和中间记录的关键字相等,则查找成功;如果给定值大于或者小千中间记录的关键字, 则在表中大于或小千中间记录的那一半中查找,这样重复操作, 直到查找成功,或者在某一步中查找区间为空, 则代表查找失败。
折半查找每一次查找比较都使查找范围缩小一 半,与顺序查找相 比,很显然会提高查找效率。 为了标记查找过程中每一 次的查找区间,下面分别用low和high来表示当前查找区间的下界和上界,mid为区间的中间位置。
【算法步骤】
①置查找区间初值,,low为 1,high为表长。
②当low小于等于hihg 时, 循环执行以下操作:
• mid取值为low和high的中间值;
• 将给定值key与中间位置记录的关键字进行比较,若相等则查找成功,返回中间位置mid;
• 若不相等则利用中间位置记录将表对分成前、后两个子表 。如果key比中间位置记录的关键字小,则 high取为mid-1 , 否则 low取为mdi +1。
③循环结束,说明查找区间为空,则查找失败,返回0。
int Search_Bin(SSTable ST,KeyType key)
{//在有序表ST 中折半查找其关键字等于key的数据元素。若找到, 则函数值为该元素在表中的位置, 否则为0
low= l;high=ST.length;
while(low<=high){
if(key==ST.R[mid].key) return mid;//找到待查元素
else if(key<ST.R[mid].key) high=mid-1;//继续在前一子表进行查找
else low=mid+l; //继续在后一子表进行查找
}
return 0;
}
- 分块查找
分块查找 (Blocking Search) 又称索引顺序查找,这是一种性能介于顺序查找和折半查找之 间的一种查找方法。在此查找法中,除表本身以外,尚需建立一个 “索引表”。例如,下图 所示 为一个表及其索引表,表中含有18个记录, 可分成3个子表(R1 , R2, …, R6)、(R7, R8, …, R12)、(R13, R14, …,R18), 对每个子表(或称块)建立一个索引项,其中包括两项内容:关键字项(其值为该子表内的最大关键字) 和指针项(指示该子表的第一个记录在表中位置)。索引表按关键字有序,则表或者有序或者分块有序。所谓 “ 分块有序” 指的是第二个子表中所有记录的关键字均大于第一个子表中的最大关键字,第三个子表中的所有关键字均大千第二个子表中的最 大关键字, …,依次类推。
因此 ,分块查找过程需 分两步进行。先确定待查记录所在的 块(子表),然后在块中顺序查找。假设给定值key=38, 则先将key依次和索引表中各最大关键字进行比较,因为22<key<48, 则 关键字为 38 的记录若存在,必定在第二个子表中,由千同一索引项 中的指针指示第二个子表中的第一个记录是表中第 7 个记录,则自第 7 个记录起进行顺序查找,直到 ST.elem[10].key = key 为止。假如此子表中没有关键字等千 key 的记录(例如: key = 29 时自第 7 个记录起至第 12 个记录的关键字和 key 比较都不等),则查找不成功。 由于由索引项组成的索引表按关键字有序,则确定块的查找可以用顺序查找,亦可用折半查找,而块中记录是任意排列的 ,则在块中只能是顺序查找。
由此,分块查找的算法为顺序查找和折半查找两种算法的简单合成。 - 树表的查找
二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
(1) 若它的左子树不空,则左子树上所有结点的值均小千它的根结点的值;(2) 若它的右子树不空,则右子树上所有结点的值均大千它的根结点的值; (3) 它的左、 右子树也分别为二叉排序树。
中序遍历一棵二叉 树时可以得到一个结点值递增的有序序列。
二叉排序树的递归查找
【算法步骤]
①若二叉排序树为空, 则查找失败,返回空指针。
②若二叉排序树非空, 将给定值key与根结点的关键字T->data.key进行比较:
• 若key等于T->data.key, 则查找成功,返回根结点地址;
• 若key小于T->data.key, 则递归查找左子树;
• 若key大于T->data.key, 则递归查找右子树。
BSTree SearchBST(BSTree- T, KeyType key)
{//在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素
//若查找成功 , 则返回指向该数据元素结点的指针, 否则返回空指针
if ((!T)I I key==T->data. key) return T;//查找结束
else if (key<T->data. key) returnSearchBST(T->lchild, key);//在左子树中继续查找
else returnSearchBST(T->rchild, key);//在右子树中继续查找
}