記一次快速排序算法的調試

同學用C++編寫了一個快速排序的程序,實現如下功能:

1,用一個數組包含原始數據;2,用一個數組包含每個原始數據的地址;3,利用快速排序算法,對第二個數組進行排序。

很顯然,排序的交換操作與原始數據的存儲分開進行,是爲了節省時間。

算法寫出來了,程序編譯運行了,但是:排序前和排序後,輸出的結果居然是一樣的。

 

我最初的想法是:既然排序前後輸出一樣,那麼很可能是根本沒有發生交換[1]。

然而看了同學的代碼,似乎又沒有這種錯誤;此外,他是按照書上的示例敲的代碼,雖然現在水貨書很多,但一般敢拿出手運行的代碼(不是僞代碼),出錯的可能性不大[2]。

第二種可能性是:數據在發生交換以後,又因爲程序中某個書寫錯誤,被換回去了。這種錯誤比較麻煩,因爲我必須讀懂算法纔行。如果要是一行行讀懂、然後一行行檢查,這個時間完全可以讓我重新寫一遍新的算法!

我不希望讀算法,另外,我覺得同學既然寫出了這個算法,而且他確實明白快速排序的實現機制,那麼至少框架上,不會有大的問題。所以,“書寫錯誤”可能性較大[3]。

我在VC中定義了觀察變量,觀察每個數組元素的變化情況(指針數組)。在調試過程中,我直接將斷點設置在swap操作上,判斷它是否中斷[4]。經測試發現,數組發生了變化:錯誤沒像我預計的那麼簡單,但是很清楚:一定是邏輯上出問題了。

既然是邏輯錯誤,那麼一定在運算的過程中發生問題(到現在爲止,我對同學的代碼基本上沒有閱讀)。我需要從算法運行過程中,產生的數據,定位“邏輯錯誤”的所在[5]。

耐心地跟蹤程序,順便花了快速排序的步驟流程:每一步發生交換,數組會是什麼樣子。交換指針其實和交換原始數據是一樣的,所以,理解上一點也不困難。老實說,這本書上的排序算法和以前學的還有點不同,在最開始的時候搞了個swap操作,將最中間的元素放到數組開始——故弄玄虛,沒有必要,BS一下這個作者。

突然靈光一閃:4、9交換以後,爲什麼又被交換成9、4了[6]?計算機是不會錯的,它一定是在進行了某次“比較”之後,發現“條件符合”,就將兩個元素交換了。

當我將注意力集中到這個地方時,swap函數的嫌疑已經大大減輕了,sort函數的開始有一些初始化代碼,也很容易排除嫌疑。再結合“比較邏輯”這個線索,我將目光集中在if語句和接下來的交換操作上:果然,一個下標的寫錯了。p[start]被寫成了p[current],對着書上代碼看一看,OK了。

 

[1] 記得在最初學習C語言“傳值”的時候,swap函數很可能出現這種情況。

[2] 其實在這個時候,如果想要排除這種可能,不妨花一點點時間,換幾組測試數據多試幾次。如果每次都輸入輸出一致,那麼“根本沒有發生交換”的可能性會較大;如果某次不一致,那這種錯誤的可能性就排除了。

[3] 在這個時候,我其實應該問問他算法的書寫過程是怎樣的——這對於我定位錯誤很有幫助。事後我才知道,同學是先閱讀算法、代碼,然後按照算法的思路進行默寫;而不是照着書本一行行地敲代碼。他思路上的理解失誤,就很可能導致程序的書寫錯誤。

[4] 如果從頭到尾都沒有發生swap操作,那麼可想而知,數組根本沒有變化,輸入輸出也就是一致的了。

[5] 否則,建議重寫程序;如果有興趣的話,前後對比。

[6] 在最開始我就應該想到:數組操作最容易出錯的地方是哪裏?下標!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章