---
# System prepended metadata

title: 2023q1 Homework1 (quiz1)

---

# 2023q1 Homework1 (quiz1)
contributed by < [willow11235811](https://github.com/willow11235811) >

## 測驗題目
:::danger
不用抄題目，闡述你的認知。
:notes: jserv
>已修改
:::

上述快速排序法，會將以 ```pivot``` 分割出數值較小的 ```list_less``` 與數值較大的 ```list_greater``` 。
```CCC``` 作用為依序走訪整個所有節點，應使用 ```list_for_each_entry_safe``` 。
用以對節點內含值比較的函式 ```cmpint``` 會比較 ```itm``` 和 ```pivot``` 的值，若 ```itm``` 較小，會回傳負值。  

```DDD``` 應將較 ```pivot``` 小的節點移出並加入 ```list_less``` 中； ```EEE``` 則是處理相等或較大的節點。
因此 ```DDD``` 與 ```EEE``` 應為 ```list_move_tail``` ，將移出的節點附加到對應佇列的尾部。
```c
    list_add(&pivot->list, head);
    list_splice(&list_less, head);
    FFF(&list_greater, head);
```
合併佇列時， ```list_add``` 將 ```pivot``` 節點加入 ```head``` 佇列的頭部。
```list_splice``` 將 ```list_less``` 黏貼至 ```pivot``` 節點之前，
因此 ```FFF``` 應為 ```list_splice_tail```，要將 ```list_greater``` 黏貼至 ```pivot``` 節點之後。
:::spoiler 測驗1 完整程式碼
```c
static void list_sort(struct list_head *head)
{
    if (list_empty(head) || list_is_singular(head))
        return;

    struct list_head list_less, list_greater;
    INIT_LIST_HEAD(&list_less);
    INIT_LIST_HEAD(&list_greater);

    struct item *pivot = list_first_entry(head, struct item, list);
    list_del(&pivot->list);

    struct item *itm = NULL, *is = NULL;
    list_for_each_entry_safe (itm, is, head, list) {
        if (cmpint(&itm->i, &pivot->i) < 0)
            list_move_tail (&itm->list, &list_less);
        else
            list_move_tail (&itm->list, &list_greater);
    }

    list_sort(&list_less);
    list_sort(&list_greater);

    list_add(&pivot->list, head);
    list_splice(&list_less, head);
    list_splice_tail(&list_greater, head);
}

```
:::

---
    
## 測驗 2
```c
#define MAX_DEPTH 512
    struct list_head stack[MAX_DEPTH];
```
利用 ```stack``` ，將程式改成迭代式的實作，但本實作能處理的節點數量顯然受限於 ```MAX_DEPTH``` 的大小。
```c
    int top = -1;
    list_splice_init(head, &stack[++top]);
```
首先，將欲處理的佇列經過 ```list_splice_init``` 接到 ```stack[0]``` 的頭部。
初始化 ```partition``` 作為處理待分割佇列的 ```list_head```。
```top``` 用以表示 ```stack``` 中還有多少佇列，也代表目前處理至 ```stack[top]``` 位置的佇列。
只要 ```top >= 0``` ，而且用以處理待分割佇列的 ```partition``` 中有兩個以上的節點，函式就要進行排序，直到 ```partition``` 中沒有或只剩一個節點。
```c
        struct item *pivot =
                list_first_entry(&partition, struct item, list);
        list_del(&pivot->list);
        INIT_LIST_HEAD(&pivot->list);
```
排序的方式是先把 ```partition``` 中的第一個節點 ```pivot``` 取出，作為排序比較的基準。
```c
        GGGG (itm, is, &partition, list) {
            list_del(&itm->list);
            if (cmpint(&itm->i, &pivot->i) < 0)
                list_move(&itm->list, &list_less);
            else
                list_move(&itm->list, &list_greater);
        }
```
```GGGG``` 應為 ```list_for_each_entry_safe``` ，用以走訪整個 ```partition```。
將 ```pivot``` 以後的節點與 ```pivot``` 比較，較小者移動至 ```list_less``` 之頭部，較大者移動至 ```list_greater``` 的頭部。
```c
        HHHH (&pivot->list, &list_less);
```
```pivot``` 也是需要處理的節點。
此處 ```HHHH``` 應為 ```list_add_tail``` ，將 ```pivot``` 加入 ```list_less``` 的尾部等待處理。
```c
        if (!list_empty(&list_greater))
            list_splice_tail(&list_greater, IIII);
        if (!list_empty(&list_less))
            list_splice_tail(&list_less, JJJJ);
```
接下來要將 ```list_greater``` 和 ```list_less``` 佇列依序連接至 ```stack``` 上，模擬遞迴呼叫。
```IIII``` 應為 ```stack[++top]``` ， ```JJJJ``` 應為 ```stack[++top]```。
以第一次進入 ```while``` 迴圈為例，此時 ```top``` 值為 -1 ，利用 ```++top``` 將 ```top``` 值變為 0 ，即將 ```stack``` 佇列的第一個元素 ```stack[0]``` 作為插入 ```list_greater``` 的位置，並以同樣操作把 ```list_less``` 插入至 ```stack[1]``` 的位置。 
此時 ```top``` 值為 1， 代表目前 ```stack``` 陣列中有 2 個排序後的佇列。
```c
    list_splice_init(&stack[top--], &partition);
```
重新進入 ```while``` 迴圈，只要 ```top>=0``` ，就繼續對最尾部的 ```stack[top]``` 進行排序。
若這時 ```stack[top]``` 內只有一個元素，就會進入 ```else``` 的敘述。
```c
        list_splice_tail(&partition, &stack[top]);
        while (top >= 0 && list_is_singular(&stack[top])) {
            struct item *tmp =
                list_first_entry(&stack[top], struct item, list);
            list_del(&tmp->list);
            INIT_LIST_HEAD(KKKK);
            list_add_tail(&tmp->list, head);
        }
```
經過反覆的排序操作，排序後的佇列會由大至小的從 ```stack``` 的頭部向尾部分佈，此時 ```stack[top]``` 的元素為佇列中最小的元素。
將該元素以 ```list_del``` 自 ```stack[top]``` 佇列中刪除，並以 ```list_add_tail``` 加入 ```head``` 佇列中。
```KKKK``` 應為 ```stack[top--]``` ，將被取出元素的 ```stack[top]``` 初始化，並將 ```top``` 減一，更新目前 ```stack``` 陣列的元素數值。
反覆上述操作，最後 ```head``` 佇列為元素排序後的結果。
:::spoiler 測驗2 完整程式碼 
```c
#define MAX_DEPTH 512
static void list_sort_nr(struct list_head *head)
{
    if (list_empty(head) || list_is_singular(head))
        return;

    struct list_head stack[MAX_DEPTH];
    for (int i = 0; i < MAX_DEPTH; i++)
        INIT_LIST_HEAD(&stack[i]);
    int top = -1;
    list_splice_init(head, &stack[++top]);

    struct list_head partition;
    INIT_LIST_HEAD(&partition);

    while (top >= 0) {
        INIT_LIST_HEAD(&partition);
        list_splice_init(&stack[top--], &partition);
        if (!list_empty(&partition) && !list_is_singular(&partition)) {
            struct list_head list_less, list_greater;
            INIT_LIST_HEAD(&list_less);
            INIT_LIST_HEAD(&list_greater);
            struct item *pivot =
                list_first_entry(&partition, struct item, list);
            list_del(&pivot->list);
            INIT_LIST_HEAD(&pivot->list);

            struct item *itm = NULL, *is = NULL;
            list_for_each_entry_safe (itm, is, &partition, list) {
                list_del(&itm->list);
                if (cmpint(&itm->i, &pivot->i) < 0)
                    list_move(&itm->list, &list_less);
                else
                    list_move(&itm->list, &list_greater);
            }

            list_add_tail (&pivot->list, &list_less);
            if (!list_empty(&list_greater))
                list_splice_tail(&list_greater, stack[++top]);
            if (!list_empty(&list_less))
                list_splice_tail(&list_less, stack[++top]);
        } else {
            top++;
            list_splice_tail(&partition, &stack[top]);
            while (top >= 0 && list_is_singular(&stack[top])) {
                struct item *tmp =
                    list_first_entry(&stack[top], struct item, list);
                list_del(&tmp->list);
                INIT_LIST_HEAD(stack[top--]);
                list_add_tail(&tmp->list, head);
            }
        }
    }
}
```
:::

---

## 測驗 3
