程式設計師程式設計藝術第二十五章:Jon Bentley:90%無法正確實現二分查詢
第二十五章:二分查詢實現(Jon Bentley:90%程式設計師無法正確實現)
作者:July
出處:結構之法演算法之道
引言
Jon Bentley:90%以上的程式設計師無法正確無誤的寫出二分查詢程式碼。也許很多人都早已聽說過這句話,但我還是想引用《程式設計珠璣》上的如下幾段文字:
“二分查詢可以解決(預排序陣列的查詢)問題:只要陣列中包含T(即要查詢的值),那麼通過不斷縮小包含T的範圍,最終就可以找到它。一開始,範圍覆蓋整個陣列。將陣列的中間項與T進行比較,可以排除一半元素,範圍縮小一半。就這樣反覆比較,反覆縮小範圍,最終就會在陣列中找到T,或者確定原以為T所在的範圍實際為空。對於包含N個元素的表,整個查詢過程大約要經過log(2)N次比較。
多數程式設計師都覺得只要理解了上面的描述,寫出程式碼就不難了;但事實並非如此。如果你不認同這一點,最好的辦法就是放下書本,自己動手寫一寫。試試吧。
我在貝爾實驗室和IBM的時候都出過這道考題。那些專業的程式設計師有幾個小時的時間,可以用他們選擇的語言把上面的描述寫出來;寫出高階虛擬碼也可以。考試結束後,差不多所有程式設計師都認為自己寫出了正確的程式。於是,我們花了半個鐘頭來看他們編寫的程式碼經過測試用例驗證的結果。幾次課,一百多人的結果相差無幾:90%的程式設計師寫的程式中有bug(我並不認為沒有bug的程式碼就正確)。
我很驚訝:在足夠的時間內,只有大約10%的專業程式設計師可以把這個小程式寫對。但寫不對這個小程式的還不止這些人:高德納在《計算機程式設計的藝術 第3卷 排序和查詢》第6.2.1節的“歷史與參考文獻”部分指出,雖然早在1946年就有人將二分查詢的方法公諸於世,但直到1962年才有人寫出沒有bug的二分查詢程式。 ”——喬恩·本特利,《程式設計珠璣(第1版)》第35-36頁。
你能正確無誤的寫出二分查詢程式碼麼?不妨一試。
二分查詢程式碼
二分查詢的原理想必不用多解釋了,不過有一點必須提醒讀者的是,二分查詢是針對的排好序的陣列。OK,紙上讀來終覺淺,覺知此事要躬行。我先來寫一份,下面是我寫的一份二分查詢的實現(之前去某一家公司面試也曾被叫當場實現二分查詢,不過結果可能跟你一樣,當時就未能完整無誤寫出),有任何問題或錯誤,懇請不吝指正:
//二分查詢V0.1實現版 //copyright@2011 July //隨時歡迎讀者找bug,email:zhoulei0907@yahoo.cn。 //首先要把握下面幾個要點: //right=n-1 => while(left <= right) => right=middle-1; //right=n => while(left < right) => right=middle; //middle的計算不能寫在while迴圈外,否則無法得到更新。 int binary_search(int array[],int n,int value) { int left=0; int right=n-1; //如果這裡是int right = n 的話,那麼下面有兩處地方需要修改,以保證一一對應: //1、下面迴圈的條件則是while(left < right) //2、迴圈內當array[middle]>value 的時候,right = mid while (left<=right) //迴圈條件,適時而變 { int middle=left + ((right-left)>>1); //防止溢位,移位也更高效。同時,每次迴圈都需要更新。 if (array[middle]>value) { right =middle-1; //right賦值,適時而變 } else if(array[middle]<value) { left=middle+1; } else return middle; //可能會有讀者認為剛開始時就要判斷相等,但畢竟陣列中不相等的情況更多 //如果每次迴圈都判斷一下是否相等,將耗費時間 } return -1; } 簡單測試下,執行結果如下所示(當然,一次測試正確不代表程式便0 bug了,且測試深度遠遠不夠):測試
也許你之前已經把二分查詢實現過很多次了,但現在不妨再次測試一下。關閉所有網頁,視窗,開啟記事本,或者編輯器,或者直接在本文評論下,不參考上面我寫的或其他任何人的程式,給自己十分鐘到N個小時不等的時間,立即編寫一個二分查詢程式。獨立一次性正確寫出來後,可以留下程式碼和郵箱地址,我給你傳一份本blog的博文集錦CHM檔案 && 十三個經典演算法研究帶標籤+目錄的PDF文件(你也可以去我的資源下載處下載:http://download.csdn.net/user/v_july_v)。
當然,能正確寫出來不代表任何什麼,不能正確寫出來亦不代表什麼,僅僅針對Jon Bentley的言論做一個簡單的測試而已。本部落格演算法交流群第17群:Algorithms_17,192036066(12月份內有效)。下一章,請見第二十六章:基於給定的文件生成倒排索引的編碼與實踐。謝謝。
總結
本文發表後,馬上就有很多朋友自己嘗試了。根據從朋友們在本文評論下留下的程式碼,發現出錯率最高的在以下這麼幾個地方:
-
註釋裡已經說得很明白了,可還是會有不少朋友犯此類的錯誤:
- //首先要把握下面幾個要點:
- //right=n-1=>while(left<=right)=>right=middle-1;
- //right=n=>while(left<right)=>right=middle;
- //middle的計算不能寫在while迴圈外,否則無法得到更新。
-
還有一個最最常犯的錯誤是@土豆:
middle= (left+right)>>1; 這樣的話left與right的值比較大的時候,其和可能溢位。
相關文章
- 《程式設計師程式設計藝術》程式設計師
- 程式設計師和程式藝術家程式設計師
- 程式設計師正確看程式碼的方式程式設計師
- 每個程式設計師都應該讀《Unix程式設計藝術》程式設計師
- 計算機程式設計藝術計算機程式設計
- 文藝程式設計師合集程式設計師
- 程式設計師計算私活薪資的正確方式程式設計師
- 程式設計藝術家之路程式設計
- 優秀的程式設計師就像藝術家?程式設計師
- 華為程式設計師面試要改:網上程式設計 90 分鐘,現場程式設計 30 分鐘程式設計師面試
- 老闆該如何正確的犒賞程式設計師程式設計師
- 程式碼藝術(程式設計師值得一看) (轉)程式設計師
- 好程式設計師web前端技術分享媒體查詢程式設計師Web前端
- Java併發程式設計藝術Java程式設計
- Redux中的程式設計藝術Redux程式設計
- 談UIView Animation程式設計藝術UIView程式設計
- 優秀程式設計的“藝術”程式設計
- iOS程式設計師利用分頁和模糊查詢技術實現一個App介面iOS程式設計師APP
- 無題程式設計師程式設計師
- 程式設計師玩連連看的正確姿勢程式設計師
- 趣圖:和程式設計師交流的正確姿勢程式設計師
- 程式設計師嘆息:太難了,三萬的程式設計師確實不如三千公務員?程式設計師
- 以前的程式設計師,現在的程式設計師程式設計師
- ios程式設計師提高程式設計能力萬無一失的辦法iOS程式設計師
- 老程式設計師:當程式設計成為第二職業程式設計師
- 寫程式碼的女程式設計師無法賣萌程式設計師
- Michael Feathers:程式設計的藝術程式設計
- Unix哲學(Unix程式設計藝術)程式設計
- Java併發程式設計的藝術Java程式設計
- Unix程式設計藝術,Unix哲學程式設計
- 程式設計也是一門藝術啊程式設計
- oracle程式設計藝術筆記-1Oracle程式設計筆記
- oracle程式設計藝術筆記-2Oracle程式設計筆記
- QT QML模組的程式設計藝術QT程式設計
- 《計算機程式設計藝術》作者高德納計算機程式設計
- 《計算機程式設計藝術》出版說明計算機程式設計
- 程式設計,不止有程式碼,還有藝術程式設計
- 好程式設計師前端教程-MVC框架的正確構建程式設計師前端MVC框架