From 5e0a815f26a6dd492aef80c899beac24539bca5f Mon Sep 17 00:00:00 2001 From: Tijmen van Nesselrooij Date: Mon, 29 Apr 2019 20:04:12 +0200 Subject: [PATCH] Single linked list impl --- lists/linkedlist.hpp | 176 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 lists/linkedlist.hpp diff --git a/lists/linkedlist.hpp b/lists/linkedlist.hpp new file mode 100644 index 0000000..7c9d3d9 --- /dev/null +++ b/lists/linkedlist.hpp @@ -0,0 +1,176 @@ +#include +#include + +namespace List +{ + +template +struct Node +{ + T value; + std::unique_ptr> next; + + Node(T const & _value) + : value(_value), + next(nullptr) + {} +}; + +template +class List +{ +protected: + std::unique_ptr> root; + Node * tailPtr; + std::size_t size; + +public: + void Append(T const value) + { + ++size; + + if(tailPtr == nullptr) + { + root = std::make_unique>(value); + tailPtr = root.get(); + return; + } + + tailPtr->next = std::make_unique>(value); + tailPtr = tailPtr->next.get(); + } + + void Prepend(T const value) + { + ++size; + + if(root == nullptr) + { + root = std::make_unique>(value); + tailPtr = root.get(); + return; + } + + auto newRoot = std::make_unique>(value); + newRoot->next.swap(root); + root.swap(newRoot); + } + + void Insert(T const value, std::size_t const index) + { + if(index >= size) + { + throw std::out_of_range("Index is greater or equal to size."); + } + + if(index == 0u) + { + Prepend(value); + return; + } + + if(index == size - 1u) + { + Append(value); + return; + } + + ++size; + + Node * prevPtr = root.get(); + Node * curPtr = root->next.get(); + std::size_t currentIndex = 1u; + while(currentIndex < index) + { + prevPtr = curPtr; + curPtr = curPtr->next().get(); + } + + auto newNode = std::make_unique>(value); + newNode->next.swap(prevPtr->next); + prevPtr->next.swap(newNode); + } + + void Delete(std::size_t const index) + { + if(index >= size) + { + throw std::out_of_range("Index is greater or equal to size."); + } + + --size; + + if(index == 0u) + { + root.swap(root->next); + return; + } + + if(index == size - 1u) + { + Node * curPtr = root.get(); + std::size_t currentIndex = 0u; + while(currentIndex < index - 2u) + { + curPtr = curPtr->next().get(); + } + + curPtr->next.release(); + return; + } + + Node * prevPtr = root.get(); + Node * curPtr = root->next.get(); + std::size_t currentIndex = 1u; + while(currentIndex < index) + { + prevPtr = curPtr; + curPtr = curPtr->next().get(); + } + + prevPtr->next.swap(curPtr->next); + } + + T & Front() + { + if(size == 0u) + { + throw std::out_of_range("List is empty."); + } + + return root->value; + } + + T & Back() + { + if(size == 0u) + { + throw std::out_of_range("List is empty."); + } + + return tailPtr->value; + } + + T & operator[](std::size_t const index) + { + if(index >= size) + { + throw std::out_of_range("Index is greater or equal to size."); + } + + Node * currentNode = root.get(); + std:size_t currentIndex = 0u; + while(currentIndex < index) + { + currentNode = currentNode->next.get(); + } + + return currentNode->value; + } + + List() + : root(nullptr), + tailPtr(nullptr) + {} +}; +}