顺序查找:普通的顺序查找方法、带监视哨的顺序查找方法
折半查找:折半查找的判定树
#include
using namespace std;
const int MaxSize = 100;
class LineSearch{
public:
LineSearch(int a[], int n);
~LineSearch() {}
int SeqSearch(int k);
int BinSearch1(int k);
int BinSearch2(int low, int high, int k);
private:
int data[MaxSize];
int length;
};
LineSearch :: LineSearch(int a[ ], int n){
for (int i = 0; i < n; i++)
data[i+1] = a[i];
length = n;
}
顺序查找 (线性查找)
基本思想: 从线性表的一端向另一端逐个将关键码与给定值进行比较, 若相等,则查找成功,给出该记录在表中的位置; 若整个表检测完仍未找到与给定值相等的关键码,则查找失败,给出失败信息。
int LineSearch :: SeqSearch(int k)
{
i=n;
while (i>0 && data[i]!=k)
i--;
return i;
}
改进的顺序查找
基本思想:设置“哨兵”。 哨兵就是待查值, 将哨兵放在查找方向的尽头处, 免去了在查找过程中每一次比较后都要判断查找位置是否越界,从而提高查找速度。
int LineSearch :: SeqSearch(int k)
{
int i = length;
data[0] = k;
while (data[i] != k)
i--;
return i;
}
顺序查找查找性能的改进方法
记录每个数据的访问频率, 把访问频率高的数据移向顺序表的右端,可以减少查找成功时所进行的比较次数,提高效率
构造有序的顺序表,减少查找失败时所进行的比较次数,提高查找效率
单链表的顺序查找
int LinkSearch::SeqSearch2(Node *first, int k){
Node *p;
int count=0;
p=first->next;
int j=1;
while (p && p->data != k)
{
p=p->next;
j++;
count++;
}
if (!p){
cout<<"查找失败,比较的次数为:"<<count<<endl;
return 0;
}
else{
cout<<"\n"<<"查找成功,比较的次数为:"<<count<<endl;
return j;
}
}
顺序查找的优点:
算法简单而且使用面广。
对表中记录的存储结构没有任何要求,顺序存储和链接存储均可;
对表中记录的有序性也没有要求,无论记录是否按关键码有序均可。
顺序查找的缺点:
平均查找长度较大,特别是当待查找集合中元素较多时,查找效率较低。
折半查找
适用条件:线性表中的记录必须按关键码有序; 必须采用顺序存储。
基本思想:
在有序表中(low, high,low<=high), 取中间记录作为比较对象, 若给定值与中间记录的关键码相等,则查找成功; 若给定值小于中间记录的关键码,则在中间记录的左半区继续查找; 若给定值大于中间记录的关键码,则在中间记录的右半区继续查找。 不断重复上述过程,直到查找成功,或所查找的区域无记录,查找失败。
int LineSearch :: BinSearch1(int k){
int mid, low = 1, high = length;
while (low <= high) {
mid = (low + high) / 2;
if (k < data[mid])
high = mid - 1;
else if (k > data[mid])
low = mid + 1;
else
return mid;
}
return 0;
}
int LineSearch :: BinSearch2(int low, int high, int k){
if (low > high)
return 0;
else {
int mid = (low + high) / 2;
if (k < data[mid])
return BinSearch2(low, mid-1, k);
else if (k > data[mid])
return BinSearch2(mid+1, high, k);
else
return mid;
}
}
折半查找判定树
判定树:折半查找的过程可以用二叉树来描述, 树中的每个结点对应有序表中的一个记录, 结点的值为该记录在表中的位置。 通常称这个描述折半查找过程的二叉树为折半查找判定树,简称判定树。
判定树的构造方法
⑴ 当n=0时,折半查找判定树为空;
⑵ 当n>0时,折半查找判定树的根结点为mid=(n+1)/2,根结点的左子树是与有序表r[1] ~ r[mid-1]相对应的折半查找判定树,根结点的右子树是与r[mid+1] ~ r[n]相对应的折半查找判定树。
判定树的特点
任意两棵折半查找判定树,若它们的结点个数相同,则它们的结构完全相同
具有n个结点的折半查找树的高度为(log2n向下取整+1)。
判定树的性质
任意结点的左右子树中结点个数最多相差1
任意结点的左右子树的高度最多相差1
任意两个叶子所处的层次最多相差1
折半查找性能分析
查找成功:在表中查找任一记录的过程,即是折半查找判定树中从根结点到该记录结点的路径,和给定值的比较次数等于该记录结点在树中的层数。
查找不成功:查找失败的过程就是走了一条从根结点到外部结点的路径, 和给定值进行的关键码的比较次数等于该路径上内部结点的个数(失败情况下的平均查找长度等于树的高度)。