From b844c786be07fd8eb1f249619f0d84b44dad7bbf Mon Sep 17 00:00:00 2001 From: jossiey Date: Mon, 5 Oct 2020 12:41:07 -0400 Subject: [PATCH] add c++ template data structure of Doubly Link List --- .../DoublyLinkedList_C++_Template/DLL.h | 247 ++++++++++++++++++ .../DoublyLinkedList_C++_Template/DLLtest.cpp | 134 ++++++++++ 2 files changed, 381 insertions(+) create mode 100644 Data_Structures/Linked_List/Doubly_Linked_List/DoublyLinkedList_C++_Template/DLL.h create mode 100644 Data_Structures/Linked_List/Doubly_Linked_List/DoublyLinkedList_C++_Template/DLLtest.cpp diff --git a/Data_Structures/Linked_List/Doubly_Linked_List/DoublyLinkedList_C++_Template/DLL.h b/Data_Structures/Linked_List/Doubly_Linked_List/DoublyLinkedList_C++_Template/DLL.h new file mode 100644 index 000000000..ad55ad839 --- /dev/null +++ b/Data_Structures/Linked_List/Doubly_Linked_List/DoublyLinkedList_C++_Template/DLL.h @@ -0,0 +1,247 @@ +#include + +/* +Class DLList is Double Linked List without a sentinel node +Class Sentinel is Double Linked List using a sentinel node +If you want to know more about sentinel node, here is the explanation from Wikipedia +https://en.wikipedia.org/wiki/Sentinel_node#:~:text=The%20list%20starts%20out%20with,previous%20pointers%20point%20to%20itself.&text=In%20a%20non%2Dempty%20list,the%20tail%20of%20the%20list. + +*/ + +/* DLL Class without a sentinel node */ +template +class DLL { + struct Node { + T m_data; + Node* m_next; + Node* m_prev; + Node(const T& data = T{}, Node* next = nullptr, Node* prev = nullptr) { + m_data = data; + m_next = next; + m_prev = prev; + } + }; + Node* m_front; + Node* m_back; +public: + DLL() { + m_front = nullptr; + m_back = nullptr; + } + void push_front(const T& data); + void push_back(const T& data); + void pop_front(); + void pop_back(); + void print() const; + void reversePrint() const; + ~DLL(); +}; + + +template +void DLL::push_front(const T& data) { + Node* nn = new Node(data, m_front); + if (m_front != nullptr) { + m_front->m_prev = nn; + } + else { + m_back = nn; + } + m_front = nn; +} + + +template +void DLL::push_back(const T& data) { + Node* nn = new Node(data, nullptr, m_back); + if (m_back != nullptr) { + m_back->m_next = nn; + } + else { + m_front = nn; + } + m_back = nn; +} + + +template +void DLL::pop_front() { + if (m_front != nullptr) { + Node* rm = m_front; + m_front = rm->m_next; + if (m_front != nullptr) { + m_front->m_prev = nullptr; + } + else { + m_back = nullptr; + } + delete rm; + } + +} + + +template +void DLL::pop_back() { + if (m_back != nullptr) { + Node* rm = m_back; + m_back = rm->m_prev; + if (m_back != nullptr) { + m_back->m_next = nullptr; + } + else { + m_front = nullptr; + } + delete rm; + } + +} + + +template +void DLL::print() const { + Node* curr = m_front; + while (curr != nullptr) { + std::cout << curr->m_data << " "; + curr = curr->m_next; + } + if (!m_front) { + std::cout << "empty list"; + } + std::cout << std::endl; +} + + +template +void DLL::reversePrint() const { + Node* curr = m_back; + while (curr != nullptr) { + std::cout << curr->m_data << " "; + curr = curr->m_prev; + } + if (!m_back) { + std::cout << "empty list"; + } + std::cout << std::endl; +} + + +template +DLL::~DLL() { + while (m_front) { + Node* it = m_front; + m_front = it->m_next; + delete it; + } +} + +/* Sentinel Class using a sentinel node */ +template +class Sentinel { + struct Node { + T m_data; + Node* m_next; + Node* m_prev; + Node(const T& data = T{}, Node* next = nullptr, Node* prev = nullptr) { + m_data = data; + m_next = next; + m_prev = prev; + } + }; + Node* m_front; + Node* m_back; +public: + Sentinel() { + m_front = new Node(); + m_back = new Node(); + m_front->m_next = m_back; + m_back->m_prev = m_front; + } + void push_front(const T& data); + void push_back(const T& data); + void pop_front(); + void pop_back(); + void print() const; + void reversePrint() const; + ~Sentinel(); +}; + + +template +void Sentinel::push_front(const T& data) { + Node* nn = new Node(data, m_front->m_next, m_front); + m_front->m_next->m_prev = nn; + m_front->m_next = nn; +} + + +template +void Sentinel::push_back(const T& data) { + Node* nn = new Node(data, m_back, m_back->m_prev); + m_back->m_prev->m_next = nn; + m_back->m_prev = nn; +} + + +template +void Sentinel::pop_front() { + //if its an empty list... note that it means + //front sentinel's next node is the back sentinel + if (m_front->m_next != m_back) { + Node* rm = m_front->m_next; + Node* B = rm->m_next; + m_front->m_next = B; + B->m_prev = m_front; + delete rm; + } +} + + +template +void Sentinel::pop_back() { + if (m_back->m_prev != m_front) { + Node* rm = m_back->m_prev; + rm->m_prev->m_next = m_back; + m_back->m_prev = rm->m_prev; + delete rm; + } +} + + +template +void Sentinel::print() const { + Node* curr = m_front->m_next; + while (curr != m_back) { + std::cout << curr->m_data << " "; + curr = curr->m_next; + } + if (m_front->m_next == m_back) { + std::cout << "empty list"; + } + std::cout << std::endl; +} + + +template +void Sentinel::reversePrint() const { + Node* curr = m_back->m_prev; + while (curr != m_front) { + std::cout << curr->m_data << " "; + curr = curr->m_prev; + } + if (m_back->m_prev == m_front) { + std::cout << "empty list"; + } + std::cout << std::endl; +} + + +template +Sentinel::~Sentinel() { + while (m_front != m_back) { + Node* it = m_front; + m_front = it->m_next; + delete it; + } +} + diff --git a/Data_Structures/Linked_List/Doubly_Linked_List/DoublyLinkedList_C++_Template/DLLtest.cpp b/Data_Structures/Linked_List/Doubly_Linked_List/DoublyLinkedList_C++_Template/DLLtest.cpp new file mode 100644 index 000000000..4d39b4c9b --- /dev/null +++ b/Data_Structures/Linked_List/Doubly_Linked_List/DoublyLinkedList_C++_Template/DLLtest.cpp @@ -0,0 +1,134 @@ +/* tester */ + +#include "DLL.h" +#include + +int main(void) { + DLL regular; + Sentinel sentinel; + + /* DLL class test */ + std::cout << "testing regular doubly linked list" << std::endl; + + // test push_front(); + for (int i = 0; i < 3; i++) { + regular.push_front(i); + regular.print(); + } + regular.reversePrint(); + + //test push_back(); + for (int i = 3; i < 6; i++) { + regular.push_back(i); + regular.print(); + } + regular.reversePrint(); + + //test pop_front() & pop_back() + for (int i = 0; i < 7; i++) { + if (i % 2 == 0) { + regular.pop_front(); + } + else { + regular.pop_back(); + } + regular.print(); + } + regular.reversePrint(); + + //test push_back(); + for (int i = 0; i < 3; i++) { + regular.push_back(i); + regular.print(); + } + regular.reversePrint(); + + + for (int i = 3; i < 6; i++) { + regular.push_front(i); + regular.print(); + } + regular.reversePrint(); + + //test pop_front() + for (int i = 0; i < 7; i++) { + if (i % 2) { + regular.pop_front(); + } + else { + regular.pop_back(); + } + regular.print(); + } + regular.reversePrint(); + + + for (int i = 0; i < 3; i++) { + regular.push_front(i); + regular.print(); + } + regular.reversePrint(); + + + /* Sentinel class test */ + + std::cout << "testing sentinel list" << std::endl; + + //test push_front() + for (int i = 0; i < 3; i++) { + sentinel.push_front(i); + sentinel.print(); + } + sentinel.reversePrint(); + + //test push_back() + for (int i = 3; i < 6; i++) { + sentinel.push_back(i); + sentinel.print(); + } + sentinel.reversePrint(); + + //test pop_front() & pup_back() + for (int i = 0; i < 7; i++) { + if (i % 2 == 0) { + sentinel.pop_front(); + } + else { + sentinel.pop_back(); + } + sentinel.print(); + } + sentinel.reversePrint(); + + for (int i = 0; i < 3; i++) { + sentinel.push_back(i); + sentinel.print(); + } + sentinel.reversePrint(); + + for (int i = 3; i < 6; i++) { + sentinel.push_front(i); + sentinel.print(); + } + sentinel.reversePrint(); + + for (int i = 0; i < 7; i++) { + if (i % 2) { + sentinel.pop_front(); + } + else { + sentinel.pop_back(); + } + sentinel.print(); + } + sentinel.reversePrint(); + + for (int i = 0; i < 3; i++) { + sentinel.push_front(i); + sentinel.print(); + } + sentinel.reversePrint(); + + + return 0; +}