contributed by <yulin0625>
list_tail
解釋: 這個函式的功能是找到鏈結串列的最後一個節點,並回傳該鏈結串列的最後一個節點的指標。
圖示說明:
Initial:
Step1:
Step2:
list_length
解釋: 原理與 list_tail
相同,當 left
每間接指到一個節點,計數器 n
就會增加一,函釋回傳值為該鏈結串列的長度。
quick_sort
解釋: 此函式是運用 Optimized QuickSort — C Implementation (Non-Recursive) 所實作非遞迴 (non-recursive; iterative) 的快速排序法程式碼。
排序過程:
圖示說明:
此時的 left, pivot, right:
更新 begin、end 堆疊,並將 i = i + 2
i--
可改進之處:
目前演算法每次都取第一個節點為 pivot ,若遇到已完成排序的鏈結串列時,就會成為 worst case,時間複雜度為O(n²)
解決方法:
Middle-of-Three: 令 middle = (left + right) /2,比較 left、middle 與 right 這三筆資料,排出中間值,再將中間值與 left 做交換
Random Pivot Selection: 用亂數選取的方式,隨機挑一個值作為 pivot,降低發生 Worst Case 的機率
運作原理:
hlist_add_head
: 此函式的功能為將新的節點加入串列的前端。新節點的 next 應指向原本的第一個節點,所以 AAAA
為 h->first
find
此段程式的功能為尋找 num
的位置,會先計算 hash 取得對應的 hlist_head
,接著走訪該鏈結串列。因此 BBBB
為 &head[hash]
, CCCC
為 list_entry
。
dfs
概念: 由前序可知哪個節點在上面 (越前面的越上面)、由中序可知哪個節點靠左(越前面的越左邊),於是可得知前序的第一個元素一定是 root 的值,且該元素對應到中序後,左邊的值就在左邊,右邊的值就在右邊。
解釋: 此函式會先取前序的第一個節點,並利用 find
尋找該節點的值出現在中序的哪個位置,並將左側的節點當成左子樹的 root 、 左側的節點當成右子樹的 root,繼續遞迴再尋找,直到 inorder 中找不到對應元素。
圖示說明:
idx
,此時 idx = 1
idx
之間的間隔,也就是 (idx - in_low)
,因此左子樹的範圍為 pre_low + 1
至 pre_low + (idx - in_low)
idx
到中序最後一個節點的間隔,也就是 in_high - (idx + 1)
,因此右子樹在前序的範圍為 pre_high - (in_high - idx - 1)
至 pre_high
LRU(Least Recently Used Cache) 是一種快取的實做方式,概念是儲存最近用過的內容,如果越常被使用,內容會被擺在 List 越前方的位置。如果快取滿了,則會從 List 最末端元素開始移除。
LRUCache
: LRU
緩存機制的主體結構。包含以下元素:
capacity
: cache 的最大容量count
: cache 當前紀錄的資料筆數dhead
: 儲存 LRU 快取中的節點,並按最近使用的順序排列。hhead[]
: 儲存每個 hash 對應串列的 head 節點LRUNode
: 是緩存中每個項目的結構,包含以下元素:
key
: 鍵值value
: 數值node
: 用於將此 cache 項目連接到 hash
的結構link
: 用於將此 cache 項目連接到雙向鏈結串列的結構lRUCacheGet
: 讀取快取
先將 key
丟入 hash function 進行計算得到對應的 hash 值。接著從快取中尋找 key
。如果 key
存在於快取內則返回該值,並將該節點移動到鏈結串列的頭部 (表示最近使用);如果不存在則返回 -1。
lRUCachePut
: 寫入快取
此函式將給定的鍵-值對(key–value pair)加入快取中,有以下三種情況
key
已存在,則更新對應的值,並將該節點被移動到鏈結串列的前端key
不存在,則判斷快取容量是否已滿
count++
目的: 找出 word 參數中最低位的1所在的位置(從0開始計算)
__ffs
__ffs()
是用來查詢一個 word
中最低位 1 的所在位置, 若 (word & 0xffffffff) == 0 即可知道較低的32位元內沒有任一位元為1, 因此將 word
右移 32 位元再進行檢查。
__clear_bit
此段程式碼是透過 BIT_MASK(nr)
產生出只有第 nr
位為 1 ,其他位皆為 0 的遮罩,並利用 ~ 運算將 mask 反轉成只有 nr
位為 0,最後利用反轉後的遮罩與 addr
做 bitwise and,將該 addr
的第 nr
位清除。
fns
此段程式碼目的為找到第 n 個被設為 1 的位置,它會不斷地呼叫 __ffs
找到最低被設為 1 的位元,若還不是第 n 個就會使用 __clear_bit
將目前的位元清除,再繼續找下一個被設為 1 的位元。
FIND_NTH_BIT
運作原理:
先利用 small_const_nbits
比較要找的位數是否超過限制的 size
, 並利用 GENMASK(h, l)
將 h 到 l 間的位元變為 1和 addr
做 & 運算 ,若 val
有值代表 addr
h 到 l 間有位元被設為1,因此再利用 fns
找到為 第 n 個被設為 1 的位元並回傳其位置。若不符合 small_const_nbits
就利用 FIND_NTH_BIT
來處理。
FIND_NTH_BIT
FIND_NTH_BIT
能夠搜尋超出單個 BITS_PER_LONG
長度的範圍。如果要查找的位元不在目前處理的字節中,能透過迴圈繼續在下一個 BITS_PER_LONG
長度的區塊中搜尋,直到找到該位為止。
因為 size
可能無法被 BITS_PER_LONG
整除,因此搜尋到最後一輪時應避免找到超出 size
範圍的字元,因此使用取餘數的方式找到最後一個字節所需要搜尋的字元數量,故 CCCC
應為 %
。