Vector::find、search查找

38 篇文章 1 订阅
22 篇文章 0 订阅

无序向量区间查找:

template <typename T> //无序向量的顺序查找:返回最后一个元素e的位置;失败时,返回lo - 1
Rank Vector<T>::find(T const & e, Rank lo, Rank hi) const { //assert: 0 <= lo < hi <= _size
   while ((lo < hi--) && (e != _elem[hi])); //从后向前,顺序查找
   return hi; //若hi < lo,则意味着失败;否则hi即命中元素的秩
}

有序向量区间查找:

// 二分查找算法(版本C):在有序向量的区间[lo, hi)内查找元素e,0 <= lo <= hi <= _size
template <typename T> static Rank binSearch(T* A, T const & e, Rank lo, Rank hi) { /*DSA*/printf("BIN search (C)\n");
   while (lo < hi) { //每步迭代仅需做一次比较判断,有两个分支
      /*DSA*/ for (int i=0; i<lo; i++) printf("     "); if (lo >= 0) for (int i=lo; i<hi; i++) printf("....^"); printf("\n");
      Rank mi = (lo + hi) >> 1; //以中点为轴点
      (e < A[mi]) ? hi = mi : lo = mi + 1; //经比较后确定深入[lo, mi)或(mi, hi)
   } //成功查找不能提前终止
   /*DSA*/ for (int i=0; i<lo-1; i++) printf("     "); if (lo > 0) printf("....|\n"); else printf("<<<<|\n");
   return --lo; //循环结束时,lo为大于e的元素的最小秩,故lo - 1即不大于e的元素的最大秩
} //有多个命中元素时,总能保证返回秩最大者;查找失败时,能够返回失败的位置

引入fibnacci数列(所谓的黄金分割):

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查找算法(版本B):在有序向量的区间[lo, hi)内查找元素e,0 <= lo <= hi <= _size
template <typename T> static Rank fibSearch(T* A, T const & e, Rank lo, Rank hi) { /*DSA*/printf("FIB search (B)\n");
   Fib fib(hi - lo); //用O(log_phi(n = hi - lo)时间创建Fib数列
   while (lo < hi) { //每步迭代仅仅做一次比较判断,有两个分支
      /*DSA*/ for (int i = 0; i < lo; i++) printf("     "); if (lo >= 0) for (int i = lo; i < hi; i++) printf("....^"); else printf("<<<<|"); printf("\n");
      while (hi - lo < fib.get()) fib.prev(); //通过向前顺序查找(分摊O(1))——至多迭代几次?
      Rank mi = lo + fib.get() - 1; //确定形如Fib(k) - 1的轴点
      (e < A[mi]) ? hi = mi : lo = mi + 1; //比较后确定深入前半段[lo, mi)或后半段(mi, hi)
   } //成功查找不能提前终止
   /*DSA*/ for (int i = 0; i < lo-1; i++) printf("     "); if (lo > 0) printf("....|\n"); else printf("<<<<|\n");
   return --lo; //循环结束时,lo为大于e的元素的最小秩,故lo - 1即不大于e的元素的最大秩
} //有多个命中元素时,总能保证返回最秩最大者;查找失败时,能够返回失败的位置
template <typename T> //在有序向量的区间[lo, hi)内,确定不大于e的最后一个节点的秩
Rank Vector<T>::search(T const & e, Rank lo, Rank hi) const { //assert: 0 <= lo < hi <= _size
   return (rand() % 2) ? //按各50%的概率随机使用
      binSearch(_elem, e, lo, hi) : fibSearch(_elem, e, lo, hi); //二分查找或Fibonacci查找
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值