Format source files
This commit is contained in:
8
makefile
8
makefile
@@ -4,7 +4,7 @@ CFLAGS = -std=c++17 -Wall -g -Wextra
|
|||||||
CPPS = $(wildcard test/*.cpp)
|
CPPS = $(wildcard test/*.cpp)
|
||||||
EXES = $(patsubst %.cpp, %.out, $(CPPS))
|
EXES = $(patsubst %.cpp, %.out, $(CPPS))
|
||||||
|
|
||||||
.PHONY: all clean rebuild check
|
.PHONY: all clean rebuild check format
|
||||||
|
|
||||||
all: $(EXES)
|
all: $(EXES)
|
||||||
|
|
||||||
@@ -19,5 +19,11 @@ EXESQUOTED = $(patsubst %, "%", $(EXES))
|
|||||||
check: all
|
check: all
|
||||||
./execute-all.sh
|
./execute-all.sh
|
||||||
|
|
||||||
|
format:
|
||||||
|
find src/ -name *.cpp -exec clang-format -i {} \;
|
||||||
|
find src/ -name *.hpp -exec clang-format -i {} \;
|
||||||
|
find test/ -name *.cpp -exec clang-format -i {} \;
|
||||||
|
find test/ -name *.hpp -exec clang-format -i {} \;
|
||||||
|
|
||||||
%.out: %.cpp
|
%.out: %.cpp
|
||||||
$(CC) $(CFLAGS) $< -o $@
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
@@ -5,187 +5,174 @@
|
|||||||
namespace List
|
namespace List
|
||||||
{
|
{
|
||||||
|
|
||||||
template<class T>
|
template<class T> struct Node
|
||||||
struct Node
|
{
|
||||||
{
|
T value;
|
||||||
T value;
|
std::unique_ptr<Node<T>> next;
|
||||||
std::unique_ptr<Node<T>> next;
|
|
||||||
|
|
||||||
Node(T const & _value)
|
Node(T const & _value) : value(_value), next(nullptr) { }
|
||||||
: value(_value),
|
};
|
||||||
next(nullptr)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
template<class T> class List {
|
||||||
class List
|
private:
|
||||||
{
|
std::unique_ptr<Node<T>> root;
|
||||||
private:
|
Node<T> * tailPtr;
|
||||||
std::unique_ptr<Node<T>> root;
|
std::size_t size;
|
||||||
Node<T> * tailPtr;
|
|
||||||
std::size_t size;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Append(T const & value)
|
void Append(T const & value)
|
||||||
{
|
{
|
||||||
if(size == 0)
|
if(size == 0)
|
||||||
{
|
{
|
||||||
root = std::make_unique<Node<T>>(value);
|
root = std::make_unique<Node<T>>(value);
|
||||||
tailPtr = root.get();
|
tailPtr = root.get();
|
||||||
++size;
|
++size;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tailPtr->next = std::make_unique<Node<T>>(value);
|
tailPtr->next = std::make_unique<Node<T>>(value);
|
||||||
tailPtr = tailPtr->next.get();
|
tailPtr = tailPtr->next.get();
|
||||||
|
|
||||||
++size;
|
++size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Prepend(T const & value)
|
void Prepend(T const & value)
|
||||||
{
|
{
|
||||||
if(size == 0)
|
if(size == 0)
|
||||||
{
|
{
|
||||||
root = std::make_unique<Node<T>>(value);
|
root = std::make_unique<Node<T>>(value);
|
||||||
tailPtr = root.get();
|
tailPtr = root.get();
|
||||||
++size;
|
++size;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newRoot = std::make_unique<Node<T>>(value);
|
auto newRoot = std::make_unique<Node<T>>(value);
|
||||||
newRoot->next.swap(root);
|
newRoot->next.swap(root);
|
||||||
root.swap(newRoot);
|
root.swap(newRoot);
|
||||||
|
|
||||||
++size;
|
++size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Insert(T const & value, std::size_t const index)
|
void Insert(T const & value, std::size_t const index)
|
||||||
{
|
{
|
||||||
if(index >= size)
|
if(index >= size)
|
||||||
{
|
{
|
||||||
throw std::out_of_range("Index is greater or equal to size.");
|
throw std::out_of_range("Index is greater or equal to size.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index == 0u)
|
if(index == 0u)
|
||||||
{
|
{
|
||||||
Prepend(value);
|
Prepend(value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
++size;
|
++size;
|
||||||
|
|
||||||
Node<T> * prevPtr = root.get();
|
Node<T> * prevPtr = root.get();
|
||||||
Node<T> * curPtr = root->next.get();
|
Node<T> * curPtr = root->next.get();
|
||||||
std::size_t currentIndex = 1u;
|
std::size_t currentIndex = 1u;
|
||||||
while(currentIndex < index)
|
while(currentIndex < index)
|
||||||
{
|
{
|
||||||
prevPtr = curPtr;
|
prevPtr = curPtr;
|
||||||
curPtr = curPtr->next.get();
|
curPtr = curPtr->next.get();
|
||||||
++currentIndex;
|
++currentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newNode = std::make_unique<Node<T>>(value);
|
auto newNode = std::make_unique<Node<T>>(value);
|
||||||
newNode->next.swap(prevPtr->next);
|
newNode->next.swap(prevPtr->next);
|
||||||
prevPtr->next.swap(newNode);
|
prevPtr->next.swap(newNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Delete(std::size_t const index)
|
void Delete(std::size_t const index)
|
||||||
{
|
{
|
||||||
if(index >= size)
|
if(index >= size)
|
||||||
{
|
{
|
||||||
throw std::out_of_range("Index is greater or equal to size.");
|
throw std::out_of_range("Index is greater or equal to size.");
|
||||||
}
|
}
|
||||||
|
|
||||||
--size;
|
--size;
|
||||||
|
|
||||||
if(index == 0u)
|
if(index == 0u)
|
||||||
{
|
{
|
||||||
if(size == 0u)
|
if(size == 0u)
|
||||||
{
|
{
|
||||||
root.release();
|
root.release();
|
||||||
tailPtr = nullptr;
|
tailPtr = nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
root = std::move(root->next);
|
root = std::move(root->next);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is index last element? Note that we subtracted 1 from size above
|
// Is index last element? Note that we subtracted 1 from size above
|
||||||
if(index == size)
|
if(index == size)
|
||||||
{
|
{
|
||||||
Node<T> * curPtr = root.get();
|
Node<T> * curPtr = root.get();
|
||||||
while(curPtr->next.get() != tailPtr)
|
while(curPtr->next.get() != tailPtr)
|
||||||
{
|
{
|
||||||
curPtr = curPtr->next.get();
|
curPtr = curPtr->next.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
tailPtr = curPtr;
|
tailPtr = curPtr;
|
||||||
tailPtr->next.release();
|
tailPtr->next.release();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node<T> * prevPtr = root.get();
|
Node<T> * prevPtr = root.get();
|
||||||
Node<T> * curPtr = prevPtr->next.get();
|
Node<T> * curPtr = prevPtr->next.get();
|
||||||
std::size_t currentIndex = 1u;
|
std::size_t currentIndex = 1u;
|
||||||
while(currentIndex < index)
|
while(currentIndex < index)
|
||||||
{
|
{
|
||||||
++currentIndex;
|
++currentIndex;
|
||||||
prevPtr = curPtr;
|
prevPtr = curPtr;
|
||||||
curPtr = curPtr->next.get();
|
curPtr = curPtr->next.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
prevPtr->next = std::move(curPtr->next);
|
prevPtr->next = std::move(curPtr->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
T & Front()
|
T & Front()
|
||||||
{
|
{
|
||||||
if(size == 0u)
|
if(size == 0u)
|
||||||
{
|
{
|
||||||
throw std::out_of_range("List is empty.");
|
throw std::out_of_range("List is empty.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return root->value;
|
return root->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
T & Back()
|
T & Back()
|
||||||
{
|
{
|
||||||
if(size == 0u)
|
if(size == 0u)
|
||||||
{
|
{
|
||||||
throw std::out_of_range("List is empty.");
|
throw std::out_of_range("List is empty.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return tailPtr->value;
|
return tailPtr->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
T & operator[](std::size_t const index)
|
T & operator[](std::size_t const index)
|
||||||
{
|
{
|
||||||
if(index >= size)
|
if(index >= size)
|
||||||
{
|
{
|
||||||
throw std::out_of_range("Index is greater or equal to size.");
|
throw std::out_of_range("Index is greater or equal to size.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Node<T> * currentNode = root.get();
|
Node<T> * currentNode = root.get();
|
||||||
std::size_t currentIndex = 0u;
|
std::size_t currentIndex = 0u;
|
||||||
while(currentIndex < index)
|
while(currentIndex < index)
|
||||||
{
|
{
|
||||||
currentNode = currentNode->next.get();
|
currentNode = currentNode->next.get();
|
||||||
++currentIndex;
|
++currentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
return currentNode->value;
|
return currentNode->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t GetSize() const
|
std::size_t GetSize() const { return size; }
|
||||||
{
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
List()
|
List() : root(nullptr), tailPtr(nullptr), size(0) { }
|
||||||
: root(nullptr),
|
};
|
||||||
tailPtr(nullptr),
|
|
||||||
size(0)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,76 +1,65 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
|
|
||||||
template<class T>
|
template<class T> class RingBuffer {
|
||||||
class RingBuffer
|
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
Vector<T> data;
|
Vector<T> data;
|
||||||
std::size_t head, tail;
|
std::size_t head, tail;
|
||||||
|
|
||||||
void AdvanceHead()
|
void AdvanceHead()
|
||||||
{
|
{
|
||||||
++head;
|
++head;
|
||||||
if(head >= data.GetSize())
|
if(head >= data.GetSize())
|
||||||
{
|
{
|
||||||
head = 0;
|
head = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvanceTail()
|
void AdvanceTail()
|
||||||
{
|
{
|
||||||
++tail;
|
++tail;
|
||||||
if(tail >= data.GetSize())
|
if(tail >= data.GetSize())
|
||||||
{
|
{
|
||||||
tail = 0;
|
tail = 0;
|
||||||
}
|
}
|
||||||
if(tail == head)
|
if(tail == head)
|
||||||
{
|
{
|
||||||
AdvanceHead();
|
AdvanceHead();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Push(T const & value)
|
void Push(T const & value)
|
||||||
{
|
{
|
||||||
data[tail] = value;
|
data[tail] = value;
|
||||||
AdvanceTail();
|
AdvanceTail();
|
||||||
}
|
}
|
||||||
|
|
||||||
T Pop()
|
T Pop()
|
||||||
{
|
{
|
||||||
if(head == tail)
|
if(head == tail)
|
||||||
{
|
{
|
||||||
throw std::out_of_range("Cannot retrieve value when size is 0");
|
throw std::out_of_range("Cannot retrieve value when size is 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
T const & toReturn = data[head];
|
T const & toReturn = data[head];
|
||||||
AdvanceHead();
|
AdvanceHead();
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t GetSize() const
|
std::size_t GetSize() const
|
||||||
{
|
{
|
||||||
if(head <= tail)
|
if(head <= tail)
|
||||||
{
|
{
|
||||||
return tail - head;
|
return tail - head;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return tail + (data.GetSize() - head);
|
return tail + (data.GetSize() - head);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsEmpty() const
|
bool IsEmpty() const { return head == tail; }
|
||||||
{
|
|
||||||
return head == tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
RingBuffer(std::size_t const size)
|
RingBuffer(std::size_t const size) : data(), head(0), tail(0) { data.Resize(size + 1ul); }
|
||||||
: data(),
|
|
||||||
head(0),
|
|
||||||
tail(0)
|
|
||||||
{
|
|
||||||
data.Resize(size + 1ul);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
@@ -1,46 +1,38 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
|
|
||||||
template<class T>
|
template<class T> class Stack {
|
||||||
class Stack
|
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
Vector<T> data;
|
Vector<T> data;
|
||||||
std::size_t actualSize;
|
std::size_t actualSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Push(T const & value)
|
void Push(T const & value)
|
||||||
{
|
{
|
||||||
++actualSize;
|
++actualSize;
|
||||||
if(actualSize > data.GetSize())
|
if(actualSize > data.GetSize())
|
||||||
{
|
{
|
||||||
data.Resize(actualSize);
|
data.Resize(actualSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
data[actualSize - 1ul] = value;
|
data[actualSize - 1ul] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
T Pop()
|
T Pop()
|
||||||
{
|
{
|
||||||
if(actualSize == 0ul)
|
if(actualSize == 0ul)
|
||||||
{
|
{
|
||||||
throw std::out_of_range("Cannot pop an empty stack.");
|
throw std::out_of_range("Cannot pop an empty stack.");
|
||||||
}
|
}
|
||||||
auto const retval = data[actualSize - 1ul];
|
auto const retval = data[actualSize - 1ul];
|
||||||
|
|
||||||
--actualSize;
|
--actualSize;
|
||||||
data.Resize(actualSize);
|
data.Resize(actualSize);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t GetSize() const
|
std::size_t GetSize() const { return actualSize; }
|
||||||
{
|
|
||||||
return actualSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
Stack()
|
Stack() : actualSize(0) { }
|
||||||
: actualSize(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
@@ -2,85 +2,73 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
template<class T>
|
template<class T> class Vector {
|
||||||
class Vector
|
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
T * data;
|
T * data;
|
||||||
std::size_t reserveSize;
|
std::size_t reserveSize;
|
||||||
std::size_t size;
|
std::size_t size;
|
||||||
|
|
||||||
void Allocate(std::size_t const allocationSize)
|
void Allocate(std::size_t const allocationSize)
|
||||||
{
|
{
|
||||||
if(allocationSize == 0ul)
|
if(allocationSize == 0ul)
|
||||||
{
|
{
|
||||||
std::free(data);
|
std::free(data);
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
reserveSize = 0ul;
|
reserveSize = 0ul;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(allocationSize == size)
|
if(allocationSize == size)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * result = std::realloc(data, sizeof(T) * allocationSize);
|
void * result = std::realloc(data, sizeof(T) * allocationSize);
|
||||||
if(result == nullptr)
|
if(result == nullptr)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Cannot allocate the requested size of memory.");
|
throw std::runtime_error("Cannot allocate the requested size of memory.");
|
||||||
}
|
}
|
||||||
|
|
||||||
reserveSize = allocationSize;
|
reserveSize = allocationSize;
|
||||||
data = reinterpret_cast<T *>(result);
|
data = reinterpret_cast<T *>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Resize(std::size_t const newSize)
|
void Resize(std::size_t const newSize)
|
||||||
{
|
{
|
||||||
if (newSize > reserveSize)
|
if(newSize > reserveSize)
|
||||||
{
|
{
|
||||||
Allocate(newSize);
|
Allocate(newSize);
|
||||||
size = newSize;
|
size = newSize;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = newSize;
|
size = newSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reserve(std::size_t const newReserveSize)
|
void Reserve(std::size_t const newReserveSize)
|
||||||
{
|
{
|
||||||
if(newReserveSize < size)
|
if(newReserveSize < size)
|
||||||
{
|
{
|
||||||
Allocate(size);
|
Allocate(size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Allocate(newReserveSize);
|
Allocate(newReserveSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
T & operator[](std::size_t const index)
|
T & operator[](std::size_t const index)
|
||||||
{
|
{
|
||||||
if(index >= size)
|
if(index >= size)
|
||||||
{
|
{
|
||||||
throw std::out_of_range("Index is greater or equal to size.");
|
throw std::out_of_range("Index is greater or equal to size.");
|
||||||
}
|
}
|
||||||
return data[index];
|
return data[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t GetSize() const
|
std::size_t GetSize() const { return size; }
|
||||||
{
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t GetReserveSize() const
|
std::size_t GetReserveSize() const { return reserveSize; }
|
||||||
{
|
|
||||||
return reserveSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector()
|
Vector() : data(nullptr), reserveSize(0ul), size(0ul) { }
|
||||||
: data(nullptr),
|
|
||||||
reserveSize(0ul),
|
|
||||||
size(0ul)
|
|
||||||
{}
|
|
||||||
};
|
};
|
||||||
@@ -3,145 +3,126 @@
|
|||||||
|
|
||||||
namespace BinaryTree
|
namespace BinaryTree
|
||||||
{
|
{
|
||||||
template <class T>
|
template<class T> struct Node
|
||||||
struct Node
|
{
|
||||||
{
|
T value;
|
||||||
T value;
|
|
||||||
|
|
||||||
std::unique_ptr<Node<T>> left;
|
std::unique_ptr<Node<T>> left;
|
||||||
std::unique_ptr<Node<T>> right;
|
std::unique_ptr<Node<T>> right;
|
||||||
|
|
||||||
bool HasChildren() const
|
bool HasChildren() const { return static_cast<bool>(left) || static_cast<bool>(right); }
|
||||||
{
|
|
||||||
return static_cast<bool>(left) || static_cast<bool>(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsLeaf() const
|
bool IsLeaf() const { return !HasChildren(); }
|
||||||
{
|
|
||||||
return !HasChildren();
|
|
||||||
}
|
|
||||||
|
|
||||||
Node(T const &_value)
|
Node(T const & _value) : value(_value), left(nullptr), right(nullptr) { }
|
||||||
: value(_value),
|
};
|
||||||
left(nullptr),
|
|
||||||
right(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
template<class T> class Tree {
|
||||||
class Tree
|
private:
|
||||||
{
|
std::unique_ptr<Node<T>> root;
|
||||||
private:
|
|
||||||
std::unique_ptr<Node<T>> root;
|
|
||||||
|
|
||||||
T ExtractSmallestLeaf(std::unique_ptr<Node<T>> &node)
|
T ExtractSmallestLeaf(std::unique_ptr<Node<T>> & node)
|
||||||
{
|
{
|
||||||
std::unique_ptr<Node<T>> *nodePtr = &(node);
|
std::unique_ptr<Node<T>> * nodePtr = &(node);
|
||||||
while ((*nodePtr)->HasChildren())
|
while((*nodePtr)->HasChildren())
|
||||||
{
|
{
|
||||||
if((*nodePtr)->left)
|
if((*nodePtr)->left)
|
||||||
{
|
{
|
||||||
nodePtr = &((*nodePtr)->left);
|
nodePtr = &((*nodePtr)->left);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
T value = (*nodePtr)->value;
|
T value = (*nodePtr)->value;
|
||||||
(*nodePtr) = std::move((*nodePtr)->right);
|
(*nodePtr) = std::move((*nodePtr)->right);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
T value = (*nodePtr)->value;
|
T value = (*nodePtr)->value;
|
||||||
(*nodePtr).release();
|
(*nodePtr).release();
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteNode(std::unique_ptr<Node<T>> & node)
|
void DeleteNode(std::unique_ptr<Node<T>> & node)
|
||||||
{
|
{
|
||||||
if(!node || node->IsLeaf())
|
if(!node || node->IsLeaf())
|
||||||
{
|
{
|
||||||
node.release();
|
node.release();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(node->left))
|
if(!(node->left))
|
||||||
{
|
{
|
||||||
node = std::move(node->right);
|
node = std::move(node->right);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(node->right))
|
if(!(node->right))
|
||||||
{
|
{
|
||||||
node = std::move(node->left);
|
node = std::move(node->left);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In order successor
|
// In order successor
|
||||||
|
|
||||||
auto newNodeValue = ExtractSmallestLeaf(node->right);
|
auto newNodeValue = ExtractSmallestLeaf(node->right);
|
||||||
node->value = newNodeValue;
|
node->value = newNodeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Node<T>> & FindNode(T const & value)
|
std::unique_ptr<Node<T>> & FindNode(T const & value)
|
||||||
{
|
{
|
||||||
std::unique_ptr<Node<T>> *currentPtr = &root;
|
std::unique_ptr<Node<T>> * currentPtr = &root;
|
||||||
while (*currentPtr && (*currentPtr)->value != value)
|
while(*currentPtr && (*currentPtr)->value != value)
|
||||||
{
|
{
|
||||||
if ((*currentPtr)->value > value)
|
if((*currentPtr)->value > value)
|
||||||
{
|
{
|
||||||
currentPtr = &((*currentPtr)->left);
|
currentPtr = &((*currentPtr)->left);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentPtr = &((*currentPtr)->right);
|
currentPtr = &((*currentPtr)->right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *currentPtr;
|
return *currentPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Insert(T const & value)
|
void Insert(T const & value)
|
||||||
{
|
{
|
||||||
std::unique_ptr<Node<T>> *currentPtr = &root;
|
std::unique_ptr<Node<T>> * currentPtr = &root;
|
||||||
while (*currentPtr)
|
while(*currentPtr)
|
||||||
{
|
{
|
||||||
if ((*currentPtr)->value > value)
|
if((*currentPtr)->value > value)
|
||||||
{
|
{
|
||||||
currentPtr = &((*currentPtr)->left);
|
currentPtr = &((*currentPtr)->left);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentPtr = &((*currentPtr)->right);
|
currentPtr = &((*currentPtr)->right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*currentPtr = std::make_unique<Node<T>>(value);
|
*currentPtr = std::make_unique<Node<T>>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertNoDuplicates(T const & value)
|
void InsertNoDuplicates(T const & value)
|
||||||
{
|
{
|
||||||
auto & toInsertIn = FindNode(value);
|
auto & toInsertIn = FindNode(value);
|
||||||
if(toInsertIn)
|
if(toInsertIn)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
toInsertIn = std::make_unique<Node<T>>(value);
|
toInsertIn = std::make_unique<Node<T>>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Contains(T const & value)
|
bool Contains(T const & value) { return static_cast<bool>(FindNode(value)); }
|
||||||
{
|
|
||||||
return static_cast<bool>(FindNode(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Delete(T const & value)
|
void Delete(T const & value)
|
||||||
{
|
{
|
||||||
auto & node = FindNode(value);
|
auto & node = FindNode(value);
|
||||||
DeleteNode(node);
|
DeleteNode(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tree()
|
Tree() : root(nullptr) { }
|
||||||
: root(nullptr)
|
};
|
||||||
{}
|
|
||||||
};
|
|
||||||
} // namespace BinaryTree
|
} // namespace BinaryTree
|
||||||
@@ -1,182 +1,183 @@
|
|||||||
#include "../src/tree/binarytree.hpp"
|
#include "../src/tree/binarytree.hpp"
|
||||||
#include "testutil.hpp"
|
#include "testutil.hpp"
|
||||||
#include <vector>
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
void FillWithUniqueRandomNumbers(BinaryTree::Tree<unsigned> & tree,
|
void FillWithUniqueRandomNumbers(
|
||||||
std::unordered_set<unsigned> & control,
|
BinaryTree::Tree<unsigned> & tree,
|
||||||
unsigned const count = 10000u)
|
std::unordered_set<unsigned> & control,
|
||||||
|
unsigned const count = 10000u)
|
||||||
{
|
{
|
||||||
for(unsigned i = 0u; i < count; ++i)
|
for(unsigned i = 0u; i < count; ++i)
|
||||||
{
|
{
|
||||||
unsigned const value = Util::GetRandomNumber();
|
unsigned const value = Util::GetRandomNumber();
|
||||||
control.insert(value);
|
control.insert(value);
|
||||||
tree.InsertNoDuplicates(value);
|
tree.InsertNoDuplicates(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestInsert()
|
bool TestInsert()
|
||||||
{
|
{
|
||||||
unsigned const testSize = 4096;
|
unsigned const testSize = 4096;
|
||||||
|
|
||||||
std::vector<unsigned> control;
|
std::vector<unsigned> control;
|
||||||
BinaryTree::Tree<unsigned> tree;
|
BinaryTree::Tree<unsigned> tree;
|
||||||
|
|
||||||
for(unsigned i = 0u; i < testSize; ++i)
|
for(unsigned i = 0u; i < testSize; ++i)
|
||||||
{
|
{
|
||||||
unsigned const value = Util::GetRandomNumber();
|
unsigned const value = Util::GetRandomNumber();
|
||||||
control.push_back(value);
|
control.push_back(value);
|
||||||
tree.Insert(value);
|
tree.Insert(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto const & num : control)
|
for(auto const & num: control)
|
||||||
{
|
{
|
||||||
if(!tree.Contains(num))
|
if(!tree.Contains(num))
|
||||||
{
|
{
|
||||||
//std::printf("\tValue %u inserted but cannot be found!\n", num);
|
//std::printf("\tValue %u inserted but cannot be found!\n", num);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestInsertNoDuplicates()
|
bool TestInsertNoDuplicates()
|
||||||
{
|
{
|
||||||
std::unordered_set<unsigned> control;
|
std::unordered_set<unsigned> control;
|
||||||
BinaryTree::Tree<unsigned> tree;
|
BinaryTree::Tree<unsigned> tree;
|
||||||
|
|
||||||
FillWithUniqueRandomNumbers(tree, control);
|
FillWithUniqueRandomNumbers(tree, control);
|
||||||
|
|
||||||
for(auto const & num : control)
|
for(auto const & num: control)
|
||||||
{
|
{
|
||||||
if(!tree.Contains(num))
|
if(!tree.Contains(num))
|
||||||
{
|
{
|
||||||
//std::printf("\tValue %u inserted but cannot be found!\n", num);
|
//std::printf("\tValue %u inserted but cannot be found!\n", num);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestDeletion()
|
bool TestDeletion()
|
||||||
{
|
{
|
||||||
std::unordered_set<unsigned> control;
|
std::unordered_set<unsigned> control;
|
||||||
BinaryTree::Tree<unsigned> tree;
|
BinaryTree::Tree<unsigned> tree;
|
||||||
|
|
||||||
FillWithUniqueRandomNumbers(tree, control);
|
FillWithUniqueRandomNumbers(tree, control);
|
||||||
|
|
||||||
std::vector<unsigned> deletedValues;
|
std::vector<unsigned> deletedValues;
|
||||||
unsigned const toDeleteCount = control.size() / 4;
|
unsigned const toDeleteCount = control.size() / 4;
|
||||||
for(unsigned i = 0u; i < toDeleteCount; ++i)
|
for(unsigned i = 0u; i < toDeleteCount; ++i)
|
||||||
{
|
{
|
||||||
auto const valueTodelete = Util::GetRandomNumber();
|
auto const valueTodelete = Util::GetRandomNumber();
|
||||||
|
|
||||||
auto controlElement = control.find(valueTodelete);
|
auto controlElement = control.find(valueTodelete);
|
||||||
if(controlElement != control.end())
|
if(controlElement != control.end())
|
||||||
{
|
{
|
||||||
control.erase(controlElement);
|
control.erase(controlElement);
|
||||||
tree.Delete(valueTodelete);
|
tree.Delete(valueTodelete);
|
||||||
deletedValues.push_back(valueTodelete);
|
deletedValues.push_back(valueTodelete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto const & num : control)
|
for(auto const & num: control)
|
||||||
{
|
{
|
||||||
if(!tree.Contains(num))
|
if(!tree.Contains(num))
|
||||||
{
|
{
|
||||||
std::puts("[ERROR] Tree does not contain a value that it should.");
|
std::puts("[ERROR] Tree does not contain a value that it should.");
|
||||||
//std::printf("Value %u inserted but cannot be found!\n", num);
|
//std::printf("Value %u inserted but cannot be found!\n", num);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto const & num : deletedValues)
|
for(auto const & num: deletedValues)
|
||||||
{
|
{
|
||||||
if(tree.Contains(num))
|
if(tree.Contains(num))
|
||||||
{
|
{
|
||||||
std::puts("[ERROR] Tree contains deleted value that it should not.");
|
std::puts("[ERROR] Tree contains deleted value that it should not.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestDeletionCase(
|
bool TestDeletionCase(
|
||||||
std::vector<unsigned> const toInsert,
|
std::vector<unsigned> const toInsert,
|
||||||
std::vector<unsigned> const toDelete,
|
std::vector<unsigned> const toDelete,
|
||||||
std::vector<unsigned> const result)
|
std::vector<unsigned> const result)
|
||||||
{
|
{
|
||||||
BinaryTree::Tree<unsigned> tree;
|
BinaryTree::Tree<unsigned> tree;
|
||||||
for(auto n : toInsert)
|
for(auto n: toInsert)
|
||||||
{
|
{
|
||||||
tree.Insert(n);
|
tree.Insert(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto n : toDelete)
|
for(auto n: toDelete)
|
||||||
{
|
{
|
||||||
tree.Delete(n);
|
tree.Delete(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
for(auto n : result)
|
for(auto n: result)
|
||||||
{
|
{
|
||||||
if(!tree.Contains(n))
|
if(!tree.Contains(n))
|
||||||
{
|
{
|
||||||
std::printf("[ERROR] Tree does not contain value %u.\n", n);
|
std::printf("[ERROR] Tree does not contain value %u.\n", n);
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto n : toDelete)
|
for(auto n: toDelete)
|
||||||
{
|
{
|
||||||
if(tree.Contains(n))
|
if(tree.Contains(n))
|
||||||
{
|
{
|
||||||
std::printf("[ERROR] Tree contains deleted value %u.\n", n);
|
std::printf("[ERROR] Tree contains deleted value %u.\n", n);
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestDeletionCases()
|
bool TestDeletionCases()
|
||||||
{
|
{
|
||||||
std::puts("[INFO] Testing deleting root with single child right.");
|
std::puts("[INFO] Testing deleting root with single child right.");
|
||||||
TestDeletionCase(
|
TestDeletionCase(
|
||||||
std::vector<unsigned> { 10, 12, 11, 13},
|
std::vector<unsigned> {10, 12, 11, 13},
|
||||||
std::vector<unsigned> { 10 },
|
std::vector<unsigned> {10},
|
||||||
std::vector<unsigned> { 12, 11, 13 });
|
std::vector<unsigned> {12, 11, 13});
|
||||||
|
|
||||||
std::puts("[INFO] Testing deleting root with single child left.");
|
std::puts("[INFO] Testing deleting root with single child left.");
|
||||||
TestDeletionCase(
|
TestDeletionCase(
|
||||||
std::vector<unsigned> { 15, 12, 11, 13},
|
std::vector<unsigned> {15, 12, 11, 13},
|
||||||
std::vector<unsigned> { 15 },
|
std::vector<unsigned> {15},
|
||||||
std::vector<unsigned> { 12, 11, 13 });
|
std::vector<unsigned> {12, 11, 13});
|
||||||
|
|
||||||
std::puts("[INFO] Testing deleting root with 2 children but no child right left.");
|
std::puts("[INFO] Testing deleting root with 2 children but no child right left.");
|
||||||
TestDeletionCase(
|
TestDeletionCase(
|
||||||
std::vector<unsigned> { 15, 10, 20, 22, 25, 18, 5},
|
std::vector<unsigned> {15, 10, 20, 22, 25, 18, 5},
|
||||||
std::vector<unsigned> { 20 },
|
std::vector<unsigned> {20},
|
||||||
std::vector<unsigned> { 15, 10, 22, 25, 18, 5 });
|
std::vector<unsigned> {15, 10, 22, 25, 18, 5});
|
||||||
|
|
||||||
std::puts("[INFO] Testing deleting root with 2 children.");
|
std::puts("[INFO] Testing deleting root with 2 children.");
|
||||||
TestDeletionCase(
|
TestDeletionCase(
|
||||||
std::vector<unsigned> { 50, 40, 60, 75, 55, 45, 42, 58 },
|
std::vector<unsigned> {50, 40, 60, 75, 55, 45, 42, 58},
|
||||||
std::vector<unsigned> { 50 },
|
std::vector<unsigned> {50},
|
||||||
std::vector<unsigned> { 40, 60, 75, 55, 45, 42, 58 });
|
std::vector<unsigned> {40, 60, 75, 55, 45, 42, 58});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Test::Execute(TestInsert, "Insertion and find test");
|
Test::Execute(TestInsert, "Insertion and find test");
|
||||||
Test::Execute(TestInsertNoDuplicates, "Insertion without duplicates test");
|
Test::Execute(TestInsertNoDuplicates, "Insertion without duplicates test");
|
||||||
Test::Execute(TestDeletion, "Insertion and deletion test");
|
Test::Execute(TestDeletion, "Insertion and deletion test");
|
||||||
Test::Execute(TestDeletionCases, "Deletion cases test");
|
Test::Execute(TestDeletionCases, "Deletion cases test");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -3,135 +3,135 @@
|
|||||||
|
|
||||||
bool TestAppending()
|
bool TestAppending()
|
||||||
{
|
{
|
||||||
unsigned const testSize = 5;
|
unsigned const testSize = 5;
|
||||||
|
|
||||||
std::vector<unsigned> truth;
|
std::vector<unsigned> truth;
|
||||||
List::List<unsigned> list;
|
List::List<unsigned> list;
|
||||||
|
|
||||||
truth.resize(testSize);
|
truth.resize(testSize);
|
||||||
for(unsigned i = 0; i < testSize; ++i)
|
for(unsigned i = 0; i < testSize; ++i)
|
||||||
{
|
{
|
||||||
unsigned const value = Util::GetRandomNumber();
|
unsigned const value = Util::GetRandomNumber();
|
||||||
truth[i] = value;
|
truth[i] = value;
|
||||||
list.Append(value);
|
list.Append(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i = 0; i < testSize; ++i)
|
for(unsigned i = 0; i < testSize; ++i)
|
||||||
{
|
{
|
||||||
if(truth[i] != list[i])
|
if(truth[i] != list[i])
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestPrepending()
|
bool TestPrepending()
|
||||||
{
|
{
|
||||||
unsigned const testSize = 5;
|
unsigned const testSize = 5;
|
||||||
|
|
||||||
std::vector<unsigned> truth;
|
std::vector<unsigned> truth;
|
||||||
List::List<unsigned> list;
|
List::List<unsigned> list;
|
||||||
|
|
||||||
truth.resize(testSize);
|
truth.resize(testSize);
|
||||||
for(unsigned i = testSize; i > 0; --i)
|
for(unsigned i = testSize; i > 0; --i)
|
||||||
{
|
{
|
||||||
unsigned const value = Util::GetRandomNumber();
|
unsigned const value = Util::GetRandomNumber();
|
||||||
truth[i - 1] = value;
|
truth[i - 1] = value;
|
||||||
list.Prepend(value);
|
list.Prepend(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i = 0; i < testSize; ++i)
|
for(unsigned i = 0; i < testSize; ++i)
|
||||||
{
|
{
|
||||||
if(truth[i] != list[i])
|
if(truth[i] != list[i])
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestPrependAppendMix()
|
bool TestPrependAppendMix()
|
||||||
{
|
{
|
||||||
std::vector<unsigned> numbers = { 5, 6, 4, 7, 3, 8, 2, 9, 1, 10 };
|
std::vector<unsigned> numbers = {5, 6, 4, 7, 3, 8, 2, 9, 1, 10};
|
||||||
List::List<unsigned> list;
|
List::List<unsigned> list;
|
||||||
|
|
||||||
for(unsigned i = 0; i < numbers.size(); i += 2)
|
for(unsigned i = 0; i < numbers.size(); i += 2)
|
||||||
{
|
{
|
||||||
list.Prepend(numbers[i]);
|
list.Prepend(numbers[i]);
|
||||||
list.Append(numbers[i + 1]);
|
list.Append(numbers[i + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i = 0; i < list.GetSize(); ++i)
|
for(unsigned i = 0; i < list.GetSize(); ++i)
|
||||||
{
|
{
|
||||||
if(list[i] != i + 1)
|
if(list[i] != i + 1)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestDeletion()
|
bool TestDeletion()
|
||||||
{
|
{
|
||||||
List::List<unsigned> list;
|
List::List<unsigned> list;
|
||||||
|
|
||||||
for(unsigned i = 1; i < 8; ++i)
|
for(unsigned i = 1; i < 8; ++i)
|
||||||
{
|
{
|
||||||
list.Append(i);
|
list.Append(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i = 0; i < list.GetSize(); ++i)
|
for(unsigned i = 0; i < list.GetSize(); ++i)
|
||||||
{
|
{
|
||||||
list.Delete(i);
|
list.Delete(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i = 0; i < list.GetSize(); ++i)
|
for(unsigned i = 0; i < list.GetSize(); ++i)
|
||||||
{
|
{
|
||||||
if(list[i] % 2 != 0)
|
if(list[i] % 2 != 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestInsertion()
|
bool TestInsertion()
|
||||||
{
|
{
|
||||||
unsigned const testSize = 11;
|
unsigned const testSize = 11;
|
||||||
List::List<unsigned> list;
|
List::List<unsigned> list;
|
||||||
|
|
||||||
for(unsigned i = 1; i < testSize; i += 2)
|
for(unsigned i = 1; i < testSize; i += 2)
|
||||||
{
|
{
|
||||||
list.Append(i);
|
list.Append(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i = 1; i < testSize - 2; i += 2)
|
for(unsigned i = 1; i < testSize - 2; i += 2)
|
||||||
{
|
{
|
||||||
list.Insert(i + 1, i);
|
list.Insert(i + 1, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i = 1; i <= list.GetSize(); ++i)
|
for(unsigned i = 1; i <= list.GetSize(); ++i)
|
||||||
{
|
{
|
||||||
if(list[i - 1] != i)
|
if(list[i - 1] != i)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Test::Execute(TestAppending, "Appending test");
|
Test::Execute(TestAppending, "Appending test");
|
||||||
Test::Execute(TestPrepending, "Prepending test");
|
Test::Execute(TestPrepending, "Prepending test");
|
||||||
Test::Execute(TestPrependAppendMix, "Prepend append mix test");
|
Test::Execute(TestPrependAppendMix, "Prepend append mix test");
|
||||||
Test::Execute(TestDeletion, "Deletion test");
|
Test::Execute(TestDeletion, "Deletion test");
|
||||||
Test::Execute(TestInsertion, "Insertion test");
|
Test::Execute(TestInsertion, "Insertion test");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -3,58 +3,58 @@
|
|||||||
|
|
||||||
bool TestInsertion()
|
bool TestInsertion()
|
||||||
{
|
{
|
||||||
std::size_t const testSize = 512u;
|
std::size_t const testSize = 512u;
|
||||||
|
|
||||||
std::vector<unsigned> truth;
|
std::vector<unsigned> truth;
|
||||||
truth.resize(testSize);
|
truth.resize(testSize);
|
||||||
RingBuffer<unsigned> ringBuffer(512u);
|
RingBuffer<unsigned> ringBuffer(512u);
|
||||||
|
|
||||||
for(std::size_t i = 0; i < testSize; ++i)
|
for(std::size_t i = 0; i < testSize; ++i)
|
||||||
{
|
{
|
||||||
truth[i] = Util::GetRandomNumber();
|
truth[i] = Util::GetRandomNumber();
|
||||||
ringBuffer.Push(truth[i]);
|
ringBuffer.Push(truth[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::size_t i = 0; i < testSize; ++i)
|
for(std::size_t i = 0; i < testSize; ++i)
|
||||||
{
|
{
|
||||||
if(truth[i] != ringBuffer.Pop())
|
if(truth[i] != ringBuffer.Pop())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestWrapAround()
|
bool TestWrapAround()
|
||||||
{
|
{
|
||||||
std::size_t const testSize = 32u;
|
std::size_t const testSize = 32u;
|
||||||
|
|
||||||
RingBuffer<unsigned> ringBuffer(testSize);
|
RingBuffer<unsigned> ringBuffer(testSize);
|
||||||
for(std::size_t i = 0; i < testSize / 2u; ++i)
|
for(std::size_t i = 0; i < testSize / 2u; ++i)
|
||||||
{
|
{
|
||||||
ringBuffer.Push(42u);
|
ringBuffer.Push(42u);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::size_t i = 0; i < testSize; ++i)
|
for(std::size_t i = 0; i < testSize; ++i)
|
||||||
{
|
{
|
||||||
ringBuffer.Push(i);
|
ringBuffer.Push(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::size_t i = 0; i < testSize; ++i)
|
for(std::size_t i = 0; i < testSize; ++i)
|
||||||
{
|
{
|
||||||
if(ringBuffer.Pop() != i)
|
if(ringBuffer.Pop() != i)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Test::Execute(TestInsertion, "Insertion test");
|
Test::Execute(TestInsertion, "Insertion test");
|
||||||
Test::Execute(TestWrapAround, "Wrap around test");
|
Test::Execute(TestWrapAround, "Wrap around test");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -4,32 +4,32 @@
|
|||||||
|
|
||||||
bool TestStack()
|
bool TestStack()
|
||||||
{
|
{
|
||||||
std::size_t testSize = 512ul;
|
std::size_t testSize = 512ul;
|
||||||
|
|
||||||
std::stack<unsigned> truth;
|
std::stack<unsigned> truth;
|
||||||
Stack<unsigned> stack;
|
Stack<unsigned> stack;
|
||||||
|
|
||||||
for(std::size_t i = 0; i < testSize; ++i)
|
for(std::size_t i = 0; i < testSize; ++i)
|
||||||
{
|
{
|
||||||
unsigned const toInsert = Util::GetRandomNumber();
|
unsigned const toInsert = Util::GetRandomNumber();
|
||||||
truth.push(toInsert);
|
truth.push(toInsert);
|
||||||
stack.Push(toInsert);
|
stack.Push(toInsert);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!truth.empty())
|
while(!truth.empty())
|
||||||
{
|
{
|
||||||
if(truth.top() != stack.Pop())
|
if(truth.top() != stack.Pop())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
truth.pop();
|
truth.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Test::Execute(TestStack, "Pop push test");
|
Test::Execute(TestStack, "Pop push test");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -7,57 +7,57 @@
|
|||||||
|
|
||||||
namespace Util
|
namespace Util
|
||||||
{
|
{
|
||||||
unsigned static GetRandomNumber()
|
unsigned static GetRandomNumber()
|
||||||
{
|
{
|
||||||
static std::default_random_engine eng;
|
static std::default_random_engine eng;
|
||||||
static std::uniform_int_distribution<unsigned> valueDist(0u, 8096u);
|
static std::uniform_int_distribution<unsigned> valueDist(0u, 8096u);
|
||||||
|
|
||||||
return valueDist(eng);
|
return valueDist(eng);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Test
|
namespace Test
|
||||||
{
|
{
|
||||||
void Execute(bool (*testFunction)(void), char const * const message)
|
void Execute(bool (*testFunction)(void), char const * const message)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(testFunction())
|
if(testFunction())
|
||||||
{
|
{
|
||||||
std::printf("[PASS] %s\n", message);
|
std::printf("[PASS] %s\n", message);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::printf("[FAIL] %s\n", message);
|
std::printf("[FAIL] %s\n", message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(std::exception & e)
|
catch(std::exception & e)
|
||||||
{
|
{
|
||||||
std::printf("[FAIL] Exception thrown during execution of <%s>, error: %s\n", message, e.what());
|
std::printf("[FAIL] Exception thrown during execution of <%s>, error: %s\n", message, e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute(bool (*testFunction)(std::vector<std::string> &), char const * const message)
|
void Execute(bool (*testFunction)(std::vector<std::string> &), char const * const message)
|
||||||
{
|
{
|
||||||
std::vector<std::string> issues;
|
std::vector<std::string> issues;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(testFunction(issues))
|
if(testFunction(issues))
|
||||||
{
|
{
|
||||||
std::printf("[PASS] %s\n", message);
|
std::printf("[PASS] %s\n", message);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::printf("[FAIL] %s\n", message);
|
std::printf("[FAIL] %s\n", message);
|
||||||
for(auto & issue : issues)
|
for(auto & issue: issues)
|
||||||
{
|
{
|
||||||
std::printf(" Issue: %s\n", issue.c_str());
|
std::printf(" Issue: %s\n", issue.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(std::exception & e)
|
catch(std::exception & e)
|
||||||
{
|
{
|
||||||
std::printf("[FAIL] Exception thrown during execution of <%s>, error: %s\n", message, e.what());
|
std::printf("[FAIL] Exception thrown during execution of <%s>, error: %s\n", message, e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
151
test/vector.cpp
151
test/vector.cpp
@@ -1,111 +1,110 @@
|
|||||||
#include "../src/sequential/vector.hpp"
|
#include "../src/sequential/vector.hpp"
|
||||||
#include "testutil.hpp"
|
#include "testutil.hpp"
|
||||||
|
|
||||||
void FillWithSequentialNumbers(Vector<unsigned> & vector,
|
void FillWithSequentialNumbers(Vector<unsigned> & vector, unsigned const count = 1024u)
|
||||||
unsigned const count = 1024u)
|
|
||||||
{
|
{
|
||||||
for(unsigned i = 0; i < count; ++i)
|
for(unsigned i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
vector[i] = i;
|
vector[i] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestInsertion()
|
bool TestInsertion()
|
||||||
{
|
{
|
||||||
unsigned const targetSize = 1024u;
|
unsigned const targetSize = 1024u;
|
||||||
Vector<unsigned> vector;
|
Vector<unsigned> vector;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
vector.Resize(targetSize);
|
vector.Resize(targetSize);
|
||||||
}
|
}
|
||||||
catch(std::exception & e)
|
catch(std::exception & e)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FillWithSequentialNumbers(vector, targetSize);
|
FillWithSequentialNumbers(vector, targetSize);
|
||||||
|
|
||||||
for(unsigned i = 0; i < vector.GetSize(); ++i)
|
for(unsigned i = 0; i < vector.GetSize(); ++i)
|
||||||
{
|
{
|
||||||
if(vector[i] != i)
|
if(vector[i] != i)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
vector[targetSize + 1] = 42;
|
vector[targetSize + 1] = 42;
|
||||||
}
|
}
|
||||||
catch(std::exception & e)
|
catch(std::exception & e)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestResize()
|
bool TestResize()
|
||||||
{
|
{
|
||||||
Vector<unsigned> vector;
|
Vector<unsigned> vector;
|
||||||
|
|
||||||
vector.Resize(2048u);
|
vector.Resize(2048u);
|
||||||
FillWithSequentialNumbers(vector);
|
FillWithSequentialNumbers(vector);
|
||||||
|
|
||||||
vector.Resize(vector.GetSize() / 2u);
|
vector.Resize(vector.GetSize() / 2u);
|
||||||
for(unsigned i = 0; i < vector.GetSize(); ++i)
|
for(unsigned i = 0; i < vector.GetSize(); ++i)
|
||||||
{
|
{
|
||||||
if(vector[i] != i)
|
if(vector[i] != i)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector.Resize(vector.GetSize() * 16u);
|
vector.Resize(vector.GetSize() * 16u);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestReserve()
|
bool TestReserve()
|
||||||
{
|
{
|
||||||
std::size_t const testSize = 8096ul;
|
std::size_t const testSize = 8096ul;
|
||||||
|
|
||||||
Vector<unsigned> vector;
|
Vector<unsigned> vector;
|
||||||
vector.Reserve(testSize);
|
vector.Reserve(testSize);
|
||||||
if(vector.GetReserveSize() != testSize)
|
if(vector.GetReserveSize() != testSize)
|
||||||
{
|
{
|
||||||
std::puts("[ERROR] Reserve size reported not equal to reserve size set.");
|
std::puts("[ERROR] Reserve size reported not equal to reserve size set.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::size_t i = 0; i < testSize; ++i)
|
for(std::size_t i = 0; i < testSize; ++i)
|
||||||
{
|
{
|
||||||
vector.Resize(i + 1ul);
|
vector.Resize(i + 1ul);
|
||||||
vector[i] = i;
|
vector[i] = i;
|
||||||
|
|
||||||
if(vector.GetReserveSize() != testSize)
|
if(vector.GetReserveSize() != testSize)
|
||||||
{
|
{
|
||||||
std::puts("[ERROR] Reserve size changed during resize.");
|
std::puts("[ERROR] Reserve size changed during resize.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::size_t i = 0; i < testSize; ++i)
|
for(std::size_t i = 0; i < testSize; ++i)
|
||||||
{
|
{
|
||||||
if(vector[i] != i)
|
if(vector[i] != i)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Test::Execute(TestInsertion, "Insertion test");
|
Test::Execute(TestInsertion, "Insertion test");
|
||||||
Test::Execute(TestResize, "Resize test");
|
Test::Execute(TestResize, "Resize test");
|
||||||
Test::Execute(TestReserve, "Reserve test");
|
Test::Execute(TestReserve, "Reserve test");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user