contributed by < Tcc0403 >
為佇列建立 list_head
結構體後,透過 INIT_LIST_HEAD
為其初始化
利用 list_for_each_entry_safe
走訪每個 element_t
,呼叫 q_relase_element
函式釋放空間
課程文章中題的到 Head 跟 q_insert_head
的 head 是不一樣的東西,這裡所指的是圖片所標記的 Node 0 ,也就是 head->next
建立 element_t
結構體 new
,利用 strdup
儲存字串內容,接著將 element_t
結構體中包含的 list_head
結構體作為參數傳入list_add
函式,使其加入佇列
目前無法通過 pre-commit 的靜態分析,顯示第 60 行出錯
把 &(new->list)
改成 &new->list
就通過了
與上面操作類似,差別在 list_add
改成 list_add_tail
利用 list_del_init
將第一項 element_t
結構體移出佇列
使用 list_del_init
而非 list_del
的原因,是擔心未來對回傳的 element_t
結構體做額外操作,導致錯誤發生
時間複雜度測試沒過,待研究
發現 eric88525 筆記 有類似情況,自己上傳後在 GitHub Actions 中也有通過
跟上方作法類似
同上
利用 list_for_each
走訪每個節點
原本以為 list_for_each
會走到 head
本身,但仔細看才發現是從 head->next
開始
利用環狀雙向鏈結串列的特性,透過兩個指標反向走訪串列,一個向前、一個向後,當兩個指標相遇或相鄰時, 向前走的指標所指向的節點即是中間節點
之後排序會使用到中間節點,因此將取得中間節點寫成函式 q_get_mid
改寫 q_delete_mid
透過 list_for_each_entry_safe
來走訪佇列並刪除與相鄰節點有相同值的節點
會發生 Segmentation fault
問題發生在 list_for_each_entry_safe
巨集的 safe
會走回串列的 head
節點,由於該節點並非 element_t
結構體,試圖讀取不存在的成員便會出錯
修正如下,在比對字串前先確認是 safe
是否為串列的 head
近期的 commit de856da 修正 q_delete_dup
函式的定義,上述程式碼需要進行修改
修正如下
多宣告一個 bool
變數來幫忙紀錄是否重複
q_swap
直接重新指派兩兩一組節點相連的六個指標
閱讀 lanser 同學的作法後,發現可以將 q_swap
視作將奇數節點移除後插入偶數節點之後
List API 中的list_move
函式正好是 list_delete
和 list_add
的連續操作
將以上程式改寫為更精簡易讀的版本
利用 list_for_each_safe
走訪串列交換 next
和 prev
,因為不會走到佇列的 head
,所以要額外處理
原本打算參考 Merge Sort 與它的變化 ,但跟本次實驗的資料結構略為不同,這次實驗是採用Intrusive linked lists
一開始想另外宣告 list_head
結構體並存放在 list_head *
陣列當中,以便進行上述筆記的分割方法,但寫完發現本次實驗不允許在 q_sort
當中進行 malloc
和 free
等操作
參考幾位同學的筆記後,決定利用 LIST_HEAD
巨集宣告區域變數接收分割出來的串列,維持雙向環狀的結構,以便透過 List API 操作串列
在 mergeTwoLists
函式中,因為兩個引數 L1
, L2
都是用來管理串列的 Head ,可以利用此特性,將兩條串列合併至其中一個 Head 之下
list_move_tail(node, head)
函式等價於把 node
節點移出原本其所在的串列,再將其插入 head
節點之前
嘗試撰寫一個 Linux 風格的 List API
依照 Fisher-Yates shuffle 演算法實作
因為每次迭代都會縮小選取範圍,直接將選到的節點移至串列最尾端即可
在 qtest.c
中參考 do_sort
函式,實作 do_shuffle
函式
console_init
函式中新增 Shuffle 的相關命令
透過 qtest
進行測試
git commit 的時候發現不能更動 queue.h
和 list.h
,將所有程式移至 qtest.c