二進位制搜尋

2021-09-08 11:04:39 字數 3143 閱讀 7110

轉會:

二分查詢演算法基本思想

二分查詢演算法的前置條件是,乙個已經排序好的序列(在本篇文章中為了說明問題的方便,假設這個序列是公升序排列的),這樣在查詢所要查詢的元素時,首先與序列中間的元素進行比較,假設大於這個元素,就在當前序列的後半部分繼續查詢,假設小於這個元素,就在當前序列的前半部分繼續查詢,直到找到同樣的元素,或者所查詢的序列範圍為空為止.

用偽**來表示, 二分查詢演算法大致是這個樣子的:

left = 0, right = n -1

while (left <= right)

mid = (left + right) / 2

case

x[mid] < t:    left = mid + 1;

x[mid] = t:    p = mid; 

break;

x[mid] > t:    right = mid -1;

return -1;

第乙個正確的程式

依據前面給出的演算法思想和偽**, 我們給出第乙個正確的程式,可是,它另一些小的問題,後面會講到

int search(

int array, 

int n, 

int v)

else

if (array[middle] < v)

else

}return -1;

}以下,講講在編寫二分查詢演算法時可能出現的一些問題.

邊界錯誤造成的問題

二分查詢演算法的邊界,一般來說分兩種情況,一種是左閉右開區間,類似於[left, right),一種是左閉右閉區間,類似於[left, right].須要注意的是, 迴圈體外的初始化條件,與迴圈體內的迭代步驟, 都必須遵守一致的區間規則,也就是說,假設迴圈體初始化時,是以左閉右開區間為邊界的,那麼迴圈體內部的迭代也應該如此.假設兩者不一致,會造成程式的錯誤.比方以下就是錯誤的二分查詢演算法:

int search_bad(

int array, 

int n, 

int v)

else

if (array[middle] < v)

else

}return -1;

}這個演算法的錯誤在於, 在迴圈初始化的時候,初始化right=n,也就是採用的是左閉右開區間,而當滿足array[middle] > v的條件是, v假設存在的話應該在[left, middle)區間中,可是這裡卻把right賦值為middle - 1了,這樣,假設恰巧middle-1就是查詢的元素,那麼就會找不到這個元素.

以下給出兩個演算法, 各自是正確的左閉右閉和左閉右開區間演算法,能夠與上面的進行比較:

(以下這兩個演算法是正確的)

int search2(

int array, 

int n, 

int v)

else

if (array[middle] < v)

else

}return -1;

}int search3(

int array, 

int n, 

int v)

else

if (array[middle] < v)

else

}return -1;

}死迴圈

上面的情況還僅僅是把邊界的當中乙個寫錯, 也就是右邊的邊界值寫錯, 假設兩者同一時候都寫錯的話,可能會造成死迴圈,比方以下的這個程式:

int search_bad2(

int array, 

int n, 

int v)

else

if (array[middle] < v)

else

}return -1;

}這個程式採用的是左閉右閉的區間.可是,當array[middle] > v的時候,那麼下一次查詢的區間應該為[middle + 1, right], 而這裡變成了[middle, right];當array[middle] < v的時候,那麼下一次查詢的區間應該為[left, middle - 1], 而這裡變成了[left, middle].兩個邊界的選擇都出現了問題, 因此,有可能出現某次查詢時始終在這兩個範圍中輪換,造成了程式的死迴圈.

溢位前面攻克了邊界選擇時可能出現的問題, 以下來解決還有乙個問題,事實上這個問題嚴格的說不屬於演算法問題,只是我注意到非常多地方都沒有提到,我認為還是提一下比較好.

在迴圈體內,計算中間位置的時候,使用的是這個表示式:

middle = (left + right) / 2;

假如,left與right之和超過了所在型別的表示範圍的話,那麼middle就不會得到正確的值.

所以,更穩妥的做法應該是這種:

middle = left + (right - left) / 2;

更完好的演算法

前面我們說了,給出的第乙個演算法是乙個"正確"的程式, 可是另一些小的問題.

首先, 假設序列中有多個同樣的元素時,查詢的時候不見得每次都會返回第乙個元素的位置, 比方考慮一種極端情況:序列中都僅僅有乙個同樣的元素,那麼去查詢這個元素時,顯然返回的是中間元素的位置.

其次, 前面給出的演算法中,每次迴圈體中都有三次情況,兩次比較,有沒有辦法降低比較的數量進一步的優化程式?

《程式設計珠璣》中給出了解決這兩個問題的演算法,結合前面提到溢位問題我對middle的計算也做了改動:

int search4(

int array, 

int n, 

int v)

else

}if (right >= n || array[right] != v)

return right;

}這個演算法是全部這裡給出的演算法中最完好的乙個,正確,精確且效率高.

可是這個演算法的還是不能非常好的理解

能夠用以下的演算法,能夠找出滿足條件的數

int bi_search(int a,int n,int b)//

else if(a[mid]>b)

high = mid -1;

else

low = mid +1;

} return last;

}int bi_search1(int a,int n,int b)//大於b的第乙個數

else if (a[mid]<=b)

}return last;

}

二進位制 二進位制起源

現代通訊技術的基礎是二進位制編碼。早在1865年麥克斯韋總結出麥克斯韋方程組之前,美國人摩斯 morse 於1837年發明了摩斯電碼和有線電報。有線電報的出現,具有劃時代的意義 它讓人類獲得了一種全新的資訊傳遞方式,這種方式 看不見 摸不著 聽不到 完全不同於以往的信件 旗語 號角 烽火,這也是二進...

判斷二進位製半整數(二進位制)

10年後,tokitsukaze大佬已經變成了年收入超百萬的的精英程式設計師,家裡沒錢也沒礦的teitoku,找tokitsukaze大佬借1000塊錢,然後tokitsukaze大佬說,借你1024吧,湊個整數。沒錯在2進製下1024是 二進位制整數 乙個正整數滿足其值為2的k次方 k為正整數 我...

mysql二進位制 MySql二進位制連線方式詳解

使用mysql二進位制方式連線 您可以使用mysql二進位制方式進入到mysql命令提示符下來連線mysql資料庫。例項以下是從命令列中連線mysql伺服器的簡單例項 root host mysql u root p enter password 在登入成功後會出現 mysql 命令提示視窗,你可以...