静态查找

顺序表的查找  
记录的逻辑顺序与其在计算机存贮器中存储顺序一致的表,称为 顺序表
顺序查找的基本思想:
    从表的一端开始,顺序扫描线性表,依次将扫描到的结点关键宇和给定值K相比较。若当前扫描到的结点关键字与K相等,则查找成功;若扫描结束后,仍未找到关键字等于K的结点,则查找失败。a
(1)类型说明
int maxsize = 100 ;        //数据表的最大长度
typedef int KeyType       //关键字的类型
struct datalist
 { KeyType key ;
  char ch ;
  //…      //其他域 
 };
datalist[maxsize] ;
(2)具体算法
void sequence_search(KeyType K,datalist r[],int n)
 { int i=0;
  r[n].key=K;
  while(r[i].key!=K)i++;
  if(i<n)cout<<"查找成功,该记录对应的下标为:"<<i<<endl;
  else cout<<"查找失败!"<<endl;
 }
算法分析:
(1) 在最坏的情况下,顺序查找需要比较 n 次,即 MSL = n 。
(2) 假定各记录的查找机会均等,即 P i = 1/n ,由于查找第 i 个记录需要比较 i 次,即 C i = i ,于是有:
        
  这样,最大查找长度和平均查找长度的数量级 ( 即算法的时间复杂度 ) 均为 O(n) 。
顺序查找的优点和缺点
  优点:算法简单,且对表的结构无任何要求,无论是用向量还是用链表来存放结点,也无论结点之间是否按关键字有序,它都同样适用。

  缺点:查找效率低,因此,当n较大时不宜采用顺序查找。

有序表的查找 
  对于以数组方式存贮的记录,如果数组中各个记录的次序是按其关键字值的大小顺序排列的,则称为有序数组有序表。
折半查找
  对顺序分配的有序表可以采用折半查找 (Binary Search) ,又称二分查找。
1.基本思想
  从第 1 个记录开始逐个顺序搜索,而是每次把要找的给定值 K ,与在中间位置的记录的关键字值进行比较。设有序记录数组 r 中每个记录的关键字值按升序排列为:
      r 0. key , r 1.key , r 2.key ,…, r m.key ,…,r n-1.key 
  其中, n 为记录个数。当 i < j 时,有 r i.key ≤ r j.key 。开始时,中间位置记录的序号为 m = [(n + 1)/2] ,相应的关键字值为 r m.key 。将给定值 K 与 r m.key 比较,有三种可能的结果:
(1) K = r m.key
  查找成功,结束查找。 
(2) K < r m.key
  由于各记录的关键字值是由小到大排列的,因此,如果要查找的记录存在,必定在有序表的左半部分。于是,对左半部分继续使用折半查找进行搜索,但搜索区间缩小了一半。
(3) K > r m.key。
  如果要查找的记录存在,则必定在有序表的右半部分于是,对右半部分继续使用折半查找进行搜索,但搜索区间缩小了一半。
  这样在查找过程中,搜索区间不断对分并成指数地缩小,因而查找速度明显地快于顺序查找。当最后只剩下一个记录,而且此记录不是要找的记录,则宣告查找失败。
2.折半查找的算法
void binary_search(KeyType K,datalist r[],int n,)
 { int m,low ,high,find;
  low=0;high=n-1;find=0;
  do{ m=(low+high)/2;
      if(K==r[m].key)
       { cout<<"查找成功,该记录对应的下标为:"<<m<<endl;
         find=1;
       }
      else if(K<r[m].key)high=m-1;
         else low=m+1;
    }while((find==0)&&(low<=high));
  if(find==0)cout<<"查找失败!\n";
 }


3.折半查找性能分析
  算法中每次将给定值 K 与中间位置记录的关键字值进行比较,最理想的情况是一次比较成功,那么,在最坏的情况下,要做多少次比较呢?不妨看看具体统计:
         
这个公式可以由归纳得到:
                  
  若 n = 2 k ,则有 k = log2 n 。进一步,当 2 k ≤ n < 2 k +1 时,恒有 k = [log2 n ] ,因而 MSL 等于 [log2 n ] + 1 。这样,折半查找所需时间的数量级最多为 O(log2 n ) 。与顺序查找所需平均时间 O (n) 相比,当 n 很大时,折半查找所需时间的数量级要小。因此,对于关键字已经有序的查找表,采用折半查找效率比较高。
4.折半查找的平均查找长度
  折半查找的过程实际上是从二叉树的根结点开始到该记录结点的查找过程。因此,比较的次数不超过二叉树的深度 d = [log2 n ] + 1 。特别地,当 n = 2 d -1 时,描述折半查找的二叉树一定是深度为 d 的满二叉树。查找第 1 层 ( 根结点 ) 的记录仅需一次比较,且只有一个记录。查找第 i 层 (1 ≤ i < d) 记录需做 i 次比较,第 i 层有 2 i-1 个记录。假定每个记录的查找概率相等,即 P i = 1/n ,则平均查找长度为:

式中, L 为叶结点个数, 1 ≤ L ≤ 2d-1 , n = 2d-1-1+L。
  所以,折半查找的平均查找长度数量级 ( 算法时间复杂度 ) 亦为 O (log2 n ) 。
5、二分查找的优点和缺点
  虽然二分查找的效率高,但是要将表按关键字排序。而排序本身是一种很费时的运算。既使采用高效率的排序方法也要花费O(nlgn)的时间。
  二分查找只适用顺序存储结构。为保持表的有序性,在顺序结构里插入和删除都必须移动大量的结点。因此,二分查找特别适用于那种一经建立就很少改动、而又经常需要查找的线性表。
  对那些查找少而又经常需要改动的线性表,可采用链表作存储结构,进行顺序查找。链表上无法实现二分查找。 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值