---
tags: Linux核心設計與實作
---
# lib/list_sort.c sort執行流程
起始狀態
且設A\<B\<C
```c
A = 0x555555566eb8;
B = 0x555555566f68;
c = 0x555555567018;
```
---
count = 0;
```
// queue的第一格節點
pending = NULL
list = 0x555555566eb8 // A
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] pending [label="pending"]
node [shape=box] list [label="list"];
list -> a;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:prev:c -> head [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:next:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:next:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
```
list->prev = pending // A->prev = NULL
pending = list // A
list = list->next // B
pending->next = NULL // A->next = NULL
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] pending [label="pending"];
node [shape=box] list [label="list"];
pending -> a;
list -> b;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:next:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
---
count = 1
```
tail = &pending; // pending point to A
// enter for loop
tail = &(*tail)->prev // tail point to pending->prev (0x555555566eb8)
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] tail
node [shape=box] pending [label="pending"];
node [shape=box] list [label="list"];
tail -> pending;
pending -> a;
list -> b;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:next:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
```
list->prev = pending // B->prev = A (nothing change)
pending = list // pending = B
list = list->next // list = C
pending->next = NULL // B->next = NULL
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] tail
node [shape=box] pending [label="pending"];
node [shape=box] list [label="list"];
tail -> pending;
pending -> b;
list -> c;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
---
count = 2
```
// ready for merge
a = *tail // B
b = a->prev // A
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] tail
node [shape=box] pending [label="pending"];
node [shape=box] list [label="list"];
node [shape=box] newA [label="a"]
node [shape=box] newB [label="b"]
tail -> pending;
pending -> b;
list -> c;
newA -> b;
newB -> a;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
merging
```
head = NULL
tail = &head
*tail = a; // head = A
tail = &a->next // tail = NULL (go to next term)
a = a->next // a = NULL (go to next term)
*tail = b // A->next = B
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] headPtr [label="head"];
node [shape=box] tail [label="tail"];
node [shape=box] newA [label="a"]
node [shape=box] newB [label="b"]
newB -> b;
headPtr -> a;
tail -> b;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:next:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
after merge
```
// 被合併的list會由head到tail接好
// 尚未被合併的list會由tail利用prev一路往前接
// 此處應該是在處理順序調換後和原本list相接的部分
a->prev = b->prev // nothing change
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] tail
node [shape=box] pending [label="pending"];
node [shape=box] list [label="list"];
node [shape=box] newA [label="a"]
node [shape=box] newB [label="b"]
tail -> pending;
pending -> a;
list -> c;
newA -> a;
newB -> a;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:next:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
```
list->prev = pending // C->prev = A
pending = list // pending = C
list = list->next // list = NULL (到底了)
pending->next = NULL
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] tail
node [shape=box] pending [label="pending"];
node [shape=box] list [label="list"];
tail -> pending;
pending -> c;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:next:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
```
list = pending // list = C
pending = pending->prev // pending = A (要併進去的list頭)
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] tail
node [shape=box] pending [label="pending"];
node [shape=box] list [label="list"];
list -> c;
tail -> pending;
pending -> a;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:next:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
prepare for merge remain nodes
```
// 盡可能地往前合併
next = pending->prev // next = NULL (沒東西能再併了)
// 跳出for loop
```
merge final
```
// 將所有剩餘節點合併並串起來
tail = head
count = 0
// 第一次迴圈
// cmp(a,b) < 0
// 重建double linked結構
tail->next = a
a->prev = tail
tail = a
// a轉到下一項
a = a->next
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] tail
node [shape=box] newA [label="a"]
node [shape=box] newB [label="b"]
tail -> a;
newA -> b;
newB -> c;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:next:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:prev:c -> head [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
```
// 第二次迴圈
// cmp(a,b) < 0
// 重建double linked結構
tail->next = a // tail->next = B (A->next = B)
a->prev = tail // B->prev = A
tail = a // tail = B
// a轉到下一項
a = a->next // a = NULL
跳出迴圈
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] tail
node [shape=box] newA [label="a"]
node [shape=box] newB [label="b"]
tail -> b;
newB -> c;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:next:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:prev:c -> head [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
```
// 合併剩下還沒被併進去的節點
tail->next = b // B->next = C (直接把剩下還沒合併的接起來)
// enter while loop
// 重建 double linked 結構
b->prev = tail // C->prev = B
tail = b // tail = C
b = b->next; // b = NULL (後面沒東西併了)
跳出迴圈
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] tail
node [shape=box] newA [label="a"]
node [shape=box] newB [label="b"]
tail -> c;
newB -> c;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:next:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:prev:c -> head [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:next:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
```
// 完成tail和head的link
tail->next = head // C->next = head
head->prev = tail // head->prev = C
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record]
head [label="{<prev> | head | <next> }"];
a [label="<value> A | {<prev> | <next>}"];
b [label="<value> B | {<prev> | <next>}"];
c [label="<value> C | {<prev> | <next>}"];
node [shape=box] tail
node [shape=box] newA [label="a"]
node [shape=box] newB [label="b"]
tail -> c;
newB -> c;
head:next:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head:prev:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:next:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:prev:c -> head [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:prev:c -> a [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:next:c -> c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:prev:c -> b [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:next:c -> head [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```