# 2021q1 Homework1 (lab0) contributed by < `kksweet8845` > ## Environment ``` $ uname-a Darwin Nobers-MacBook-Pro.local 20.3.0 Darwin Kernel Version 20.3.0: Thu Jan 21 00:07:06 PST 2021; root:xnu-7195.81.3~1/RELEASE_X86_64 x86_64 $ gcc --version | head -1 Apple clang version 12.0.0 (clang-1200.0.32.29) ``` ## Implementation ### q_new() - Check if malloc return NULL. Otherwise, initialize the queue with NULL and '0'. ```cpp queue_t *q_new() { queue_t *q = malloc(sizeof(queue_t)); /* TODO: What if malloc returned NULL? */ if(q == NULL) return NULL; else { q->head = NULL; q->tail = NULL; q->len = 0; } return q; } ``` ### q_free() - Check if queue is `NULL` - Free each node inside queue and need to store the address of `cur->next` in advance. If I don't take this action, it will happen segment fault by access a NULL adress of `next`. ```cpp void q_free(queue_t *q) { /* Free queue structure */ if(q == NULL) return; list_ele_t *cur, *temp; for(cur = q->head; cur != NULL; cur = temp){ temp = cur->next; if(cur ->value != NULL) free(cur->value); if(cur != NULL) free(cur); } free(q); } ``` ### q_insert_head() - Check if queue is `NULL` - Create a `list_ele_t` type object and check if malloc return NULL - Perform the insertion operation ```cpp bool q_insert_head(queue_t *q, char *s) { list_ele_t *newh; if(q == NULL) return false; newh = list_new(s); if(newh == NULL) return false; /* Don't forget to allocate space for the string and copy it */ /* What if either call to malloc returns NULL? */ newh->next = q->head; q->head = newh; q->len += 1; if(q->len == 1){ q->tail = newh; } return true; } ``` ### q_insert_tail() - Same precaution as `q_insert_head` - There is different situation when perform insertion with size is 0. ```cpp bool q_insert_tail(queue_t *q, char *s) { list_ele_t *newh; if(q == NULL) return false; newh = list_new(s); if(newh == NULL) return false; if(q->len != 0) q->tail->next = newh; q->tail = newh; q->len += 1; if(q->len == 1){ q->head = newh; } return true; } ``` ## q_remove_head() - Check if queue is NULL ```cpp bool q_remove_head(queue_t *q, char *sp, size_t bufsize) { if(q == NULL || (q->head == NULL && q->tail == NULL) || q->len == 0 || sp == NULL){ return false; } list_ele_t *cur = q->head; q->head = q->head->next; q->len -= 1; memset(sp, '\0', (bufsize) * sizeof(char)); strncpy(sp, cur->value, bufsize-1); if(cur->value != NULL){ free(cur->value); } if(cur != NULL){ free(cur); } if(q->len == 0){ q->tail = NULL; q->head = NULL; } return true; } ``` ## q_reverse() - Perform the insertion to head. ```cpp void q_reverse(queue_t *q) { if(q == NULL) return; list_ele_t *cur, *pre, *tmp_head = NULL; q->tail = q->head; for(cur = q->head; cur != NULL; cur = q->head){ pre = tmp_head; tmp_head = cur; q->head = cur->next; cur->next = pre; } q->head = tmp_head; } ``` ## q_sort() - Implement Merge sort - It occurred worst case O(n^2) with a Descending order link list with quick sort. ```cpp list_ele_t* _m_sort(list_ele_t* list){ if(list == NULL || list->next == NULL){ return list; } list_ele_t* slow, *fast; fast = list; slow = list; for(slow=list;slow!= NULL;slow=slow->next){ if(fast->next == NULL || fast->next->next == NULL) break; fast=fast->next->next; } fast = slow->next; slow->next = NULL; list_ele_t* l1 = _m_sort(list); list_ele_t* l2 = _m_sort(fast); list_ele_t* h = NULL, *cur = NULL; while(l1 != NULL && l2 != NULL){ if(strcmp(l1->value, l2->value) < 0){ if(h == NULL) cur = h = l1; else{ cur->next = l1; cur = cur->next; } l1 = l1->next; }else{ if(h == NULL) cur = h = l2; else{ cur->next = l2; cur = cur->next; } l2 = l2->next; } cur->next = NULL; } if(l2 != NULL){ while(l2){ cur->next = l2; cur = cur->next; l2 = l2->next; } } if(l1 != NULL){ while(l1){ cur->next = l1; cur = cur->next; l1 = l1->next; } } cur->next = NULL; return h; } /* * Sort elements of queue in ascending order * No effect if q is NULL or empty. In addition, if q has only one * element, do nothing. */ void q_sort(queue_t *q) { if(q == NULL || q->len <= 1) return; // _q_sort(&(q->head)); q->head = _m_sort(q->head); while (q->tail->next) { q->tail = q->tail->next; } } ```