数据结构-查找-二分法插值法菲波那切法查找

数据结构-查找-二分法插值法菲波那切法查找


为了讲解清楚各个方法的原理,下面是我们要查找的序列,

nums1162435475962738899
序号0123456789

二分法在这就不在赘述了,其实际复杂度显然是O(logn).

插值法

在猜目标key=59的时候,我们知道59相对来说是略微偏大的,所以但偏大多少用什么来度量呢,在二分法的时候 m i d = l o w + 1 2 ( h i g h + m i d ) mid= low+\frac{1}{2} (high+mid) mid=low+21(high+mid)
这里采用的是中间1/2来统一度量,但我们有时知道目标key 靠近右端(左端),此时应该再采用统一度量有点吃力不讨好,这也是二分法的一个缺点,故由此引入了插值法,将递归的mid
值修改成 m i d = l o w + k e y − n u m s [ l o w ] n u m s [ h i g h ] − n u m s [ l o w ] ( h i g h + m i d ) mid= low+\frac{key-nums[low]}{nums[high]-nums[low]} (high+mid) mid=low+nums[high]nums[low]keynums[low](high+mid)
若目标先对靠近左端,我们查找的对象mid就较为靠近左端;此种算法对原序列有一定的依赖性,需要原序列分布比较均匀,时间复杂度也有O(logn)。

菲波那切查找

这里要引入菲波那切数列1,1,2,3,5,8,13,21……;我们先将一些后面所附的代码吧,

  1. 找出序列nums的长度对应的斐波那契数列的项(这里我们找的是f[k=6]=13);
  2. 将原序列根据最后一元素进行填充到长度为13;
  3. 计算中间值mid, m i d = l o w + F [ k − 1 ] − 1 mid = low+F[k-1]-1 mid=low+F[k1]1
  4. 如果目标key靠近low的时候k - =1,这是因为在取mid的时候左端的长度是等于F[k-1]的,而右端的长度是等于F[k-2]的;
  5. key靠近high时k-=2;
  6. 若还没有取得nums[mid]==key时继3迭代。

斐波那契查找的时间复杂度也是O(logn),就平均性能来看要优于二分法,但如果key=16,那么查找将一直处于左边的长半区间查找,此时的效率就比二分法低。其优点在于迭代的更新函数mid值的计算斐波那契法只用到了加减,此在效率上有一定的提高,但在不能保证避免插值法和斐波那契缺点的时候建议还是使用二分法。 啊这emmmm^ < ^

def erfen(nums,key,sort=0):
    if sort == 0:
        nums.sort() 
    high = len(nums)-1
    low = 0
    while  low<=high:
        mid = int((low+high)/2)
        if nums[mid] > key:
            high = mid-1
        elif nums[mid] < key:
            low = mid+1
        else:
            return mid
    return -1

def interp(nums,key,sort=0):
    if sort == 0:
        nums.sort()    
    high = len(nums)-1
    low = 0
    while  low<=high:
        mid = int( low + (key-nums[low])*(high-low)/(nums[high]-nums[low]) )
        if nums[mid] > key:
            high = mid-1
        elif nums[mid] < key:
            low = mid+1
        else:
            return mid
    return -1

def Fibon(nums,key,sort=0):
    if sort == 0:
        nums.sort()   #若开始的列表无序就先安排排序
    low, n, high  = 0, len(nums)-1, len(nums)-1
    #------------------------- 生成菲波那切数列;
    F = [1,1]
    while F[-1] < n:
        F.append(F[-1]+F[-2])
        print (F)
    print('==============')
    #--------------------------
    #将有序列表补齐
    for i in range(len(nums),F[-1],1):
        nums.append(nums[-1])
    k = len(F)-1
    while low<=high:
        mid = low+F[k-1]-1
        print('mid',mid)
        if nums[mid] > key:   # 说明在mid的左边,此时的个数是F[k-1]个
            high = mid-1
            k-=1
        elif nums[mid] < key:  # 说明在mid的右边,此时的个数是F[k-2]个
            low = mid+1
            k = k-2
        else:
            if mid <= n:
                return mid
            else:  
                return n
    return -1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值