#include #include /*This is a doubly linked list*/ /*Struct to make it easy*/ typedef struct Node { /* data */ int data; struct Node *next; // Pointer to the next element struct Node *previous; // Pointer to the previous element } Node; /* **pheadNode should be interpreted as first obtain pointer to Node. Then by dereferencing that pointer you are able to set the value at that address. This is why we use the & address of operator. It is saying Provide the address of the pointer variable. Use that to obtain a pointer to that address location, then derefence that pointer to assign a value to it. */ void insert_at_beginning(Node **pheadNode, int value); void insert_at_end(Node **pheadNode, int value); void print_list(Node *headNode); void print_list_backwards(Node *headNode); void free_list(Node *headNode); int main(void) { printf("Just so you know a Node in our linked list is %lu bytes\n", sizeof(Node)); /*Sometimes in a doubly linked list the last node is also stored*/ Node *head = NULL; // Pointers to the front of the list printf("Inserting a node at the beginning of the list.\n"); insert_at_beginning(&head, 5); // Sets data at *head to 5 print_list(head); printf("Insert a node at the beginning, then print the list backwards.\n"); insert_at_beginning(&head, 10); print_list_backwards(head); // should print 5, 10 printf("Insert a node at the end and then print the list.\n"); insert_at_end(&head, 15); print_list(head); free_list(head); return EXIT_SUCCESS; } void print_list_backwards(Node *headNode) { if (headNode == NULL) { return; } /* Iterate through the list, and once we get to the end, iterate backwards to print out the items in reverse order (this is done with the pointer to the previous node). This can be done even more easily if a pointer to the last node is stored. */ Node *i = headNode; /* An Arrow operator in C/C++ allows to access elements in Structures and Unions. It is used with a pointer variable pointing to a structure or union. Use Dot(.) with struct values Use -> to with struct pointer */ while (i->next != NULL) { i = i->next; // sets the pointer to the next pointer of the struct. } // i points to the last element of the list now while (i != NULL) { printf("Value: %d\n", i->data); i = i->previous; } } void print_list(Node *headNode) { Node *i = headNode; while (i != NULL) { printf("Value: %d\n", i->data); i = i->next; } } void insert_at_beginning(Node **pheadNode, int value) { Node *currentNode; if (pheadNode == NULL) { return; } currentNode = malloc(sizeof *currentNode); //deref pointer; currentNode->next = NULL; currentNode->previous = NULL; currentNode->data = value; if (*pheadNode == NULL) // list is empty { *pheadNode = currentNode; // set the object at pheadNode memory location to currentNode which is on the heap. return; } currentNode->next = *pheadNode; (*pheadNode)->previous = currentNode; *pheadNode = currentNode; } void insert_at_end(Node **pheadNode, int value) { Node *currentNode; if (pheadNode == NULL) { return; } currentNode = malloc(sizeof *currentNode); Node *i = *pheadNode; //save a ref to the current head so we can traverse the list currentNode->data = value; currentNode->next = NULL; currentNode->previous = NULL; if (*pheadNode == NULL) // If pheadNode is NULL meaning an empty list { *pheadNode = currentNode; return; } while (i->next != NULL) // Go to the end of the list { i = i->next; } i->next = currentNode; currentNode->previous = i; } void free_list(Node *node) { while (node != NULL) { Node *next = node->next; free(node); node = next; } }