Skip to main content

Section 27.20 Appendix - Doubly Linked List

Listing 27.20.1. Doubly Linked List - A doubly linked list with size and tail
module;

#include <cassert>
#include <iostream>
#include <stdexcept>

export module DoublyLinkedList;

using namespace std;

///-----------------------------LIST NODE---------------------------------
export template<typename T>
struct ListNode {
  T data;
  ListNode<T>* next;
  ListNode<T>* prev;

  // Maintain a count of active nodes for testing
  //  Not normally a part of the struct.
  //  You should NOT modify or even use this value in your code.
  static int nodeCount;

  ListNode() {
    next = nullptr;
    prev = nullptr;
    // Call default constructor for type T
    //   produces 0 for primitive types
    data = T();
    nodeCount++;
  }

  ListNode(const T& value) {
    next = nullptr;
    prev = nullptr;
    data = value;
    nodeCount++;
  }

  ~ListNode() {
    nodeCount--;
  }
};

template<typename T>
int ListNode<T>::nodeCount = 0;

///-----------------------------LINKED LIST---------------------------------
export template<typename T>
class DoublyLinkedList {
  // These would normally be private.
  // They are public to enable simpler unit tests.
public:
  ListNode<T>* head;
  ListNode<T>* tail;
  int size;

public:
  DoublyLinkedList();
  ~DoublyLinkedList();

  // Assignment Operator and Copy Ctor not implemented
  // declare as = delete to prevent default shallow versions
  DoublyLinkedList(const DoublyLinkedList& other) = delete;
  DoublyLinkedList& operator=(const DoublyLinkedList& other) = delete;

  int listSize() const;

  void insertStart(const T& value);
  void removeEnd();

  void insertAt(int index, const T& value);
  void removeAt(int index);
  T retrieveAt(int index) const;

  void print() const;
};

///-----------------------------LINKED LIST FUNCTIONS-----------------------
template<typename T>
void DoublyLinkedList<T>::print() const {
  ListNode<T>* current = head->next;
  while (current != tail) {
    cout << current->data;
    if (current->next != tail)
      cout << ", ";
    current = current->next;
  }
  cout << endl;
}

template<typename T>
DoublyLinkedList<T>::~DoublyLinkedList() {
  // Delete all nodes, including dummies
  while (head != nullptr) {
    ListNode<T>* temp = head;
    head = head->next;
    delete temp;
  }
}

template<typename T>
int DoublyLinkedList<T>::listSize() const {
  return size;
}

template<typename T>
void DoublyLinkedList<T>::insertStart(const T& value) {
  ListNode<T>* newNode = new ListNode<T>(value);
  newNode->prev = head;
  newNode->next = head->next;

  newNode->next->prev = newNode;
  head->next = newNode;

  size++;
}

template<typename T>
T DoublyLinkedList<T>::retrieveAt(int index) const {
  if (index >= size || index < 0)
    throw out_of_range("Bad index in retrieveAt");

  // Start at node after dummy
  ListNode<T>* current = head->next;
  // Advance index times
  for (int i = 0; i < index; i++)
    current = current->next;

  return current->data;
}
You have attempted of activities on this page.