# 2019q1 Homework1 (lab0) contributted by < [`billqwer1687`](https://github.com/billqwer1687) > :::danger 認真看作業要求,除了提及如何逐步達到要求,還需要進行: 1. 改善程式效能 2. 解釋自動評分系統運作的原理 3. 提及 qtest 的行為和裡頭的技巧 還未達成符合預期目標,請繼續付出! :notes: jserv ::: ## 開發環境 ```shell $ uname -a Linux bill-X550JX 4.18.0-15-generic #16~18.04.1-Ubuntu SMP Thu Feb 7 14:06:04 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux $ gcc --version gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 ``` ## 作業要求 實作以下 LIFO FIFO Queue 之功能 * ***qnew:*** Create a new, empty queue. * ***qfree:*** Free all storage used by a queue. * ***qinserthead:*** Attempt to insert a new element at the head of the queue (LIFO discipline). * ***qinserttail:*** Attempt to insert a new element at the tail of the queue (FIFO discipline). * ***qremovehead:*** Attempt to remove the element at the head of the queue. * ***qsize:*** Compute the number of elements in the queue. * **詳細說明 :** * [作業說明](https://hackmd.io/s/BJA8EgFB4) * [C Programming Lab](http://www.cs.cmu.edu/~213/labs/cprogramminglab.pdf) ## 實作 ### queue structure ```clike= typedef struct { list_ele_t *head; /* Linked list of elements */ list_ele_t *tail; int size; } queue_t; ``` 新增了指標tail與變數size,目的是為了讓insert from tail與計算size的時間複雜度為$O(1)$ ### q_new ```clike= queue_t *q_new() { queue_t *q = malloc(sizeof(queue_t)); /* What if malloc returned NULL? */ if (q == NULL) { return q; } q->head = NULL; q->tail = NULL; q->size = 0; return q; } ``` 將queue初始化,且要記得malloc為NULL的狀況 ### q_free ```clike= void q_free(queue_t *q) { /* How about freeing the list elements and the strings? */ if (!q) { return; } while (q->head) { list_ele_t *temp; temp = q->head; q->head = q->head->next; free(temp->value); free(temp); } /* Free queue structure */ free(q); } ``` 這邊要先free value才能free temp等到queue為空時再將queue給清空 ### q_insert_head ```clike= bool q_insert_head(queue_t *q, char *s) { if (!q) { return false; } list_ele_t *newh; /* What should you do if the q is NULL? */ newh = malloc(sizeof(list_ele_t)); if (!newh) { return false; } newh->value = malloc(strlen(s) + 1); if (newh->value == NULL) { free(newh); return false; } strcpy(newh->value, s); if (q->head == NULL) { q->head = newh; q->tail = newh; q->tail->next = NULL; q->size++; return true; } /* Don't forget to allocate space for the string and copy it */ /* What if either call to malloc returns NULL? */ newh->next = q->head; q->head = newh; q->size++; return true; } ``` 在寫作業的時候忘記將tail指向NULL所以出現了Bug ### q_insert_tail ```clike= bool q_insert_tail(queue_t *q, char *s) { /* You need to write the complete code for this function */ if (!q) { return false; } list_ele_t *newh; /* What should you do if the q is NULL? */ newh = malloc(sizeof(list_ele_t)); if (!newh) { return false; } newh->value = malloc(strlen(s) + 1); if (newh->value == NULL) { free(newh); return false; } strcpy(newh->value, s); if (q->tail == NULL) { q->head = newh; q->tail = newh; q->tail->next = NULL; q->size++; return true; } else { q->tail->next = newh; q->tail = q->tail->next; q->tail->next = NULL; q->size++; /* Remember: It should operate in O(1) time */ return true; } } ``` 這邊也是忘記將tail指向NULL ### q_remove_head ```clike= bool q_remove_head(queue_t *q, char *sp, size_t bufsize) { /* You need to fix up this code. */ if (!q || q->head == NULL) { return false; } if (sp) { strncpy(sp, q->head->value, bufsize - 1); sp[bufsize - 1] = '\0'; } list_ele_t *temp; temp = q->head; q->head = q->head->next; free(temp->value); free(temp); q->size--; return true; } ``` sp[bufsize-1]是為了將'\0'放入字串的尾端,因為strncpy不會在尾端留'\0' ### q_size ```clike= int q_size(queue_t *q) { /* You need to write the code for this function */ if (!q) { return 0; } /* Remember: It should operate in O(1) time */ return q->size; } ``` 因為有使用變數size儲存queue的大小所以在這裡可以以$O(1)$的時間複雜度求得queue的size ### q_reverse ```clike= void q_reverse(queue_t *q) { /* You need to write the code for this function */ if (!q || q->size < 2) { return; } list_ele_t *current = q->head; list_ele_t *prev = NULL; list_ele_t *rear; while (current != NULL) { rear = current->next; current->next = prev; prev = current; current = rear; } q->tail = q->head; q->head = prev; } ``` 此處queue的反轉參考了以下的資料[資料參考](https://www.geeksforgeeks.org/reverse-a-linked-list/),然後在q->tail = q->head的地方打反了,找了一下子 :::info TOTAL 100/100 ::: ## 自動評分系統運作的原理 在trace資料夾中有cmd命令檔案,test會依據這些cmd的命令所回傳的結果去判定程式執行是否正確 ***待補完*** ## ```qtest``` 的行為和裡頭的技巧 待補