contributed by < ShawnLu31
>
q_new
: 建立新的「空」佇列q_free
: 釋放佇列所佔用的記憶體q_insert_head
: 在 head 插入 (insert) 給定的新節點 (LIFO)q_insert_tail
: 在 tail 插入 (insert) 給定的新節點 (FIFO)q_remove_head
: 從 head 移去 (remove) 節點,回傳該節點q_remove_tail
: 從 tail 移去 (remove) 節點,回傳該節點q_release_element
: 釋放特定節點的記憶體空間q_size
: 計算目前佇列的節點總量q_delete_mid
: 移走佇列中間的節點q_delete_dup
: 在已經排序的狀況,移走佇列中具備重複內容的節點q_swap
: 交換佇列中鄰近的節點q_reverse
: 以反向順序重新排列鏈結串列,不配置或釋放任何節點(重排已經存在的節點)q_sort
: 以遞增順序來排序鏈結串列的節點INIT_LIST_HEAD()
- Initialize empty list headlist_add()
- Add a list node to the beginning of the listlist_add_tail()
- Add a list node to the end of the listlist_splice()
- Add list nodes from a list to beginning of another listlist_splice_tail()
- Add list nodes from a list to end of another listlist_splice_init()
- Move list nodes from a list to beginning of another listlist_splice_tail_init()
- Move list nodes from a list to end of another listlist_del()
- Remove a list node from the listlist_del_init()
- Remove a list node from the list and reinitialize itlist_empty()
- Check if list head has no nodes attachedlist_is_singular()
- Check if list head has exactly one node attachedlist_cut_position()
- Move beginning of a list to another listlist_move()
- Move a list node to the beginning of the listlist_move_tail()
- Move a list node to the end of the listlist_first_entry()
- get first entry of the listlist_last_entry()
- get last entry of the listlist_for_each
- iterate over list nodeslist_for_each_entry
- iterate over list entriesq_new
用 malloc
取得 struct list_head
大小的記憶體。
NULL
。INIT_LIST_HEAD()
做初始化。注意共筆書寫規範:中英文間用一個半形空白區隔
q_free
此函式須釋放佇列所有空間,所以須釋放 element
和 l
。
用 list_for_each_entry_safe()
走訪節點。
用 list_del()
移出佇列, q_release_element()
釋放節點空間。
釋放佇列 l
。
q_insert_head
若佇列是NULL
立刻回傳 false 。
用 malloc
取得 element_t
大小的記憶體。失敗回傳 false 。
用 malloc
取得 s 字串大小的記憶體。失敗釋放 e 的空間並回傳 false 。
用 memcpy
複製字串和 INIT_LIST_HEAD()
初始化新節點,再用 list_add
加入佇列最前端。
用 gen_element
取代與 q_insert_tail
相同的程式。
q_insert_tail
大致與 q_insert_head()
相同。用 list_add_tail()
加入佇列尾端。
gen_element
q_remove_head
若佇列為 NULL
或空,回傳 NULL
。
list_first_entry()
取得第一個節點位置, list_del_init()
移除該節點。
若 sp
不為 NULL
,複製節點的 value
到 sp
。
回傳該節點。
q_remove_tail
用 q_remove_head()
實作,傳入 head->prev->prev
,其取得的節點便是 head->prev
。
q_size
一開始檢查佇列是否為 NULL
或空。
使用 list_for_each()
走訪佇列,計算節點數量,並回傳。
q_delete_mid
根據你所不知道的 C 語言: linked list 和非連續記憶體中的範例實作
一開始檢查佇列是否為 NULL
或空。
使用快慢指標找到中間的節點。
indir
指標一個迴圈走到下個節點(一個節點), fast
指標一個迴圈走到下下個節點(兩個節點)。fast = head
(q_size is even) 或 fast->next = head
(q_size is odd) 時,fast 已走 n 個節點, *indir
指向第 節點,即為中間的節點 (0-based indexing)。
fast
停在 5th 節點,*indir
指向 3th 節點 。fast
停在 3th 節點,*indir
指向 2th 節點 。list_del()
移除要刪除的節點,用 list_entry()
找到節點位置,再釋放空間。q_delete_dup
若佇列為 NULL
回傳 false
。
用 list_for_each_entry_safe()
,因為它允許在走訪佇列時刪除節點。
str
與 node->value
字串相同。移除 node
並釋放空間。否則將 node->vale
複製給 str
,成為下一個要比較的字串。
str
時,同時至少有兩個節點,前一個是更新 str
時走訪,目前的節點是發現重複字串且將被刪除的節點,後續重複節點也被走訪後刪除。str
和 next->value
,若是不同,表示重複的 n-1 個節點已被刪除完畢,此時 next
的前一個節點就是重複的第一個節點(兩節點之前的其他節點都被移除),用 list_entry()
取得該節點 first_dup
,移除並釋放空間。str
存目前比要對的字串。node
目前的節點,可被 delete 。next
, node
的下一個節點。first_dup
, n 個有相同字串的節點中的第一個節點。改進:
將 str
指標指向目前比對的節點的 value
,取代原本的 malloc
和 memcpy
,減省記憶體空間。初始化則改為指向 \0
。
q_swap
若佇列為 NULL
、空,或只有一個節點,則回傳,不須 swap 。
根據 list_for_each_safe
迴圈,加上 safe != head
的條件,用來在節點為奇數時,剩下最後一個時停止迴圈。
交換節點位置:
safe
後移一個節點,原本 safe
的位置為 node->next
, 交換 node
和 node->next
兩節點。node->prev
和 node->next
。node
和 node->next
。node
和 safe
。q_reverse
確認佇列是否為 NULL
或空。
用 list_for_each_safe
走訪節點,交換 node
的兩個指標 node->prev
node-。next
指向的位址。因為 list_for_each_safe
是從第一個節點開始,迴圈結束後交換 head
的兩個指標 prev
next
指向的位址(此時 node == head
)。
q_sort
若佇列為 NULL
、空或只有一個節點,則不做排序。
根據 Quick sort 實作排序,將傳入的第一個節點 head
當作比較的基準值,數值小的節點移動到 head
前,數值相同或大於則維持原位。再用遞迴繼續排序 head
的左右子佇列。
用 prev
和 next
兩個指標的指標操作。
tail->next == head
表示上一層遞迴後左子佇列或右佇列為空。head == tail
表示上一層遞迴後左子佇列或右佇列只有移的節點。prev
next
都指向 head
。*next->next
value
小於 head
value
,移到 *prev
節點的前面,然後 prev
指標指向該節點。*next->next
value
大於等於 head
value
), next
指向下一個節點。*next == tail
(*prev == tail
) 表示此子佇列已比較完所有節點且最後一個節點大於等於(小於)head
。prev
和 next
再比較後都會指向比較後的節點,因此分別作為左子佇列的 head
和右子佇列 tail
。