有序表查找 ---二分查找、插值查找

在前面的文章中介绍了对于顺序表的查找方法,从线性表中的第一个(或最后一个)数据元素开始,逐个进行数据元素关键字和给定值的比较,若某个数据元素的关键字和给定值相等则查找成功;如果直到最后一个(或第一个)数据元素,其关键字和给定值都不等时,则查找失败。

这里介绍另一种顺序表的查找方法。

有序表查找 ---二分查找、插值查找_第1张图片

代码编写:

采用递归方式:
需要注意的是下面代码中low和high为数组的下标号,从0到size()-1。

int binary_search(int a[], int low, int high, int key) // O(log2 n)
//采用递归方式,二分查找,a为查找的数组,low和high为两个端点序号,key为要查找的值 
{
    int ret = -1;

    if( low <= high )
    {
        int mid = (low + high) / 2;

        if( a[mid] == key )
        {
            ret = mid;
        }
        else if( key < a[mid] )
        {
            ret = binary_search(a, low, mid-1, key);
        }
        else if( key > a[mid] )
        {
            ret = binary_search(a, mid+1, high, key);
        }
    }
    return ret;
}

不采用递归方式,耗时少:

int binary_search_ex(int a[], int low, int high, int key) // O(log2n)
//二分查找,a为查找的数组,low和high为两个端点序号,key为要查找的值 
{
    int ret = -1;

    while( low <= high )
    {
        int mid = (low + high) / 2;        

        if( a[mid] == key )
        {
            ret = mid;
            break;
        }
        else if( key < a[mid] )
        {
            high = mid - 1;
        }
        else if( key > a[mid] )
        {
            low = mid + 1;
        }
    }   
    return ret;
}

在二分查找中,mid固定的为(high+low)/2,这在某些情况下会增加程序运行的时间,降低效率。因此提出了插值查找。

插值查找的mid的查找方法如下所示:
有序表查找 ---二分查找、插值查找_第2张图片

但是应当注意:
这里写图片描述
也就是: a[low] <= key <= a[high]

代码编写:

int interpolation_search(int a[], int low, int high, int key)
//插值查找,a为查找的数组,low和high为两个端点序号,key为要查找的值 
{
    int ret = -1;

    while( (low <= high) && (a[low] <= key) && (key <= a[high]) )
    {
        float fx = 1.0f * (key - a[low]) / (a[high] - a[low]);
        int mid = low + fx * (high - low);

        if( a[mid] == key )
        {
            ret = mid;
            break;
        }
        else if( key < a[mid] )
        {
            high = mid - 1;
        }
        else if( key > a[mid] )
        {
            low = mid + 1;
        }
    }   
    return ret;
}

小结

顺序查找比较土,但却是其他查找算法的基础。
二分查找基于有序的线性表,时间复杂度为O(log2 n)。
二分查找可以根据需要进一步演变为插值查找。

你可能感兴趣的:(数据结构)