前言
二分查詢演算法也稱為折半查詢演算法,是一種在查詢演算法中普遍使用的演算法。其演算法的基本思想是:在有序表中,取中間的記錄作為比較關鍵字,若給定值與中間記錄的關鍵字相等,則查詢成功;若給定的值小於中間記錄的關鍵字,則在中間記錄的左半區間繼續查詢;若給定值大於中間記錄的關鍵字,則在中間記錄的右半區間繼續查詢;不斷重複這個過程,直到查詢成功。否則查詢失敗。這個思想與孔子中的中庸思想和相似。
二分查詢演算法的實現
基於上述的思想,可以很快寫出如下**:
public
int binarysearch(int a,int key)
return -1;
}
實際上,二分查詢的過程可以繪製成一棵二叉樹,每次二分查詢的過程就相當於把原來的樹劃分為兩棵子樹,所以每次二分之後下次就只需要查詢其中一半的資料就可以了。那麼二分查詢演算法的時間複雜度是多少呢?在最好的情況下,只需要查詢一次就可以了,因為這時候中間記錄的關鍵字與要查詢的key是相等,自然一次就夠了。在最壞的情況下是從根節點查詢到最下面的葉子結點,這個過程需要的時間複雜度是o(
logn
) 。
需要注意的是,雖然二分查詢演算法的效率很高(這也是二分查詢演算法被廣泛應用的原因),但是仍然是有使用條件的:有序。就是說在需要頻繁進行插入或者刪除操作的資料記錄中使用二分查詢演算法不太划算,因為要維持資料的有序還需要額外的排序開銷。
二分查詢演算法的變種一:插值查詢演算法
可以發現二分查詢每次都是選取中間的那個記錄關鍵字作為劃分依據的,那為什麼不可以是其他位置的關鍵字呢?在有些情況下,使用二分查詢演算法並不是最合適的。舉個例子:在1-1000中,一共有1000個關鍵字,如果要查詢關鍵字10,按照二分查詢演算法,需要從500開始劃分,這樣的話效率就比較低了,所以有人提出了插值查詢演算法。說白了就是改變劃分的比例,比如三分或者四分。
插值查詢演算法對二分查詢演算法的改進主要體現在mid的計算上,其計算公式如下: m
id=l
ow+k
ey−a
[low
]a[h
igh]
−key
(hig
h−lo
w)
而原來的二分查詢公式是這樣的: m
id=l
ow+1
2(hi
gh−l
ow)
所以我們發現主要變化的地方是12
這個係數。其思想可以總結如下:插值查詢是根據要查詢的關鍵字的key與查詢表中最大最小記錄的關鍵字比較之後的查詢演算法,其核心是上述計算mid的計算公式。由於大體框架與二分查詢演算法是一致的,所以時間複雜度仍然是o(
logn
) 。
二分查詢演算法變種二:斐波那契查詢演算法
從前面的分析中可以看到,無論劃分的關鍵字太大或者太小都不合適,所以又有人提出了斐波那契查詢演算法,其利用了**分割比原理來實現的。
乙個數列如果滿足f(n)=f(n-1)+f(n-2),則稱這個數列為斐波那契數列。在斐波那契查詢演算法中計算mid的公式如下: m
id=l
ow+f
(k−1
)−1
其實現**如下:
package com.rhwayfun.algorithm.search;
public
class fibonaccisearch
//將不滿的數值補全
int newarray = new
int[f(k) - 1];
system.arraycopy(a, 0, newarray, 0, a.length);
for(i = a.length; i < f(k) - 1; i++)
newarray[i] = a[a.length - 1];
a = newarray;
//查詢過程
while(low <= high)else
if(key > a[mid])elseelse}}
return
0; }
//返回第n項斐波那契數列的值
private
intf(int n) else
if(n == 1)
int one = 1;
int two = 0;
int sum = 0;
for (int i = 2; i <= n; i++)
return sum;
}public
static
void
main(string args) ;
int i = new fibonaccisearch().fibonaccisearch(a, 59);
system.out.println(a[i]);
}}
可以看出斐波那契查詢演算法的核心是如果要查詢的記錄在右側,則左邊就不會再去查詢了,不斷反覆進行下去,知道查詢成功。雖然斐波那契查詢演算法的時間複雜度也是o(
logn
) ,但是從效能看,仍然是優於二分查詢演算法的。
二分查詢演算法及其變種
前言 二分查詢演算法也稱為折半查詢演算法,是一種在查詢演算法中普遍使用的演算法。其演算法的基本思想是 在有序表中,取中間的記錄作為比較關鍵字,若給定值與中間記錄的關鍵字相等,則查詢成功 若給定的值小於中間記錄的關鍵字,則在中間記錄的左半區間繼續查詢 若給定值大於中間記錄的關鍵字,則在中間記錄的右半區...
演算法 二分查詢及其變種
二分查詢的前提條件是序列是有序的!時間複雜度log n 需要注意的幾個地方 public intfindtarget int nums else return 1 沒找到 返回 1 需要注意的地方 public intfindtargetleft int nums else return l 同樣如...
二分查詢及其變種
返回帶查詢元素key的下標。若沒有key元素,則返回 1。注意 1 while迴圈的條件是low high 2 每次迭代hi mid 1 或lo mid 1 二分查詢,找到該值在陣列中的下標,否則為 1 static int binaryserach int array,int key else i...