【数据结构与算法】二分搜索和斐波那契搜索-C实现

二分和斐波

一直在家,无聊就看看.
二分搜索有O(1.5logn)的时间复杂度,斐波那契搜索可以进一步提升至O(1.4logn).

注:这两种检索方法都是针对有序集合的.

二分搜索

基本思路就是把集合分成两部分,当然这里是指有序集合。
把搜索目标与分界点元素作比较,从而决定去往哪一部分检索目标。
二分搜索优解:单击查看实现代码


C代码描述为:

size_t Fibonacci(size_t number);
/** Fib搜索 传入容器、区间和目标;返回<下标>\<-1> **/
template <typename T>
int FibSearch(vector<T> vec,size_t low,size_t high,T var)
{
	/* 取集合两部分的分界点为mid */
	size_t mid;
	while(low<high){
		mid = (high+low)/2;
		if(var == vec[mid]) return mid;
		else if(var<vec[mid]) high = mid;
		else low = mid+1;
	}
	/* 没有找到--返回-1 */
    return -1;
}

斐波那契查找

斐波那契查找的思路可从于二分查找的思路领悟
二分查找总要根据mid位置和var的值的比较结果,在三件事:

1.返回mid
2.更新high
3.更新low

而根据判定结果选择更新high或者low需要的操作次数是不同的(必然是其中一个只需要比较一次,而另一个需要比较两次)

这就引发一种猜想:把更多的元素分到需要操作更少的那边,就能够减少总的操作次数,从降低时间复杂度,节省时间


对于上面代码所示的这种实现,我们更新high只需要:

else if(var<vec[mid]) high = mid;

这一次操作.

而更新low则需要:

else if(var<vec[mid]) high = mid;
else low = mid+1;

两次操作.


故而按照前面的猜想,我们可以在选取分界点时稍往右偏些,把更多的元素分到左侧。
也就是说,二分搜索是对半开,两边各占0.5,现在让左边占比略高于0.5,而右边略低于0.5

分析发现,这个比值在大概0.6:0.4时使得这个思路得到的优化效果最佳.
也就是借用Fibonacci代替原代码中的:

mid = (high+low)/2;

来更新mid的数值


Fibonacci搜索方法的一种实现如下

size_t Fibonacci(size_t number);
/** Fib搜索 传入容器、区间和目标;返回<下标>\<-1> **/
template <typename T>
int FibSearch(vector<T> vec,size_t low,size_t high,T var)
{
    /* 斐波那契数种子 */
    size_t FibSeed = high-low;
    /* 所谓mid */
    size_t ptr = low + Fibonacci(FibSeed)-1;
    while(low<high){
        /* 更新mid */
        while(Fibonacci(FibSeed) > high-low)
        	ptr = low + Fibonacci(--FibSeed)-1;
        if(var == vec[ptr]) return ptr;
        else if(var<vec[ptr]) high = ptr;
        else low = ptr+1;
    }
    return -1;
}

其中Fibonacci的实现如下:

/* 斐波那契数列生成器  -- <传入序号,返回对应位置数值>*/
size_t Fibonacci(size_t number)
{
    /** 初始化数列种子 <Fo> and <Be> **/
    size_t Fo=1,Be=0;
    while(number--){
        /* 暂且这样规避上溢 ^_^ */
        if(Fo>100000)
            return -1;
        Fo+=Be;
        Be = Fo-Be;
    }
    return Fo;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值