----------------siwuxie095
二分查詢法
二分查詢(binary search),也稱 折半查詢(half-interval search),
是一種在有序陣列中查詢某一特定元素的搜尋演算法
「或稱二分搜尋,折半搜尋」
正如定義所示,二分查詢法有一定的限制:對於有序數列,才能使用二分查詢法
由此可知,排序演算法在很多時候是作為其它演算法的乙個子過程。例如:如果使用
二分查詢法,就要先使用一次排序演算法,對要查詢的內容進行一次排序
之所以進行這次排序,是因為處理有序陣列,要比處理無序陣列容易很多
具體查詢過程:
要在乙個有序陣列中查詢某個元素,就先看這個陣列的中間元素
v 與要查詢的
元素,二者的大小的關係
如果中間元素
v 正好是要查詢的元素,即 二者相等,非常好,直接就找到了該
元素,查詢結束
否則,整個陣列就被中間元素 v 分成了兩部分:小於 v 的部分和大於 v 的部分
1)如果要查詢的元素比
v 小,就在小於
v 的這部分繼續查詢即可
2)如果要查詢的元素比
v 大,就在大於 v 的這部分繼續查詢即可
「前提:整個陣列是有序的」
不難想象,整個查詢過程,感覺上構造出了一棵樹,即
是乙個樹形問題,
整個二分查詢法的時間複雜度是
lgn 級別的
二分查詢法的思想非常簡單,而且這個思想在很早的時候就被提出來了
二分查詢法的思想在 1946 年提出,但有意思的是,第乙個沒有
bug 的
二分查詢法在 1962 年提出
程式 1:迭代的二分查詢法
binarysearch.h:
#ifndef binarysearch_h
#define binarysearch_h
// 用迭代的方式寫二分查詢法
////
二分查詢法
,在有序陣列
arr中,查詢
target
// 如果找到
target,
返回相應的索引
index
// 如果沒有找到
target,
返回-1
template
intbinarysearch(t arr, intn, t target) //
在arr[l...mid-1]
之中查詢
target//或
arr[mid+1...r]
之中查詢
target
if(arr[mid] > target)
else }
return-1;
}#endif
main.cpp:
#include"binarysearch.h"
#include
#include
#include
using namespacestd;
intmain()
// 測試非遞迴二分查詢法(迭代)
clock_tstarttime = clock();
for(inti = 0; i < 2* n; i++)
else }
clock_tendtime = clock();
cout << "binary search (without recursion): "<< double(endtime - starttime)
/ clocks_per_sec << " s"<< endl;
deletea;
system("pause");
return0;}
執行一覽:
程式 2:遞迴的二分查詢法
binarysearch.h:
#ifndef binarysearch_h
#define binarysearch_h
template
int__binarysearch(t arr, intl, intr, t target)
intmid = (l + r) / 2;
if(arr[mid] == target)
else if(arr[mid] > target)
else }
// 用遞迴的方式寫二分查詢法
template
intbinarysearch(t arr, intn, t target) //
遞迴實現通常思維起來更容易,因為每一次不需要考慮全域性,
//只需要考慮乙個子問題
////
想好它們的遞迴關係,想清楚在最基礎的層面是怎麼做的,
//就能寫出這個函式來,不過遞迴也存在一些缺點:相比於
//迭代,遞迴在效能上會略差(這種差異是常數級的)
////
不管是遞迴還是迭代,二分查詢法的時間演算法複雜度都是
//o(lgn)
級別的#endif
main.cpp:
#include"binarysearch.h"
#include
#include
#include
using namespacestd;
intmain()
// 測試遞迴的二分查詢法
clock_tstarttime = clock();
for(inti = 0; i < 2* n; i++)
else }
clock_tendtime = clock();
cout << "binary search (recursion): "<< double(endtime - starttime)
/ clocks_per_sec << " s"<< endl;
deletea;
system("pause");
return0;}
執行一覽:
二分查詢法的變種
二分查詢法的變種有兩個非常重要的、也是應用非常廣的函式,
分別叫做
floor和 ceil
「有的地方也叫做 lower_bound 和 upper_bound」
之前實現的二分查詢法,通常都是假設陣列中沒有重複元素
當然,即使陣列中有重複元素,對於乙個排好序的陣列來說,依然能找到
相應元素的索引,只不過,該元素在這個陣列中可能會出現很多次,之前
實現的二分查詢法並不能保證找到的這個元素的索引,具體是哪個索引
但floor 和 ceil 這兩個函式,卻能保證:
1)呼叫 floor 來找元素 v,可以找到
v 在整個陣列中第一次出現的位置
2)呼叫
ceil 來找元素 v,可以找到 v 在整個陣列中最後一次出現的位置
這兩個函式還有乙個優勢,即
當在陣列中查詢元素,如果這個元素
不存在,之前實現的二分查詢法直接返回了
-1,但 floor 和 ceil 的
返回值卻有所不同
具體如下:
如果要在陣列中查詢元素 42,可以看到 42 在這個陣列中並不存在,
那麼floor 返回的就是最後乙個 41 的元素,而 ceil 返回的就是第一
個 43 的元素
【made by siwuxie095】
二分查詢法
二分查詢要求 1.必須採用順序儲存結構 2.必須按關鍵字大小有序排列。優缺點 折半查詢法的優點是比較次數少,查詢速度快,平均效能好 其缺點是要求待查表為有序表,且插入刪除困難。因此,折半查詢方法適用於不經常變動而查詢頻繁的有序列表。演算法思想 首先,將表中間位置記錄的關鍵字與查詢關鍵字比較,如果兩者...
二分查詢法
有序陣列中的find 方法 public int find long serchkey int lowerbound 0 int upperbound nelems 1 while true curin lowerbound upperbound 2 if a curin serchkey retu...
二分查詢法
演算法基本思想 二分查詢演算法的前置條件是,乙個已經排序好的序列 假設這個序列是公升序排列的 這樣在查詢所要查詢的元素時,首先與序列中間的元素進行比較,如果大於這個元素,就在當前序列的後半部分繼續查詢,如果小於這個元素,就在當前序列的前半部分繼續查詢,直到找到相同的元素,或者所查詢的序列範圍為空為止...