Restructure project directories
This commit is contained in:
176
sequential/linkedlist.hpp
Normal file
176
sequential/linkedlist.hpp
Normal file
@@ -0,0 +1,176 @@
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace List
|
||||
{
|
||||
|
||||
template<class T>
|
||||
struct Node
|
||||
{
|
||||
T value;
|
||||
std::unique_ptr<Node<T>> next;
|
||||
|
||||
Node(T const & _value)
|
||||
: value(_value),
|
||||
next(nullptr)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class List
|
||||
{
|
||||
protected:
|
||||
std::unique_ptr<Node<T>> root;
|
||||
Node<T> * tailPtr;
|
||||
std::size_t size;
|
||||
|
||||
public:
|
||||
void Append(T const value)
|
||||
{
|
||||
++size;
|
||||
|
||||
if(tailPtr == nullptr)
|
||||
{
|
||||
root = std::make_unique<Node<T>>(value);
|
||||
tailPtr = root.get();
|
||||
return;
|
||||
}
|
||||
|
||||
tailPtr->next = std::make_unique<Node<T>>(value);
|
||||
tailPtr = tailPtr->next.get();
|
||||
}
|
||||
|
||||
void Prepend(T const value)
|
||||
{
|
||||
++size;
|
||||
|
||||
if(root == nullptr)
|
||||
{
|
||||
root = std::make_unique<Node<T>>(value);
|
||||
tailPtr = root.get();
|
||||
return;
|
||||
}
|
||||
|
||||
auto newRoot = std::make_unique<Node<T>>(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<T> * prevPtr = root.get();
|
||||
Node<T> * curPtr = root->next.get();
|
||||
std::size_t currentIndex = 1u;
|
||||
while(currentIndex < index)
|
||||
{
|
||||
prevPtr = curPtr;
|
||||
curPtr = curPtr->next().get();
|
||||
}
|
||||
|
||||
auto newNode = std::make_unique<Node<T>>(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<T> * curPtr = root.get();
|
||||
std::size_t currentIndex = 0u;
|
||||
while(currentIndex < index - 2u)
|
||||
{
|
||||
curPtr = curPtr->next().get();
|
||||
}
|
||||
|
||||
curPtr->next.release();
|
||||
return;
|
||||
}
|
||||
|
||||
Node<T> * prevPtr = root.get();
|
||||
Node<T> * 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<T> * currentNode = root.get();
|
||||
std:size_t currentIndex = 0u;
|
||||
while(currentIndex < index)
|
||||
{
|
||||
currentNode = currentNode->next.get();
|
||||
}
|
||||
|
||||
return currentNode->value;
|
||||
}
|
||||
|
||||
List()
|
||||
: root(nullptr),
|
||||
tailPtr(nullptr)
|
||||
{}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user