几种查找算法总结与比较—顺序查找、有序查找、散列表查找

静态查找表只进行查找操作的查找表

动态查找表:在查找过程中同时插入查找表中不存在的元素,或者删除已存在的元素

本文主要总结静态查找表

1.顺序表查找:从第一个或者最后一个记录开始,将每个记录的关键字与给定值比较,若相等则查找成功。

C++实现:

for(int i=0;i<n;i++)

{

    if(a[i]==key)

        return i;

}

return 0;

时间复杂度:

最好情况:O(1),第一次就找到

最坏情况:O(n),需要逐个比较完

平均:O(n)

2.有序表查找:元素是有序排列的,且是顺序存储的(存在数组或者vector)。主要包括二分查找,插值查找,斐波拉契查找

2.1二分查找(折半查找)

基本思想:

(1)与中间元素比较,其中mid=low+1/2*(low+high)

(2)等于中间元素,则查找成功

(3)大于中间元素,在它的右半区查找,重复(1);小于中间元素,在它的左半区查找,重复(1),直到找到给定值。

C++实现:

//n是有序表长度

int low=0,high=n-1;

while(low<high)

{

    int mid=(low+high)/2;

    if(key<a[mid])

        high=mid-1;

    else if(key>a[mid])

        low=mid+1;

    else

        return mid;     

}

return 0;

时间复杂度:

最好:O(1)

最坏:O(logn+1)

平均:O(logn)

2.2插值查找(折半查找升级版)

二分查找中:

mid=low+1/2*(low+high)

插值查找:

mid = low + (key – a[low]) / (a[high] – a[low]) * (high – low),也就是将上述的比例参数1/2改进了,根据关键字在整个有序表中所处的位置,让mid值的变化更靠近关键字key,这样也就间接地减少了比较次数

因为如果在一个有序表中找相对较小的元素(即离low更近一点),就mid向low靠近一点;找相对较大的元素(即离high更近一点),就mid向high靠近一点;这样效率比较高。但要求表中元素分布比较均匀。

时间复杂度:O(logn)

2.3斐波那契查找

斐波拉契数列:0,1,1,2,3,5,8,13,21,34,F(k)

基本思想:

(1)将有序数组的数值补全,使它的长度等于某个斐波拉契数F(k)-1

(2)取low=0,mid=low+F(k-1)-1,high=F(k)-2

(3)当给定值小于a[mid]值,在mid前半段查找,且前半段长度为F(k-1)-1;当给定值大于a[mid]值,在mid后半段查找,且后半段长度为F(k-2)-1;重复(2)

时间复杂度:O(logn)

因为斐波拉契查找求mid=low+F(k-1)-1,只有加减法,没有乘法,这种细微差别相比较前两种方法要好一些。

C++实现:

int low=0,high=n-1,mid,k=0;

while(n>F(k)) 

    k++;

for(i=n;i<F(k)-2;i++)

    a[i]=a[n-1];

while(low<high)

{

    mid=low+F(k-1)-1;

    if(key<a[mid])

    {

        high=mid-1;

        k=k-1;

    }

    else if(key>a[mid])

    {

        high=mid+1;

        k=k-2;

    }

    else

    {

        if(mid<=n) return mid;

        else return n;  //是后面补的

}

return 0;

3.散列表查找(哈希表,hash table)

散列表:关键字key和存储位置之间有一个确定关系f,称为散列函数(哈希函数),要找到关键字key,只需计算f(key)就可以直接得到存储位置。连续存储。查找复杂度O(1)。

但有时候两个不同的关键字k1和k2,f(k1)=f(k2),会产生冲突。这就尴尬了……所以尽量构造散列函数让冲突尽可能少。

    

    原文作者:查找算法
    原文地址: https://blog.csdn.net/code_caq/article/details/68922160
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞