# 2024q1 Homework2 (quiz1+2)
contributed by <`EisEisHet`>
## Quiz 1
> [Link to Quiz 1](https://hackmd.io/@sysprog/linux2024-quiz1#%E6%B8%AC%E9%A9%97-1")
> TODO LIST :
> Extension Questions:
> Explain how the above code works, propose improvement plans, and implement them.
> Override the above code using the Linux core-style List API, and propose a quicksort implementation for linked columns that avoids worst-case scenarios, and design a test program for performance evaluation.
### Test 1
The quicksort algorithm implemented in quiz 1 uses a non-recursive (iterative) approach and implements a linked list instead of an array. To simulate recursion, a stack method is implemented.
Consider the struct node_t:
```c
typedef struct __node {
struct __node *left, *right;
struct __node *next;
long value;
} node_t;
```
Each node in the linked list contains a value of type `long`, two pointers `*left` and `*right` pointing to the left and right nodes from the current node (children nodes), and a pointer `*next` pointing to the next node. If we put it visually:
```graphviz
digraph "queue"{
rankdir = "LR"
subgraph "cluster node1"{
node1_1[shape = record, label = "next"]
node1_2[shape = record, label = "value"]
node1_3[shape = record, label = "{<left> left | <right> right}"]
}
subgraph "cluster node2"{
node2_1[shape = record, label = next]
node2_2[shape = record, label = value]
node2_3[shape = record, label = "{<left> left | <right> right}"]
}
subgraph "cluster node3"{
node3_1[shape = record, label = next]
node3_2[shape = record, label = value]
node3_3[shape = record, label = "{<left> left | <right> right}"]
}
node1_1 -> node2_1
node2_1 -> node3_1
}
```
### Related Linked List functions
Consider the following functions for linked lists:
#### list_add()
```c
void list_add(node_t **list, node_t *node){
node->next = *list;
*list = node;
}
```
This function works by adding the node to the beginning of a linked list. This is done by assigning the `next` pointer of the passing `*node` variable to the current head of the list `*list`, and then updating the head of the list to the new `node`.
#### list_tail()
```c
node_t list_tail(node_t **left){
while((*left) && (*left)->next){
left = &((*left)->next);
}
return left;
}
```
This function takes the indirect pointer `**left` as a parameter to start from the head of the list. The while loop will continue iterating through the list from the head as long as the current node `*left` is not NULL and the next node is not NULL.
* While iterating, if the list is non-empty, the `left`variable will be constantly updated until the loop terminates, where `left` will contain the last node of the list.
* If the list is empty or NULL, the function would immediately return `left` or the list itself.
#### list_length()
```c
int list_length(node_t **left){
int count = 0;
while(*left){
++count;
left = &((*left)->next);
}
return count;
}
```
This function passes in the indirect pointer `**left` as a parameter, which represents the head, and it checks whether the current node is not NULL in a while loop. If it is not NULL, then `count` will be incremented by 1, and the current node `left`is assigned to be the `next` pointer of the current node. This repeats until `*left = null` where it will then return the `count`.
#### list_construct()
```c
node_t *list_construct(node_t *list, int n)
{
node_t *node = malloc(sizeof(node_t));
node->next = list;
node->value = n;
return node;
}
```
This function is used to construct a node and add it to the beginning of the list. It first allocates memory of size `node_t`to a single node, `node`will then be assigned a value `n` and have its `next`pointer point to the `list`.
#### list_free()
```c
void list_free(node_t **list)
{
node_t *node = (*list)->next;
while (*list) {
free(*list);
*list = node;
if (node)
node = node->next;
}
}
```
This function works by accessing every single node from the list and freeing every single node of its memory. The while loop constantly checks if `*list`is not NULL, and frees the next node from the current node.
#### Non-recursive Quicksort implementation
Using the above linked list functions, we can implement a non-recursive quicksort algorithm.
```c
void quick_sort(node_t **list){
int n = list_length(list);
int value;
int i = 0;
int max_level = 2 * n;
node_t *begin[max_level], *end[max_level];
node_t *result = NULL, *left = NULL, *right = NULL;
begin[0] = *list;
end[0] = list_tail(list);
while (i >= 0) {
node_t *L = begin[i], *R = end[i];
if (L != R) {
node_t *pivot = L;
value = pivot->value;
node_t *p = pivot->next;
pivot->next = NULL;
while (p) {
node_t *n = p;
p = p->next;
list_add(n->value > value ? &right : &left, n);
}
begin[i] = left;
end[i] = list_tail(&begin[i]);
begin[i + 1] = pivot;
end[i + 1] = pivot;
begin[i + 2] = right;
end[i + 2] = list_tail(&begin[i + 2]);
left = right = NULL;
i += 2;
} else {
if (L)
list_add(&result, L);
i--;
}
}
*list = result;
}
```
1. We assign the first and last entry of `list` to the first entry of the pointer arrays `*begin` and `*end` respectively. The pivot variable `p` will begin from the head of `list`. Keep in mind that `begin` and `end` both act as the stack to keep track of sublists being partitioned.
```c
while (p) {
node_t *n = p;
p = p->next;
list_add(n->value > value ? &right : &left, n);
}
```
2. This while loop acts as the partitioner of the linked list. It iterates through every single node in the linked list and checks if the value of node `n` is more or less than the value of the pivot `value`. If `n` is greater than the pivot, then `n`will be added to the `right` sublist. Otherwise, it will be added to the `left` sublist.
```c
begin[i] = left;
end[i] = list_tail(&begin[i]);
begin[i + 1] = pivot;
end[i + 1] = pivot;
begin[i + 2] = right;
end[i + 2] = list_tail(&begin[i + 2]);
```
3. `begin[i]` and `end[i]` are then assigned the pointers to the start and end of the `left` sublist. Similarly, `begin[i+2]` and `end[i+2]` are assigned the start and end of the `right` sublist. `begin[i+1]` and `end[i+1]` represents the partition point, thus they are assigned the value of `pivot`.
4. After the sublists are updated, then index`i` will be incremented by 2 to move to the next level of the stack for the next iteration, and the process repeats. However, if the sublist `L` only has one element (`L == R`), then it is added to the list `result`. Index `i`is then decremented to move to the parent level of the stack.
5. After the partitioning and sorting process is complete, the head of the sorted list `result` will be assigned to the original list pointer `list`, which means successfully updating it to the sorted list.
### Test 2
#### Timsort
Timsort is a type of sorting sorting algorithm that specializes in sorting arrays that have partially sorted subsequences, which often occur with real life data.
```graph
```
### Timsort