contributed by < 164253
>
96121503
node
及 val
是否為空和有檢查的情況,可以補上兩種情況計算速度的比較結果。後來發現不檢查會造成錯誤的記憶體釋放,因此不用測試這種錯誤作法
無論標題和內文中,中文和英文字元之間要有空白字元 (對排版和文字搜尋有利)
空間滿了所以沒裝雙系統 所以我是 windows10 的 WSL2
目前本機 100 分, git push
後僅有 95 分,無法通過第 17 筆的常數複雜度測試
配置一個 list_head
,如果沒有空間要繼續嘗試直到成功
接著用 INIT_LIST_HEAD
初始化並回傳 list_head
用 list_for_each_entry_safe
走訪所有節點,由於要刪除遇到的節點,所以用 safe
版
將途經節點的字串及節點本身釋放掉 最後釋放 head
配置一個 element_t
並用 strdup
處理字串配置
原本跳過 node
和 val
記憶體配置失敗的情況,但會造成錯誤的釋放記憶體
若 node, val, head
中記憶體有問題,釋放掉已經配置的記憶體
此處沒有檢查
node, val
是否為 NULL ,雖然不影響函式結果,但之後需要實驗補上速度差異不檢查會造成錯誤的記憶體釋放,因此無須討論這種狀況
否則將 val
字串給 node
,並用 list_add
將 node
插入至 head
改進你的漢語表達
原本我複製 q_insert_head
的內容並改掉 list_add
,但有許多重複程式碼
因此改為呼叫 q_insert_head(head->prev, s)
達成插入在最後一項的功能
若 list
指向 NULL 或者是空的,終止並回傳 NULL
否則用 list_first_entry
找到第一個元素,並用 list_del
移除他
將他的 value
存至 sp
和 q_insert_tail
一樣 可以簡單的用 q_remove_head
完成
但由於 q_remove_head
是刪除 head
的下一個元素 應該傳入 head->prev->prev
才對
特別處理 head
指向 NULL 的情況
其餘用 list_for_each
走訪過所有節點,並記錄共有幾個元素即可
原本是用快慢指標的技巧找到中間那項並刪除
針對環狀且雙向的佇列,是否有更快的方法?
考慮雙向環狀的條件可以發現,用兩個指標從頭和尾向對方移動,
只需要存取 個節點就好,不需要快慢指標的 個
由於 q_sort
採用 merge sort ,也需要尋找中間那項,獨立成函式 q_find_mid
走訪除了第一個以外的節點
檢查上一個節點和現在的是否相同,重複就刪掉上一個,並記錄這個節點也是重複的
若上一個和現在不同但被記錄,也要將上一個刪除
由於和 q_ascend
與 q_descend
有許多重疊,使用另一個子函式一併實現
先將最後一項的 next
設為 NULL ,每遇到兩個節點就把他們的連結互換
由於 head
被留下來最後接回去,至少有一個 next
指針可以拿來更改
每修改一個指針,就會多出一個指向重複節點的指針,因此自由度始終是一,可以執行到底
最初實作時沒有注意到 head
和他後面那項會被交換,要存下來的是 head->next
後來直接用 q_reverse(head, 2)
取代
走訪所有節點並交換 prev, next
用 do while
一直執行到遇到 head
可以重用 q_reverse
來實作,需要注意必須傳入環狀佇列,要將第 K 個跟第一個連起來
TODO: 改進程式碼的重用程度。
要求回傳一個非嚴格遞增或遞減的佇列,一種想法是用 monostack,但均攤需要
可以反過來做,如果下一個節點會破壞性質,就把他刪掉
為了重用程式碼 q_descend
可以選擇反轉後用 q_ascend
再反轉,並改成刪除左邊的節點
但需要
由於和 qdelete_dup
有許多重疊,使用另一個子函式一併實現,改進原本重用率低的問題
考量到要在 q_sort
中重用,我將 q_merge_two
獨立出來,整個 list 每兩項合併一次
若還有兩項以上重複進行,且會一直合併至只剩一個 list
但因為需要保留 queue_contex_t
的結構,結束函式後程式會自己回收
所以實際上不能把相鄰項直接移除,採用清空被合併的 list ,每次要合併時尋找非空的 list
許多同學實作上把所有 list 合併到第一個,假設總共 個節點 個 list
第一個 list 中有 個節點,總共會需要 次合併
比較則要
走訪 個節點
比較次數最多發生在 ,但 最多只能到
所以實際上最多比較次數會是
而我的作法要 次合併,走訪 個節點,比較 ,證明見 2024-3-19 課程簡記
走訪節點的成本是固定的,但比較取決於資料型別,若是字串成本會很高
採用 merge sort ,將整個 list 切割開,並呼叫 q_merge_two
當作 n 個長度一的 list 合併
現在用 q_delete_mid
中尋找中點的做法,亦可用 q_reverseK
, K 設為 q_size()+1>>1