二分搜索和斐波那契搜索-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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章