提前看目录
1、设置监视哨的顺序查找
普通的顺序查找就是利用循环遍历,例如n个数据查找,利用for(i=n;i>0;i--)循环,在进行if语句的判断,我们会发现每一次都会执行i>0的判断,而实际上只要存在这个元素,都是满足这个条件的,所以这就增加了时间的复杂度。因此就有了设置监视哨的顺序查找,简单来说就是将n[0]存放要查找的元素,这样就一定可以找得到(即查找成功返回下标,失败下标返回为0),就不需要去判断i>0,从而减少了时间复杂度。
【算法描述】
int Search_Seq(SSTable ST,KeyType key)
{//在顺序表ST中顺序查找其关键字等于key的数据元素。若找到,则函数值作为该元素在表中的位置,否则为0
ST.R[0].key=key;//哨兵
for(i=ST.length;ST.R[i].key!=key;-i);//从后往前找
return i;
}
【算法分析】
虽然只是程序设计技巧上的改进,即通过设置监视哨,免去查找过程中每一步都要检测整个表是否查找完毕。而然实践证明,整个改进能使顺序查找在ST.lenth>=1000时,查找平均时间几乎减少一半。
2、折半查找
这般查找也是很基础的(前提有序表),所以我们可以直接将算法给出复习一下。
【算法描述】
int Search_Bin(SSTable ST,KeyType key)
{//在有序表ST中折半查找其关键字等于key的数据元素。若找到,则函数值为该元素在表中的位置,否则为0
low = 1;high = ST,length;//置查找区间初值
while(low<=high)
{
mid=(low+high)/2;
if(key==ST.T[mid].key) return mid;//找到待查找元素
else if(key<ST.R[mid].key) high=mid-1;//在前一子表进行查找
else low = mid +1;//在后一子表进行查找
}
return 0;
}
当然啦,聪明的你一定也发现了这个其实也可以用递归来写,一起看看。
int Search_Bin(SSTable ST,KeyType key,int low,int high)
{
mid = (low+high)/2;
if(key==ST.T[mid].key) return mid;
else if(key<ST.R[mid].key)
Search_Bin(SSTable ST,KeyType,low,mid-1);
else Search_Bin(SSTable ST,KeyType,mid,high);
}
【算法分析】
折半查找也可用二叉树来描述。把当前查找区间的中间位置作为根,左子表和右子表分别作为根的左子树和右子树,由此得到的二叉树成为折半查找的判定树。这样的时间复杂度可以降到log2n+1,比之前的O(n)要小很多。
比如有数据:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
5 | 16 | 20 | 27 | 30 | 36 | 44 | 55 | 60 | 67 | 71 |
判定数就为:
这样时间复杂度也降低到了log层度。
3、分块查找
分块查找又称索引顺序查找,其实很好理解,就是将数据分为几部分,每部分之间是有序的,而内部是无序的(块间有序,块内无序)。这样我们思考到可以用二分查找索引表,而用顺序查找块内元素,时间复杂度也很小,而且由于块内的元素无序,这样我们进行元素的插入删除就很方便。
例如:
这样作为动态查找表是很适合的。
后记:打好基础,冲冲冲!