Program Listing for File doubly_linked_list.h
↰ Return to documentation for file (data_structures/doubly_linked_list.h)
#ifndef DATA_STRUCTURES_DOUBLY_LINKED_LIST_H
#define DATA_STRUCTURES_DOUBLY_LINKED_LIST_H
#include <iostream>
#include <stdexcept>
namespace DataStructures {
template <typename T>
class DoublyLinkedList {
public:
DoublyLinkedList()
{
head = new Node(T());
tail = new Node(T());
head->next = tail;
tail->prev = head;
size = 0;
}
~DoublyLinkedList()
{
while (size > 0) {
del_first();
}
delete head;
delete tail;
}
/* Insert functions */
void add_first(const T& data)
{
Node* x = new Node(data);
Node* temp = head->next;
temp->prev = x;
x->next = temp;
head->next = x;
x->prev = head;
size++;
}
void add_last(const T& data)
{
Node* x = new Node(data);
Node* temp = tail->prev;
temp->next = x;
x->prev = temp;
x->next = tail;
tail->prev = x;
size++;
}
void add(int pos_index, const T& data)
{
check_position_index(pos_index);
if (pos_index == int(size)) {
add_last(data);
return;
}
Node* p = get_node(pos_index);
Node* temp = p->prev;
Node* x = new Node(data);
temp->next = x;
x->prev = temp;
x->next = p;
p->prev = x;
size++;
}
/* Delete functions */
T del_first()
{
if (size == 0) {
throw std::out_of_range("No elements to remove");
}
Node* x = head->next;
Node* temp = x->next;
head->next = temp;
temp->prev = head;
T data = x->data;
delete x;
size--;
return data;
}
T del_last()
{
if (size == 0) {
throw std::out_of_range("No elements to remove");
}
Node* x = tail->prev;
Node* temp = tail->prev->prev;
tail->prev = temp;
temp->next = tail;
T data = x->data;
x->prev = nullptr;
x->next = nullptr;
delete x;
size--;
return data;
}
T del(int index)
{
check_element_index(index);
Node* x = get_node(index);
Node* prev = x->prev;
Node* next = x->next;
prev->next = next;
next->prev = prev;
T data = x->data;
x->prev = nullptr;
x->next = nullptr;
delete x;
size--;
return data;
}
/* Get Functions */
T get_first() const
{
if (is_empty()) {
throw std::out_of_range("No nodes in the list");
}
return head->next->data;
}
T get_last() const
{
if (is_empty()) {
throw std::out_of_range("No nodes in the list");
}
return tail->prev->data;
}
T get(int index)
{
Node* p = get_node(index);
return p->data;
}
/* Set function */
T set(int index, T data)
{
Node* p = get_node(index);
T old_val = p->data;
p->data = data;
return old_val;
}
/* Utility functions */
size_t get_size() const { return size; }
bool is_empty() const { return size == 0; }
void display() const
{
std::cout << "Size = " << size << '\n';
Node* p = head->next;
while (p != tail) {
std::cout << p->data << " <-> ";
p = p->next;
}
std::cout << "nullptr" << '\n';
std::cout << '\n';
}
private:
struct Node {
T data;
Node* prev;
Node* next;
Node(T val) : data(val), prev(nullptr), next(nullptr) {}
};
Node* head;
Node* tail;
size_t size;
Node* get_node(int index)
{
check_element_index(index);
Node* p = head->next;
if (index < int(size) / 2) {
p = head->next;
for (int i = 0; i < index; i++) {
p = p->next;
}
} else {
p = tail->prev;
for (int i = int(size) - 1; i > index; i--) {
p = p->prev;
}
}
return p;
}
bool is_element_index(int index) const
{
return index >= 0 && index < int(size);
}
bool is_position_index(int pos_index) const
{
return pos_index >= 0 && pos_index <= int(size);
}
void check_element_index(int index) const
{
if (!is_element_index(index)) {
throw std::out_of_range(
"Element Index: " + std::to_string(index) +
", Size: " + std::to_string(size));
}
}
void check_position_index(int pos_index) const
{
if (!is_position_index(pos_index)) {
throw std::out_of_range(
"Position Index: " + std::to_string(pos_index) +
", Size: " + std::to_string(size));
}
}
};
} // namespace DataStructures
#endif // DATA_STRUCTURES_DOUBLY_LINKED_LIST_H