contributed by < youjiaw >
1
鏈結串列結構體如下:
*list_tail
left
指向下一個節點,最後回傳鏈結串列的最後一個節點,因此 AAAA
為 (*left)->next
。list_length
BBBB
同為(*left)->next
。quick_sort
pivot
的節點加到 right
,小於等於 pivot
的節點加到 left
,因此 CCCC
為 p->next
。left
, pivot
及 right
的範圍資訊存放在 begin
及 end
。DDDD
為 list_tail(&left)
,EEEE
為 list_tail(&right)
。其中,非遞迴的快速排序法是用堆疊模擬遞迴呼叫。
L
與 R
分別為鏈結串列的開頭與結尾, pivot
為開頭節點,用來走訪節點的 p
則是 pivot->next
。value
設為 pivot
的值,並把 pivot->next
指向 NULL。n
指向 p
並逐一走訪節點。
n->value
> value
:將此節點新增至 right
。n->value
<= value
:將此節點新增至 left
。left
, pivot
及 right
的範圍記錄在 begin
與 end
。right
,直到剩下一個節點,並將其加到 result
的開頭,再向左邊進行排序,因此 result
中的節點最後會是由小排到大。我的想法為:
begin
與 end
是否真的需要兩倍的空間?決定 begin
與 end
的空間
經過測試,在有 shuffle 的狀況下,list 的長度每增加十倍,begin
與 end
的最大深度只增加不到一倍。
但是若有 worst case 出現,就會需要 2 * n - 1 的空間,以下為 n = 10 時的 worst case,此時 begin
與 end
的最大深度為 19。
檢查 malloc 是否成功
參照 tools/perf/util/intlist.c 的程式碼,加入 malloc 的檢查。
查閱 Linux 核心程式碼時,發現 scripts/kconfig/lxdialog/checklist.c 並沒有在 malloc 後進行檢查,這是為什麼?
使用雙向鏈結串列
雙向鏈結串列可以改善以下的函式:
*list_tail(node_t **left)
的時間複雜度由 O(N) 變為 O(1)。quick_sort(node_t **list)
的 end
可以移除。TODO: 改為雙向鏈結串列
於 commit 0286652 改寫。
2
*merge
merge
會把兩個已排序的鏈結串列,合併成一個新的已排序鏈結串列,用 *head
與 **tail
紀錄。
**tail
初始化為 &head
。a
與 b
的第一個節點,將比較小的節點加到新的鏈結串列尾部,因此 BBBB
為 &a->next
,CCCC
則為 &b->next
。build_prev_link
在走訪所有節點的同時建立 prev
,走訪到尾部就會跳出迴圈,因此最後要將頭尾相連。
timsort
Timsort 最後會確認是否有剩下的節點,如果有就會做 merge_final
,因此 FFFF
為1。
1
hlist_add_head
把節點加入到開頭位置,要將新節點的指標指向"原本的開頭節點"和"指向原本開頭節點的指標"。
node_add
依照節點的值,對 size
取餘數得到相對應的 hash 值,並呼叫 hlist_add_head
將該節點加到該雜湊表中,即 &heads[hash]
。
find
find
的目的是找出節點在中序的位置,因此取得 hash
值後,會用迴圈找尋對應的雜湊表 &heads[hash]
是否有符合該節點值的 order_node
,並返回該節點的 index。
first
為 NULL。order_node
結構中。hash
值後,更改節點與對應雜湊表的指標,將節點加在雜湊表的開頭。dfs
建構二元數。
find
找出該節點在中序的 idx
。2
hlist_del
刪除傳入的節點 n
。
lRUCacheFree
此函式會走訪所有節點並將其刪除,由於 pos
是 list_head
結構, list_entry
的 member
應傳入 link
。
lRUCacheFree
3