# 2024q1 Homework1 (lab0) contributed by < [YeeeLiang](https://github.com/YeeeLiang) > ### Reviewed by `yenslife` - [ ] GitHub :::danger command 是「命令」,而非「指令」(instruction)。 不用假裝有禮貌說「建議」,就是因為同學沒做好,你要求他改進。 ::: <s>建議</s> 將程式碼上傳到 Github 上,方便追蹤。你可以使用 `git push origin [分支名稱]` <s>指令</s>來上傳 (origin 表示你的 remote repo 的 url,可以透過 `git remote -v` 來查看) :::danger 留意各式細節,唯有重視小處並步步為營,方可挑戰原始程式碼規模超越三千七百萬行的 Linux 核心 ::: ### Reviewed by `yeh-sudo` 開發過程沒有描述你的想法與作法,只有貼上程式碼,在你的 Github 上也沒有你上傳的程式碼,請將程式碼上傳至你的 Github ,並且有完整的 git commit message 來闡述你做了什麼以及你的實作方法,可以參考〈[How to Write a Git Commit Message](https://cbea.ms/git-commit/)〉。 # 開發環境 ```shell $ gcc --version gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0 $ lscpu Architecture: x86_64 CPU op-mode(s): 64-bit Byte Order: Little Endian Address sizes: 39 bits physical, 48 bits virtual CPU(s): 8 On-line CPU(s) list: 0-7 Thread(s) per core: 2 Core(s) per socket: 4 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 126 Model name: Intel(R) Core(TM) i5-1035G1 CPU @ 1.00GHz Stepping: 5 CPU MHz: 1200.000 CPU max MHz: 3600.0000 CPU min MHz: 400.0000 BogoMIPS: 2380.80 Virtualization: VT-x L1d cache: 192 KiB L1i cache: 128 KiB L2 cache: 2 MiB L3 cache: 6 MiB NUMA node0 CPU(s): 0-7 ``` ## 針對佇列操作的程式碼實作 :::danger 改進你的漢語表達。 ::: 這個函式將在佇列的頭部插入一個新節點,資料為傳遞給函式的 data。如果佇列是空的,新節點將同時成為尾端節點。 :::danger 說好的進度呢? ::: :::info 抱歉,之前Git遇上傳輸困難,目前正努力補齊中 > 你唯一需要跟我道歉的理由是,你不夠強。 :notes: jserv ::: <s> ## q_new ```c /* Create an empty queue */ struct list_head *q_new() { struct list_head *head = malloc(sizeof(struct list_head)); if (head != NULL) { INIT_LIST_HEAD(head); } return head; } ``` ## q_free ```c /* Free all storage used by queue */ void q_free(struct list_head *head) { struct list_head *pos, *temp; element_t *entry; list_for_each_safe(pos, temp, head) { entry = list_entry(pos, element_t, list); free(entry->data); list_del(pos); free(entry); } free(head); } ``` ## q_insert_head ```c /* Insert an element at head of queue */ bool q_insert_head(struct list_head *head, char *s) { element_t *new_element = malloc(sizeof(element_t)); if (new_element == NULL) { return false; } new_element->data = strdup(s); if (new_element->data == NULL) { free(new_element); return false; } list_add(&new_element->list, head); return true; } ``` ## q_insert_tail ```c /* Insert an element at tail of queue */ bool q_insert_tail(struct list_head *head, char *s) { element_t *new_element = malloc(sizeof(element_t)); if (new_element == NULL) { return false; } new_element->data = strdup(s); if (new_element->data == NULL) { free(new_element); return false; } list_add_tail(&new_element->list, head); return true; } ``` ## q_remove_head ```c /* Remove an element from head of queue */ element_t *q_remove_head(struct list_head *head, char *sp, size_t bufsize) { if (list_empty(head)) { return NULL; } element_t *entry = list_first_entry(head, element_t, list); strncpy(sp, entry->data, bufsize - 1); sp[bufsize - 1] = '\0'; list_del(&entry->list); free(entry->data); free(entry); return entry; } ``` ## q_remove_tail ```c /* Remove an element from tail of queue */ element_t *q_remove_tail(struct list_head *head, char *sp, size_t bufsize) { if (list_empty(head)) { return NULL; } element_t *entry = list_last_entry(head, element_t, list); strncpy(sp, entry->data, bufsize - 1); sp[bufsize - 1] = '\0'; list_del(&entry->list); free(entry->data); free(entry); return entry; } ``` ## q_size :::danger 留意用語。 $\to$ [資訊科技詞彙翻譯](https://hackmd.io/@sysprog/it-vocabulary) ::: 光看<s>函數</s> 名字,不容易想起功用為何(筆記一下) 主要功能:計算目前佇列的節點總量 ```c /* Return number of elements in queue */ int q_size(struct list_head *head) { return list_empty(head) ? 0 : list_size(head); } ``` ## q_delete_mid ```c /* Delete the middle node in queue */ bool q_delete_mid(struct list_head *head) { if (list_empty(head)) { return false; } struct list_head *slow = head; struct list_head *fast = head; while (fast != NULL && fast->next != NULL) { slow = slow->next; fast = fast->next->next; } struct list_head *temp = slow->prev->next; list_del(temp); free(list_entry(temp, element_t, list)->data); free(list_entry(temp, element_t, list)); return true; } ``` ## q_delete_dup ```c /* Delete all nodes that have duplicate string */ bool q_delete_dup(struct list_head *head) { if (list_empty(head)) { return false; } struct list_head *current, *temp; element_t *current_entry, *temp_entry; list_for_each_safe(current, temp, head) { current_entry = list_entry(current, element_t, list); struct list_head *compare, *temp_compare; element_t *compare_entry, *temp_compare_entry; list_for_each_safe(compare, temp_compare, head) { if (compare != current) { compare_entry = list_entry(compare, element_t, list); if (strcmp(current_entry->data, compare_entry->data) == 0) { temp_compare_entry = list_entry(temp_compare, element_t, list); list_del(temp_compare); free(temp_compare_entry->data); free(temp_compare_entry); } } } } return true; } ``` ## q_swap 兩個鄰近的node進行交換,[如圖](https://leetcode.com/problems/swap-nodes-in-pairs/description/) ```c /* Swap every two adjacent nodes */ void q_swap(struct list_head *head) { if (list_size(head) < 2) { return; } struct list_head *pos; element_t *current, *next; list_for_each(pos, head) { current = list_entry(pos, element_t, list); if (pos->next != head) { next = list_entry(pos->next, element_t, list); char *temp = current->data; current->data = next->data; next->data = temp; } pos = pos->next; } } ``` :::danger HackMD 不是讓你張貼完整程式碼的地方,GitHub 才是!因此你在開發紀錄只該列出關鍵程式碼 (善用 diff 標示),可附上對應 GitHub commit 的超連結,列出程式碼是為了「檢討」和「便於他人參與討論」,不是用來「假裝自己有付出」 ::: ## q_reverse :::danger 無論標題和內文中,中文和英文字元之間要有空白字元 (對排版和文字搜尋有利)。 ::: 注意:q_reverse 只能重排已經存在的節點,因此不該配置或釋放任何鏈結串列節點 ```c /* Reverse elements in queue */ void q_reverse(struct list_head *head) { if (list_empty(head) || list_size(head) == 1) { return; } struct list_head *current, *temp; element_t *current_entry, *temp_entry; list_for_each_safe(current, temp, head) { current_entry = list_entry(current, element_t, list); // Move the current element to the front list_move(&current_entry->list, head); } } ``` ## q_reverseK 也是反向順序排列,與q_reverse不同在於,q_reverseK指定每 k 個節點為一組 ```c /* Reverse the nodes of the list k at a time */ void q_reverseK(struct list_head *head, int k) { if (list_size(head) < k) { return; } struct list_head *pos, *temp; element_t *current, *next; int count = 0; list_for_each_safe(pos, temp, head) { if (count == k) { count = 0; continue; } current = list_entry(pos, element_t, list); if (count < k) { next = list_entry(pos->next, element_t, list); char *temp_data = current->data; current->data = next->data; next->data = temp_data; } count++; } } ``` :::danger HackMD 不是讓你張貼完整程式碼的地方,GitHub 才是!因此你在開發紀錄只該列出關鍵程式碼 (善用 diff 標示),可附上對應 GitHub commit 的超連結,列出程式碼是為了「檢討」和「便於他人參與討論」,不是用來「假裝自己有付出」 ::: ## q_sort 以遞增順序來排序 ```c /* Sort elements of queue in ascending/descending order */ void q_sort(struct list_head *head, bool descend) { if (list_empty(head) || list_size(head) == 1) { return; } } ``` ## q_descend 可參閱[2487. Remove Nodes From Linked List](https://leetcode.com/problems/remove-nodes-from-linked-list/description/)的圖,有助於程式碼的理解 ```c /* Remove every node which has a node with a strictly greater value anywhere to * the right side of it */ int q_descend(struct list_head *head) { if (list_empty(head) || list_size(head) == 1) { return 0; } int removed_nodes = 0; struct list_head *current, *temp; element_t *current_entry, *temp_entry; list_for_each_safe(current, temp, head) { current_entry = list_entry(current, element_t, list); struct list_head *compare, *temp_compare; element_t *compare_entry, *temp_compare_entry; list_for_each_safe(compare, temp_compare, head) { if (compare != current) { compare_entry = list_entry(compare, element_t, list); if (strcmp(current_entry->data, compare_entry->data) < 0) { temp_compare_entry = list_entry(temp_compare, element_t, list); list_del(temp_compare); free(temp_compare_entry->data); free(temp_compare_entry); removed_nodes++; } } } } return removed_nodes; } ``` :::danger HackMD 不是讓你張貼完整程式碼的地方,GitHub 才是!因此你在開發紀錄只該列出關鍵程式碼 (善用 diff 標示),可附上對應 GitHub commit 的超連結,列出程式碼是為了「檢討」和「便於他人參與討論」,不是用來「假裝自己有付出」 ::: ## q_merge ```c /* Merge all the queues into one sorted queue, which is in ascending/descending * order */ int q_merge(struct list_head *head, bool descend) { return 0; } int main() { return 0; } ``` </s> :::danger HackMD 不是讓你張貼完整程式碼的地方,GitHub 才是!因此你在開發紀錄只該列出關鍵程式碼 (善用 diff 標示),可附上對應 GitHub commit 的超連結,列出程式碼是為了「檢討」和「便於他人參與討論」,不是用來「假裝自己有付出」 :::