1. 程式人生 > >基礎算法之二分查找總結

基礎算法之二分查找總結

blog 是我 問題 arch grand 進化 查找 數組 span

本博客是我在做題和看書遇到各種情況的總結。

參考了書,鄧俊輝老師編寫的《數據結構(C++語言版)(第3版)》,同時還有網友的總結(以下會給出相應的鏈接)。

一、查找等於目標元素的位置(若是多個,只要求找到即可)

 1 /二分查找的主體
 2 int binarySearch(int A[], int n, int target)
 3 {
 4     int lo = 0, hi = n;  //n為數組的A元素的個數
 5     
 6     while (lo < hi)
 7     {
 8         int mid = lo + (hi - lo)/2;
 9         if
(A[mid] == target) 10 return mid; 11 else if (target < A[mid]) 12 hi = mid; 13 else 14 lo = mid + 1; 15 } 16 return -1; 17 }

這裏關於右邊界hi的取值值得註意的有幾點:

1)在while循環外面的hi=n,說明是前開後閉型([0,n) ),那麽在while循環中的hi的取值應構成前開後閉型([ lo,mid )),此時while循環的條件為lo<hi

2)在while循環外面的hi=n-1,說明是前開後閉型([0,n-1]),那麽在while循環中的hi的取值應構成前開後閉型([ lo,mid-1]),此時while循環的條件為lo<=hi

這裏不是說,其他情況下的使用,就不能使用,只是有時候會出錯。

二、查找重復元素的第一個值的下標,若是沒有重復元素則返回第一個不小於目標值的下標

 1 //二分查找的主體
 2 int binarySearch(int A[], int n, int target)
 3 {
 4     int lo = 0, hi = n;
 5     
 6     while (lo < hi)
7 { 8 int mid = lo + (hi - lo)/2; 9 10 if (A[mid] < target) 11 lo = mid + 1; 12 else 13 hi = mid; 14 } 15 return hi; 16 }

:這裏的hi值也可以像一種那樣變化,要對應的變化。只不過這樣改變以後,在不存在目標值的情況下,返回的是第一個小於目標值(從目標值往左數)的下標。

三、查找重復元素的最後一個下標,或者不存在目標值時,第一個小於目標值的下標。這種情況,鄧老師書上有嚴格的證明。

 1 //二分查找的主體
 2 int binarySearch(int A[], int n, int target)
 3 {
 4     int lo = 0, hi = n;
 5     
 6     while (lo < hi)
 7     {
 8         int mid = lo + (hi - lo)/2;
 9         
10         if (A[mid] <= target)
11             lo = mid + 1;
12         else
13             hi = mid;
14     }
15     return --lo;    //必須減減
16 }

註意:第二種和第三種的區別在於if條件判斷語句的差別,和返回值的區別,

四、將二、三結合就可以求出存在多個目標值時,目標值所在的區間。詳情見search for a range。

版本一的進化版是斐波那契查找,這和二分查找的主要區別在於中間點mid是使用斐波那契進行選擇的,版本三的各分支的平均查更好些,詳情請見參考書。

總結

針對二分查找,值得註意的是區間的選取(見第一種情況下的說明);要是求目標值給定條件下(第一個或最後一個)下的下標,可以通過變化while循環中的if條件內的等號所在來實現。

下面給出第三種情況下測試程序,第一、二中可以通過變化數組A所含的值來實現。

 1 #include<iostream>
 2 #include<vector>
 3 
 4 using namespace std;
 5 
 6 int binarySearch(int A[], int n, int target);
 7 
 8 int main()
 9 {
10     int A[] = { 0,1,2,3,4,4,4,4,5,6,7,8,9 };
11     int target = 4;
12     int res = binarySearch(A, 13, target);    
13     cout << "目標值的下標是:" << res << endl;
14     return 0;
15 }
16 
17 //二分查找的主體
18 int binarySearch(int A[], int n, int target)
19 {
20     int lo = 0, hi = n;
21     
22     while (lo < hi)
23     {
24         int mid = lo + (hi - lo)/2;
25         
26         if (A[mid] <= target)
27             lo = mid + 1;
28         else
29             hi = mid;
30     }
31     return --lo;    //必須減減
32 }
33 
34 
35 /*
36     int A[] = { 0,1,2,3,4,4,4,4,5,6,7,8,9 },target=4時,返回值為7
37     int A[] = { 0,1,2,4,4,4,4,5,6,7,8,9 },target=3時,返回值為2
38     int A[] = { 0,1,2,4,4,4,4,5,6,7,8,9 },target=3,返回lo時,返回值為3
39 */

若是各位看官發現什麽問題,多多留言哈,共同進步~

參考:

http://www.61mon.com/index.php/archives/187/

http://blog.csdn.net/sunmenggmail/article/details/7540970

http://www.cnblogs.com/luoxn28/p/5767571.html

http://www.cnblogs.com/grandyang/p/6854825.html

基礎算法之二分查找總結