Demo - Doubly-linked list

Here is an example implementation of a doubly-linked list in C++:

// DoublyLinkedListNode.h // Created by Kevin Roark #ifndef DoublyLinkedListNode_h #define DoublyLinkedListNode_h // Define a generic node for the doubly linked list template <typename T> class DoublyLinkedListNode { public: T value; // Store the value of the node DoublyLinkedListNode* prev; // Pointer to the previous node DoublyLinkedListNode* next; // Pointer to the next node // Constructor to initialize the node with a value DoublyLinkedListNode(T value) : value(value), prev(nullptr), next(nullptr) {} }; #endif /* DoublyLinkedListNode_h */
// DoublyLinkedList.h // Created by Kevin Roark #ifndef DoublyLinkedList_h #define DoublyLinkedList_h #include "DoublyLinkedListNode.h" // Include the node definition for the doubly linked list #include <iostream> // Include the standard I/O library for printing using namespace std; // Template class for a generic doubly linked list template <typename T> class DoublyLinkedList { private: DoublyLinkedListNode<T>* head; // Pointer to the head of the list DoublyLinkedListNode<T>* tail; // Pointer to the tail of the list public: // Constructor to initialize an empty list DoublyLinkedList() : head(nullptr), tail(nullptr) {} // Destructor to clean up the list ~DoublyLinkedList() { clear(); // Use the clear method to delete all nodes } // Clear the list by deleting all nodes void clear() { while (head) { DoublyLinkedListNode<T>* nodeToDelete = head; head = head->next; delete nodeToDelete; } tail = nullptr; } // Insert a new node with the specified value at the head of the list void insertAtHead(T value) { DoublyLinkedListNode<T>* newNode = new DoublyLinkedListNode<T>(value); if (!head) { // If the list is empty head = tail = newNode; } else { newNode->next = head; head->prev = newNode; head = newNode; } } // Insert a new node with the specified value at the tail of the list void insertAtTail(T value) { DoublyLinkedListNode<T>* newNode = new DoublyLinkedListNode<T>(value); if (!tail) { // If the list is empty head = tail = newNode; } else { tail->next = newNode; newNode->prev = tail; tail = newNode; } } // Insert a new node at a specified position in the list void insertAtPosition(int position, T value) { if (position == 0) { // If the position is at the head insertAtHead(value); return; } DoublyLinkedListNode<T>* current = head; int index = 0; while (current != nullptr && index < position) { current = current->next; index++; } // Insert at the tail if position is out of bounds if (current == nullptr && index == position) { insertAtTail(value); } else if (current != nullptr) { // Insert in the middle DoublyLinkedListNode<T>* newNode = new DoublyLinkedListNode<T>(value); newNode->next = current; newNode->prev = current->prev; if (current->prev) { current->prev->next = newNode; } current->prev = newNode; } } // Remove a node at a specified position void removeAtPosition(int position) { if (position < 0 || head == nullptr) { // Handle invalid position or empty list cout << "Invalid position or list is empty." << endl; return; } if (position == 0) { // Removing the head node DoublyLinkedListNode<T>* nodeToDelete = head; head = head->next; if (head) { head->prev = nullptr; } else { tail = nullptr; // If the list is now empty } delete nodeToDelete; return; } DoublyLinkedListNode<T>* current = head; int index = 0; while (current != nullptr && index < position) { current = current->next; index++; } if (current != nullptr) { // Node found at the position if (current->next) { current->next->prev = current->prev; } else { tail = current->prev; // Update tail if last node is removed } if (current->prev) { current->prev->next = current->next; } delete current; } else { cout << "Position out of bounds." << endl; } } // Print the list in forward direction void printListForward() const { DoublyLinkedListNode<T>* current = head; while (current) { cout << current->value << " "; current = current->next; } cout << endl; } // Print the list in reverse direction void printListReverse() const { DoublyLinkedListNode<T>* current = tail; while (current) { cout << current->value << " "; current = current->prev; } cout << endl; } }; #endif /* DoublyLinkedList_h */
// Doubly Linked List Demonstration // Created by Kevin Roark #include <iostream> #include "DoublyLinkedList.h" using namespace std; // Main function to demonstrate the use of the doubly linked list int main() { // Demonstrating DoublyLinkedList with integers DoublyLinkedList<int> myList; // Create a new list of integers // Insert elements at the head and tail myList.insertAtHead(1); myList.insertAtTail(2); myList.insertAtTail(5); myList.insertAtHead(10); // Print the integer list in both directions cout << "Printing Integer List Forward: " << endl; myList.printListForward(); cout << "Printing Integer List Backward: " << endl; myList.printListReverse(); // Insert an element at a specific position cout << "Inserting 20 at position 2 in Integer List: " << endl; myList.insertAtPosition(2, 20); myList.printListForward(); // Remove an element at a specific position cout << "Removing element at position 1 in Integer List: " << endl; myList.removeAtPosition(1); myList.printListForward(); // Demonstrating DoublyLinkedList with strings (Task List) DoublyLinkedList<string> taskList; // Create a new list of tasks (strings) // Insert tasks at the head and tail taskList.insertAtHead("Write report\n"); taskList.insertAtTail("Attend meeting\n"); taskList.insertAtTail("Review code\n"); taskList.insertAtHead("Plan project\n"); // Print the task list in both directions cout << "\nPrinting Task List Forward: " << endl; taskList.printListForward(); cout << "Printing Task List Backward: " << endl; taskList.printListReverse(); // Insert a task at a specific position cout << "Inserting 'Submit budget' at position 2 in Task List: " << endl; taskList.insertAtPosition(2, "Submit budget\n"); taskList.printListForward(); // Remove a task at a specific position cout << "Removing task at position 1 in Task List: " << endl; taskList.removeAtPosition(1); taskList.printListForward(); return 0; }

 

image-20241020-151201.png

In this example, we define a DoublyLinkedListNode class to represent a node in the list, which has a value, a reference to the previous node, and a reference to the next node.

We then define a DoublyLinkedList class to represent the list itself, which has references to the head and tail of the list. We provide member functions to insert, remove and to print the list.

In the main function, we create a DoublyLinkedList object, insert and remove some nodes.

Doubly-linked lists have the advantage of allowing for efficient traversal of the list in both directions. However, they have some disadvantages, such as a higher overhead due to the need to maintain the prev pointers and more complex insertion and deletion operations.

2024 - Programming 3 / Data Structures - Author: Dr. Kevin Roark