09-查找-01-静态查找

静态查找表

(一)顺序表的查找


Ø 静态查找表的存储结构可用顺序表或线性链表表示。
Ø 本节只讨论在顺序存储结构中查找的实现。
顺序查找的基本思想:
从表中最后一个记录开始,逐个进行记录的关键字和给定值的比较,若某个记录的关键字和给定值比较相等,

则查找成功,找到所查记录;反之,若直至第一个记录,其关键字和给定值比较都不等,则表明表中没有所查记录,查找不成功。



#define  M  500
typedef  struct
{  int  key ;
    float  info ;
}JD ;

int seqsrch ( JD r[ ], int n, int k )
{  int i=n ;
    r[0].key=k ;
   while ( r[i].key!= k )   
        i-- ;
   return ( i ) ;
}


监测哨的作用:


(1)省去判定循环中下标越界的条件,从而节约比较时间。


(2)保存查找值的副本,查找时若遇到它,则表示查找不
成功。这样在从后向

前查找失败时,不必判断查找表是否检测完,从而达到算法统一。


顺序查找性能分析:

  对一个含有 n 个数据元素的表,查找成功时有:




  上述算法中,对于有 n 个数据元素的表,给定值 k与表中第 i 个元素的关键字相等

,即定位第 i 个记录时,需进行:ni+1次关键字比较,即 Ci=ni+1。则查找成功时

,顺序查找的平均查找长度为:




算法中的基本工作就是关键字的比较,因此,

查找长度的量级就是查找算法的时间复杂度为 O(n) 。

顺序查找缺点是当 n 很大时,平均查找长度较大,效率低;优点是对


表中数据元素的存储没有特殊要求。


(二)有序表的查找(二分法查找)


以有序表表示静态查找表时,可用二分法查找法来实现查找。

二分查找,是一种效率较高的查找方法,但前提是表中元素必须按关键字有序(按关键字递增或递减)排列。


算法思想

二分法查找的基本思想:
在有序表中,取中间元素作为比较对象,若给定值与中间元素的关键字相等,则查找成功;若给定值小于中间元素的关键字,则在中间元素的左半区继续查找;若给定值大于中间元素的关键字,则在中间元素的右半区继续查找。不断重复上述查找过程,直到查找成功,或所查找的区域无数据元素,查找失败。

算法实现:

设表长为n,low,high 和 mid分别指向待查元素所在区间的上界、下界和中点, k为给定值。

初始时,令low=1 , high=n , mid=(low+high)/2

让 k 与 mid 指向的记录比较:

若 k == r[mid].key,则查找成功
若 k < r[mid].key, 则 high=mid-1
若 k > r[mid].key, 则 low=mid+1

重复上述操作,直至low>high时,查找失败




代码实现

#define  M  500
typedef  struct
{  int  key ;
   float  info ;
}JD ;
int binsrch (  JD r[ ], int n, int k  )
{  int  low, high, mid, found ;
   low=1;  high=n;  
   found=0;               // found 为找到标志。值为 0 表示未找到。
   while ( (low<=high) && (found==0) )
   {   mid=( low+high ) / 2;
        if ( k>r[mid].key )  low=mid+1;
        else if ( k==r[mid].key )  found=1;
        else   high=mid-1;
   }
   if ( found==1 )        // 如果已找到
        return ( mid ) ;  // 找到的记录的下标肯定为 mid
   else
        return ( 0 );
}

性能分析

从二分法查找的过程看,每次查找都是以表的中点为比较对象,并以中
点将表分割为两个子表,对定位到的子表继续作同样的操作。所以,对表
中每个数据元素的查找过程,可用二叉树来描述,称这个描述查找过程的
二叉树称为判定树。
判定树中每一结点对应表中一个记录,但结点值不是某个记录的关键
字,而是某个记录在表中的位置序号。根结点对应当前区间的中间记录,
左子树对应前一子表,右子树对应后一子表。




从上面判定树可看到,查找第一层的根结点 56,一次比较即可找
到; 查找第二层的结点 19 和 80, 二次比较即可找到; 查找第三层的
结点 5、21、64、88,三次比较即可找到;查找第四层的结点 13,37、
75、92,四次比较即可找到。

查找表中任一元素的过程,即是判定树中从根到该元素结点路径上各结点关键字的比较次数,也即该元素结点在树中的层次数。
n 个结点的判定树,树高为 k,则有 2k-1-1<n≤2k-1,即 k-1<log2(n+1)≤k,
所以 k= log2(n+1) 。因此,二分查找在查找成功时,进行的关键字比较次数至
多为 log2(n+1) 。
以树高为 k 的满二叉树( n=2k-1 )为例。
假设表中每个元素的查找是等概率的,即 Pi= ,
则树的第 i 层有 2i-1 个结点。
二分查找的平均查找长度为:


时间复杂度分析




所以,二分查找的时间复杂度为:O (log2n)。
二分查找的优点:效率高。
二分查找的缺点:
必须按关键字排序,有时排序也很费时;
只适用顺序存储结构,所以进行插入、删除操作必须移动大量的结点。
二分查找适用于一经建立就很少改动,而又经常需要查找的线性表。
对于经常需要改动的线性表,可采用链表存储结构,进行顺序查找。

3.索引顺序表的查找

Ø若以索引顺序表表示静态查找表,可用 分块查找法实现查找。
Ø分块查找又称索引顺序查找,是顺序查找的一种改进方法。

查找过程:

将表分成几块,块内无序,块间有序;先确定待查记录所在块,
再在块内查找。

算法实现:


用数组存放待查记录,每个数据元素至少含有关键字域。

建立索引表,每个索引表结点含有最大关键字域和指向本块第一个结点的指针。


typedef  struct
{  int key ;
    int link ;
} SD;

typedef  struct
{  int  key;
   float info;
}JD;

int blocksrch (  JD r[ ], SD d[ ],  int b,  int k,  int n )
{  int i=1, j ;

   while( (  k > d[i].key ) &&( i<=b ) )  // 确定要比较的值 k 在哪一块
        i++;            //  k <= d[i].key  时的 i 就确定了 k 所在块的索引结点下标序号

   if ( i>b ) 
      { printf("\n Not found"); return( 0 ); }

   j = d[i].link;  // 要比较的值 k 在以d[i].link 为起点下标的块中

   while ( (j<n) && (k!=r[j].key) && (r[j].key<=d[i].key))
        j++;         // 在所在块中进行顺序查找

   if ( k != r[j].key )
      { j=0;  printf ("\n Not found"); }

   return ( j ) ;
}


分块查找方法评价:


查找方法比较

 顺序查找二分法查找索引查找
ASL最大最小两者之间
表结构有序表、无序表有序表分块有序表
分块有序表顺序存储结构
线性链表

顺序存储结构
线性链表

顺序存储结构
线性链表


















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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值