contributed by <Shiang1212
>
1
結構體與函式介紹:
void list_add(node_t **list, node_t *node_t)
node_t
加入至 list
的前端。node_t *list_tail(node_t \*\*left)
int list_length(node_t \*\*left)
node_t *list_construct(node_t *list, int n)
value
為 n
的節點,並將其 next
指向 list
。void list_free(node_t \*\*list)
list
內沒有結點。void shuffle(int *array, size_t n)
array
裡的值,完成亂序。其中,shuffle
的程式碼如下:
第 6、7 行可見,宣告一個 size_t i
走訪每個元素,並用第 i
個元素跟第 i ~ n
個元素交換,完成亂序操作。
介紹完基本操作,接下來介紹 main
函式在做什麼:
建立一個陣列 test_arr
,大小為 100000,內容為 0, 1, 2, …, 100000, shuffle
對其進行亂序操作後,用 list_construct
建立一個亂序內容的鏈結串列,最後使用 quick_sort
,對該鏈結串列進行排序。
此處為用於排序鏈結串列的非遞迴 (non-recursive; iterative) 快速排序法 (QuickSort),以下為程式碼:
list
的首尾節點分別指派給 begin[0]
和 end[0]
。(此圖修改自 vestata)
(此圖修改於 YangYeh-PD)
left
,大於 pivot 的節點存進 right
。begin[i]
存放 left
,begin[i + 1]
存放 pivot,begin[i + 2]
存放 right
。end[i]
~ end[i + 2]
存放 begin[i]
~ begin[i + 2]
的末端節點。begin[i + 2]
開始,也就是 begin[]
最末端的串列,繼續找 pivot 切割成 left
和 right
。begin[i]
== end[i]
時,代表串列已經無法再切割,就可以把該節點加入 result
,當作排序完成的節點。問題
2
待完成
1
用 preoreder 和 inorder 的排序,要求回傳重建的二元樹。
使用雙向鏈結串列處理 Hash Table 發生碰撞 (collision) 的情況。
next
指向相鄰的節點本身,而 pprev
指向指著自身節點的指標。
hlist_add_head
這個函式執行 hash table 中,將 n
插入雙向鏈結串列。將 hlist_node n
插入於 hlist_head h
的前端。
find
用傳入的 num
值尋找 hash table 中的位置索引。宣告 hash
得知該節點放於 hash table 中的哪個槽,用 hlist_for_each
走訪每個節點,尋找節點並回傳索引。
待完成
node_add
這裡執行的是建立一個 node 並將其存放至 hash table。建立一個新節點,宣告 hash
決定該節點要存放於 hash table 的哪個槽裡,最後使用 hlist_add_head
將該節點加入 hash table
2
待完成
3
實作 find_nth_bit
可在指定的記憶體空間找出第 N 個設定的位元。
__ffs
find first bit set in a word
依循 binary search 的概念,用 mask 做 bit-wise and 找出首個 bit 為 1 的位置 (由右至左),有了這個函式就可以往下繼續做 fns。
fns
find N'th bit set in a word
使用 __fns
從 LSB 找出首個 bit 為 1 的位置,並判斷是否為該 word 中第 n
個 1 (由右至左),若不是的話就把該 bit 清除掉,用 __fns
繼續找下一個 bit 為 1 的位置。
__clear_bit
clear certain bit
功能:將 addr
的第 nr
個 bit 改成 0。
其中的 BIT_MASK(nr)
和 BIT_WORD(nr)
巨集程式碼如下:
1UL
代表無號長整數 1,也就是
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001
1UL << ((nr) % BITS_PER_LONG)
將 1UL
向左位移 (nr) % BITS_PER_LONG
個 bit。
例如:BIT_MASK(5)
的結果
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 0000
計算 word 的 offset。
不知道第 4 行為什麼要加 BIT_WORD(nr)
,如果想要清除大於 64 的 bit,那不就代表要清除到該 word 以外的 bit 嗎?為什麼要允許這樣的行為?
small_const_nbits(size)
判定 size
是否為正常的常數且長度大於 0、小於 BIT_PER_LONG (64)。
GENMASK(h, l)
產生一個第 l+1
到 h+1
個 bit 皆為 1,其餘為 0 的遮罩。
用一個例子快速了解 GENMASK
在幹嘛:
FIND_NTH_BIT(FETCH, size, num)
用來在指定的 bitmap 中,找尋第 n 個 set bit的 index。
find_nth_bit
find N'th set bit in a memory region
輸入參數:
接下來讓我們逐行檢視:
第 3~4 行:若欲查找的設定位元數超出最大搜尋範圍,則判定為尋找失敗,回傳 size
。
第 8~15 行:透過 small_const_nbits(size)
檢查 size
是否為正常的常數且長度大於 0、小於 BIT_PER_LONG (64)。
GENMASK()
設定一個遮罩,找出要處理的範圍。然後將遮罩後的值傳進 fns()
來找第 n 個被設置的位元的索引位置。FIND_NTH_BIT()
,來處理跨字節邊界的情況。待完成