# 2020q3 Homework1 (quiz1)
contribted by < `joe-U16` >
###### tags: `sysprog2020`
:::warning
由於對Git 的不熟悉,導致有兩個帳號commit 這個作業,但這兩個帳號都是我的。
Github 上commit 的有 \<papd32> \<joe-U16>
:::
Directory:
[toc]
## Node示意圖
* 單個節點
```graphviz
digraph foo {
rankdir=LR;
node [shape=record];
a [label="{ node name | value | <ref> }"]
a:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
* linked list,各節點名稱分別為a b c d,value 為 1 2 3 4
```graphviz
digraph indirect{
rankdir=LR;
node [shape=record];
a [label="{ <data> a | <value> 1 | <ref> }"];
b [label="{ <data> b | <value> 2 | <ref> }"];
c [label="{ <data> c | <value> 3 | <ref> }"];
d [label="{ <data> d | <value> 4 | <ref> }"];
a:ref:c -> b:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c -> c:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c -> d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d:ref:c -> NULL[arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
## Q1
考慮一個單向 linked list,其結構定義為:
```cpp=
typedef struct __node {
int value;
struct __node *next;
} node_t;
```
已知不存在 circular (環狀結構),接下來將對該單向 linked list 進行下列操作:
* ```add_entry```: 新增節點,當 linked list 沒有內容時,必須由開發者更新指向開頭的指標。因此實際得到 reference,而非 copy
* ```remove_entry```: 移除指定節點,指向開頭的指標可能因此變更,所以需要用到 a pointer to a pointer (指標的指標)
* ```swap_pair```: 交換一對相鄰的節點,取自 LeetCode: Swap Nodes in Pairs,給定 ```1->2->3->4```,則該回傳 ```2->1->4->3```
* ```reverse```: 將給定的 linked list 其內節點予以反向,即 ```1->2->3->4```,則該回傳 ```4->3->2->1```
### <font color=#4588C1>add_entry</font>
```cpp=
#include <stdio.h>
#include <stdlib.h>
typedef struct __node {
int value;
struct __node *next;
} node_t;
void add_entry(node_t **head, int new_value)
{
node_t **indirect = head;
node_t *new_node = malloc(sizeof(node_t));
new_node->value = new_value;
new_node->next = NULL;
assert(new_node); \\AA1
while (*indirect)
indirect = &(*indirect)->next;
*indirect = new_node; \\AA2
}
```
* ==#13==幫new_node配置大小為```node_t```的記憶體
* ==#14==把new_value assign 給 new_node->value
* ==#15==new_node->next 指向 NULL
* ==#17==用[assert](https://pubs.opengroup.org/onlinepubs/9699919799/)判斷new_node 這個pointer variable的記憶體有沒有配置成功
```graphviz
digraph foo {
rankdir=LR;
node [shape=record];
a [label="{ new_node | new_value | <ref> }"]
a:ref:c -> NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
* ==#18==因為前面有```node_t **indirect = head;```,所以會從```head```開始,當```*indrect```還有東西,就持續前進
1. 最初狀態
```graphviz
digraph indirect{
rankdir=LR;
node [shape=record];
a [label="{ <data> a | <value> 1 | <ref> }"];
b [label="{ <data> b | <value> 2 | <ref> }"];
c [label="{ <data> c | <value> 3 | <ref> }"];
d [label="{ <data> d | <value> 4 | <ref> }"];
indirect [label="{ indirect | <value> | <ref> }"];
new_node [label="{ <data> new_node | <value> new_value| <ref>}"]
valindirect [label="{ <data>*indirect | <value> | <ref> }"];
head [label="{ <data> *head | <value> | <ref> }"];
valhead [label="{ *head | <value> | <ref> }"];
head -> valhead:value [arrowhead=ornomal]
new_node:ref:c -> NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
valindirect -> a:value [arrowhead=onormal]
indirect -> valindirect:value [arrowhead=onormal]
valhead->a:value [arrowhead=onormal]
a:ref:c -> b:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c -> c:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c -> d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d:ref:c -> NULL[arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
2. 經過一次while迴圈,執行```indirect = new_node;```後
```graphviz
digraph indirect{
rankdir=LR;
node [shape=record];
a [label="{ <data> a | <value> 1 | <ref> }"];
b [label="{ <data> b | <value> 2 | <ref> }"];
c [label="{ <data> c | <value> 3 | <ref> }"];
d [label="{ <data> d | <value> 4 | <ref> }"];
indirect [label="{ indirect | <value> | <ref> }"];
new_node [label="{ <data> new_node | <value> new_value| <ref>}"]
valindirect [label="{ <data>*indirect | <value> | <ref> }"];
head [label="{ <data> *head | <value> | <ref> }"];
valhead [label="{ *head | <value> | <ref> }"];
head -> valhead:value [arrowhead=ornomal]
new_node:ref:c -> NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
valindirect -> b:value [arrowhead=onormal]
indirect -> valindirect:value [arrowhead=onormal]
valhead->a:value [arrowhead=onormal]
a:ref:c -> b:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c -> c:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c -> d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d:ref:c -> NULL[arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
3. 重複直到 *indirect is null
---
* ==#20==```*indirect = new_node; \\AA2```
```graphviz
digraph indirect{
rankdir=LR;
node [shape=record];
a [label="{ <data> a | <value> 1 | <ref> }"];
b [label="{ <data> b | <value> 2 | <ref> }"];
c [label="{ <data> c | <value> 3 | <ref> }"];
d [label="{ <data> d | <value> 4 | <ref> }"];
sizeof [label="{ <data> | <value> | <ref> }"];
indirect [label="{ indirect | <value> | <ref> }"];
new_node [label="{ <data> new_node | <value> new_value| <ref>}"]
valindirect [label="{ <data>*indirect | <value> | <ref> }"];
head [label="{ <data> *head | <value> | <ref> }"];
valhead [label="{ *head | <value> | <ref> }"];
head -> valhead:value [arrowhead=ornomal]
new_node:ref:c -> NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
new_node -> sizeof [arrowhead=onormal]
valindirect -> sizeof:value [arrowhead=onormal]
indirect -> valindirect:value [arrowhead=onormal]
valhead->a:value [arrowhead=onormal]
a:ref:c -> b:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c -> c:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c -> d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d:ref:c -> NULL[arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
---
### <font color="#4588C1">find_entry</font>
```cpp=
node_t *find_entry(node_t *head, int value)
{
node_t *current = head;
for (; current && current->value != value; current = current->next)
/* interate */;
return current;
}
```
* ==#3==current 這個pointer variable跟head存相同位址。
* ==#4==current有東西且current->value不等於value時,current移動到下一個位址
1. 初始狀態,current和head相同位址
```graphviz
digraph indirect{
rankdir=LR
node [shape=record];
{rank=same}
a [label="{<data> | <value> | <ref>}"];
b [label="{<data> | <value> | <ref>}"];
head [label="{<data> head | <value> | <ref>}"];
head -> a:value [arrowhead=ornomal]
current [label="{<data> current | <value> | <ref>}"];
current -> a:value [arrowhead=onormal]
a:ref:c -> b:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
2. current前進一格,判斷這個位子的value有沒有一樣,沒有的話繼續前進。 ==這邊假設在這裡找到value。==
```graphviz
digraph indirect{
rankdir=LR
node [shape=record];
nodea [label="{<A> | <value> | <ref>}"];
nodeb [label="{<C> | <value> value | <ref>}"];
head [label="{<data> head | <value> | <ref>}"];
head -> nodea:value [arrowhead=onormal]
current [label="{<data> current | <value> | <ref>}"];
current -> nodeb:value [arrowhead=onormal]
nodea:ref:c -> nodeb:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
3. 跳脫迴圈,回傳current 這個pointer variable
### <font color="#4588C1">remove_entry</font>
```cpp=
void remove_entry(node_t **head, node_t *entry)
{
node_t **indirect = head;
while ((*indirect) != entry)
indirect = &(*indirect)->next;
*indirect = entry->next;
free(entry);
}
```
1. 初始狀態
* 假設entry在C節點
```graphviz
digraph graphname{
node[shape=box]
rankdir=LR
head[shape=plaintext]
indirect[shape=plaintext];
NULL[shape=plaintext];
n[shape=plaintext,label="entry"]
{
rank=same
indirect->head->A
}
{
rank=same
n->C
}
A->B->C->D->NULL
}
```
2. ==#5==一直前進下一個位址,直到找到entry;
```graphviz
digraph graphname{
node[shape=box]
rankdir=LR
head[shape=plaintext]
indirect[shape=plaintext];
NULL[shape=plaintext];
n[shape=plaintext,label="entry(*indirect)"]
{
rank=same
head->A
}
{
rank=same
indirect->n->C
}
A->B->C->D->NULL
}
```
3. ==#8==跳脫迴圈,```*indirect = entry->next``` *indirect會存entry的下一個位址,而entry最後釋放
```graphviz
digraph graphname{
node[shape=box]
rankdir=LR
head[shape=plaintext]
indirect[shape=plaintext];
NULL[shape=plaintext];
m[shape=plaintext,label="*indirect"]
{
rank=same
head->A
}
{
rank=same
indirect->m->D
}
A->B->C->D->NULL
}
```
<!--
```graphviz
digraph indirect{
rankdir=LR;
node [shape=record];
a [label="{ <data> a | <value> | <ref> }"];
b [label="{ <data> b | <value> | <ref> }"];
c [label="{ <data> c | <value> | <ref> }"];
entry [label="{ <data> entry | <value> | <ref> }"];
entry->b:value [arrowhead=onormal]
headptr [label="{<headptr> headptr||}"]
currentptr [label="{<currentptr> currentptr||}"]
current [label="{ <data> current | <value> | <ref> }"];
current -> a:value [arrowhead=onormal]
head [label="{ <data> head | <value> | <ref> }"];
head -> a:value [arrowhead=onormal]
currentptr ->current:value [arrowhead=onormal]
headptr ->head:value:n [arrowhead=onormal]
a:ref:c -> b:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c -> c:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
```graphviz
digraph indirect{
rankdir=LR;
node [shape=record];
a [label="{ <data> a | <value> | <ref> }"];
b [label="{ <data> b | <value> | <ref> }"];
c [label="{ <data> c | <value> | <ref> }"];
entry [label="{ <data> entry | <value> | <ref> }"];
entry->b:value [arrowhead=onormal]
headptr [label="{<headptr> headptr||}"]
currentptr [label="{<currentptr> currentptr||}"]
head [label="{ <data> head | <value> | <ref> }"];
head -> a:value [arrowhead=onormal]
current [label="{ <data> current | <value> | <ref> }"];
current -> b:value [arrowhead=onormal]
currentptr ->current:value [arrowhead=onormal]
headptr ->head:value:n [arrowhead=onormal]
a:ref:c -> b:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c -> c:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c ->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
3. 跳脫迴圈,*current存 entry下一個位址。
```graphviz
digraph indirect{
rankdir=LR;
node [shape=record];
a [label="{ <data> a | <value> | <ref> }"];
b [label="{ <data> b | <value> | <ref> }"];
c [label="{ <data> c | <value> | <ref> }"];
entry [label="{ <data> entry | <value> | <ref> }"];
entry->b:value [arrowhead=onormal]
headptr [label="{<headptr> headptr||}"]
currentptr [label="{<currentptr> currentptr||}"]
head [label="{ <data> head | <value> | <ref> }"];
head -> a:value [arrowhead=onormal]
current [label="{ <data> current | <value> | <ref> }"];
current -> c:value [arrowhead=onormal]
currentptr ->current:value [arrowhead=onormal]
headptr ->head:value:n [arrowhead=onormal]
a:ref:c -> b:data; b:ref:c ->c:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
//b:ref:c -> c:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c ->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
}
```
-->
4. 釋放entry;
### <font color="#4588C1">swap_pair</font>
```cpp=
node_t *swap_pair(node_t *head)
{
for (node_t **node = &head; *node && (*node)->next; node = &(*node)->next->next) {
node_t *tmp = *node;
*node = (*node)->next;
tmp->next = (*node)->next;
(*node)->next = tmp;
}
return head;
}
```
* 一開始node存head的address,只要目前這個位址和下個位址有值就持續執行
1. ```node_t *tmp = *node;```
```graphviz
digraph indirect{
node [shape=record];
rankdir=LR
a [label="{<data> a | <value> | <ref>}"];
b [label="{<data> b | <value> | <ref>}"];
c [label="{<data> c | <value> | <ref>}"];
d [label="{<data> d | <value> | <ref>}"];
a:ref:c->b:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c->c:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c->d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head [label="{<data> *node | <value> | <ref>}"];
node1 [label="{<data> node | <value> | <ref>}"];
tmp [label="{<data> tmp | <value> | <ref>}"];
head->a:value [arrowhead=onormal]
node1->head:value [arrowhead=onormal]
tmp->a:value [arrowhead=onormal]
}
```
2. ```*node = (*node)->next;```
```graphviz
digraph indirect{
node [shape=record];
rankdir=LR
a [label="{<data> a | <value> | <ref>}"];
b [label="{<data> b | <value> | <ref>}"];
c [label="{<data> c | <value> | <ref>}"];
d [label="{<data> d | <value> | <ref>}"];
a:ref:c->b:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c->c:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c->d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head [label="{<data> *node | <value> | <ref>}"];
node1 [label="{<data> node | <value> | <ref>}"];
tmp [label="{<data> tmp | <value> | <ref>}"];
head->b:value [arrowhead=onormal]
node1->head:value [arrowhead=onormal]
tmp->a:value [arrowhead=onormal]
}
```
3. ```tmp->next = (*node)->next```
```graphviz
digraph indirect{
node [shape=record];
rankdir=LR
a [label="{<data> a | <value> | <ref>}"];
b [label="{<data> b | <value> | <ref>}"];
c [label="{<data> c | <value> | <ref>}"];
d [label="{<data> d | <value> | <ref>}"];
a:ref:c->c:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c->c:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c->d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head [label="{<data> *node | <value> | <ref>}"];
node1 [label="{<data> node | <value> | <ref>}"];
tmp [label="{<data> tmp | <value> | <ref>}"];
head->b:value [arrowhead=onormal]
node1->head:value [arrowhead=onormal]
tmp:n->a:value [arrowhead=onormal]
}
```
4. ```(*node)->next = tmp;```
```graphviz
digraph indirect{
node [shape=record];
rankdir=LR
a [label="{<data> a | <value> | <ref>}"];
b [label="{<data> b | <value> | <ref>}"];
c [label="{<data> c | <value> | <ref>}"];
d [label="{<data> d | <value> | <ref>}"];
a:ref:c->c:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c->a:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c->d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head [label="{<data> *node | <value> | <ref>}"];
node1 [label="{<data> node | <value> | <ref>}"];
tmp [label="{<data> tmp | <value> | <ref>}"];
head->b:value [arrowhead=onormal]
node1->head:value [arrowhead=onormal]
tmp:n->a:value [arrowhead=onormal]
}
```
* node 前進兩格
```graphviz
digraph indirect{
node [shape=record];
rankdir=LR
a [label="{<data> a | <value> | <ref>}"];
b [label="{<data> b | <value> | <ref>}"];
c [label="{<data> c | <value> | <ref>}"];
d [label="{<data> d | <value> | <ref>}"];
a:ref:c->c:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c->a:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c->d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
head [label="{<data> *node | <value> | <ref>}"];
node1 [label="{<data> node | <value> | <ref>}"];
tmp [label="{<data> tmp | <value> | <ref>}"];
head->c:value [arrowhead=onormal]
node1->head:value [arrowhead=onormal]
tmp:n->a:value [arrowhead=onormal]
}
```
### <font color="#4588C1">*reverse(node_t *head)</font>
```cpp=
node_t *reverse(node_t *head)
{
node_t *cursor = NULL;
while (head) {
node_t *next = head->next;
head->next = cursor;
cursor=head;
head = next;
}
return cursor;
}
```
* ==#3==當head不為NULL時,重複1 2 3 4
```graphviz
digraph indirect{
node [shape=record];
rankdir=LR
a [label="{<data> a | <value> | <ref>}"];
b [label="{<data> b | <value> | <ref>}"];
c [label="{<data> c | <value> | <ref>}"];
d [label="{<data> d | <value> | <ref>}"];
a:ref:c->b:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c->c:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c->d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
n [label="{NULL}"]
head [label="{<data> head | <value> | <ref>}"];
head->a:value [arrowhead=onormal]
cursor [label="{<data> cursor | <value> | <ref>}"];
cursor->n
}
```
1. ```node_t *next = head->next;```
```graphviz
digraph indirect{
node [shape=record];
rankdir=LR
a [label="{<data> a | <value> | <ref>}"];
b [label="{<data> b | <value> | <ref>}"];
c [label="{<data> c | <value> | <ref>}"];
d [label="{<data> d | <value> | <ref>}"];
a:ref:c->b:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c->c:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c->d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
n [label="{NULL}"]
cursor [label="{<data> cursor | <value> | <ref>}"];
cursor->n [arrowhead=normal]
head [label="{<data> head | <value> | <ref>}"];
head->a:value [arrowhead=onormal]
next [label="{<data> next | <value> | <ref>}"];
next->b:value [arrowhead=onormal]
}
```
2. ```head->next = cursor;```
```graphviz
digraph indirect{
node [shape=record];
rankdir=LR
a [label="{<data> a | <value> | <ref>}"];
b [label="{<data> b | <value> | <ref>}"];
c [label="{<data> c | <value> | <ref>}"];
d [label="{<data> d | <value> | <ref>}"];
a:ref:c->n:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c->c:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c->d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
n [label="{NULL}"]
cursor [label="{<data> cursor | <value> | <ref>}"];
cursor->n [arrowhead=onormal]
head [label="{<data> head | <value> | <ref>}"];
head->a:value [arrowhead=onormal]
next [label="{<data> next | <value> | <ref>}"];
next->b:value [arrowhead=onormal]
}
```
3. ```cursor=head;```
```graphviz
digraph indirect{
node [shape=record];
rankdir=LR
a [label="{<data> a | <value> | <ref>}"];
b [label="{<data> b | <value> | <ref>}"];
c [label="{<data> c | <value> | <ref>}"];
d [label="{<data> d | <value> | <ref>}"];
a:ref:c->n:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c->c:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c->d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
n [label="{NULL}"]
cursor [label="{<data> cursor | <value> | <ref>}"];
cursor->a [arrowhead=onormal]
head [label="{<data> head | <value> | <ref>}"];
head->a:value [arrowhead=onormal]
next [label="{<data> next | <value> | <ref>}"];
next->b:value [arrowhead=onormal]
}
```
4. ```head = next```
```graphviz
digraph indirect{
node [shape=record];
rankdir=LR
a [label="{<data> a | <value> | <ref>}"];
b [label="{<data> b | <value> | <ref>}"];
c [label="{<data> c | <value> | <ref>}"];
d [label="{<data> d | <value> | <ref>}"];
a:ref:c->n:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c->c:data:c [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c->d:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
d->NULL [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
n [label="{NULL}"]
cursor [label="{<data> cursor | <value> | <ref>}"];
cursor->a [arrowhead=onormal]
head [label="{<data> head | <value> | <ref>}"];
head->b:value [arrowhead=onormal]
next [label="{<data> next | <value> | <ref>}"];
next->b:value [arrowhead=onormal]
}
```
* 利用三個指標重複動作,最後將linked list 反轉。
## Q2 利用指標的指標改寫swap_pair、reverse避免回傳指標
* swap_pair
```cpp=
void swap_pair(node_t **head)
{
for (node_t **node = head; *node && (*node)->next; node = &(*node)->next->next) {
node_t *tmp = *node;
*node = (*node)->next;
tmp->next = (*node)->next;
(*node)->next = tmp;
}
}
```
* reverse
```cpp=
void reverse(node_t **head)
{
node_t *cursor = NULL;
while (*head) {
node_t *next = (*head)->next;
(*head)->next = cursor;
cursor = *head;
*head = next;
}
head = &cursor;
}
```
## Q3 以遞迴改寫上述的 reverse,注意,你可能因此需要建立新的函式,如 rev_recursive,隨後在 reverse 函式中呼叫 rev_recursive
* 初始狀態為
```graphviz
digraph name{
node [shape=box]
null [shape=plaintext]
{
rank=same
a->b->c->d->null
}
}
```
* 使用遞迴:step1
```graphviz
digraph name{
node [shape=box]
null [shape=plaintext]
{
rank=same
cur [width=4]
cur->a
a->null
}
}
```
* step2
```graphviz
digraph name{
node [shape=box]
null [shape=plaintext]
{
rank=same
cur [width=3.5]
cur->b->a
a->null
}
}
```
* 持續直到結束就完成啦
```cpp=
node_t *rev_reverse(node_t *head, node_t **pos)
{
if(head->next) {
node_t *tmp = rev_reverse(head->next, pos);
tmp->next = head;
head->next = NULL;
return head;
}
*pos = head;
return head;
}
void reverse(node_t **head)
{
if (!*head || !(*head)->next)
return;
node_t **pos;
pos = head;
rev_reverse(*head, pos);
head = pos;
}
```
## Q4 針對 singly-linked list 的節點,實作 [Fisher–Yates shuffle](https://en.wikipedia.org/wiki/Fisher–Yates_shuffle),你應該儘量降低記憶體的使用量;
```cpp=
void find_pos(node_t **tmp, uint16_t pos)
{
for (pos--;pos;pos--) {
*tmp = (*tmp)->next;
}
}
void shuffle(node_t **head)
{
uint16_t count = 0;
for (node_t *current = *head; current; current = current->next) {
count += 1;
}
if (count == 1)
return;
node_t *tail = NULL;
node_t *cursor = *head;
node_t *tmp = *head;
uint16_t pos = rand() % count;
if (pos == 0) {
tail = cursor;
cursor = cursor->next;
count -= 1;
} else {
find_pos(&tmp, pos);
node_t *target = tmp->next;
tmp->next = target->next;
target->next = cursor;
tail = target;
count -= 1;
}
*head = tail;
for (count--; count; count--) {
tmp = cursor;
uint16_t pos = rand() % count;
if (pos == 0) {
tail = cursor;
cursor = cursor->next;
continue;
}
find_pos(&tmp, pos);
node_t *target = tmp->next;
tmp->next = target->next;
target->next = cursor;
tail->next = target;
tail = tail->next;
}
}
```
<!--
```graphviz
digraph circle{
a -> b;
b -> c;
c -> a;
a -> b
}
```
```graphviz
digraph foo {
rankdir=LR;
node [shape=record];
a [label="{ <data> 12 | <ref> }", width=1.2]
b [label="{ <data> 99 | <ref> }"]
c [label="{ <data> 37 | <ref> }"]
d [shape=box];
a:ref:c -> b:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
a:ref:c -> c:data [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
c:ref:c -> d [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
b:ref:c -> e [arrowhead=vee]
}
```
```graphviz
digraph indirect{
node [shape=record];
{rank=same; structa, structb}
structa [label="<A> | |<ref>"]
structb [label="<B> | |<ref>"]
head [label="<head> head||"]
current [label="<current> current ||"]
//structa:ref -> :B:nw
head -> structa [arrowhead=onormal]
current -> structb [arrowhead=onormal]
}
```
```graphviz
digraph indirect{
node [shape=record];
{rank=same; structa, structc}
structp [label="p|<p>&A"]
structptr [label="<name_ptr> prtA | <ptr> &A"]
structa [label="<A> A|1"];
structc [label="<C> B|3"];
structp:ptr->structptr:A:nw
structptr:ptr -> structa:A:nw
}
```
-->