contributed by <DokiDokiPB
>
使用主機: Macbook Air 2014 A1466 (Ubuntu Linux)
在 queue.c
中,使用 list.h
的 list_head
串接資料,list.h
中具有幾個好用函式與巨集
INIT_LIST_HEAD
list_add
, list_add_tail
head
:list_splice
node
:表示具有元素( element_t
)的節點list
:具有多個節點的佇列開頭,或是head
:表示佇列開頭改進漢語表達。
透過 malloc
配置 head
,依據 list_head
,皆為 head->next
, head->prev
指向 heaed
在 list_for_each_entry_safe
中,利用 *safe
指標保留下個節點的位址,就能將現在操作的節點釋放
將節點加入至 head
, q_insert_head
透過 list_add
加為首個節點;q_insert_tail
透過 list_add_tail
加為末個節點
將指定節點的元素從 head
移除
依據在 queue.h
中函式的說明,bufsize
為 *sp
的陣列長度
bufsize
小於元素中的字串長度(變數 len
),則擷取部分元素字串。bufsize
大於 len
,則整段複製到 *sp
思考如何精簡程式碼,善用前置處理器。
利用 list_for_each
走過整個佇列,取得元素數量
依據 LeetCode 2095. Delete the Middle Node of a Linked List 以及其圖片的說明
在第 15 ~ 17 行中,透過一次移動一個節點的 slow
指標與一次移動兩個節點的 fast
指標,當 fast
回到 head
指標時,slow
指標即在中間節點的位址上。
改進程式碼,使其更精簡的程式碼。
反向 = reverse
需要詞彙精準的定義。
在第 6 行中,先將 doubly-linked list 尾端元素 head->prev->next
指派為 NULL
,使得在 9 行中能夠脫離 while
迴圈,表示到尾端處理完畢
node
變數走過每個節點,並將每個節點反向。cur
表示 node
的前一個節點;在第 18 行中表示反向後的第一個節點,串接至 head
每 k
個節點,將該複數節點加入到 sub_head
中,透過既有的函式 q_reverse
處理;再將處理好的 sub_head
中的節點加回 head
中
看其他同學的實作,傾向直接操作節點。我的實作還是以一個 sub_head
包裝想要操作的節點。
TODO: 撰寫更精簡的程式碼。參照他人的程式碼時,應標註出處。
原本的實作考量 list_cut_postition
的函式參數名稱都為 head_from
, head_to
,可能僅適用完成的佇列而非節點。之後,觀摩 yanjiew 後,我發現可以使用 list_cut_position
去切割 head
的多個節點,再使用 list_splice
接回原本的 head
在作業說明中, q_swap
是一種 q_reverseK(head, 2);
的特例。
避免張貼完整程式碼,你應該闡述自己的想法、考量因素,還有相關的策略。程式碼列表僅為輔助性質。
這裡採用 merge sort,程式碼主體可分為 divide, conquer and merge
head
切為左半邊 left_head
與右半邊 right_head
,在程式碼中,切割的中間的節點為 slow
left_head
與 right_head
分別用 q_sort
函式處理head
中,若其中一方沒有元素,即把另一方整個加入至 head
尾端中在實作的過程中,可以利用 list_cut_position
切割左半與右半佇列
在 LeetCode 2487. Remove Nodes From Linked List 以及圖片的說明中
可以視為由後往前來數的嚴格遞增的佇列。在實作上,也是從後往前的方式移除較小的元素。
less
表示要被刪除的節點,先將欲刪除的節點預先加入至 less
佇列中cur
表示當前最大數值的節點node
表示當前比較的節點,若大於 cur
的字串,則 cur
變為 node
,ret
累計加 1雖然有提供 LeetCode 23. Merge k Sorted Lists,根據函式註解說明,並無特別強調排序。
在沒有排序的佇列中,每次比較一個節點是否有重複,皆必須走過所有節點確認
cur
表示當前的節點node
表示被比較的節點,如果與 cur
的元素相同,則加入到 delete_head
中delete_head
重複的節點刪除。此程式碼移除重複的節點,憑肉眼觀察也是,不過卻有 ERROR: Duplicate strings are in queue or distinct strings are not in queue
,即使使用 q_sort
也會出現。
🤔🤔🤔 問題待排除
如果是兩個佇列合併,則只需要 merge_two_lists
函式,若是多個佇列合併,則需要考量使用 priority queue 紀錄最小值
free
會造成程式進入無窮迴圈避免使用「卡住」這樣不精準的詞彙。
遇到了一個錯誤,步驟如下
./qtest
啟動程式new
兩次,會有兩個不同 ID 的 queuefree
一次會造成程式碼卡住q_free
造成的無限迴圈解決思路:
gdb qtest
重現錯誤Ctrl+C
中斷執行,查看無限迴圈的行數where
查看 call stacks
逐行檢查卡住的部份
qtest.c
的第 851 ~ 853 行p cur
, p currnet->q
, p currnet->q->next
檢查記憶體位址透過比較 do_free
與 do_prev
函式內容,發現多打 &
符號
do_free
函式do_prev
函式因此在 do_free
函式中移除 &
即可
後來發現 github/lab0-c 已經修正該錯誤,因此只要 git
操作即可
git remote add lab0-c https://github.com/sysprog21/lab0-c.git
gir remote update
git merge lab0-c/master
使用指令測試單獨的檔案
valgrind 會回報以下問題:
後來發現 git commit c7d31497c5845bc0af308bf4601e7636c18f0153 修正此問題
command 的翻譯是「命令」,instruction 的翻譯是「指令」
參考其他巨集的實作,新增一個 shuffle
命令
由於在 git 設定中,不能變更 queue.h
與 list.h
,因此實作只能在 q_test.c
進行
台北大學歐士田教授的假設檢定的介紹,閱讀之後對於論文的理解非常有幫助,使用了基本的統計學在驗證
TIMING LEAKAGE DETECTION
使用測試案例 trace-17-complexity.cmd
會獲得 Probably not constant time or wrong implementation
,觀察其測試內容
計算 approximate of df(degree of freedom)公式,參考 Welch (Unpooled Variance) t Tests and Confidence Intervals: Introduction 提及的公式:
參考 RinHizakura 的筆記中的描述,在 fixture.c
的report
函式中
max_t
表示 t value新增以下程式碼:
附註: