部分查找算法总结(重点:指数搜索)

前提是列表有序。

二分查找

是一种分治算法,每次将数组分为大小相等的部分。很熟悉就不用介绍了。时间复杂度为O(lg⁡n)O(\lg n)O(lgn)
示例伪代码:

binary_search(A, n, T)
{
    L = 0
    R = n − 1
    while (L <= R){
        m = floor((L + R) / 2)
        if (A[m] < T){
            L = m + 1
        }else if (A[m] > T){
            R = m - 1
        }else{
            return m
        }
    }
    return unsuccessful
}

斐波那契查找

类似二分查找,同样是分治算法。但不是等份划分数组,而是使用斐波那契数来缩小搜索范围。平均和最坏的时间复杂度为O(lg⁡n)O(\lg n)O(lgn)
平均而言,同二分查找相比,执行比较的操作增加了4%(参考维基百科)。
优点是只需要用到加减法来计算数组索引,而二分搜索需要用到移位或者除法计算数组索引。

指数搜索

指数搜索时间复杂度为O(lg⁡i)O(\lg i)O(lgi)iii为搜索元素在数组中的索引位置。

原始算法包含两个阶段:

  1. 确定搜索元素keykeykey位于数组中的范围,假定数组是按升序排序,首先查找第一个满足条件的指数jjjjjj每次自加 1,要满足的条件为key≤a[2j]key\le a[2^j]keya[2j] 。由于是第一个满足条件的jjj,所以有a[2j−1]&lt;key≤a[2j]a[2^{j-1}]&lt;key\le a[2^j]a[2j1]<keya[2j]成立。
  2. 2j−12^{j-1}2j1为下界,2j2^j2j为上界,在范围内执行二分查找。

示例伪代码:

exponential_search(arr, size, key)
{
    if (size == 0) {
        return NOT_FOUND;
    }

    int bound = 1;
    while (bound < size && arr[bound] < key) {
        bound *= 2;//可以改为左移运算
    }

    return binary_search(arr, key, bound/2, min(bound + 1, size));
}

算法的变种

为了更快的确定搜索元素所在的范围,在原始算法的第一阶段前加一个阶段,这样变种的指数搜索算法就分为了三个阶段。
新的第一阶段,与之前类似,同样是确定第一个满足条件的指数j∗j^*j,条件同样为key≤a[2j∗]key\le a[2^{j^*}]keya[2j],但是和之前每次自加1不同,j∗j^*j是每次自乘2(即从242^424变为了282^828而非252^525)。所以有a[2j∗/2]&lt;key≤a[2j∗]a[2^{j^*/2}]&lt;key\le a[2^{j^*}]a[2j/2]<keya[2j]。相较于之前,新的第一阶段更快的确定了一个更粗糙的上下界。
接着在这个较为粗糙的上下界(2j∗/2,2j∗](2^{j^*/2},2^{j^*}](2j/2,2j]上执行原始的指数搜索算法,即确定一个更精确的上下界(2j−1,2j](2^{j-1},2^j](2j1,2j],并在更精确的上下界上面执行二分查找。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值