二分搜尋需要注意開閉區間的問題,限制條件和邊界要保持配對:low<=high , low = mid +1 ,high = mid-1。
二分搜尋的模板如下:
[cpp]view plain
copy
// 二分搜尋
intbinarysearch(
int*num,
intkey,
intlow,
inthigh)
return
low;
//查詢不成功時,返回應該插入的位置,或者直接返回-1,表示查詢失敗也是可以的
}
二分搜尋的擴充套件:對已排好序的陣列a,一般來說可用二分查詢 可以很快找到。現有一特殊陣列a,它是迴圈遞增的,如a=,試在這樣的陣列中找一元素x,看看是否存在。請寫出你的演算法,必要時可寫偽**,並分析其空間、時間複雜度。
思路分析:
在乙個陣列中檢索乙個元素,最普通的演算法就是時間複雜度為o(n)的順序檢索。要降低時間複雜度,並結合迴圈遞增陣列的元素已有一定程度順序的性質,很容易想到二分查詢。
我最初的想法是:樸素的二分查詢在是下標區間[0 n-1]內進行二分,那麼利用迴圈遞增的性質,我們可以在陣列的有效下標區間[0 n-1]的乙個偏移區間[r+1 n+r-1]裡進行二分(其中r是上述迴圈遞增陣列定義中的那個分界下標r)。但是,這個想法的乙個最大問題是:給定乙個迴圈遞增陣列,我如何去確定其分界下標r?最明顯的做法就是順序掃瞄一遍陣列,然後確定其分界下標r。但是,既然你都掃瞄一遍了,也就能確定檢索元素是否在該陣列中了,何必再去利用分界下標r去檢索呢?
上述想法不成功,我們再去深入地去思考二分查詢方法的一些原理特性。在乙個嚴格遞增的陣列中,我們將要檢索的元素和陣列中間的元素進行比較,然後根據要檢索的元素與陣列中間的元素的大小關係來確定該元素落在那個範圍內,然後遞迴地在該範圍內進行檢索。
現在在迴圈遞增陣列中,我們不能簡單地通過與陣列中間元素的大小關係來確定要檢索的元素所落在的區間範圍。要確定範圍,我們可以再加上要檢索的元素與陣列兩端的元素的大小關係。
迴圈遞增陣列有這麼乙個性質:以陣列中間元素將迴圈遞增陣列劃分為兩部分,則一部分為乙個嚴格遞增陣列,而另一部分為乙個更小的迴圈遞增陣列。當中間元素大於首元素時,前半部分為嚴格遞增陣列,後半部分為迴圈遞增陣列;當中間元素小於首元素時,前半部分為迴圈遞增陣列;後半部分為嚴格遞增陣列。
記要檢索的元素為key,陣列的首元素為a[low],中間元素為a[mid],末尾元素為a[high]。則當key不等於a[mid] 時,
1、a[mid] > a[low],即陣列前半部分為嚴格遞增陣列,後半部分為迴圈遞增陣列時,若key小於a[mid]並且不小於a[low]時,則key落在陣列前半部分;否則,key落在陣列後半部分。
2、a[mid] < a[high],即陣列前半部分為迴圈遞增陣列,後半部分為嚴格遞增陣列時,若key大於a[mid]並且不大於a[high]時,則key落在陣列後半部分;否則,key落在陣列前半部分。
通過上面利用陣列首元素,中間元素和末尾元素確定要檢索的元素所在範圍,我們就可以使用修改後的二分查詢演算法了。
實現**如下:
[cpp]view plain
copy
// 改進後的二分搜尋
intsearch(
inta,
intn,
intnum)
if(a[left] <= a[mid])
//前半部分是嚴格遞增的,後半部分是乙個更小的迴圈遞增陣列
else
} else
//後半部分是嚴格遞增的,前半部分是乙個更小的迴圈遞增陣列
else
} } return
pos;
}
二分搜尋及其擴充套件
二分搜尋 折半搜尋,也稱二分查詢演算法 二分搜尋,是一種在有序陣列中查詢某一特定元素的搜尋演算法。搜素過程從陣列的中間元素開始,如果中間元素正好是要查詢的元素,則搜素過程結束 如果某一特定元素大於或者小於中間元素,則在陣列大於或小於中間元素的那一半中查詢,而且跟開始一樣從中間元素開始比較。如果在某一...
二分搜尋以及其擴充套件形式
歡迎 如有錯誤敬請指正 二分搜尋使用的前提是陣列必須有序,在本文中,我們用lo low 表示查詢範圍的起始下標,hi hight 表示查詢範圍的結束下標,mid表示lo和hi的中間位置。1.一般情況二分搜尋 普通二分搜尋,如果找到key,返回任意乙個和key相等的元素下標,否則返回 1 public...
二分搜尋及其擴充套件(迴圈遞增陣列的搜尋)
二分搜尋需要注意開閉區間的問題,限制條件和邊界要保持配對 low high low mid 1 high mid 1。二分搜尋的模板如下 cpp view plain copy 二分搜尋 intbinarysearch int num,intkey,intlow,inthigh return low...