# 2020q3 Homework1 (quiz1) contributed by < `chi-ming5566` > --- ## 程式運作 以 `add_entry()`, `find_entry()`, `remove_entry()`, `swap_pair()`, `reverse()`, `print_list()` 等函式所組成 --- ### `add_entry()` ```cpp= 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; AA1; while (*indirect) indirect = &(*indirect)->next; AA2; } ``` * 答案 * AA1為 `(a) assert(new_node)` * AA2為 `(b) *indirect = new_node` * 說明 * `*head`會指向 linked list 的尾端,在其插入一個 value 為 `new_value` 的 node。 * `**indirect` 是用來尋找 linked list (**head) 的尾端,而當 `*indirect` 找到尾端時, `*indirect == NULL`,就會將 `new_node` 插入linked list。 * 而 `assert` 是要確保 `new_node` 會正確分配記憶體,於是建立第一個 node,所以會直接跳到第 11 行,將 `indirect` 所存放的 value 當作 adrress,並且更改此 address 存放的 value,將該 value 改為 new_node 的 value。 --- ### `find_entry()` ```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; } ``` * 說明 * 用 for 迴圈找到`*head` 後,傳回存放的值為 `value` 的 node,用於刪除某一個 node。 --- ### `remove_entry()` ```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); } ``` * 說明 * 在 linked list 中找到 `**head`找到 node `*head` 然後刪除。 * 需要變更的 pointer 只有指向 `entry` 的 pointer,因此以 `**indirect` 存放此 pointer 的 address。 * 最後將此 `*indirect` 指向 `entry->next`,就不會有其他 pointer 指向該處。 * 以作業為例: ```cpp= 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); ``` 先執行到第10行,接著將 `head` 的 address與要刪除的 node 的 address 當作參數,一起傳入`remove_entry()`。 ```graphviz digraph a{ node [shape=record]; rankdir=LR entry [label="{<addr>(entry)|<ref>}"] head [label="{<addr>(main_head)|}"]; a [label="{{<addr>|<next_addr>}|{72|<ref>}}"]; b [label="{{<addr>|<next_addr>}|{101|<ref>}}"]; c [label="{{<addr>|<next_addr>}|{108|<ref>}}"]; d [label="{{<addr>|<next_addr>}|{109|<ref>}}"]; e [label="{{<addr>|<next_addr>}|{110|<ref>}}"]; f [label="{{<addr>|<next_addr>}|{111|<ref>}}"]; head->a:addr; a:ref->b:addr; entry:ref->b:addr; b:ref->c:addr; c:ref->d:addr; d:ref->e:addr; e:ref->f:addr; } ``` --- ```cpp= void remove_entry(node_t **head, node_t *entry) { node_t **indirect = head; ``` `head` 的 value 是 `main` 的 `head` 的 address `indirect` 存放 `head` 存放的 value ```graphviz digraph a{ node [shape=record]; rankdir=LR a [label="{{<addr>|<next_addr>}|{72|<ref>}}"]; b [label="{{<addr>|<next_addr>}|{101|<ref>}}"]; c [label="{{<addr>|<next_addr>}|{108|<ref>}}"]; d [label="{{<addr>|<next_addr>}|{109|<ref>}}"]; e [label="{{<addr>|<next_addr>}|{110|<ref>}}"]; f [label="{{<addr>|<next_addr>}|{111|<ref>}}"]; a:ref->b:addr; b:ref->c:addr; c:ref->d:addr; d:ref->e:addr; e:ref->f:addr; now_head [label="{<addr>(head)|<data>}"] head [label="{<addr>(main_head)|<data>}"]; now_head:data->head:addr; head:data->a:addr; indirect [label="{<addr>(indirect)|<data>}"]; indirect:data->head:addr; entry [label="{<addr>(entry)|<data>}"]; entry:data->b:addr; } ``` --- ```cpp= *indirect = entry->next; ``` 讓 `*indirect` 所存放的值換為 `entry->next`,如此便可以達到刪除的目的 ```graphviz digraph a{ node [shape=record]; rankdir=LR a [label="{{<addr>|<next_addr>}|{72|<ref>}}"]; b [label="{{<addr>|<next_addr>}|{101|<ref>}}"]; c [label="{{<addr>|<next_addr>}|{108|<ref>}}"]; d [label="{{<addr>|<next_addr>}|{109|<ref>}}"]; e [label="{{<addr>|<next_addr>}|{110|<ref>}}"]; f [label="{{<addr>|<next_addr>}|{111|<ref>}}"]; a:ref->c:addr [color=red]; b:ref->c:addr; c:ref->d:addr; d:ref->e:addr; e:ref->f:addr; main_head [label="{<addr>(main_head)|<data>}"]; main_head->a:addr; head [label="{<addr>(head)|<data>}"]; head:data->main_head:addr; indirect [label="{<addr>(indirect)|<data>}"]; indirect:data->a:next_addr; entry [label="{<addr>(entry)|<data>}"]; entry:data->b:addr; } ``` --- ### `swap_pair()` ```cpp= node_t *swap_pair(node_t *head) { for (node_t **node = &head; *node && (*node)->next; BB1) { node_t *tmp = *node; BB2; tmp->next = (*node)->next; (*node)->next = tmp; } return head; } ``` 目的:交換一對相鄰的節點,取自 LeetCode: Swap Nodes in Pairs,給定 1->2->3->4,則該回傳 2->1->4->3 ```graphviz digraph swap{ node [shape="record"] rankdir=LR; A [label="{{<addr>|<next_addr>}|{72|<ref>}}"]; //B [label="{{<addr>|<next_addr>}|{101|<ref>}}"]; C [label="{{<addr>|<next_addr>}|{108|<ref>}}"]; D [label="{{<addr>|<next_addr>}|{109|<ref>}}"]; E [label="{{<addr>|<next_addr>}|{110|<ref>}}"]; //F [label="{{<addr>|<next_addr>}|{111|<ref>}}"]; A:ref->C:addr; //B:ref->C:addr; C:ref->D:addr; D:ref->E:addr; //E:ref->F:addr; main_head [label="{<addr>(main_head)|<data>}"]; main_head->A:addr; //head [label="{<addr>(head)|<data>}"]; //head:data->main_head:addr; //indirect [label="{<addr>(indirect)|<data>}"]; //indirect:data->A:next_addr; //entry [label="{<addr>(entry)|<data>}"]; } ```