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

来源:互联网 发布:彩票源码 设计 编辑:程序博客网 时间:2024/05/17 06:57

我们知道,对于有序数据序列进行查找,二分查找法性能是相当好的,时间效率达到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;
}
 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 笔记本电脑自带鼠标动不了怎么办 包包弹簧扣松了怎么办 耳钉氧化成黑色怎么办 想买点小股票玩玩要怎么办 玩具子弹打到眼睛怎么办 玩具汽车遥控器码乱了怎么办 索尼A7屏幕花了怎么办? 汽车冷冻器坏了怎么办 sim卡损坏怎么办 补卡 异或门一个输入怎么办 迷你世界加不了好友怎么办 电脑软件显示无效应用程序怎么办 美的滚筒洗衣机打不开门怎么办 手机存储卡坏了怎么办 回南天地板潮湿怎么办 lg滚筒洗衣机门打不开怎么办 西门子滚桶洗衣机门打不开怎么办 洗衣机离合器螺丝卸不动怎么办 门锁保险栓坏了怎么办 小车电瓶没电了怎么办 重装机兵战车底盘坏了怎么办 父亲沉迷安利十年该怎么办 脚的大脚骨痛怎么办 自考准考证号忘记了怎么办 有桌子老师不出马怎么办 电商遇到职业打假人怎么办 超市遇到职业打假人怎么办 阿里巴巴碰到职业打假人怎么办 商家遇到职业打假人怎么办 买过期食品不赔怎么办 淘宝卖假货遇到打假师怎么办 网店遇到职业打假人怎么办 职业打假师把我起诉法院怎么办 被职业打假举报了怎么办 车档杆拉不动显示不在p档怎么办 宜人贷还不起了怎么办 买高跟鞋一只脚合适一只脚挤怎么办 脚瘦穿高跟鞋撑不起来怎么办 银川市阅海幼儿园进不去怎么办 考编专业不对口怎么办 北京55中国际部怎么办