AAAA =
BBBB =
CCCC =
DDDD =
EEEE =
FFFF =
GGGG =
Timsort 是混合 insertion sort
與 merge sort
的 stable 排序演算法,主要原理是將資料分割成小區塊 runs
,將這些 runs
用 insertion sort
排序,最後將這些 runs
用 merge sort
合併。
Timsort
會將 runs
放入堆疊中,為了達到 balanced merges,也就是合併時兩個 runs
大小差不多,所以限制當 top-2
的 run
比 top
的 run
+ top-1
的 run
的長度較大時,才能合併。
這裡主要是將資料分割成 runs
,去計算 runs
的數量,因為需要所有的 runs
都是遞增的,所以會判斷是否為遞增的序列,若不是,則將該 runs
反轉成遞增的序列。
若是 run
的長度小於 MIN_RUN
,則會用 insertion sort
去排序,當長度短且為排序過的序列,用 insertion sort
的效率會較好。
merge
這個函式就是將兩個 runs
進行合併。
inplace_merge
會有多一個 inplace_merge
函式,主要是因為當一個 run
裡面包含兩個不同的 run
時,不需要額外的空間來儲存合併後的 run
,實作起來會較為簡單。
首先初始狀態會宣告兩個變數 cur1, cur2
分別指向 first1, first2
。
再來先將 cur1
右移,找出第一個 > cur2
的值,也就是找出小區塊 1, 3
。
再將 cur2
右移,找出第一個 > cur1
的值,也就是找出小區塊 2, 4
。
最後進行 3 次 reverse
,第一次做 cur1
到 first_2 - 1
的 reverse
。
第二次做 first_2
到 cur_2 - 1
的 reverse
。
第三次做 cur_1
到 cur_2 - 1
的 reverse
。
最後移動 first_1, first_2
,再開始新的一輪直到合併成一個 run
。
AAAA = __reverse(cur_1, cur_2, size)
BBBB = top - 1
CCCC = top - 2
DDDD = first + MIN_RUN * size
EEEE = top--
FFFF = top++
GGGG = stack[top-1].last = stack[top].last
在 process 中,最多有 1 << (sizeof(void *) << 3) / sizeof(rb_node(x_type)).
個節點,所以 RB_LOG2_MAX_NODES
就是上式取 log ,也就是:
(1 << (sizeof(void *) << 3) / sizeof(rb_node(x_type)))
= (1 << (sizeof(void *) << 3) - (sizeof(rb_node(x_type)))
= RB_LOG2_MAX_MEM_BYTES - (sizeof(rb_node(x_type)))
所以 (sizeof(rb_node(x_type))) 就等於下式
範例輸入為:7, 11, 1, 99, 22, 33, 44, 9, 3, 5
判斷若是左節點沒有子節點,表示為最左節點,最左節點是最小的值,則印出。
這裡利用左節點的最右子節點來紀錄前一個較大的節點,於是下個迴圈會輸出最小的節點,然後進到 for 迴圈內就會判斷是否要透過剛剛紀錄的值回到最小節點的前一個節點,再將用來紀錄的最右子節點設成 NULL
。
HHHH = 3
IIII = 2
JJJJ = rbtn_left_get
KKKK = rbtn_right_get
LLLL = rbtn_right_get