数据结构复习七:查找算法之线性表的查找

一、查找的基本概念

1)查找表

查找表是由同一类型的数据元素或记录构成的集合。

2)关键字

关键字是数据元素或记录中某个数据项的值,用它可以标识一个数据元素或记录;
若一个关键字可以唯一地标识一个记录,则称之为主关键字;反之,称用以识别若干记录的关键字为次关键字
当数据元素只有一个数据项时,其关键字为该数据元素的值。

3)查找

查找是指根据给定的某个值,在查找表中确定一个其关键字等于给定值的记录或数据元素。若表中存在这样一个记录,则称查找成功,否则称查找不成功

4)动态查找表和静态查找表

若在查找的同时对表做修改操作(如插入和删除),则相应的表称之为动态查找表,否则称之为静态查找表

5)平均查找长度(ASL)

为确定记录在查找表中的位置,需和给定值进行比较的关键字个数的期望值,称为查找算法在查找成功时的平均查找长度

ASL=\sum_{i=1}^{n}P_{i}C_{i}
Pi为查找表中第i个记录的概率,且\sum_{i=1}^{n}P_{i}=1
Ci为找到表中其关键字与给定值相等的第i个记录时,和给定值已进行过比较的关键字个数。

二、线性表的查找

1)顺序查找(Sequential Search)

        查找过程:按顺序从表的一端向另一端查找,依次将表中记录的关键字和给定值进行比较,若某个表中值和给定值相等,则查找成功;反之,若整个表扫描完毕也未找到和给定值相等的记录,则查找失败。
        顺序查找适用于线性表的顺序存储结构和链式存储结构。

顺序表的数据结构:

typedef struct{
    Elemtype *R;    //存储空间基地址
    int length;     //当前长度
}

1.一般的顺序查找算法

int Search_seq(SStable ST,KeyType key){
    for(i=ST.length;i>=1;--i){      //从后往前找
        if(ST.R[i].key==key) return i;
    }
    return 0;   //未找到则返回0
}

2.设置监视哨的顺序查找算法

把查找的最后一位设为给定值,免去了每次判断是否越界的问题

int Search_seq(SStable ST,KeyType key){
    ST.R[0].key=key;    //“哨兵”
    for(i=ST.length;ST.R[i].key!=key;--i){  //从后往前找
        if(ST.R[i].key!=key) return i;
    }
    return 0;
}

算法分析:

时间复杂度:O(n);
优点:简单,对表结构无任何要求;
缺点:平均查找长度较大,查找效率低。

2)折半查找(Binary Search)

也称二分查找,要求线性表必须采用顺序存储结构,且表中元素按关键字有序排列。

查找过程:从表的中间记录开始,如果给定值和中间记录的关键字相等,则查找成功;如果给定值大于或者小于中间记录的关键字,则在表中大于或小与中间记录的那一半中查找,这样重复操作,直到查找成功,或者在某一步中查找区间为空,则代表查找失败。

折半查找算法

//以low和high来表示当前查找区间的下界和上界,mid为区间的中间位置
int Search_Bin(SStable ST,KeyType key){
    low=1;
    high=ST.length;
    while(low<=high){
        mid=(low+high)/2;
        if(key==ST.R[mid].key) return mid;  //找到待查元素
        else if(key<ST.R[mid].key) high=mid-1;  //继续在迁移子表进行查找    
        else low=mid+1;     //继续在后一子表中进行查找
    }
    return 0;       //查找失败
}

算法分析:

折半查找过程可用二叉树来描述。树中每一结点对应表中一个记录,但结点值不是记录的关键字,而是记录在表中的位置序号。把当前查找区间的中间位置作为根,左子表和右子表分表作为根的左子树和右子树,由此得到的二叉树称为折半查找的判定树
        成功的折半查找恰好是走了一条从判定树的根到被查结点的路径,精力比较的关键字个数恰为该结点在树中的层次,由此可计算折半查找的平均查找长度:以长度为11的有序表为例,ASL=1/11(1+2*2+3*4+4*4)=3
一般情况下,n较大时,有ASL=log_{2}(n+1)-1 (可以以满二叉判定树为例计算出)
因此,折半查找的时间复杂度:O(log2(n));
优点:比较次数少,查找效率高;
缺点:对表结构要求高,只能用于顺序存储的有序表。查找前需要排序,而排序本身也费时。同时,折半查找也不适用于数据元素经常变动的线性表,因为为保持顺序表的有序性,插入和删除操作平均要比较和移动表中一半元素。

3)分块查找(Blocking Search)

又称索引顺序查找,性能介于顺序查找和折半查找之间。分块查找是将表中记录分成几个子表(或称块),对每个子表建立一个索引项,包括该子表的最大记录以及第一个记录在表中的位置,各个子表的索引项组成一个索引表,索引表中“分块有序”,如第二个子表的最小值大于第一个子表的最大值,以此类推。查找时先确定待查记录所在的块(子表),然后在块中顺序查找。

算法分析:

确定块的查找可以用顺序查找或折半查找,在块中只能用顺序查找,分块查找中ASL_{bs}=L_{b}+L_{s}
优点:由于块内无序,插入删除比较容易;
缺点:要增加一个索引表的存储空间,并对初始索引表进行排序运算。


注:本文所有内容均来源于《数据结构(C语言第二版)》(严蔚敏老师著)


 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值