You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
4.0 KiB
C
163 lines
4.0 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
/*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;
|
|
}
|
|
}
|