Broke the binary tree, please fix :-)
This commit is contained in:
@@ -1,22 +1,22 @@
|
|||||||
#include "../tree/binarytree.hpp"
|
#include "../tree/binarytree.hpp"
|
||||||
#include "testutil.hpp"
|
#include "testutil.hpp"
|
||||||
#include <unordered_set>
|
#include <vector>
|
||||||
|
|
||||||
void FillWithRandomNumbers(BinaryTree::Tree<unsigned> & tree,
|
void FillWithRandomNumbers(BinaryTree::Tree<unsigned> & tree,
|
||||||
std::unordered_set<unsigned> & control,
|
std::vector<unsigned> & control,
|
||||||
unsigned const count = 512u)
|
unsigned const count = 512u)
|
||||||
{
|
{
|
||||||
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.push_back(value);
|
||||||
tree.Insert(value);
|
tree.Insert(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestInsertContains()
|
bool TestInsertContains()
|
||||||
{
|
{
|
||||||
std::unordered_set<unsigned> control;
|
std::vector<unsigned> control;
|
||||||
BinaryTree::Tree<unsigned> tree;
|
BinaryTree::Tree<unsigned> tree;
|
||||||
|
|
||||||
FillWithRandomNumbers(tree, control);
|
FillWithRandomNumbers(tree, control);
|
||||||
@@ -26,7 +26,7 @@ bool TestInsertContains()
|
|||||||
{
|
{
|
||||||
if(!tree.Contains(num))
|
if(!tree.Contains(num))
|
||||||
{
|
{
|
||||||
std::printf("Value %u inserted but cannot be found!\n", num);
|
std::printf("\tValue %u inserted but cannot be found!\n", num);
|
||||||
good = false;
|
good = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,23 +36,19 @@ bool TestInsertContains()
|
|||||||
|
|
||||||
bool TestDeletion()
|
bool TestDeletion()
|
||||||
{
|
{
|
||||||
std::unordered_set<unsigned> control;
|
std::vector<unsigned> control;
|
||||||
BinaryTree::Tree<unsigned> tree;
|
BinaryTree::Tree<unsigned> tree;
|
||||||
|
|
||||||
FillWithRandomNumbers(tree, control);
|
FillWithRandomNumbers(tree, control);
|
||||||
|
|
||||||
unsigned i = 0u;
|
|
||||||
unsigned const toDeleteCount = control.size() / 4;
|
unsigned const toDeleteCount = control.size() / 4;
|
||||||
while(i < toDeleteCount)
|
for(unsigned i = 0u; i < toDeleteCount; ++i)
|
||||||
{
|
{
|
||||||
auto const toDelete = Util::GetRandomNumber();
|
auto const toDeleteIndex = Util::GetRandomNumber() % control.size();
|
||||||
auto iter = control.find(toDelete);
|
auto const toDeleteValue = control[toDeleteIndex];
|
||||||
if(iter != control.end())
|
|
||||||
{
|
control.erase(control.begin() + toDeleteIndex);
|
||||||
control.erase(iter);
|
tree.Delete(toDeleteValue);
|
||||||
tree.Delete(i);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool good = true;
|
bool good = true;
|
||||||
|
|||||||
@@ -48,11 +48,11 @@ void Execute(bool (*testFunction)(std::vector<std::string> &), char const * cons
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
std::printf("[FAIL] %s\n", message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(std::exception & e)
|
catch(std::exception & e)
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ namespace BinaryTree
|
|||||||
template <class T>
|
template <class T>
|
||||||
struct Node
|
struct Node
|
||||||
{
|
{
|
||||||
Node *parent;
|
|
||||||
|
|
||||||
T value;
|
T value;
|
||||||
|
|
||||||
std::unique_ptr<Node<T>> left;
|
std::unique_ptr<Node<T>> left;
|
||||||
@@ -18,9 +16,10 @@ struct Node
|
|||||||
return left == nullptr && right == nullptr;
|
return left == nullptr && right == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node(T const &_value, Node<T> *_parent)
|
Node(T const &_value)
|
||||||
: parent(_parent),
|
: value(_value),
|
||||||
value(_value)
|
left(nullptr),
|
||||||
|
right(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -31,9 +30,9 @@ class Tree
|
|||||||
private:
|
private:
|
||||||
std::unique_ptr<Node<T>> root;
|
std::unique_ptr<Node<T>> root;
|
||||||
|
|
||||||
std::unique_ptr<Node<T>> & GetRightMostLeaf(std::unique_ptr<Node<T>> &localRoot)
|
std::unique_ptr<Node<T>> & GetRightMostLeaf(std::unique_ptr<Node<T>> &node)
|
||||||
{
|
{
|
||||||
std::unique_ptr<Node<T>> *nodePtr = &localRoot;
|
std::unique_ptr<Node<T>> *nodePtr = &node;
|
||||||
while ((*nodePtr)->right != nullptr)
|
while ((*nodePtr)->right != nullptr)
|
||||||
{
|
{
|
||||||
nodePtr = &((*nodePtr)->right);
|
nodePtr = &((*nodePtr)->right);
|
||||||
@@ -42,91 +41,91 @@ private:
|
|||||||
return *nodePtr;
|
return *nodePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
void DeleteNode(std::unique_ptr<Node<T>> & node)
|
||||||
void Insert(T value)
|
|
||||||
{
|
{
|
||||||
Node<T> *previousPtr = nullptr;
|
if(node == nullptr || node->IsLeaf())
|
||||||
std::unique_ptr<Node<T>> *rootPtr = &root;
|
|
||||||
while (*rootPtr != nullptr)
|
|
||||||
{
|
{
|
||||||
previousPtr = rootPtr->get();
|
node.release();
|
||||||
if ((*rootPtr)->value > value)
|
|
||||||
{
|
|
||||||
rootPtr = &((*rootPtr)->left);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rootPtr = &((*rootPtr)->right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*rootPtr = std::make_unique<Node<T>>(value, previousPtr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Contains(T const value)
|
if(node->left == nullptr)
|
||||||
{
|
{
|
||||||
std::unique_ptr<Node<T>> *rootPtr = &root;
|
node = std::move(node->right);
|
||||||
while (*rootPtr != nullptr)
|
|
||||||
{
|
|
||||||
if ((*rootPtr)->value == value)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*rootPtr)->value > value)
|
if(node->right == nullptr)
|
||||||
{
|
{
|
||||||
rootPtr = &((*rootPtr)->left);
|
node = std::move(node->left);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rootPtr = &((*rootPtr)->right);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
auto & replacementNode = GetRightMostLeaf(node);
|
||||||
}
|
replacementNode->left.swap(node->left);
|
||||||
|
replacementNode->right.swap(node->right);
|
||||||
|
node.swap(replacementNode);
|
||||||
|
|
||||||
void Delete(T const value)
|
|
||||||
{
|
|
||||||
std::unique_ptr<Node<T>> *rootPtr = &root;
|
|
||||||
while (*rootPtr != nullptr)
|
|
||||||
{
|
|
||||||
if ((*rootPtr)->value == value)
|
|
||||||
{
|
|
||||||
if ((*rootPtr)->IsLeaf())
|
|
||||||
{
|
|
||||||
rootPtr->release();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((*rootPtr)->left == nullptr)
|
|
||||||
{
|
|
||||||
rootPtr->swap((*rootPtr)->right);
|
|
||||||
(*rootPtr)->right.release();
|
|
||||||
}
|
|
||||||
else if ((*rootPtr)->right == nullptr)
|
|
||||||
{
|
|
||||||
rootPtr->swap((*rootPtr)->left);
|
|
||||||
(*rootPtr)->left.release();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto &replacementNode = GetRightMostLeaf((*rootPtr)->left);
|
|
||||||
rootPtr->swap(replacementNode);
|
|
||||||
replacementNode.release();
|
replacementNode.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
std::unique_ptr<Node<T>> & FindNode(T const & value)
|
||||||
}
|
|
||||||
|
|
||||||
if ((*rootPtr)->value > value)
|
|
||||||
{
|
{
|
||||||
rootPtr = &((*rootPtr)->left);
|
std::unique_ptr<Node<T>> *currentPtr = &root;
|
||||||
|
while (*currentPtr != nullptr && (*currentPtr)->value != value)
|
||||||
|
{
|
||||||
|
if ((*currentPtr)->value > value)
|
||||||
|
{
|
||||||
|
currentPtr = &((*currentPtr)->left);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rootPtr = &((*rootPtr)->right);
|
currentPtr = &((*currentPtr)->right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return *currentPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Insert(T const & value)
|
||||||
|
{
|
||||||
|
std::unique_ptr<Node<T>> *currentPtr = &root;
|
||||||
|
while ((*currentPtr) != nullptr)
|
||||||
|
{
|
||||||
|
if ((*currentPtr)->value > value)
|
||||||
|
{
|
||||||
|
currentPtr = &((*currentPtr)->left);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentPtr = &((*currentPtr)->right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*currentPtr = std::make_unique<Node<T>>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InsertNoDuplicates(T const & value)
|
||||||
|
{
|
||||||
|
auto & toInsertIn = FindNode(value);
|
||||||
|
if(toInsertIn != nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
toInsertIn = std::make_unique<Node<T>>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Contains(T const & value)
|
||||||
|
{
|
||||||
|
return FindNode(value) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Delete(T const & value)
|
||||||
|
{
|
||||||
|
auto & node = FindNode(value);
|
||||||
|
if (node == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DeleteNode(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tree()
|
Tree()
|
||||||
|
|||||||
Reference in New Issue
Block a user