contributed by < linhoward0522
>
1
list
有無排序的必要後再往下執行,判斷 list
是否沒有節點或是只有一個節點list_less
, list_greater
, INIT_LIST_HEAD
後, list_less
, list_greater
分別用來當比 pivot
小以及比 pivot
大 list
的 head
list_first_entry
的定義list
中的第一個元素當作 pivot
,用 list_first_entry
來取出元素,所以 AAA
為 struct item
, BBB
為 list
pivot
先從 list
中移除,因為 pivot
並不用跟著遞迴CCC
為 list_for_each_entry_safe
用來走訪整個 list
cmpint
來判斷節點數值跟 pivot
的大小
pivot
,則會將該節點移動到 list_less
的尾端pivot
,則會將該節點移動到 list_greater
的尾端DDD
與 EEE
應皆為 list_move_tail
pivot
數值小的節點都放在 pivot
前面,數值大的節點都放在 pivot
後面list_add
將 pivot
節點加入 head
list_splice
從定義可以看出是用來將節點加到開頭,所以將 list_less
串接到 head
list_greater
串接到尾端,所以 FFF
應為 list_splice_tail
,即可得到一個排序過後的 list
避免張貼完整程式碼,善用 GitHub 來保存及管理。
2
list
有無排序的必要後再往下執行,判斷 list
是否沒有節點或是只有一個節點define
可知,先宣告一個大小為 512 的 stack
,接著用 INIT_LIST_HEAD
做初始化list_splice_init(head, &stack[++top])
會把 head
節點的資料移動到 stack[0]
, 然後初始化 head
partition
並將它初始化partition
初始化,再把 stack[top]
的資料移動到 partition
, 然後初始化 stack[top]
,最後因為從 stack[top]
拿出資料,所以 TOP
減一partition
所指向的 list
有節點且不只有一個節點list_less
, list_greater
, INIT_LIST_HEAD
後, list_less
, list_greater
分別用來當比 pivot
小以及比 pivot
大 list
的 head
list
中的第一個元素當作 pivot
,用 list_first_entry
來取出元素pivot
先從 list
中移除,因為 pivot
並不用跟著遞迴pivot
節點GGGG
為 list_for_each_entry_safe
用來走訪整個 list
cmpint
來判斷節點數值跟 pivot
的大小
pivot
,則會將該節點移動到 list_less
pivot
,則會將該節點移動到 list_greater
pivot
移動到 list_less
的尾端,所以 HHHH
為 list_move_tail
list_greater
, list_less
不為空,就把它們串接到 stack[++top]
尾端IIII
,JJJJ
皆為 stack[++top]
partition
所指向的 list
沒有節點或是只有一個節點,則會進入 else
partition
串接到 stack[top]
尾端stack[top]
裡面只有一個節點時,就把 stack[top]
的節點加到 head
的尾端並初始化KKKK
應為 &stack[top--]
其中 list_del(&tmp->list)
與 list_add_tail(&tmp->list, head)
可以根據 list_move_tail
的定義改成 list_move_tail(&tmp->list, head);
stack
是從數值大放到數值小的,也就是 TOP
會放最小值stack
中只有一個節點,就表示為當前的最小值,並會進入 else
把該節點加到 head
的尾巴根據自己 lab0-c
量測 merge_sort
的 Perf
實驗,來實驗 recursive
, non-recursive
版本 qucik sort
的效能
recursive
# node | cache-misses | branches | instructions | context-switches | time |
---|---|---|---|---|---|
1000 | 1941 | 77,9096 | 527,1670 | 0 | 0.0009604 |
10000 | 5036 | 613,9708 | 4443,3334 | 1 | 0.0056116 |
100000 | 115,6576 | 6397,8997 | 4,6220,5173 | 0 | 0.070447 |
1000000 | 7964,9292 | 6,7530,3741 | 48,1683,4390 | 4 | 1.23062 |
non-recursive
# node | cache-misses | branches | instructions | context-switches | time |
---|---|---|---|---|---|
1000 | 1361 | 85,0934 | 575,9383 | 0 | 0.0009421 |
10000 | 3604 | 696,6615 | 5004,3747 | 0 | 0.006474 |
100000 | 120,2711 | 7312,8727 | 5,2320,1918 | 0 | 0.078943 |
1000000 | 8768,6011 | 7,6389,7122 | 54,3217,4602 | 0 | 1.4274 |
3
xor_node_t
xor_list_t
test_node
XOR linked list
uintptr_t
可以將指標儲存為整數
The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer
stdint.h
中可以發現對 uintptr_t
的定義
intptr_t
為 long int
, uintptr_t
為 unsigned long int
intptr_t
為 int
, uintptr_t
為 unsigned int
stdint.h
列出 C 語言規格書相關的描述。
XOR
運算的函式,但我們必須要將 a
, b
做 casting
LLL
應為 (uintptr_t) a ^ (uintptr_t) b
main
list
,以及 malloc
一個 test_node
,接著將他們傳入 xorlist_add
xorlist_add
來插入節點
real_prev
指向 list
的 head
node
指向 real_prev
所指向 head
的 cmp
所指向的地方,也就是指向 tail
node
在初始狀態的話 real_next
就應是 &list->tail
MMMM
為 &list->tail
real_prev
的 cmp
指向 n
,其中
n
指向要加入的新節點real_prev
就是 list
的 head
n
所指向節點的記憶體位址,存放到 cmp
XOR
head
的位址為 A
, tail
的位址為 B
,新節點的位址為 C
cmp
要存放的位址,其中 real_prev
要先和 PPPP
做 XOR
是為了要將 head
的位址消除掉,所以 PPPP
應為 real_next->cmp
count++