C 資料結構(二)向量(5)二分查詢

2021-09-02 20:00:30 字數 2951 閱讀 6150

【注】二分查詢的前提是有序向量,亦或有序線性表

template

<

typename t>

// 查詢演算法同一介面,0 <= lo < hi <= _size

rank vector

::search

(t const

&e, rank lo, rank hi)

const

應該便於有序向量自身的維護:v.insert(1 + v.search(e), e)

即便失敗,也應給出新元素適當的插入位置

若允許重複元素,則每一組也需按其插入的次序排列

【約定】

減而治之:以任一元素x = s[mi]為界,都可將待查詢區間分為三部分,s[lo, mi) <= s[mi] <= s(mi, hi)

只需將目標元素 e 與 x 做一比較,即可分三種情況進一步處理:

1、e < x:則 e 若存在必屬於左側子區間s[lo, mi),故可遞迴深入

2、x < e:則 e 若存在必屬於右側子區間s(mi, hi),亦可遞迴深入

3、e = x:已在此處命中,可隨即返回

二分(折半)策略:軸點 mi 總是取作中點 —— 於是每經過至多兩次比較,或者能夠命中,或者將問題規模縮減一半

template

<

typename t>

// 在有序向量區間 [lo, hi) 內查詢元素 e

static rank binsearch

(t *a, t const

&e, rank lo, rank hi)

return-1

;// 查詢失敗

}

s.search(8, 0, 7):共經 2 + 1 + 2 = 5 次比較,在s[4]處命中

s.search(3, 0, 7):共經 1 + 1 + 2 = 4 次比較,在s[1]處失敗

線性遞迴:t(n) = t(n/2) + o(1) = o(logn),大大優於順序查詢

遞迴跟蹤:軸點總取中點,遞迴深度o(logn);各遞迴例項均耗時o(1)

如何更為精細地評估查詢演算法地效能?

考查關鍵碼地比較次數,即查詢長度(search length)

通常,需分別針對成功與失敗查詢,從最好、最壞、平均等角度評估

比如,成功、失敗時地平均查詢長度均大致為o(1.50 * logn)

直接解決二分查詢中左、右分支轉向代價不平衡的問題

比如,每次迭代(或每個遞迴例項)僅做1次關鍵碼比較

如此,所有分支只有2個方向,而不再是3個

同樣的,軸點mi取作中點,則查詢每深入一層,問題規模也縮減一半

1、e < x:則e若存在必屬於左側子區間s[lo, mi),故可遞迴深入

2、x <= e:則e若存在必屬於右側子區間s[mi, hi),亦可遞迴深入

只有當元素數目hi - lo = 1時,才判斷該元素是否命中

template

<

typename t>

static rank binsearch

(t *a, t const

&e, rank lo, rank hi)

// 出口時 hi = lo + 1,查詢區間僅含乙個元素 a[lo]

return

(e == a[lo]

)? lo :-1

;// 返回命中 or -1

}// 相對於版本a,最好(壞)情況下更壞(好);各種情況下的 sl 更加接近,整體效能更趨穩定

以上二分查詢演算法

未嚴格兌現search()介面的語義約定:返回不大於 e 的最後乙個元素

1、當有多個命中元素時,必須返回最靠後(秩最大)者

2、失敗時,應返回小於 e 的最大者(含哨兵[lo - 1])

template

<

typename t>

static rank binsearch

(t *a, t const

&e, rank lo, rank hi)

// 出口時, a[lo = hi] 為大於 e 的最小元素

return

--lo;

// 故 lo - 1 即不大於 e 的元素的最大秩

}

1、待查詢區間寬度縮短至0而非1時,演算法才結束

2、轉入右側子向量時,左邊界取作mi + 1而非mi

3、無論成功與否,返回的秩嚴格符合介面的語義

不變性:a[0, lo) <= e < a[hi, n)a[hi]總是大於 e 的最小者

初始時,$ lo = 0 且 hi = n,a[0, lo) = a[hi, n) = \emptyset $,自然成立

數學歸納:假設不變性一直保持至(a),以下無非兩種情況 …

資料結構基礎 5 二分查詢

include include include include int binary serch int arr,int arr len,int value else if value arr m else return 1 int main int argc,char argv for pos 0...

c 資料結構與演算法 5 二分查詢

include include includeusing namespace std 二分查詢 int binarysearch int array,const int n,const int search 選擇排序 void selectsort int array,int n int main ...

資料結構 二分查詢

二分查詢演算法也稱為折半搜尋 二分搜尋,是一種在有序陣列中查詢某一特定元素的搜尋演算法。搜素過程從陣列的中間元素開始,如果中間元素正好是要查詢的元素,則搜素過程結束 如果某一特定元素大於或者小於中間元素,則在陣列大於或小於中間元素的那一半中查詢,而且跟開始一樣從中間元素開始比較。如果在某一步驟陣列為...