# 2019q1 Homework1 (lab0)
contributed by < `LiunuXXX` >
[作業解說](https://hackmd.io/s/BJA8EgFB4)
[C Programming Lab](http://www.cs.cmu.edu/~213/labs/cprogramminglab.pdf)
###### tags: DesignOfLinuxkernel-HW
## 題目要求
* #### By modifying the code in queue.h and queue.c to fully implement the following fuctions.
* **q_new :** Create a new, empty queue
> (Notice that An empty queue is one pointing to a valid structure, but the head field has value NULL.)
* **q.free :** Free all storage used by a queue.
* **q_insert_head :** Attempt to insert a new element at the head of the queue (LIFO discipline).
* **q_insert_tail :** Attempt to insert a new element at the tail of the queue (FIFO discipline).
* **q_remove_head :** Attempt to remove the element at the head of the queue.
* **q_size :** Compute the number of elements in the queue.
* **q_reverse :** Reorder the list so that the queue elements are reversed in order.
>(Noitce that this function should not allocate or free any list elements.)
-------
## 實作
### Queue Structure :
為了使 q_size 和 q_insert_tail 在 $O(1)$ 時間內完成,在 Queue Structure 內加入 tail 和 size 分別記錄尾端指標和大小。
```clike=
/* Queue structure */
typedef struct {
int size;
list_ele_t *tail;
list_ele_t *head; /* Linked list of elements */
/*
You will need to add more fields to this structure
to efficiently implement q_size and q_insert_tail
*/
} queue_t;
```
### q_new :
初始化queue
```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 :
釋放 queue 所佔用的空間,若 queue 為空則 return,
否則利用 this 記錄 head,並逐步釋放每一個 node 的 value 及其空間。
```clike=
/* Free all storage used by queue */
void q_free(queue_t *q)
{
/* How about freeing the list elements and the strings? */
if (!q)
return;
list_ele_t *this = q->head;
while (this) {
list_ele_t *temp;
temp = this;
this = this->next;
free(temp->value);
free(temp);
}
/* Free queue structure */
free(q);
}
```
### q_insert_head :
* 插入 node 於 queue_head
* 以下三種情況回傳false :
1. queue is NULL
2. malloc 失敗
3. input string 為 NULL
* 此外,若 queue 為 empty queue,則 head 和 tail 均指向 inserted node (newh)
```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;
/* Don't forget to allocate space for the string and copy it */
/* What if either call to malloc returns NULL? */
newh->value = strdup(s);
if (!newh->value) {
free(newh);
return false;
}
if (!q->head) {
q->tail = newh;
}
newh->next = q->head;
q->head = newh;
q->size++;
return true;
}
```
### q_insert_tail
* 插入 node 於 queue_tail,
* 同 q_insert_head,以下三種情況回傳 false :
1. queue is NULL
2. malloc 失敗
3. input string 為 NULL
* 若 queue 為 empty queue,則 head 和 tail 均指向 inserted node (newh)
```clike=
bool q_insert_tail(queue_t *q, char *s)
{
/* You need to write the complete code for this function */
/* Remember: It should operate in O(1) time */
if (!q)
return false;
list_ele_t *newh;
newh = malloc(sizeof(list_ele_t));
if (!newh)
return false;
newh->value = strdup(s);
if (!newh->value) {
free(newh);
return false;
}
newh->next = NULL;
if (!q->head) {
q->tail = newh;
q->head = newh; /* if queue is empty */
}
q->tail->next = newh;
q->tail = newh;
q->size++;
return true;
}
```
### q_remove_head
* 若 queue is NULL 或 queue is empty 則 return false
* 將 removed node 中的字串複製到 sp
* 若 q_size >= 2,將 head 指向 head 指的下一個 node,並釋放 removed node
```clike=
bool q_remove_head(queue_t *q, char *sp, size_t bufsize)
{
/* You need to fix up this code. */
if (!q || !q->head)
return false;
list_ele_t *temp;
temp = q->head;
/* Copy removed value to sp */
if (sp) {
strncpy(sp, temp->value, bufsize);
sp[bufsize - 1] = '\0';
}
/* If queue has only one node */
if (q->size == 1) {
q->head = NULL;
q->tail = NULL;
} else {
q->head = q->head->next;
}
q->size--;
/* Free temp */
free(temp->value);
free(temp);
return true;
}
```
### q_size
若 queue is NULL 則 return 0,否則 return q->size 即可
```clike=
int q_size(queue_t *q)
{
/* You need to write the code for this function */
/* Remember: It should operate in O(1) time */
if (!q)
return 0;
return q->size;
}
```
### q_reverse
將queue反轉,策略是利用 r 指標緊跟著 p 後面,並從 q_head 開始,循序將各個 node(即 p) 的 next 指向 r,最後再將 head 和 tail 互換即可
```clike=
void q_reverse(queue_t *q)
{
if (!q || q->size <= 1)
return;
list_ele_t *p, *r, *s, *temp; /* r follows p */
p = NULL;
s = q->head;
while (s) {
r = p;
p = s;
s = s->next;
p->next = r;
}
/* Swap head and tail */
temp = q->tail;
q->tail = q->head;
q->head = temp;
}
```
## 解釋自動評分系統運作的原理
未完成待補
## 提及 qtest 的行為和裡頭的技巧
未完成待補