二分查詢法

2021-08-02 09:45:17 字數 3931 閱讀 5472

----------------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...

二分查詢法

演算法基本思想 二分查詢演算法的前置條件是,乙個已經排序好的序列 假設這個序列是公升序排列的 這樣在查詢所要查詢的元素時,首先與序列中間的元素進行比較,如果大於這個元素,就在當前序列的後半部分繼續查詢,如果小於這個元素,就在當前序列的前半部分繼續查詢,直到找到相同的元素,或者所查詢的序列範圍為空為止...