contributed by < visitorckw
>
Current score: 83/100
一開始的實作如下:
後來想到可以寫得更精簡,當 malloc 配置記憶體成功後,才使用 INIT_LIST_HEAD
巨集。
使用 list_for_each_entry_safe
巨集逐一釋放每個單元占用的空間。
使用 malloc 函式去配置記憶體,若失敗就先用 free 函式釋放記憶體後 return false ,否則利用 list_add macro 來將新的節點加入到 list 之中。
原先採用 strcpy 函式進行字串的複製,但在 git commit 時會遇到以下錯誤:
因此定義了 strlcpy 巨集,在複製時需指定長度,透過改成 sprintf 函式來實作:
最後完整的 q_insert_head 函式如下:
邏輯與 q_insert_head 函式相同。唯一的不同之處是原先使用 list_add 巨集來完成,這裡是要從尾端加入新節點,因此要改用 list_add_tail 巨集。
先用 list_entry macro 抓出將要 remove 的節點,將節點的 value 字串的內容複製給 sp 之後,再用 list_del macro 刪除。
後來發現須要先檢查 sp 的值是否是 NULL,若是 NULL則不應該將字串複製給它。
跟 q_remove_head 的邏輯相同,差在要抓的節點是 head->prev。
和 q_remove_head 一樣,後來加入了 sp 是否為 NULL 的檢查機制。
使用 list_for_each 巨集走訪整個 list 計算節點的數量。
慢指標一次移動一格,快指標一次移動兩格。
因此當快指標走完整個 list 時,慢指標的位置會剛好只走了快指標的一半。
使用 list_for_each 巨集走訪整個鏈結串列。
額外用一個字串 str 來記錄當前節點的 value 字串內容。
並且再另外用一個 while 迴圈來找字串內容相同的元素,並使用 list_del 巨集對節點做 remove 。
目前猜測是由於刪除時有發生 memory leak 的情形,需用 valgrind 等工具檢查錯誤產生的原因。
迴圈每次將指標移動兩格,將自身與下一個節點的 value 交換。
交換採用三次 bitwise xor 的技巧。
撰寫更精簡的程式碼。
:notes: jserv
修正後的程式碼如下,使用 flag 變數來記錄是否跟前一個節點交換 value 。
將所有節點的 next 和 prev 的值交換 ( 須包含 head )。
交換採用 3 次 bitwise xor 的技巧。
將每 k 個拆成一段獨立出來的 list 。
呼叫前面所實作好的 q_reverse 函式之後,再拼接回原本的鏈結串列中。
由於實作 q_sort 以及 q_merge 兩個函式時都需要用到合併已排序連結串列的操作。因此額外實作本函式以利後續開發與維護。
合併兩個已經由小到大排序好的 list 合併。
採用 indirect pointer 技巧使程式碼更簡潔易讀。
先利用和前面實作 q_delete_mid 所用到的快慢指針技巧找到將 list 拆分成兩半的位置。然後加入 dummy node 形成兩個獨立的 list。分別 sort 兩個list 之後,再將兩個排序好的 list 利用前面實作的 mergeTwoLists 函式合併。
類似於 monotonic stack 的概念,反向迭代整個 list ,並同時記錄當前所遇到最大的 value 。若當前的 value 比過去最大的 value 還要小則利用 list_del 函式來進行 remove 的動作。
採用頭尾兩兩合併的方式,不斷重複直到剩下一個 list 為止。
執行 make valgrind
過後,發現多數結果都如下:
代表檢測到程式結束時,仍然有著還沒被釋放的記憶體,但有指標依然指向它。可能是由於 globla 變數所導致的現象。
首先在 qtest.c 裡面增加 shuffle 命令:
然後參考其他 do_
開頭的函式實作 do_shuffle
另外由於 commit hook 不允許更動 queue.h 之中的程式碼,因此另外用一個標頭檔 shuffle.h 並在裡面增加 q_shuffle 函式的宣告
並在 qtest.c 之中引入此標頭檔。
lib/list_sort.c
由於 list_sort.c 程式碼中所引入的標頭檔都是 linux 核心之中的標頭檔,因此需要自己做對應的修改才能順利的執行。
改進漢語描述,注意作業書寫規範。
:notes: jserv
本論文介紹了 dutect 工具,用於評估代碼在特定平台上是否以恆定時間運行,並且不需要對硬體有特別的要求。
方法步驟
percentile 處理
percentile 是論文中步驟二所提及的 cropping 處理,目的是為了去除極值。