# Week 3 - Linked Lists
## Team
Team name: Error
Date: 8th March 2022
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. |Minh 511907 |
| **Spokesperson** communicates group’s questions and problems to the teacher and talks to other teams; presents the group’s findings. |Hoa 487272 |
| **Reflector** observes and assesses the interactions and performance among team members. Provides positive feedback and intervenes with suggestions to improve groups’ processes. |Thanh 516467 |
| **Recorder** guides consensus building in the group by recording answers to questions. Collects important information and data. |Kaloyan 511216 |
## 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 | 0x7ffccb24c954 | 42 |
| ptr | 0x7ffccb24c958 | 42 |
| pptr | 0x7ffccb24c960 | 42 |
| ppptr | 0x7ffccb24c968 | 42 |
Explain: The value of ppptr represent that this pointer pointing to pptr which store the address of ptr and pointing to ptr. Ptr store the address of value and when derefference ptr can retrieve the value of "value" which is 42. Hence
***ppptr -> **pptr -> *ptr -> value
### Activity 2: Chaining pointers
```c
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};
struct node_t *ptr;
ptr = &first;
printf("first: %d\n", ptr-> value);
printf("second: %d\n", ptr-> next-> value);
printf("third: %d\n", ptr-> next-> next-> value);
printf("fourth: %d\n", ptr-> next-> next-> next-> value);
return 0;
}
```
### Activity 3: Traversal
```c
int main() {
node fourth = {.value = 42, .next = NULL};
node third = {.value = 7, .next = &fourth};
node second = {.value = 3, .next = &third};
node first = {.value = 2, .next = &second};
struct node_t *ptr;
ptr = malloc(sizeof(struct node_t));
ptr = &first;
struct node_t *temp = NULL;
temp = malloc(sizeof (struct node_t));
temp = ptr;
int count = 0;
while(temp != NULL){
count++;
temp = temp->next;
}
for(int i = 1;i <= count; i++){
printf("%d\n", ptr-> value);
ptr = ptr-> next;
}
free(ptr);
free(temp);
return 0;
}
```
### Activity 4: Linked list deallocation
```c
void list_free(list ** plist) {
free(*plist);
*plist = NULL;
}
```
Although the code still has no-error, it fails to deallocate all the node in the list. The program just deallocates 2 pointers: head and tail pointers which point to node in link list. So other nodes which are between head and tail are still left
So here is the code to delete all the node:
```c
void list_free(list**plist){
while((*plist)->head!=(*plist)->tail){
node*cur=(*plist)->head;
(*plist)->head=(*plist)->head->next;
free(cur);
}
free(*plist);
*plist=NULL;
}
```
The program will create a temporary node which point to the first node and then, the head node will change to next node, the current node will be deleted.
### 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=NULL;
node_init(&temp,value);
temp->next=plist->head;
plist->head=temp;
}
}
```
Firstly, it need to check if the plist is NULL or not to decide to create a new node. If there is already a node, then it will create a temporary node to store the new node, and then link the new node to the head node, then change the pointer from head node to new node.
### Activity 6: Time complexity of prepend and append
The time complexity of appending new if we already have pointer to the end of the node is O(1).
However, the time complexity of appending a new node if we would not keep track of the tail is O(n). Because we have to travel until the end of the list so as to insert the node.
### Activity 7: Access by index
Record your answer here
```c
const node*list_at(const list*plist,int index){
node*temp=plist->head;
for(int i=0;i<index;i++){
temp=temp->next;
}
return temp;
}
```
The function will create a temporary node first to point to first node in the linked list. Then it will travel until the index. If the index is out of range, because we let the final node in the link list point to NULL, so the temporary node will also become NULL.
### Activity 8: Time complexity of accessing by index
The time complexity of list_at(const list *plist, int index) function will be between O(1) and O(n) and n is the number of elements in the list. This is because the element we need to find may be at the first index or at the last.
### Activity 9: A bad for-loop
The for-loop n this activity is bad because it is a nested one, which means that it will run while there is another for loop running inside it. This will result in worst-time complexity O(n2) (n to the power of 2).
### Activity 10: Removal in a singly-linked list
Record your answer here
```c
void list_remove_last(list *plist) {
for (int i = 0; i < sizeof(list); i++) {
if ((plist + i)->tail == NULL) {
if (i != 0) {
(plist - 1)->tail->next = plist->tail;
} else {
(plist + i)->tail = plist->tail = plist->head;//one single element
}
}
}
node_free(&plist->tail);
}
```
### Activity 11: Code update - I
```c
typedef struct node_t {
int value;
struct node_t *next;
struct node_t *previous;///////New
} node;
void node_init(node **ptr, int value) {
node *p = (node *) malloc(sizeof(node));
if (p != NULL) {
p->next = NULL;
p->value = value;
p->previous = NULL;//////////New
}
*ptr = p;
}
```
### Activity 12: Code update - II
Record your answer here
```c
void list_prepend(list**plist,int value){
struct node_t*temp=NULL;
node_init(&temp,value);
temp->prev=NULL;
if((*plist)->head==NULL){
(*plist)->head=temp;
(*plist)->tail=temp;
}
else{
(*plist)->head->prev=temp;
temp->next=(*plist)->head;
(*plist)->head=temp;
}
}
```
### Activity 13: Implementation of removal
Record your answer here
```c
// updates the list by removing the node referred to by pnode from the list
void list_remove(list *plist, node * pnode)
{
/* base case */
if (plist == NULL || pnode == NULL)
return;
/* If node to be deleted is head node */
if (plist->head == pnode){
plist->head = pnode->next;
}
/* Change next only if node to be deleted is NOT the last node */
if (pnode->next != NULL) {
pnode->next->prev = pnode->prev;
}
/* Change prev only if node to be deleted is NOT the first node */
if (pnode->prev != NULL) {
pnode->prev->next = pnode->next;
}
/* Finally, free the memory occupied by pnode*/
free(pnode);
}
```
### 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;
pnode->prev = NULL;
}
pbefore->prev = pnode;
}
```
### Activity 15: Time complexities
Record your answer here
| Operation | Array | Linked List |
| --------------- | -------------------------- | ----------- |
| Access | 0(1) | 0(N) |
| Append | 0(N) | 0(1) |
| Insert | 0(N) | 0(N) |
| Remove | 0(N) | 0(N) |
## Looking back
### What we've learnt
- understand how pointer to pointer work
- be able to retrieve elements from a linked list
- recognize the differences between singly and doubly linked lists
- run a doubly linked list
### What were the surprises
Nothing
### What problems we've encountered
Nothing
### What was or still is unclear
Everything is quite clear
### How did the group perform?
Well group collaboration
> Written with [StackEdit](https://stackedit.io/).