# Week 3 - Linked Lists ## Team Team name: Date: Members | Role | Name | |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------| | **Facilitator** keeps track of time, assigns tasks and makes sure all the group members are heard and that decisions are agreed upon. | | | **Spokesperson** communicates group’s questions and problems to the teacher and talks to other teams; presents the group’s findings. | | | **Reflector** observes and assesses the interactions and performance among team members. Provides positive feedback and intervenes with suggestions to improve groups’ processes. | | | **Recorder** guides consensus building in the group by recording answers to questions. Collects important information and data. | | ## Activities Make sure to have the activities signed off regularly to ensure progress is tracked. Set up a project in CLion to write the small programs needed in some of the activities. ### Activity 1: Pointers to pointers Record your answer here | Variable | Address | Value | | ----------- | --------------------- | ----------- | | value | 00000092667ffa8c | |42 | ptr | 00000092667ffa80 | |42 | pptr | 00000092667ffa78 | |42 | ppptr | 00000092667ffa70 | |42 Variable ppptr represents that the variable is pointed to pptr, which is pointed to ptr, which is pointed to value, which is equal with 42. ### Activity 2: Chaining pointers ```c #include <stdio.h> typedef struct node_t { int value; struct node_t * next; } node; int main(void) { node fourth = {.value = 42, .next = NULL}; node third = {.value = 7, .next = &fourth}; node second = {.value = 3, .next = &third}; node first = {.value = 2, .next = &second}; printf("first: %d\n", first.value); printf("second: %d\n", first.next->value); printf("third: %d\n",first.next->next->value ); printf("fourth: %d\n", first.next->next->next->value); } ``` ### Activity 3: Traversal ```c node fourth = {.value = 42, .next = NULL}; node third = {.value = 7, .next = &fourth}; node second = {.value = 3, .next = &third}; node first = {.value = 2, .next = &second}; for ( node * i = &first; i !=NULL; i= i->next ){ printf("%d\n", i->value); } ``` For an array, we would do something like: ```c= int values[10]; for (int i = 0; i < 10; i++) printf("%d\n", value[i]); ``` Starting point: first index: `i = 0` Linked list: starting point = memory address of the first node. Record your answer here ### Activity 4: Linked list deallocation ```c void list_free(list ** plist){ node *i = (*plist)->head; node * next; while(i!=NULL){ next=i->next; node_free(&i); i = next; } free(*plist); *plist= NULL; } ``` ### Activity 5: Prepending ```c void list_prepend(list * plist, int value){ if (plist->head == NULL) { node_init(&plist->head, value); plist->tail = plist->head; } else{ node * temp; node_init(&temp, value); temp->next=plist->head; plist ->head->prev = temp; plist->head=temp; } } ``` ### Activity 6: Time complexity of prepend and append Each insert operation should take O(1), so the total will be O(n) (where n is the count of numbers we want to insert), because our append function will call also the node init function after every step. ### Activity 7: Access by index Record your answer here ```c const node *list_at(const list *plist, int index){ node* current = plist; int count = 0; while (current != NULL) { if (count == index) return (current->value); count++; current = current->next; } } ``` ### Activity 8: Time complexity of accessing by index The time complexity of the list_at function is O(n), because it depends on the number of elements of the list. ### Activity 9: A bad for-loop I think the complexity of the for loop in which it also calls the list_at function would be O(n^2), therefore it will be a bad implementation. ### Activity 10: Removal in a singly-linked list Record your answer here ```c void list_remove_last(list * plist) { if(plist->head != NULL) { if(plist->head->next == NULL) { plist->head = NULL; } else { node* temp = plist->head; while(temp->next->next != NULL) temp = temp->next; node* lastNode = temp->next; temp->next = NULL; free(lastNode); } } } ``` ### Activity 11: Code update - I Record your answer here ```c typedef struct node_t { int value; struct node_t *next; struct node_t *prev; } node; // the node_t stays the same as it has prev, next and the value void node_init(node ** ptr, int value) { node *p = (node*) malloc(sizeof(node)); if (p != NULL) { p->next = NULL; p->value = value; p->prev = NULL; } } ### Activity 12: Code update - II ```c void list_prepend(list * plist, int value){ if (plist->head == NULL) { node_init(&plist->head, value); plist->tail = plist->head; } else{ node * temp; node_init(&temp, value); temp->next=plist->head; plist->head=temp; temp->prev = NULL; } } ### Activity 13: Implementation of removal Record your answer here ```c // updates the list by removing the node referred to by pnode from the list // needs fixing void list_remove(list *plist, node *pnode) { //if the node is not the head or the tail if(plist ->head != pnode || plist-> tail != pnode ){ // list has no head AND no tail -> list is empty, can't remove anything pnode->prev->next = pnode->next; //segmentation fault pnode->next->prev = pnode->prev; pnode->next = pnode->prev = NULL; } if(pnode == plist -> head){ // won't work //2nd node will now be the head plist ->head ->next ->prev = NULL; plist ->head = pnode -> next; free(pnode); //2nd node prev will now point to null } if(plist->tail == pnode){ // won't work // tail.prev == tail //tail.prev.next == NULL // free pnode plist -> tail = pnode ->prev; plist -> tail -> prev ->next = NULL; free(pnode); } } Code to test: int main(void) { list * plist; list_init(&plist); list_prepend(plist, 4); list_prepend(plist, 3); list_prepend(plist, 2); list_prepend(plist, 1); list_remove(plist, plist->head->next); // remove value 2 for (node * ptr = plist->head; ptr != NULL; ptr = ptr->next) { printf("%d\n", ptr->value); } } //Process finished with exit code 139 (interrupted by signal 11: SIGSEGV) ``` ### Activity 14: Implementing insertion Record your answer here ```c // updates the list by inserting value before the node referred to by pInsertionPoint void list_insert(list *plist, node *pbefore, node *pnode) { pnode->next = pbefore; pnode->prev = pbefore->prev; if (pbefore->prev != NULL) pbefore->prev->next = pnode; else plist->head = pnode; pbefore->prev = pnode; } ``` list_insert(plist, plist->head, node) ### Activity 15: Time complexities Record your answer here | Operation | Array | Linked List | | --------------- | -------------------------- | ----------- | | Access | O(1) | | O(n) | Append | O(n) | | O(1) | Insert | O(1) | | O(1) | Remove | O(1) | | O(1) ## Looking back ### What we've learnt Formulate at least one lesson learned. ### What were the surprises Fill in... ### What problems we've encountered Fill in... ### What was or still is unclear Fill in... ### How did the group perform? How was the collaboration? What were the reasons for hick-ups? What worked well? What can be improved next time? > Written with [StackEdit](https://stackedit.io/).