静态查找的方法:顺序查找、对半查找、分块查找,C++代码实现

转自 : http://blog.csdn.net/hackerain/article/details/6093165


  1. #include<iostream>  
  2. using namespace std;  
  3. typedef struct  
  4. {  
  5.     int r[100];  
  6.     int length;  
  7. }SSTable;  
  8. //顺序查找  
  9. int Search_Seq(SSTable &ST,int k)  
  10. {  
  11.     int i;  
  12.     ST.r[0]=k;//将0号单元作为哨兵,从而避免了每次查找都要判断i是否越界的问题  
  13.     i=ST.length;  
  14.     while(ST.r[i]!=k)  
  15.         i--;  
  16.     return i;//即如果查找失败,则返回0  
  17. }  
  18. //折半查找  
  19. //***************************************************  
  20. //折半查找要求静态查找表中的记录必须按关键字有序,  
  21. //故对一组无序数,要先进行排序,才能进行折半查找  
  22. //***************************************************  
  23. int Search_Bin(SSTable &ST,int k)  
  24. {  
  25.     int low,high,mid;  
  26.     low=1;  
  27.     high=ST.length;  
  28.     while(low<=high)  
  29.     {//low从1开始,即0号位置不用  
  30.         mid=(low+high)/2;  
  31.         if(k==ST.r[mid])  
  32.             return mid;  
  33.         else if(k<ST.r[mid])  
  34.             high=mid-1;  
  35.         else  
  36.             low=mid+1;  
  37.     }  
  38.     if(low>high)  
  39.         return 0;  
  40. }  
  41. //分块查找——索引查找  
  42. typedef struct  
  43. {  
  44.     int key;  
  45.     int stadr;  
  46. }IndexItem;  
  47. typedef struct  
  48. {  
  49.     IndexItem elem[51];  
  50.     int length;  
  51. }IndexTable;//索引表  
  52. int Search_Index(SSTable &ST,IndexTable &ID,int k)  
  53. {  
  54.     int low,high,mid;  
  55.     int p;//p用来保存查找的关键字所属的索引中的位置  
  56.     int s,t;//s,t分别用来保存查找的关键字所在块的起始和终点位置  
  57.     low=0;  
  58.     high=ID.length-1;  
  59.     while(low<=high && p<0)  
  60.     {//该循环是用对半查找的方法,对索引表进行查找,从而定位要查找的元素所在的块  
  61.         mid=(low+high)/2;  
  62.         if(k>ID.elem[mid-1].key && k<ID.elem[mid].key)  
  63.             p=mid;//判断关键字对应哪个索引位置,就是k比前一个值大,比后一个值小,  
  64.                     //那个大的就是k对应的索引位置  
  65.         else  
  66.         {  
  67.             if(k<ID.elem[mid].key)  
  68.                 high=mid-1;  
  69.             else if(k>ID.elem[mid].key)  
  70.                 low=mid+1;  
  71.             else  
  72.                 p=mid;  
  73.         }  
  74.     }  
  75.     s=ID.elem[p].stadr;  
  76.     if(p==ID.length-1)  
  77.         t=ST.length;//这里对p的判断很重要,p若是索引中最后一个位置,则t应该为ST的表长  
  78.     else  
  79.         t=ID.elem[p+1].stadr-1;  
  80.     while(k!=ST.r[s]&&s<=t)//这里在块里进行顺序查找  
  81.         s++;  
  82.     if(s>t)  
  83.         return 0;  
  84.     else  
  85.         return s;  
  86. }  
  87. //建立需要查找的表,和对半查找用的索引表  
  88. void CreateTable(SSTable &ST,IndexTable &ID,int n,int m)  
  89. {  
  90.     int i;  
  91.     cin>>ST.length;  
  92.     for(i=1;i<=n;i++)  
  93.         cin>>ST.r[i];  
  94.     cin>>ID.length;  
  95.     for(i=0;i<m;i++)  
  96.         cin>>ID.elem[i].key>>ID.elem[i].stadr;  
  97. }  
  98. void main()  
  99. {  
  100.     freopen("in.txt","r",stdin);  
  101.     //freopen("in1.txt","r",stdin);  
  102.     int i,j,k;  
  103.     SSTable ST;  
  104.     IndexTable ID;  
  105.     CreateTable(ST,ID,34,7);  
  106.     i=Search_Index(ST,ID,80);  
  107.     cout<<ST.r[i]<<endl;//分块查找  
  108.     /*cin>>ST.length;  
  109.     for(i=1;i<=10;i++)  
  110.         cin>>ST.r[i];  
  111.     j=Search_Bin(ST,30);//对半查找  
  112.     cout<<ST.r[j]<<endl;*/  
  113.     k=Search_Seq(ST,120);//顺序查找  
  114.     cout<<ST.r[k]<<endl;  
  115. }  
 

静态查找本身不是很难,要说难的话,难点就在于分块查找。分块查找是先构建一个索引,该索引是有序的,如果在索引里用对半查找的话,肯定要能节省一些时间,而在每个块中的元素是无序的,所以只能用顺序查找,但是我在用对半查找方法写索引时,遇到点问题,对索引表的对半查找,不像单纯的对半查找一样,需要考虑比较多的情况,一开始我看书上的没看懂,又去网上搜一下,可是搜到的全都是用顺序查找方法查找的索引,我想既然索引表是有序的,如果不利用它这个特性,岂不是浪费?所以我就硬着头皮,去考虑对半查找的方法查找索引表的情况,程序中是我自己想出来的一个方法。书上的方法,虽然简单可行,但是让人理解起来可是非常不容易的。我觉得写程序追求的就是简单并且具有很好的可理解性,如果程序能符合我们大脑的正常思维过程,那是最好的了,易理解但执行起来又很快,但是个别除外(像一些特殊的算法)。不管怎么样,今天又写程序了,又克服了一个小难题,挺开心的!等你写程序,真正的深入到它以后,发现就会越来越喜欢它了,写程序也是一件蛮有意思的一件事情。


平均查找长度:


设关键字个数为n,在各关键字等概率查找的前提下,
1、顺序查找的平均查找长度ASL=(n+1)/2,
2、在n趋于无穷大时,折半查找的ASL=((n+1)log2(n+1))/n - 1,当n大于50时,ASL约等于log2(n+1)-1
3、设分块查找中将长为 n 的表分成均等的 b 个块,每块 s 个元素,则 b = (n / s)上取整,如果索引表中采用顺序查找,则ASL=(b+1)/2+(s+1)/2;如果索引表中采用折半查找,则ASL=(s+1)/2+log2(b+1)-1

追问:
144个记录的文件,分块查找法,折半查找确定块,每块长度8,则平均查找长度是多少 帮做一下,我算的结果和答案不一样
追答:
差别不会很大吧,因为那个ASL=(s+1)/2+log2(b+1)-1中的折半查找用的是理论值 144条记录,每块8条,则索引项为144/8=18项,块内查找是(8+1)/2= 4.5,索引中用折半查找18项的ASL准确值是(1*1+2*2+4*3+8*4+3*5)/18 = 64/18约等于3.5 所以ASL约为3.5+4.5 = 8
追问:
答案不是那个啊 答案是14难道是答案错了
追答:
答案是14,那就是这个索引表中采用顺序查找而不是折半查找,则ASL=(b+1)/2+(s+1)/2=(8+1)/2+(18+1)/2=14 如果确实题目是如此:分块查找法,折半查找确定块,那就是答案弄错了


  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值