# 2019q1 Homework1 (lab0) contributed by < `ChienHisang` > ###### tags: `linux_kernel` --- ### 作業目標 : 修改 queue.c 與 queue.h 並通過測試。 ### queue.h 功能說明: * 定義 queue 結構 * 定義 node 結構 * 定義介面: * q_new() * q_free * q_insert_head * q_insert_tail * q_remove_head * q_size * q_reverse ### queue.c 功能說明: * 實作 queue.h 中定義的所有函數 --- ## 修改 queue.h ### 原因 : 作業要求在 O(1) 內回傳該 queue 的長度與在 queue 尾部插入節點 ### `struct queue_t` #### 說明 : 加入 *tail 與 size。 ```clike /* Queue structure */ typedef struct { list_ele_t *head; /* Linked list of elements */ list_ele_t *tail; int size; /*Linked list size*/ } queue_t; ``` ## 修改 queue.c ### 原因 : 實作 queue.h 中所有函數 ### `q_new()` #### 說明 : 獲取一個 queue_t 大小的記憶體空間指派給q。 ```clike= queue_t *q_new() { queue_t *q = malloc(sizeof(queue_t)); /* What if malloc returned NULL? */ if (!q) return NULL; q->head = NULL; q->tail = NULL; q->size = 0; return q; } ``` ### `q_free()` #### 說明 : cur 指向當前的 node,由於當前 node 會被 free 掉,所以在那之前需用 cur_next 暫存下一個 node 的地址,待當前 node 被 free 後再把下一個 node 的地址移交給 cur,反覆動作直到 cur==null,須注意當發現 queue 的 head 為 null 時,記得把queue free 掉。 ```clike= void q_free(queue_t *q) { if (!q) return; list_ele_t *cur = q->head, *cur_next = NULL; if (!cur) { free(q); return; } while (cur) { cur_next = cur->next; free(cur->value); free(cur); cur = cur_next; } free(q); } ``` ### `q_insert_head()` #### 說明 : 將新增的 node 加在當前 queue 的最前端,需特別注意當前 queue 的 node 數,若新增的 node 為該 queue 中的第一個節點,則不需作將原本的 head 指派給 node->next。 ```clike= bool q_insert_head(queue_t *q, char *s) { if (!q) return false; list_ele_t *newh; newh = malloc(sizeof(list_ele_t)); if (!newh) return false; newh->value = malloc(sizeof(char) + strlen(s)); if (!newh->value) { free(newh); return false; } strcpy(newh->value, s); newh->next = NULL; if (!q->head) q->head = newh; else { newh->next = q->head; q->head = newh; } if (!q->tail) q->tail = newh; q->size++; return true; } ``` ### `q_insert_tail()` #### 說明 : 因為在 queue_t 中加入 tail 指標,故能在 o(1) 內將新增的 node 插入 queue 結尾,須注意 malloc 給 node->value 時,記得幫 char 陣列結尾符號'\0'留位子,可以是 1 或 sizeof(char),還須注意當前 queue 中的 node 數。 ```clike= bool q_insert_tail(queue_t *q, char *s) { if (!q) return false; list_ele_t *newt = malloc(sizeof(list_ele_t)); if (!newt) return false; newt->value = malloc(sizeof(char) + strlen(s)); if (newt->value) { strcpy(newt->value, s); newt->next = NULL; } else { free(newt); return false; } if (q->tail) q->tail->next = newt; q->tail = newt; if (!q->head) q->head = newt; q->size++; return true; } ``` ### `q_remove_head()` #### 說明 : 將head值移轉給sp後,把head指標只給原本head的next node,須注意memeset的使用方法。 ```clike= bool q_remove_head(queue_t *q, char *sp, size_t bufsize) { if (!q || !sp || !q->head || !q->head->value) return false; list_ele_t *tmp = q->head; memset(sp, '\0', bufsize); strncpy(sp, tmp->value, bufsize - 1); q->head = tmp->next; if (!q->head) q->tail = NULL; free(tmp->value); free(tmp); q->size--; return true; } ``` ### `q_size()` #### 說明 : 在O(1)時間內返回值,故無法使用遍例queue的方式,因此在queue_t中加入size,因為size不可能為負值,故宣告成size_t 或 unsigned int會更好。 ```clike= int q_size(queue_t *q) { if (!q || !q->head) return 0; return q->size; } ``` ### `q_reverse()` #### 說明 : 將cur指到的node的next指給pre指向的node,由於這個動作或造成cur指到的node之next丟失,所以在這之前需要用next_tmp將其保存下來,完成動作後,pre向後一格,cur也向後一格,反覆直到cur為null,最後記得把queue中的head與tail對調。 ```clike= void q_reverse(queue_t *q) { if (!q || !q->head || !q->head->next) return; list_ele_t *pre = q->head, *cur = q->head->next, *next_tmp = NULL; pre->next = NULL; while (cur) { next_tmp = cur->next; cur->next = pre; pre = cur; cur = next_tmp; } q->tail = q->head; q->head = pre; } ```