From 19bc9aed6b5c1d875f24c026debd3b4d3e109101 Mon Sep 17 00:00:00 2001 From: Tijmen van Nesselrooij Date: Sun, 12 May 2019 12:01:09 +0200 Subject: [PATCH] Broke the binary tree, please fix :-) --- test/binarytree.cpp | 28 ++++----- test/testutil.hpp | 2 +- tree/binarytree.hpp | 143 ++++++++++++++++++++++---------------------- 3 files changed, 84 insertions(+), 89 deletions(-) diff --git a/test/binarytree.cpp b/test/binarytree.cpp index 1c8bc0f..6f5e219 100644 --- a/test/binarytree.cpp +++ b/test/binarytree.cpp @@ -1,22 +1,22 @@ #include "../tree/binarytree.hpp" #include "testutil.hpp" -#include +#include void FillWithRandomNumbers(BinaryTree::Tree & tree, - std::unordered_set & control, + std::vector & control, unsigned const count = 512u) { for(unsigned i = 0u; i < count; ++i) { unsigned const value = Util::GetRandomNumber(); - control.insert(value); + control.push_back(value); tree.Insert(value); } } bool TestInsertContains() { - std::unordered_set control; + std::vector control; BinaryTree::Tree tree; FillWithRandomNumbers(tree, control); @@ -26,7 +26,7 @@ bool TestInsertContains() { 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; } } @@ -36,23 +36,19 @@ bool TestInsertContains() bool TestDeletion() { - std::unordered_set control; + std::vector control; BinaryTree::Tree tree; FillWithRandomNumbers(tree, control); - unsigned i = 0u; unsigned const toDeleteCount = control.size() / 4; - while(i < toDeleteCount) + for(unsigned i = 0u; i < toDeleteCount; ++i) { - auto const toDelete = Util::GetRandomNumber(); - auto iter = control.find(toDelete); - if(iter != control.end()) - { - control.erase(iter); - tree.Delete(i); - ++i; - } + auto const toDeleteIndex = Util::GetRandomNumber() % control.size(); + auto const toDeleteValue = control[toDeleteIndex]; + + control.erase(control.begin() + toDeleteIndex); + tree.Delete(toDeleteValue); } bool good = true; diff --git a/test/testutil.hpp b/test/testutil.hpp index 6570323..82e5107 100644 --- a/test/testutil.hpp +++ b/test/testutil.hpp @@ -48,11 +48,11 @@ void Execute(bool (*testFunction)(std::vector &), char const * cons } else { + std::printf("[FAIL] %s\n", message); for(auto & issue : issues) { std::printf(" Issue: %s\n", issue.c_str()); } - std::printf("[FAIL] %s\n", message); } } catch(std::exception & e) diff --git a/tree/binarytree.hpp b/tree/binarytree.hpp index b74ec3c..42833cc 100644 --- a/tree/binarytree.hpp +++ b/tree/binarytree.hpp @@ -6,8 +6,6 @@ namespace BinaryTree template struct Node { - Node *parent; - T value; std::unique_ptr> left; @@ -18,9 +16,10 @@ struct Node return left == nullptr && right == nullptr; } - Node(T const &_value, Node *_parent) - : parent(_parent), - value(_value) + Node(T const &_value) + : value(_value), + left(nullptr), + right(nullptr) { } }; @@ -31,9 +30,9 @@ class Tree private: std::unique_ptr> root; - std::unique_ptr> & GetRightMostLeaf(std::unique_ptr> &localRoot) + std::unique_ptr> & GetRightMostLeaf(std::unique_ptr> &node) { - std::unique_ptr> *nodePtr = &localRoot; + std::unique_ptr> *nodePtr = &node; while ((*nodePtr)->right != nullptr) { nodePtr = &((*nodePtr)->right); @@ -42,91 +41,91 @@ private: return *nodePtr; } + void DeleteNode(std::unique_ptr> & node) + { + if(node == nullptr || node->IsLeaf()) + { + node.release(); + } + + if(node->left == nullptr) + { + node = std::move(node->right); + } + + if(node->right == nullptr) + { + node = std::move(node->left); + } + + auto & replacementNode = GetRightMostLeaf(node); + replacementNode->left.swap(node->left); + replacementNode->right.swap(node->right); + node.swap(replacementNode); + + replacementNode.release(); + } + + std::unique_ptr> & FindNode(T const & value) + { + std::unique_ptr> *currentPtr = &root; + while (*currentPtr != nullptr && (*currentPtr)->value != value) + { + if ((*currentPtr)->value > value) + { + currentPtr = &((*currentPtr)->left); + } + else + { + currentPtr = &((*currentPtr)->right); + } + } + + return *currentPtr; + } + public: - void Insert(T value) + void Insert(T const & value) { - Node *previousPtr = nullptr; - std::unique_ptr> *rootPtr = &root; - while (*rootPtr != nullptr) + std::unique_ptr> *currentPtr = &root; + while ((*currentPtr) != nullptr) { - previousPtr = rootPtr->get(); - if ((*rootPtr)->value > value) + if ((*currentPtr)->value > value) { - rootPtr = &((*rootPtr)->left); + currentPtr = &((*currentPtr)->left); } else { - rootPtr = &((*rootPtr)->right); + currentPtr = &((*currentPtr)->right); } } - *rootPtr = std::make_unique>(value, previousPtr); + *currentPtr = std::make_unique>(value); } - bool Contains(T const value) + void InsertNoDuplicates(T const & value) { - std::unique_ptr> *rootPtr = &root; - while (*rootPtr != nullptr) + auto & toInsertIn = FindNode(value); + if(toInsertIn != nullptr) { - if ((*rootPtr)->value == value) - { - return true; - } - - if ((*rootPtr)->value > value) - { - rootPtr = &((*rootPtr)->left); - } - else - { - rootPtr = &((*rootPtr)->right); - } + return; } - return false; + toInsertIn = std::make_unique>(value); } - void Delete(T const value) + bool Contains(T const & value) { - std::unique_ptr> *rootPtr = &root; - while (*rootPtr != nullptr) + return FindNode(value) != nullptr; + } + + void Delete(T const & value) + { + auto & node = FindNode(value); + if (node == 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(); - } - - return; - } - - if ((*rootPtr)->value > value) - { - rootPtr = &((*rootPtr)->left); - } - else - { - rootPtr = &((*rootPtr)->right); - } + return; } + DeleteNode(node); } Tree()