contributed by < ShawnLu31
>
map_add
分配一個節點空間,並將此節點放入 hash table 。
宣告完 h
n
後:
first
指向該 hash table 的欄位的必一個節點,可能是 NULL
,因此用 if 確認節點的的存在。
對節點執行已知的操作後:
由此可得知 n->pprev
須指到 hlist_head, n->next
須指向原本的首位節點 fisrt
。
AAA => n->next = first;
BBB => n->pprev = &h->first;
建立 hash table 。
分配 map_t
大小的空間。
依照參數 bits
分配 hlist_head
空間給 ht
指標。
做初始化,將所有 linked list 開頭指標指向 NULL
。
回傳 hash table 的指標 map
。
在 hash table 中搜尋並回傳一節點 kn
, 且 kn->key
等於 key
。
將 key
經過 hash function 計算後找到對應的 hlist_head
,依序走訪該 linked list 並檢查目標資料 key
是否存在該 linked list 中。若存在則回傳該節點 kn
,若不存在則回傳 NULL
。
呼叫 find_key
取得 bucket,回傳 bucket 中儲存的 data
(索引值)。
若資料不存在於 hash table ,則加入元素資料至 hash table 。
分配節點空間,儲存元素的數值與索引值。
經過 hash function 計算找對對應的 linked list 並加到 linked list 的開頭。
釋放 hash table 的空間。
走訪所有 hash table 的節點,將其從 linked list 移除後釋放其空間。
TODO: why !n->pprev == /* unhashed */ ?
給定一陣列 nums
和一個目標值 target
,回傳 nums
的 2 個元素相加會等於 target
的索引值。
建立 hash table map
。
依序檢查陣列的元素, map_get
會在 hash table 尋找是否有元素與現在的元素相加為 target
。若存在, p
即為另一元素的索引值。若不存在,則用 map_add
將現在檢查的元素儲存至 hash table。
最後清除 hash table ,並回傳 2 個元素的索引值 ret
。
刪除 Singly-linked list 裡所有重複的節點, 串列可能為空或 NULL
。
程式碼被 if
分成三個部分:
head
為 NULL
。處理傳入的串列為 NULL
的情況,可能是原串列為 NULL
或遞迴到串列尾端的終止遞迴條件。
head
不為 NULL
,且 COND1
成立。處理刪除重複節點的部分。
COND1
檢查 head
head->next
兩節點資料重複時,所以 COND1
為 head->val == head->next->val
。但傳入的 head
可能只有一個節點 (head->next
為 NULL
),所以須檢查 head->next != NULL
。所以 COND1
為
再透過 while
迴圈刪除其他重複數值的節點。當 head
下一個節點 head->next
重複時,將 head
直接指到下一個節點 head->next
,跳過重複的節點 head
。且與 COND1
相同,走到最後一個節點時, head->next
會為 NULL
,所以 COND2
為
離開迴圈後,要繼續尋找並刪除下一個重複節點,所以再次呼叫 deleteDuplicates
,且因為 head
也是重複的節點,所以傳入 deleteDuplicates
的參數為 head->next
。
因為重複的節點已被第二部分處理完,所以這裡的 head
不會是重複的節點,只需使用 deleteDuplicates
找到 head->next
要接的節點,在回傳 head
。
使用指標的指標 indir
實作迭代版本。
比較兩個節點,若為重複節點則移除後者,直到重複的節點只剩一個(首個重複節點),並用 is_dup
紀錄此節點是否為剩餘的重複節點。
MMM1
for
迴圈的巨集。safe
版本的巨集。MMM1
為 list_for_each_entry_safe
MMM2
for
迴圈的巨集。safe
保護。MMM2
為 list_for_each_entry
MMM3
MMM2
相同。MMM3
為 list_for_each_entry
MMM4
MMM3
的程式碼中,比對到的節點 (Used) 會使用 list_move
將該節點加入 obj->dhead
的首個節點,因此 obj->dhead
的最後一個節點就是 LRU 的節點。MMM4
為 list_last_entry
題目 | 解答 |
---|---|
MMM1 | list_for_each_entry_safe |
MMM2 | list_for_each_entry |
MMM3 | list_for_each_entry |
MMM4 | list_last_entry |
capacity
, hash table 的容量大小。count
, 已加入的資料數量。dhead
, 快取,紀錄存取過資料的 linked list ,開頭為最近存取的資料,尾端則是 LRU 的資料。hheads
, hash table 。key
, 儲存的資料,用來計算 hash 值,幫助搜尋。value
, 儲存的資料。hlink
, 連接 hash table 的節點。dlink
, 連接 dhead
linked list 的節點。left
和 right
分別往 num
的左右兩側在 hash table 中尋找有連續數值的節點,若找到長度 len
加一, 所以 left
會隨著迴圈減一, right
則會加一。而兩者的初始值都是 num
,在尋找前須先減一(加一),避免重複找到 num
。
LLL
為 --left
。
RRR
為 ++right
。
在 hash table 中尋找數值是否存在。
根據 hash
值到對應的欄位搜尋數值 num
是否存在,若存在則回傳該節點,否則回傳 NULL
。
分成兩部分:
nums
的元素加入 hash table。第一部分
迴圈依序檢查陣列 nums
的元素,因目標為計算連續的數值,重複的數值只須計入一次,所以需檢查該元素是否以存在 hash table ,若存在,跳過該元素,若不存在則將其加入 hash table 。
第二部分
for 迴圈依序在 hash table 尋找陣列 nums
的元素。若找到 num
,表示該數值尚未被計算過,使用 while(node)
迴圈計算連續數值長度 len
。若 find
回傳 NULL
表示該數值已被計算過,則跳過此元素,避免重複計算。
while(node)
迴圈裡,長度 len
加一,刪除 num
的節點,避免重複計算。
接著使用 left
和 right
變數分別向 num
的左右兩側尋找連續的數值是否存在, left
會隨著迴圈逐漸減一, right
逐漸加一。若是找到該數值的節點,使長度 len
加一並刪除該節點。
length
為該陣列最長連續數值長度, len
為單次迴圈計算最長連續數值長度,檢查 len
是否大於 length
,更新 length
。
最後回傳 length
。