記一次快速排序演算法的除錯

2021-04-22 07:03:59 字數 1510 閱讀 6111

同學用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] 在最開始我就應該想到:陣列操作最容易出錯的地方是**?下標!

記一次除錯

這是我最近幾個月來遇到的最棘手的乙個問題 昨天花了4個小時找出第一層次的原因 這個糾結啊,本來和老婆說好準時下班回家吃飯的,結果被這個問題拖了老久。這是乙個gradle的plugin,用來resolve公司內部的dependency的,弄完了跑測試專案的,拋乙個npe,而且npe還不在自己的 裡面。...

記一次除錯

這是我最近幾個月來遇到的最棘手的乙個問題 昨天花了4個小時找出第一層次的原因 這個糾結啊,本來和老婆說好準時下班回家吃飯的,結果被這個問題拖了老久。這是乙個gradle的plugin,用來resolve公司內部的dependency的,弄完了跑測試專案的,拋乙個npe,而且npe還不在自己的 裡面。...

記一次nginx module 除錯

參考了 先進入nginx工作目錄 usr local nginx sbin 使用gdb q tui q選項是以安靜模式啟動,不顯示gdb版本等資訊。tui選項可以顯示 介面 然後在gdb中啟動nginx shell nginx 啟動之後,可以檢視當前nginx中的程序號 shell pidof ng...