contributed by < jerry7961
>
jychen0611
what? why? how?
描述每次更改的內容直接列出 git commits 的超連結並討論,不要只談「心法」,跟同學說你認為要改成什麼,細節!
不用說「建議」,什麼沒做好,就去改什麼。假裝有禮貌無助於工程品質的提升。
:notes: jserv
jimmy01240397
q_insert_head
q_insert_tail
q_remove_head
q_remove_tail
提供說明用的程式碼,不要只談「心法」。
:notes: jserv
jujuegg
strcpy
。q_new
q_free
先檢查佇列是否為空,若為空則 return
。
用 list_for_each_entry_safe
巨集走訪所有節點,並釋放節點。
最後釋放開頭節點。
q_insert_head
一開始誤用 strcpy
(如下) 。
strcpy(s1,s2)
的功能是複製字串 s2
到字串 s1
,不會為 s1
分配内存, s1
的長度必須大於 s2
的長度。
因此在沒有為 new_element->value
分配內存的情況下直接用 strcpy(new_element->value,s)
會造成錯誤。
事先為 new_element->value
分配內存再用 strcpy
複製字串即可修正錯誤。
另一種做法是使用 strdup
來代替 strcpy
,strdup
會為字串分配內存空間,並返回新分配空間的指標。
HackMD 不是讓你張貼完整程式碼的地方,GitHub 才是!因此你在開發紀錄只該列出關鍵程式碼 (善用 diff 標示),可附上對應 GitHub commit 的超連結,列出程式碼是為了「檢討」和「便於他人參與討論」,不是用來「假裝自己有付出」
q_insert_tail
與 q_insert_head
的做法類似,差別是改用 list_add_tail
。
q_remove_head
對照 Dictionary.com 對 implement 一詞的解釋:
「實作」會是符合上述 "implement" 語意的譯詞,取「起」以「創作」的意思,而「製造」本質上是固定輸入並通常產生固定輸出的行為。
q_remove_head
的作用是從鏈結串列的開頭移除一個元素。
首先檢查 head
是否為空指標,以及鏈結串列中是否至少有一個節點,確保鏈結串列存在且不為空。接著用 list_first_entry
取得鏈結串列第一個元素的指標,並透過 list_del
將這個元素從鏈結串列中移除。
如果 sp
不為 NULL
,使用 strncpy
函式將被移除元素的字串 (to_delete->value)
複製到 sp
指向的位址中。複製的字元數量最多為 bufsize - 1
,這是為了在字串結尾預留一個位置,用來存放 \0
。
q_remove_tail
與 q_remove_head
類似,差別在使用 list_last_entry
來取得要移除的元素。
q_size
使用 list_for_each
來走訪所有節點,每走訪一個節點 count
值就加一。
說好的進度呢?
q_delete_mid
使用快慢指標,快指標每次前進兩步,慢指標每次前進一步。
head
,此時慢指標將指向中間兩個節點中的第二個。為了使 q_delete_mid
能夠刪除中間兩個節點中的第一個,需要增加一個 if
語句來調整慢指標的位置。改進你的漢語表達。
使用作業規範的程式碼縮排風格
q_delete_dup
q_delete_dup
是要在鏈結串列已經排序好的狀況下,移走其中具有重複內容的節點。
list_for_each_safe
來走訪鏈結串列中的每個節點。mark_del
用來標記是否遇到重複節點。mark_del
來判斷當前節點是否與前一個節點重複,如果重複則刪除它。mark_del
設為 true
,表示已遇到重複節點。mark_del
為 true
,這表示當前節點與上一個節點內容相同,因此刪除當前節點,並將 mark_del
設為 false
。q_swap
q_swap
的作用是交換鏈結串列中鄰近的節點。
q_swap
從頭部節點的下一個節點開始走訪鏈結串列。對於每對相鄰節點,q_swap
會先將它們從鏈結串列中移除,然後以交換後的順序將它們重新插入到鏈結串列中。這個過程會一直重複,直到走訪完鏈結串列的所有節點。q_reverse
從頭部節點開始走訪鏈結串列,交換每個節點的 next
和 prev
指標以反轉鏈結串列方向,直到走訪完整個鏈結串列。
q_sort
一開始使用 Insertion Sort ,無法通過測資,後來參考同學寫法,改用 Merge Sort 。
q_merge
使用 list_for_each_entry_safe
走訪整個鏈結串列。從第二個鏈結串列開始,透過 list_splice_init
將每個鏈結串列中的節點合併到第一個鏈結串列中。完成合併後,利用 q_sort
對合併後的鏈結串列進行排序。
在 trace-03-ops 出現以上錯誤,經過排查,問題出在 q_merge
函式。原始版本的 q_merge
創建了一個新的 first_queue
指標,它用來指向第一個遇到的非空鏈結串列,這個鏈結串列將作為所有鏈結串列合併的目標,所有其他鏈結串列的元素都會被合併到這個 first_queue
中,其他鏈結串列在合併到 first_queue
後 q
指標會被設為 NULL
,但相關內存沒有被釋放,導致錯誤。修改 q_merge
函式後, trace-03-ops 可順利通過。
trace-eg.cmd
進行分析