contributed by <pine0113
>
宣告 begin[]
與 end[]
作為堆疊,其中 max_level 設定為 2n
將 list 的開頭放置在 begin[0] ,結尾放置在 end[0]
是第一個需要被完整處理的資料紀錄
這個迴圈是用來確認堆疊裡是否還有未處理的資料
當還有資料時,堆疊中的待排序的資料的第i組讀入 L 跟 R
當 L!=R 代表的是讀入的序列 begin[i] 到 end [i] 之間沒排序好
則繼續運作,如果已經排序好,則將 begin[i] 中所存的資料儲存到
result 中,並用 i--
來表示這個堆疊已經處理好了,可以回到前一層
L從左邊開始掃,逐漸往右移動
從p點開始逐點往右看,
若比 pivot 的值大 則把 p 點紀錄在 right 中
若比 pivot 的值小 則把 p 點紀錄在 left 中
把這一組left跟right成對紀錄在 begin[i]、end[i] (即紀錄在堆疊) 中後
清空 left 跟 right 準備紀錄下一對
使用 pair 類別做成的堆疊 result 將 find_run() 找出來的 run 依序放入堆疊中
find_run(),傳入連結串列指標 跟 cmp,
傳回一個升序或是降序的 run ,
其中如果是降序的 run 會在製作 run 時同時將這段鏈結串列重新排序
最後 將頭尾整理到 result 後傳回 result
這段程式碼就是把清單中的每一個 run 讀出
把 run 放在 tp
把 run 移出 list 並堆疊層數 +1
然後對 tp 執行 merge_collapse
檢查堆疊頂端的 3 個 run 是否滿足以下原則:
A 的長度要大於 B 和 C 的長度總和。
n >= 3 時檢查
A 的長度要大於 B 和 C 的長度總和。
*tp->prev->prev
*tp->prev
*tp
B 的長度要大於 C 的長度
n>=4 的時候檢查
A 的長度要大於 B 和 C 的長度總和。
*tp->prev->prev->prev
*tp->prev->prev
*tp->prev
B 的長度要大於 C 的長度
如果不符合的時候用 merge_at 將 BC 合併
合併 2 個 run 並讓堆疊數 stk_size
-1
當 run 都已經放置到堆疊中後,會再用 merge_force_collapse 強制檢查一次
A 的長度要大於 B 和 C 的長度總和。
B 的長度要大於 C 的長度
做完 merge 後,把每一個堆疊依序銜接起來
這段對應到的是題目文件上的
當 A 的長度小於 B 時,會先將 A 數列暫存。直觀的合併方法是從 A 和 B 的開頭開始進行逐對比較,將較小的元素放置於 A 的原位置,這一過程一直持續到 A 和 B 完全排序,類似於經典的合併排序類似,也稱為逐對合併(one-pair-at-a-time)。
文件中提到的改進方向 Galloping mode 並沒有在這份程式實作
持續改進:首先尋找 B 的首個元素(即 )在 A 中的排序位置,從而確定 A 中有一段是小於 者,可將這部分元素放回 A。接著,尋找剩餘 A 的首個元素在 B 中的位置,如此反覆進行,直到完成排序
程式以 hash table 來實作二元樹
二元樹建立的過程分成以下幾個步驟
以範例 9,3,15,20,7 來說,Hash Table 就會變成
dfs函式中 用 find(preorder[pre_low], size, in_heads);
找出該點在 inorder 的 index,再透過該 index
preorder 以 3 為例, 透過數值 3 可以取得 has_listhead[3] 的第一個節點,idx=1
來區分 左子樹有 9, 右子樹有 15,20,7
一個 LRUCache 物件由 dll 跟 hash table 組成,
另外用兩個 int 紀錄 capacity 跟 count
LRUNode
LRUCache 透過 HashTable 的方式來存取 LRUNode
hlist_head 的數量就是 capacity
LRUCacheGet 為用 key 去向 LRUCache 要求資料
如果該資料在 LRUCache 的 Hash Table 有資料
將 key 跟 value 配對放進 Cache中
如果
如果 cache 不存在
檢查是否已經到達上限了,如果到達上限則將最沒使用的 cache 移掉並加入新的點
如果還未達上限則直接建立新的 cache 並將技術 +1
find_nth_bit