# 2020q3 Homework1 (lab0)
contributed by < [@wiasliaw77210](https://github.com/wiasliaw77210) >
###### tags: `sysprog2020`
## Outline
[TOC]
## Environment
### Kernel
```bash=
uname -srv
# Linux 4.15.0-115-generic #116-Ubuntu SMP Wed Aug 26 14:04:49 UTC 2020
```
### Compiler
```bash=
gcc -v
# gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)
```
## Requirement
### queue implement
<pre>
queue.c 僅提供介面 (interface) 但尚未有完整程式實作,需要由學員補完並逐步精進,包含以下:
q_new: 建立新的「空」佇列;
q_free: 釋放佇列所佔用的記憶體;
q_insert_head: 在佇列開頭 (head) 加入 (insert) 給定的新元素 (以 LIFO 準則);
q_insert_tail: 在佇列尾端 (tail) 加入 (insert) 給定的新元素 (以 FIFO 準則);
q_remove_head: 在佇列開頭 (head) 移除 (remove) 給定的元素。
q_size: 計算佇列中的元素數量。
q_reverse: 以反向順序重新排列鏈結串列,該函式不該配置或釋放任何鏈結串列元素,換言之,它只能重排已經存在的元素;
q_sort: 「進階電腦系統理論與實作」課程所新增,以遞增順序來排序鏈結串列的元素,可參閱 Linked List Sort 得知實作手法;
</pre>
#### data type
```cpp=
/* queue.h */
/* Queue structure */
typedef struct {
list_ele_t *head, *last;
int size;
} queue_t;
```
#### q_new
> Requirement
> 1. Create empty queue.
> 2. Return NULL if could not allocate space.
根據 [參考](https://en.cppreference.com/w/c/memory/malloc), `malloc` 如果沒有辦法分配記憶體給 `q` 或是出現錯誤,會回傳 `NULL`。所以透過檢查 `q` 是否是 NULL 即可。
```cpp=
queue_t *q_new()
{
queue_t *q = malloc(sizeof(queue_t));
if (!q)
return q;
q->head = q->last = NULL;
q->size = 0;
return q;
}
```
#### q_free
> Requirement
> 1. Free all the element in queue
> 2. Free queue structure
從 queue 的 head 開始,將每個 head 之中的 char* 指標與 head 都釋放掉,最後再來釋放 queue。
```cpp=
void q_free(queue_t *q)
{
if (!q)
return;
while (q->head) {
list_ele_t *node = q->head;
q->head = q->head->next;
free(node->value);
free(node);
}
free(q);
}
```
#### q_insert_head
> Requirement
> 1. Return true if successful.
> 2. Return false if q is NULL or could not allocate space.
> 3. allocate space for the string and copy it
```cpp=
bool q_insert_head(queue_t *q, char *s)
{
if (!q)
return false;
list_ele_t *newh = malloc(sizeof(list_ele_t));
if (!newh)
return false;
newh->value = malloc(sizeof(char) * strlen(s));
if (!newh->value) {
free(newh);
return false;
}
strncpy(newh->value, s, strlen(s));
newh->next = q->head;
q->head = newh;
if (q->size == 0)
q->last = newh;
q->size++;
return true;
}
```
#### q_insert_tail
```cpp=
bool q_insert_tail(queue_t *q, char *s)
{
if (!q)
return false;
list_ele_t *newh = malloc(sizeof(list_ele_t));
if (!newh)
return false;
newh->value = malloc(sizeof(char) * strlen(s));
if (!newh->value) {
free(newh);
return false;
}
strncpy(newh->value, s, strlen(s));
newh->next = NULL;
if (q->last != NULL)
q->last->next = newh;
else
q->head = newh;
q->last = newh;
q->size++;
return true;
}
```
#### q_remove_head
```cpp=
bool q_remove_head(queue_t *q, char *sp, size_t bufsize)
{
/*
* Check if queue is NULL or EMPTY
*/
if (!q || !q->head)
return false;
list_ele_t *node = q->head;
// if sp is non-NULL, copy the removed element's value
if (sp) {
memset(sp, 0, bufsize);
strncpy(sp, node->value, bufsize);
}
// remove and free the element
q->head = q->head->next;
q->size--;
free(node->value);
free(node);
return true;
}
```
#### q_size
> Requirement
> 1. Return number of elements in queue.
> 2. It should operate in O(1) time.
我在 `queue_t` 新加了一個欄位 `size`,用以紀錄 queue 之中的數量,所以在其他 `queue` method 都有正確的實作之下,將 `size` 回傳即可。
```cpp=
int q_size(queue_t *q)
{
return q->size;
}
```
#### q_reverse
```cpp=
void q_reverse(queue_t *q)
{
list_ele_t *current = q->head, *prev = NULL, *next = q->head->next;
q->last = q->head;
while (next != NULL) {
current->next = prev;
prev = current;
current = next;
next = next->next;
}
current->next = prev;
q->head = current;
}
```
#### q_sort
```cpp=
list_ele_t *mergeSort(list_ele_t *head)
{
// check condition
if (!head || !head->next)
return head;
// split
list_ele_t *fast = head->next, *slow = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
fast = slow->next;
slow->next = NULL;
list_ele_t *l1 = mergeSort(head);
list_ele_t *l2 = mergeSort(fast);
return sortedMerge(l1, l2);
}
list_ele_t *sortedMerge(list_ele_t *a, list_ele_t *b)
{
// check condition
if (!a)
return b;
else if (!b)
return a;
if (strcmp(a->value, b->value) < 0) {
a->next = sortedMerge(a->next, b);
return a;
} else {
b->next = sortedMerge(a, b->next);
return a;
}
}
```
## 遇到的問題
1. Merge Sort Segmentation fault occurred
不知道哪個 statement 造成
## 參考資料
- [lab0 說明](https://hackmd.io/@sysprog/2020-lab0#-%E4%BD%9C%E6%A5%AD%E8%A6%81%E6%B1%82)
- [Merge Sort](https://github.com/alrightchiu/SecondRound/blob/master/content/Algorithms%20and%20Data%20Structures/BasicDataStructures/LinkedList/Article/LinkedList_MemberFunction.md)
- [Merge Sort - geeksforgeeks](https://www.geeksforgeeks.org/merge-sort-for-linked-list/)