contributed by < YOYOPIG
>
linux2021
由各 function 名稱不難看出,這支程式主要是在實作對 Singly linked list 的 quick sort 演算法。有了大致的認知後,從 main function 開始 trace code。
main function 做的事相當簡單,先隨機產生給定數量(20)的 nodes,印出之後做 sort,再印出排序完的 list。最後,檢查排序是否成功並 free 掉資源。
這支程式最主要的程式碼,我們可以看到有許多行被挖空了
首先是 Edge case 的檢查,如果傳入的值為 NULL,則直接 return,作為後續 recursive call 的中斷點。程式碼如下:
接著,取出 quick sort 演算法中的 pivot node,切開 next 指標。
一個一個 traverse 剩下的 nodes,比較它們的值和 pivot 的大小,分成兩堆。較大的那堆應該位在 pivot 的右邊,小的那堆位於 pivot 的左邊。因此,我們可以完成程式碼的填空,AAA
應為(e) &right
,BBB
應為(c) &left
。完整結果如下:
透過 Recursive call 分別對左堆及右堆作排序,最後依照排序好的左堆-> pivot ->排序好的右堆這樣的順序,即可完成對整個 list 的排序。因此,我們可以知道CCC
應該要選(b) list_concat(&result, pivot); list_concat(&result, right)
。完整結果如下:
透過程式名稱不難猜出他的功用應該是把兩個 list 串接起來。我們只要找到 left list 的最後一個 node,把該 node 的 next 指向 right list 的 head 即可。因此這裡LLL
應該要選(c) left = &((*left)->next)
根據 GNU C Library 文件說明,要修正輸出結果相仿的問題,可以透過給定不同的 seed value來達成。最常見的作法,便是使用執行程式當下的時間作為選擇 seed 的依據。
在這份實作中,利用了 recursive 的形式。儘管程式可讀性不錯,但在反覆的 function call 時,效能相對較差,且需要存大量的資料進 stack,資料量大時可能會有 overflow 的可能。因此,這篇文章指出,可以試著改寫成 iterative 的形式。參考該篇文章的範例程式,改寫成下面這樣:
注意,這份程式尚未優化完全,getNode 真的是個爛到爆的寫法