基礎算法之二分查找總結
本博客是我在做題和看書遇到各種情況的總結。
參考了書,鄧俊輝老師編寫的《數據結構(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
基礎算法之二分查找總結