# 2020q3 Homework1 (quiz1) contributed by <`solnone`> [2020q3 第 1 週測驗題](https://hackmd.io/@sysprog/sysprog2020-quiz1) ## 1. 解釋上述程式運作原理,搭配 [Graphviz](https://graphviz.org/),比照 [Linked List 練習題](https://hackmd.io/@sysprog/linked-list-quiz) 在 HackMD 筆記上視覺化展現 ```cpp= #include <assert.h> #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)); /* AA1: a */ assert(new_node); new_node->value = new_value; new_node->next = NULL; while (*indirect) indirect = &(*indirect)->next; /* AA2: b */ *indirect = new_node; } node_t *find_entry(node_t *head, int value) { node_t *current = head; for (; current && current->value != value; current = current->next) /* interate */; return current; } void remove_entry(node_t **head, node_t *entry) { node_t **indirect = head; while ((*indirect) != entry) indirect = &(*indirect)->next; *indirect = entry->next; free(entry); } node_t *swap_pair(node_t *head) { for (node_t **node = &head; *node && (*node)->next; /* BB1: e */ node = &(*node)->next->next) { node_t *tmp = *node; /* BB2: c */ *node = (*node)->next; tmp->next = (*node)->next; (*node)->next = tmp; } return head; } node_t *reverse(node_t *head) { node_t *cursor = NULL; while (head) { node_t *next = head->next; /* CCC: b */ head->next = cursor; cursor = head; head = next; } return cursor; } void print_list(node_t *head) { for (node_t *current = head; current; current = current->next) printf("%d ", current->value); printf("\n"); } int main(int argc, char const *argv[]) { node_t *head = NULL; print_list(head); add_entry(&head, 72); add_entry(&head, 101); add_entry(&head, 108); add_entry(&head, 109); add_entry(&head, 110); add_entry(&head, 111); print_list(head); node_t *entry = find_entry(head, 101); remove_entry(&head, entry); entry = find_entry(head, 111); remove_entry(&head, entry); print_list(head); /* swap pair. * See https://leetcode.com/problems/swap-nodes-in-pairs/ */ head = swap_pair(head); print_list(head); head = reverse(head); print_list(head); return 0; } ``` ### node_t ```graphviz digraph node_t { rankdir=LR; node [shape=Mrecord, color=black]; node_t [label="{ <data> value | <ref> *next }"]; } ``` ### add_entry 加入第二筆資料時追蹤 add_entry ```cpp add_entry(&head, 72); add_entry(&head, 101); ``` 傳入 main function 的 head 位址 &(main.head) ```cpp void add_entry(node_t **head, int new_value) { node_t **indirect = head; node_t *new_node = malloc(sizeof(node_t)); /* AA1: a */ assert(new_node); new_node->value = new_value; new_node->next = NULL; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=indigo]; head; indirect; node [shape=record, color=forestgreen]; address_of_head [label="main.head", fontcolor=blue]; new_node; node [shape=Mrecord, color=black]; first [label="{ <data> 72 | <ref> }"]; new [label="{ <data> 101 | <ref> }"]; node [shape=none]; null [label="NULL"]; address_of_head -> first [arrowhead=vee, arrowtail=dot, dir=both]; head -> address_of_head [arrowhead=vee, arrowtail=crow, dir=both]; indirect -> address_of_head [arrowhead=vee, arrowtail=crow, dir=both]; first:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; new_node -> new [arrowhead=vee, arrowtail=dot, dir=both]; new:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; } ``` ```cpp while (*indirect) indirect = &(*indirect)->next; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=indigo]; head; indirect; node [shape=record, color=forestgreen]; address_of_head [label="main.head", fontcolor=blue]; new_node; node [shape=Mrecord, color=black]; first [label="{ <data> 72 | <ref> }"]; new [label="{ <data> 101 | <ref> }"]; node [shape=none]; null [label="NULL"]; address_of_head -> first [arrowhead=vee, arrowtail=dot, dir=both]; head -> address_of_head [arrowhead=vee, arrowtail=crow, dir=both]; first:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; new_node -> new [arrowhead=vee, arrowtail=dot, dir=both]; new:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; indirect -> first:ref [arrowhead=vee, arrowtail=crow, dir=both, color=red]; } ``` ```cpp *indirect = new_node; } ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=indigo]; head; indirect; node [shape=record, color=forestgreen]; address_of_head [label="main.head", fontcolor=blue]; new_node; node [shape=Mrecord, color=black]; first [label="{ <data> 72 | <ref> }"]; new [label="{ <data> 101 | <ref> }"]; node [shape=none]; null [label="NULL"]; address_of_head -> first [arrowhead=vee, arrowtail=dot, dir=both]; head -> address_of_head [arrowhead=vee, arrowtail=crow, dir=both]; indirect -> first:ref [arrowhead=vee, arrowtail=crow, dir=both]; new_node -> new [arrowhead=vee, arrowtail=dot, dir=both]; new:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; first:ref:c -> new [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false, color=red]; } ``` ### swap_pair ```cpp node_t *swap_pair(node_t *head) { for (node_t **node = &head; ...; ...) { node_t *tmp = *node; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=indigo]; n [label="node"]; node [shape=record, color=forestgreen]; head; tmp; node [shape=Mrecord, color=black]; first [label="{ <data> 72 | <ref> }"]; second [label="{ <data> 108 | <ref> }"]; third [label="{ <data> 109 | <ref> }"]; fourth [label="{ <data> 110 | <ref> }"]; node [shape=none]; null [label="NULL"]; head -> first [arrowhead=vee, arrowtail=dot, dir=both]; n -> head [arrowhead=vee, arrowtail=crow, dir=both]; first:ref:c -> second [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; second:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; tmp -> first [arrowhead=vee, arrowtail=dot, dir=both]; } ``` ```cpp *node = (*node)->next; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=indigo]; n [label="node"]; node [shape=record, color=forestgreen]; head; tmp; node [shape=Mrecord, color=black]; first [label="{ <data> 72 | <ref> }"]; second [label="{ <data> 108 | <ref> }"]; third [label="{ <data> 109 | <ref> }"]; fourth [label="{ <data> 110 | <ref> }"]; node [shape=none]; null [label="NULL"]; n -> head [arrowhead=vee, arrowtail=crow, dir=both]; first:ref:c -> second [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; second:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; tmp -> first [arrowhead=vee, arrowtail=dot, dir=both]; head -> second [arrowhead=vee, arrowtail=dot, dir=both, color=red]; } ``` ```cpp tmp->next = (*node)->next; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=indigo]; n [label="node"]; node [shape=record, color=forestgreen]; head; tmp; node [shape=Mrecord, color=black]; first [label="{ <data> 72 | <ref> }"]; second [label="{ <data> 108 | <ref> }"]; third [label="{ <data> 109 | <ref> }"]; fourth [label="{ <data> 110 | <ref> }"]; node [shape=none]; null [label="NULL"]; head -> second [arrowhead=vee, arrowtail=dot, dir=both]; n -> head [arrowhead=vee, arrowtail=crow, dir=both]; second:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; tmp -> first [arrowhead=vee, arrowtail=dot, dir=both]; first:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false, color=red]; } ``` ```cpp (*node)->next = tmp; } ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=indigo]; n [label="node"]; node [shape=record, color=forestgreen]; head; tmp; node [shape=Mrecord, color=black]; first [label="{ <data> 72 | <ref> }"]; second [label="{ <data> 108 | <ref> }"]; third [label="{ <data> 109 | <ref> }"]; fourth [label="{ <data> 110 | <ref> }"]; node [shape=none]; null [label="NULL"]; head -> second [arrowhead=vee, arrowtail=dot, dir=both]; n -> head [arrowhead=vee, arrowtail=crow, dir=both]; first:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; tmp -> first [arrowhead=vee, arrowtail=dot, dir=both]; second:ref:c -> first [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false, color=red]; } ``` ```cpp for (...; *node && (*node)->next; node = &(*node)->next->next) { node_t *tmp = *node; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=indigo]; n [label="node"]; node [shape=record, color=forestgreen]; head; tmp; node [shape=Mrecord, color=black]; first [label="{ <data> 72 | <ref> }"]; second [label="{ <data> 108 | <ref> }"]; third [label="{ <data> 109 | <ref> }"]; fourth [label="{ <data> 110 | <ref> }"]; node [shape=none]; null [label="NULL"]; head -> second [arrowhead=vee, arrowtail=dot, dir=both]; first:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; second:ref:c -> first [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; n -> first:ref [arrowhead=vee, arrowtail=crow, dir=both, color=red]; tmp -> third [arrowhead=vee, arrowtail=dot, dir=both, color=red]; } ``` ```cpp *node = (*node)->next; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=indigo]; n [label="node"]; node [shape=record, color=forestgreen]; head; tmp; node [shape=Mrecord, color=black]; first [label="{ <data> 72 | <ref> }"]; second [label="{ <data> 108 | <ref> }"]; third [label="{ <data> 109 | <ref> }"]; fourth [label="{ <data> 110 | <ref> }"]; node [shape=none]; null [label="NULL"]; head -> second [arrowhead=vee, arrowtail=dot, dir=both]; second:ref:c -> first [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; n -> first:ref [arrowhead=vee, arrowtail=crow, dir=both]; tmp -> third [arrowhead=vee, arrowtail=dot, dir=both]; first:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false, color=red]; } ``` ```cpp tmp->next = (*node)->next; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=indigo]; n [label="node"]; node [shape=record, color=forestgreen]; head; tmp; node [shape=Mrecord, color=black]; first [label="{ <data> 72 | <ref> }"]; second [label="{ <data> 108 | <ref> }"]; third [label="{ <data> 109 | <ref> }"]; fourth [label="{ <data> 110 | <ref> }"]; node [shape=none]; null [label="NULL"]; head -> second [arrowhead=vee, arrowtail=dot, dir=both]; second:ref:c -> first [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; n -> first:ref [arrowhead=vee, arrowtail=crow, dir=both]; tmp -> third [arrowhead=vee, arrowtail=dot, dir=both]; first:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false, color=red]; } ``` ```cpp (*node)->next = tmp; } ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=indigo]; n [label="node"]; node [shape=record, color=forestgreen]; head; tmp; node [shape=Mrecord, color=black]; first [label="{ <data> 72 | <ref> }"]; second [label="{ <data> 108 | <ref> }"]; third [label="{ <data> 109 | <ref> }"]; fourth [label="{ <data> 110 | <ref> }"]; node [shape=none]; null [label="NULL"]; head -> second [arrowhead=vee, arrowtail=dot, dir=both]; second:ref:c -> first [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; n -> first:ref [arrowhead=vee, arrowtail=crow, dir=both]; tmp -> third [arrowhead=vee, arrowtail=dot, dir=both]; first:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false, color=red]; } ``` ```cpp for (...; *node && (*node)->next; node = &(*node)->next->next) { ... } return head; } ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=indigo]; n [label="node"]; node [shape=record]; head; node [shape=Mrecord, color=black]; first [label="{ <data> 72 | <ref> }"]; second [label="{ <data> 108 | <ref> }"]; third [label="{ <data> 109 | <ref> }"]; fourth [label="{ <data> 110 | <ref> }"]; node [shape=none]; null [label="NULL"]; head -> second [arrowhead=vee, arrowtail=dot, dir=both]; second:ref:c -> first [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; first:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; n -> third:ref [arrowhead=vee, arrowtail=crow, dir=both, color=red]; } ``` ### reverse ```cpp node_t *reverse(node_t *head) { node_t *cursor = NULL; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=forestgreen]; head; cursor; node [shape=Mrecord, color=black]; first [label="{ <data> 108 | <ref> }"]; second [label="{ <data> 72 | <ref> }"]; third [label="{ <data> 110 | <ref> }"]; fourth [label="{ <data> 109 | <ref> }"]; node [shape=none]; null [label="NULL"]; head -> first [arrowhead=vee, arrowtail=dot, dir=both]; first:ref:c -> second [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; second:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; cursor -> null [arrowhead=vee, arrowtail=dot, dir=both]; } ``` Round 1 ```cpp while (head) { node_t *next = head->next; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=forestgreen]; head; cursor; next; node [shape=Mrecord, color=black]; first [label="{ <data> 108 | <ref> }"]; second [label="{ <data> 72 | <ref> }"]; third [label="{ <data> 110 | <ref> }"]; fourth [label="{ <data> 109 | <ref> }"]; node [shape=none]; null [label="NULL"]; head -> first [arrowhead=vee, arrowtail=dot, dir=both]; first:ref:c -> second [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; second:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; cursor -> null [arrowhead=vee, arrowtail=dot, dir=both]; next -> second [arrowhead=vee, arrowtail=dot, dir=both, color=red]; } ``` ```cpp head->next = cursor; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=forestgreen]; head; cursor; next; node [shape=Mrecord, color=black]; first [label="{ <data> 108 | <ref> }"]; second [label="{ <data> 72 | <ref> }"]; third [label="{ <data> 110 | <ref> }"]; fourth [label="{ <data> 109 | <ref> }"]; node [shape=none]; null [label="NULL"]; head -> first [arrowhead=vee, arrowtail=dot, dir=both]; second:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; cursor -> null [arrowhead=vee, arrowtail=dot, dir=both]; next -> second [arrowhead=vee, arrowtail=dot, dir=both]; first:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false, color=red]; } ``` ```cpp cursor = head; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=forestgreen]; head; cursor; next; node [shape=Mrecord, color=black]; first [label="{ <data> 108 | <ref> }"]; second [label="{ <data> 72 | <ref> }"]; third [label="{ <data> 110 | <ref> }"]; fourth [label="{ <data> 109 | <ref> }"]; node [shape=none]; null [label="NULL"]; head -> first [arrowhead=vee, arrowtail=dot, dir=both]; second:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; next -> second [arrowhead=vee, arrowtail=dot, dir=both]; first:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; cursor -> first [arrowhead=vee, arrowtail=dot, dir=both, color=red]; } ``` ```cpp head = next; } ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=forestgreen]; head; cursor; next; node [shape=Mrecord, color=black]; first [label="{ <data> 108 | <ref> }"]; second [label="{ <data> 72 | <ref> }"]; third [label="{ <data> 110 | <ref> }"]; fourth [label="{ <data> 109 | <ref> }"]; node [shape=none]; null [label="NULL"]; second:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; next -> second [arrowhead=vee, arrowtail=dot, dir=both]; first:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; cursor -> first [arrowhead=vee, arrowtail=dot, dir=both]; head -> second [arrowhead=vee, arrowtail=dot, dir=both, color=red]; } ``` Round 2 ```cpp while (head) { node_t *next = head->next; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=forestgreen]; head; cursor; next; node [shape=Mrecord, color=black]; first [label="{ <data> 108 | <ref> }"]; second [label="{ <data> 72 | <ref> }"]; third [label="{ <data> 110 | <ref> }"]; fourth [label="{ <data> 109 | <ref> }"]; node [shape=none]; null [label="NULL"]; second:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; first:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; cursor -> first [arrowhead=vee, arrowtail=dot, dir=both]; head -> second [arrowhead=vee, arrowtail=dot, dir=both]; next -> third [arrowhead=vee, arrowtail=dot, dir=both, color=red]; } ``` ```cpp head->next = cursor; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=forestgreen]; head; cursor; next; node [shape=Mrecord, color=black]; first [label="{ <data> 108 | <ref> }"]; second [label="{ <data> 72 | <ref> }"]; third [label="{ <data> 110 | <ref> }"]; fourth [label="{ <data> 109 | <ref> }"]; node [shape=none]; null [label="NULL"]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; first:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; cursor -> first [arrowhead=vee, arrowtail=dot, dir=both]; head -> second [arrowhead=vee, arrowtail=dot, dir=both]; next -> third [arrowhead=vee, arrowtail=dot, dir=both]; second:ref:c -> first [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false, color=red]; } ``` ```cpp cursor = head; ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=forestgreen]; head; cursor; next; node [shape=Mrecord, color=black]; first [label="{ <data> 108 | <ref> }"]; second [label="{ <data> 72 | <ref> }"]; third [label="{ <data> 110 | <ref> }"]; fourth [label="{ <data> 109 | <ref> }"]; node [shape=none]; null [label="NULL"]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; first:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; head -> second [arrowhead=vee, arrowtail=dot, dir=both]; next -> third [arrowhead=vee, arrowtail=dot, dir=both]; second:ref:c -> first [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; cursor -> second [arrowhead=vee, arrowtail=dot, dir=both, color=red]; } ``` ```cpp head = next; } ``` ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=forestgreen]; head; cursor; next; node [shape=Mrecord, color=black]; first [label="{ <data> 108 | <ref> }"]; second [label="{ <data> 72 | <ref> }"]; third [label="{ <data> 110 | <ref> }"]; fourth [label="{ <data> 109 | <ref> }"]; node [shape=none]; null [label="NULL"]; third:ref:c -> fourth [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; first:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; next -> third [arrowhead=vee, arrowtail=dot, dir=both]; second:ref:c -> first [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; cursor -> second [arrowhead=vee, arrowtail=dot, dir=both]; head -> third [arrowhead=vee, arrowtail=dot, dir=both, color=red]; } ``` Round 3 ... ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=forestgreen]; head; cursor; next; node [shape=Mrecord, color=black]; first [label="{ <data> 108 | <ref> }"]; second [label="{ <data> 72 | <ref> }"]; third [label="{ <data> 110 | <ref> }"]; fourth [label="{ <data> 109 | <ref> }"]; node [shape=none]; null [label="NULL"]; third:ref:c -> second [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; first:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; next -> fourth [arrowhead=vee, arrowtail=dot, dir=both]; second:ref:c -> first [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; cursor -> third [arrowhead=vee, arrowtail=dot, dir=both]; head -> fourth [arrowhead=vee, arrowtail=dot, dir=both, color=red]; } ``` Round 4 ... ```graphviz digraph linkedlist { rankdir=LR; node [shape=record, color=forestgreen]; head; cursor; next; node [shape=Mrecord, color=black]; first [label="{ <data> 108 | <ref> }"]; second [label="{ <data> 72 | <ref> }"]; third [label="{ <data> 110 | <ref> }"]; fourth [label="{ <data> 109 | <ref> }"]; node [shape=none]; null [label="NULL"]; third:ref:c -> second [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; fourth:ref:c -> third [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; first:ref:c -> null [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; next -> null [arrowhead=vee, arrowtail=dot, dir=both]; second:ref:c -> first [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false]; cursor -> fourth [arrowhead=vee, arrowtail=dot, dir=both]; head -> null [arrowhead=vee, arrowtail=dot, dir=both, color=red]; } ``` ```cpp return cursor; } ``` ## 2. 函式 swap_pair 和 reverse 對於指標的操作方式顯然異於 add_entry 及 remove_entry,需要額外做 head = ... 的更新,請用指標的指標來改寫,並避免回傳指標 ### swap_pair ```cpp void swap_pair(node_t **head) { for (; *head && (*head)->next; head = &(*head)->next->next) { node_t *tmp = *head; *head = (*head)->next; tmp->next = (*head)->next; (*head)->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; } ``` ## 3. 以遞迴改寫上述的 reverse,注意,你可能因此需要建立新的函式,如 rev_recursive,隨後在 reverse 函式中呼叫 rev_recursive ```cpp node_t *rev_recursive(node_t *node, node_t *cursor) { node_t *next = node->next; node->next = cursor; return (next) ? rev_recursive(next, node) : node; } void reverse(node_t **head) { if (*head) *head = rev_recursive(*head, NULL); } ``` ## 4. 針對 singly-linked list 的節點,實作 [Fisher–Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle),你應該儘量降低記憶體的使用量 ```cpp #include <time.h> size_t list_size(node_t *head) { size_t i = 0; for (; head; i++) head = head->next; return i; } void push_node(node_t **indirect, node_t *node) { node->next = *indirect; *indirect = node; } node_t *pop_node_by_pseudo_index(node_t *pseudo, size_t index) { for (; index; index--) pseudo = pseudo->next; node_t *cursor = pseudo; pseudo = pseudo->next; cursor->next = pseudo->next; pseudo->next = NULL; return pseudo; } void shuffle(node_t **head) { size_t size = list_size(*head); if (size < 2) return; node_t pseudo = {.next = *head}; *head = NULL; for (size_t i = size; 0 < i; i--) { size_t roll = rand() % i; push_node(head, pop_node_by_pseudo_index(&pseudo, roll)); } } int main(int argc, char const *argv[]) { srand((unsigned) time(NULL)); ... shuffle(&head); print_list(head); return 0; } ``` ## Reference * [2020q3 第 1 週測驗題](https://hackmd.io/@sysprog/sysprog2020-quiz1) * [Graphviz](https://graphviz.org/) * [LeetCode: Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs) * [Fisher–Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle)