二分查找,改进-斐波那契查找

二分查找
在这里插入图片描述
在这里插入图片描述
平均查找长度O(1.5logn),
实现代码:

// 二分查找算法(版本A):在有序向量的区间[lo, hi)内查找元素e,0 <= lo <= hi <= _size
typdef int Rank;
template <typename T> 
static Rank binSearch ( T* S, T const& e, Rank lo, Rank hi ) {
   while ( lo < hi ) { //每步迭代可能要做两次比较判断,有三个分支
       Rank mi = ( lo + hi ) >> 1; //以中点为轴点(区间宽度的折半,等效于宽度之数值表示的右移)
     if      ( e < S[mi] ) hi = mi; //深入前半段[lo, mi)继续查找
      else if ( S[mi] < e ) lo = mi + 1; //深入后半段(mi, hi)继续查找
      else                  return mi; //在mi处命中
    } //成功查找可以提前终止
   return -1; //查找失败
 } //有多个命中元素时,不能保证返回秩最大者;查找失败时,简单地返回-1,而不能指示失败的位置
 // 二分查找算法(版本B):在有序向量的区间[lo, hi)内查找元素e,0 <= lo < hi <= _size
 template <typename T> static Rank binSearch ( T* S, T const& e, Rank lo, Rank hi ) {
    while ( 1 < hi - lo ) { //每步迭代仅需做一次比较判断,有两个分支;成功查找不能提前终止
       Rank mi = ( lo + hi ) >> 1; //以中点为轴点(区间宽度的折半,等效于宽度之数值表示的右移)
     ( e < S[mi] ) ? hi = mi : lo = mi; //经比较后确定深入[lo, mi)或[mi, hi)
    } //出口时hi = lo + 1,查找区间仅含一个元素A[lo]
    return e < S[lo] ? lo - 1 : lo; //返回位置,总是不超过e的最大者
 } //有多个命中元素时,不能保证返回秩最大者;查找失败时,简单地返回-1,而不能指示失败的位置
 // 二分查找算法(版本C):在有序向量的区间[lo, hi)内查找元素e,0 <= lo <= hi <= _size
 template <typename T> static Rank binSearch ( T* S, T const& e, Rank lo, Rank hi ) {
    while ( lo < hi ) { //每步迭代仅需做一次比较判断,有两个分支
       Rank mi = ( lo + hi ) >> 1; //以中点为轴点(区间宽度的折半,等效于宽度之数值表示的右移)
       ( e < S[mi] ) ? hi = mi : lo = mi + 1; //经比较后确定深入[lo, mi)或(mi, hi)
    } //成功查找不能提前终止
    return lo - 1; //循环结束时,lo为大于e的元素的最小秩,故lo - 1即不大于e的元素的最大秩
 } //有多个命中元素时,总能保证返回秩最大者;查找失败时,能够返回失败的位置

斐波那契查找改进
改进原因:二分查找,相同的递归深度下,左边比较一次,右边需要比较两次
所以:可以通过递归深度的不均衡转向成本不均衡补偿(也就是加深比较次数少的左边的深度)
在这里插入图片描述
实现代码:

 class Fib { //Fibonacci数列类
 private:
    int f, g; //f = fib(k - 1), g = fib(k)。均为int型,很快就会数值溢出
 public:
    Fib ( int n ) //初始化为不小于n的最小Fibonacci项
   { f = 1; g = 0; while ( g < n ) next(); } //fib(-1), fib(0),O(log_phi(n))时间
    int get()  { return g; } //获取当前Fibonacci项,O(1)时间
    int next() { g += f; f = g - f; return g; } //转至下一Fibonacci项,O(1)时间
    int prev() { f = g - f; g -= f; return g; } //转至上一Fibonacci项,O(1)时间
 };
 #include "fibonacci/Fib.h" //引入Fib数列类
 // Fibonacci查找算法(版本A):在有序向量的区间[lo, hi)内查找元素e,0 <= lo <= hi <= _size
 template <typename T> 
 static Rank fibSearch ( T* S, T const& e, Rank lo, Rank hi ) {
     //用O(log_phi(n = hi - lo)时间创建Fib数列
    for ( Fib fib ( hi - lo ); lo < hi; ) {  //Fib数列制表备查;此后每步迭代仅一次比较、两个分支
       while ( hi - lo < fib.get() ) fib.prev(); //自后向前顺序查找(分摊O(1))
       Rank mi = lo + fib.get() - 1; //确定形如Fib(k) - 1的轴点
       if      ( e < S[mi] ) hi = mi; //深入前半段[lo, mi)继续查找
       else if ( S[mi] < e ) lo = mi + 1; //深入后半段(mi, hi)继续查找
       else                  return mi; //在mi处命中
    } //成功查找可以提前终止
    return -1; //查找失败
 } //有多个命中元素时,不能保证返回秩最大者;失败时,简单地返回-1,而不能指示失败的位置
 #include "fibonacci/Fib.h" //引入Fib数列类
 // Fibonacci查找算法(版本B):在有序向量的区间[lo, hi)内查找元素e,0 <= lo <= hi <= _size
 template <typename T>
  static Rank fibSearch ( T* S, T const& e, Rank lo, Rank hi ) {
    for( Fib fib ( hi - lo ); lo < hi;  ) { //Fib数列制表备查
       while( hi - lo < fib.get() ) fib.prev(); //自后向前顺序查找(分摊O(1))
       Rank mi = lo + fib.get() - 1; //确定形如Fib(k) - 1的轴点
       ( e < S[mi] ) ? hi = mi : lo = mi + 1; //比较后确定深入前半段[lo, mi)或后半段(mi, hi)
    } //成功查找不能提前终止
    return --lo; //循环结束时,lo为大于e的元素的最小秩,故lo - 1即不大于e的元素的最大秩
 } //有多个命中元素时,总能保证返回最秩最大者;查找失败时,能够返回失败的位置
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值