``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74``` ```#include #include #include #include // LINKED LIST typedef struct _Node { int value; struct _Node* next; } Node; void append(int value, Node** a_head, Node** a_tail) { // Create (allocate and initialize) the new node, which will become the tail. Node* new_tail = malloc(sizeof(*new_tail)); new_tail -> value = value; // same as `(*new_tail).value = value` new_tail -> next = NULL; if(*a_tail == NULL) { // if list is empty // List is empty, so head will also be tail. *a_head = new_tail; } else { // List is not empty, so connect new_tail to the old tail. (*a_tail) -> next = new_tail; } // Connect the tail of the list to new_tail. *a_tail = new_tail; assert(*a_head != NULL && *a_tail != NULL); // Sanity check: list is not empty anymore } void destroy_list(Node** a_head, Node** a_tail) { while(*a_head != NULL) { // as long as list is not empty Node* new_head = (*a_head) -> next; free(*a_head); *a_head = new_head; // Now head is the next node in the list. } } void print_list(Node* head) { // Step through the linked list, printing each value. for(Node* curr = head; curr != NULL; curr = curr -> next) { printf("[%d]→", curr -> value); } printf("NULL\n"); } // RULE: Use a for loop to iterate through a linked list, not a while loop. int main(int argc, char* argv[]) { // size==0 Node* head = NULL; Node* tail = NULL; // You don't always need to keep track of the tail. It helps here. // size==1 append(10, &head, &tail); // Pass address of head and tail so they can be modified. assert(head != NULL && tail != NULL); // Sanity check: list is no longer empty assert(head == tail); // Sanity check: head and tail are same (size==1) assert(head -> value == 10); // Sanity check: head's value is 10 // size==2 append(11, &head, &tail); assert(head != tail); // Sanity check: head and tail are same (size==1) assert(head -> value == 10); // Sanity check: head's value is 10 assert(tail -> value == 11); // Sanity check: tail's value is 11 assert(tail -> next == NULL); print_list(head); destroy_list(&head, &tail); return EXIT_SUCCESS; } /* vim: set tabstop=4 shiftwidth=4 fileencoding=utf-8 noexpandtab: */ ```

© Copyright 2023 Alexander J. Quinn         This content is protected and may not be shared, uploaded, or distributed.