整段程式碼是用來測試 list_insert_before()
及 list_size()
函式的正確性
list_insert_before()
是否正確插入節點list_size()
是否回傳正確的 list 長度根據函式的語意,list_insert_before
是將新的 item 插入 list 中某個特定的 item 之前,並且當 before
參數指向整個 list 的 head,則會將新的 item 插入在最前面,如果指向 NULL,則插入到 list 的最後面
Macro
my_assert(test, message)
: 測試條件是否為 true,否則回傳錯誤訊息my_run_test(test)
: 執行測試函式 test(),如果有錯誤則回傳訊息全域變數
list_item_t
節點。Function
list_insert_before()
及 list_size()
函式的正確性test_list()
由於 list_insert_before
是將新的 item 插入到 before 之前,搭配指標的指標 p
,函式內容應為:
依據註解,要找到左子樹中的最右節點,因此 EEEE
及 FFFF
應為:
remove_free_tree
負責從二元搜尋樹 (BST) 中刪除節點 target,其中 root 是樹的根節點指標,而 target 是要刪除的記憶體區塊
首先找到目標節點
由於題目解說中提到 「指標 p 會一直往右走,將大於 pivot 的節點存入 right , 小於的存入 left ,接著可得到三組分割 left pivot right,其對應的分割編號分別為 i i+1 i+2 」,begin
與 end
的用意是在保存 left pivot right 的邊界資訊
根據以上所以 CCCC 應為 p->next
,DDDD 應為 list_tail(left)
,EEEE 應為 list_tail(right)
由於先前的排序破壞了雙向鏈結串列的結構,rebuild_list_link
的作用是重建雙向鏈結串列的鏈接關係,使其變為一個頭尾相連的環狀雙向鏈結串列
因此,GGGG 應為 head->prev = prev
程式碼中第 11 行針對 n_value
與 value
進行比大小,所以 HHHH 及 IIII 應為
而 begin
與改寫之前相同,主要是用於紀錄 left pivot 及 right 的邊界資訊,所以 JJJJ = pivot 跟 KKKK = right 。
結構體 listitem
中包含一個 uint16_t
的變數 i
,及一個 list_head
,其中 list_head
又包含兩個指標,分別是 prev
與 next
,整體結構應如下圖
cmpint
用於比較傳入參數的大小
ARRAY_SIZE(x)
:計算陣列中有幾個元素
getnum
:利用三個靜態變數,個別進行乘積與模除,接著透過 xor 運算得到一個 8 位元的隨機數
get_unsigned16
:將兩個 8 位元的數值組合成一個 16 位元的數值
random_shuffle_array
:對於傳入的陣列進行洗牌
main
首先是隨機填入數值到陣列 values 中,對 testlist 進行初始化,並且檢查 testlist 是否是空的,接著透過 list_add_tail() 將元素逐一加入 testlist 的尾端
再來是對 values 及 testlist 中的元素進行排序,檢查排序結果,並釋放記憶體
最後檢查串列是否已清空
依據 quiz1-3,quick sort 的流程會將整個串列拆成三組,分別是 left pivot right,首先會將 pivot 從串列中移除,接著將串列中的元素逐一與 pivot
進行比對,如果串列中的元素小於 pivot
,則移動到 list_less
,反之則移動到 list_greater
,因此我們可以推測:
根據題意「每次呼叫 clz2() 函式時,代表將目前關注的位元(bits)「切成一半」,以檢查 leading zero 的數量」,再加上 mask 陣列中的元素是有規律的,從一開始(c = 0)的 0 ,接著(c = 1)是 8 ,再來(c = 2)是 12,此可以推得 因此 GGGG 應為 14
若 c 與 x 皆為 0 ,則直接回傳 0
使用兩個變數 upper 和 lower 把 x 切成兩半
c == JJJJ
為終止條件,依據題意 step3 「遞迴呼叫 clz2() 函式,直到僅剩 2 位元(bits)需要檢查 leading zero,然後回傳結果」,當 16 >> c == 2
,c
會等於 3,因此 JJJJ 應為 3