---
# System prepended metadata

title: 2020q1 Homework1 (lab0)

---

# 2020q1 Homework1 (lab0)
contributed by < `tim00631` >

## 作業說明

[作業要求](https://hackmd.io/@sysprog/linux2020-lab0#-%E4%BD%9C%E6%A5%AD%E8%A6%81%E6%B1%82)
[Programming Lab](http://www.cs.cmu.edu/~213/labs/cprogramminglab.pdf)
[作業區](https://hackmd.io/@sysprog/linux2020-homework1)

### 作業要求

* 實作以下 queue 之相關操作
    * `q_new` - 建立一個空的 queue
    * `q_free` - 清空一個已創造的 queue
    * `q_insert_head` - 在 queue head 新增元素 (LIFO)
    * `q_insert_tail` - 在 queue tail 新增元素 (FIFO)
    * `q_remove_head` - 移除 queue 的開頭元素
    * `q_size` - return queue 之 元素個數
    * `q_reverse` - 反轉 queue 中的順序
* 注意事項
    * 須處理無效操作 (如，從空佇列或 `NULL` 佇列中刪除)
    * `q_insert_tail` 和 `q_size` 需在 $O(1)$ 完成

## queue.h 實作

### 在`queue_t` 增加 `size`  及 `tail` 
```c=
typedef struct {
    list_ele_t *head, *tail; /* Head and tail of this queue */
    unsigned long size; /* Size of queue_t */
} queue_t;
```
1. `size`欄位可使 `q_size` 在 $O(1)$ 內完成
2. `tail` 指向 queue 之末端元素

## queue.c 實作
### q_new
```c=
queue_t *q_new()
{
    queue_t *q = malloc(sizeof(queue_t));
    /* TODO: What if malloc returned NULL? */
    if (!q)
        return NULL;
    q->head = NULL;
    q->tail = NULL;
    q->size = 0;
    return q;
}
```
這裡檢查 `malloc` 是否成功分配記憶體空間，以及初始化賦值。
### q_free
```c=
void q_free(queue_t *q)
{
    if (q != NULL) {
        list_ele_t *tmp;
        while (q->head != NULL) {
            tmp = q->head->next;
            free(q->head->value);
            free(q->head);
            q->head = tmp;
        }
        free(q);
    }
}
```
釋放 queue 裡頭的每個元素 以及它的 `value` 欄位。
### q_insert_head
```c=
bool q_insert_head(queue_t *q, char *s)
{
    list_ele_t *newh;
    /* If q is NULL, return false */
    if (!q)
        return false;
    newh = (list_ele_t *)malloc(sizeof(list_ele_t));
    /* Check whether the space is enough or not */
    if (!newh)
        return false;
    size_t length = strlen(s) + 1;
    newh->value = (char *)malloc(length * sizeof(char));
    /* Check whether the space is enough or not */
    if (!newh->value) {
        free(newh);
        return false;
    }
    memcpy(newh->value, s, length);
    newh->next = q->head;
    /* If the queue is empty, let the tail pointer point to the new head */
    if (q->size == 0)
        q->head = q->tail = newh;
    else {
        q->head = newh;
    }
    q->size++;
    return true;
}
```
1. 如果 `queue` 為 `NULL`，回傳 `false`
2. 如果新增元素時 `malloc` 失敗，回傳 `false`
4. 如果新增 `value` 時 `malloc` 失敗，回傳 `false` ，且記得釋放先前 `malloc` 的元素，不然會有 memory leak 問題
5. 記得最後檢查當前是否只有一個元素，將 `head` 及 `tail` 指向它
### q_insert_tail
```c=
bool q_insert_tail(queue_t *q, char *s)
{
    list_ele_t *newt;
    /* If q is NULL, return false */
    if (!q)
        return false;
    newt = (list_ele_t *)malloc(sizeof(list_ele_t));
    /* Check whether the space is enough or not */
    if (!newt)
        return false;
    size_t length = strlen(s) + 1;
    newt->value = (char *)malloc(length * sizeof(char));
    /* Check whether the space is enough or not */
    if (!newt->value) {
        free(newt);
        return false;
    }
    memcpy(newt->value, s, length);
    /* If the queue is empty, let the head pointer point to the new tail */
    if (q->size == 0)
        q->head = q->tail = newt;
    else {
        q->tail->next = newt;
        q->tail = newt;
    }
    q->size++;
    return true;
}
```
1. 幾乎和 `q_insert_head` 實作相同，但需注意當前只有 1 個元素時， head 與 tail 的指標要修改
### q_remove_head
```c=

```
### q_size
```c=
int q_size(queue_t *q)
{
    return (q == NULL) ? 0 : q->size;
}
```
1. 需注意 queue 是否為 `NULL` ，如果不是，才可以 access 它的欄位
### q_reverse