比二分查找法更好的,我的估算值查找法

我们知道,对于有序数据序列进行查找,二分查找法性能是相当好的,时间效率达到O(Log2N),但该算法其实还有些可以进行改进的地方。
普通的二分查找法,直接通过折半的方式来对有序数据序列进行筛选,这种方法实际上不是十分有效。对于大多数的有序数据序列,通常分布都是比较均匀的,我们完全可以通过对数据的分布进行估算,找出合理位置,减少折半次数。
基于估算数据序列折点的方式进行查找,在数据分布最好的情况下,与二分查找法一样,时间效率都是O(1), 但在最坏的情况下,与普通情况下,都有着比二分查找法,更优越的情能。
以下是一个简单的估算查找法实现:
#include <cstdlib>
#include <iostream>

using namespace std;

//普通估算法,没有对分布不均匀的情况进行特殊处理
int fEval(int a[], int first, int last, int targe)
{
   int nDevValue = 0;
   nDevValue = (a[last] - a[first]) / (last - first);
   if ((a[last] - a[first]) % (last - first) != 0)
       ++nDevValue;
   int nDev = (targe - a[first]) / nDevValue;
   if (targe - a[first] < nDevValue)
       return first + nDev + 1;
   else
       return first + nDev;
}

//对分布不均匀的情况,进行了特殊(跳跃式)处理
int fEval2(int a[], int first, int last, int targe)
{
    int cValue = a[(first + last)/2];
    if (cValue > targe)
    {
        return fEval(a, first, (first + last)/2, targe);
    }
    else
    {
        return (first + last)/2 + fEval(a, (first + last)/2, last, targe);
    }
}

//普通二分查找法
int fBin(int a[], int first, int last, int targe)
{
   return (first + last) / 2;
}

template<typename EVAL>
int Find(int a[], int first, int last, int targe, EVAL feval)
{
    int result = -1;
    int count = 0;
    int nEvalFirst = first;
    int nEvalLast = last;
    int nEvalMid = 0;
    while ((nEvalFirst < nEvalLast)
           && (a[nEvalFirst] <= targe)
           && (a[nEvalLast] >= targe))
    {
        nEvalMid = feval(a, nEvalFirst, nEvalLast, targe);
        if (targe == a[nEvalMid])
        {
            result = nEvalMid;
            break;
        }
        else if (nEvalMid != nEvalLast && targe > a[nEvalMid])
        {
            nEvalFirst = nEvalMid + 1;
        }
        else if (nEvalMid != nEvalLast && targe < a[nEvalMid])
        {
            nEvalLast = nEvalMid;
        }
        else
        {
            break;
        }
        ++count;
    }
    cout << count << "/n";
    return result;
};

int main(int argc, char *argv[])
{
    //最差情况
    int a[] = {1, 2, 3, 4, 5, 100, 400};
    cout << Find(a, 0, 6, 201, fBin) << "/n";
    cout << Find(a, 0, 6, 201, fEval) << "/n";
    cout << Find(a, 0, 6, 201, fEval2) << "/n";

    //最好情况
    int b[] = {1, 2, 3, 4, 5, 6, 7};
    cout << Find(b, 0, 6, 4, fBin) << "/n";
    cout << Find(b, 0, 6, 4, fEval) << "/n";
   
    //普通情况
    int c[] = {1, 4, 6, 10, 15, 17, 20, 26, 40, 45, 48, 50, 52, 57, 59, 63,
               68, 74, 78, 82, 85, 93, 96, 101, 105, 109, 112, 117, 120, 121,
               123, 129, 133, 136, 140, 145, 147, 151, 154, 160, 163, 167,
               170, 176, 179, 180, 183, 187, 188, 192, 194, 197, 201, 204,
               210, 211, 215, 217, 220, 223, 225, 228, 231, 233, 237, 240,
               245, 247, 248, 256, 258, 261, 263, 267, 269, 272, 275, 277,
               279, 282, 283, 285, 289, 294, 297, 300};
    cout << Find(c, 0, 85, 123, fBin) << "/n";
    cout << Find(c, 0, 85, 123, fEval) << "/n";
   
    system("PAUSE");
    return EXIT_SUCCESS;
}
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值