From 60c1371a9d13da064237767cba7a57711bcb118f Mon Sep 17 00:00:00 2001 From: Brett Date: Wed, 11 Jan 2023 18:56:42 -0500 Subject: [PATCH] Switching to recursive delete. Fixed search --- CMakeLists.txt | 13 ++++- include/blt/std/binary_tree.h | 93 ++++++++++++++++++++++++++--------- src/tests/binary_trees.h | 40 +++++++++++++++ src/tests/main.cpp | 6 +++ 4 files changed, 127 insertions(+), 25 deletions(-) create mode 100644 src/tests/binary_trees.h create mode 100644 src/tests/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 412306d..12308f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ set(CMAKE_CXX_STANDARD 17) option(BUILD_STD "Build the BLT standard utilities." ON) option(BUILD_PROFILING "Build the BLT profiler extension" ON) +option(BUILD_TESTS "Build the BLT test set" OFF) if(${BUILD_STD}) file(GLOB_RECURSE STD_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/blt/std/*.cpp") @@ -34,5 +35,15 @@ message("Current Source: ${CMAKE_CURRENT_SOURCE_DIR}") add_library(BLT ${STD_FILES} ${PROFILING_FILES}) target_include_directories(BLT PUBLIC include/) target_link_libraries(BLT phmap) - message("BLT ${CMAKE_PROJECT_VERSION} Successfully included!") + +if(${BUILD_TESTS}) + project(BLT_TESTS) + + file(GLOB_RECURSE TESTS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/*.cpp") + + add_executable(BLT_TESTS ${TESTS_FILES}) + + target_link_libraries(BLT_TESTS BLT) + message("BLT tests included!") +endif() \ No newline at end of file diff --git a/include/blt/std/binary_tree.h b/include/blt/std/binary_tree.h index 5ec88c5..b368dff 100644 --- a/include/blt/std/binary_tree.h +++ b/include/blt/std/binary_tree.h @@ -7,6 +7,7 @@ #include #include #include +#include #ifndef BLT_BINARY_TREE_H #define BLT_BINARY_TREE_H @@ -45,7 +46,7 @@ namespace blt { // basically we are iterating through the tree looking for a valid node to insert into. while (true) { if (element == searchNode->payload) - throw binary_search_tree_error{"Unable to insert. Nodes cannot have equal values!\n"}; + throw binary_search_tree_error{"Unable to insert. Nodes cannot have equal values! (" + std::to_string(element) + ")\n"}; // check for left and right tree traversal if it exists if (searchNode->left != nullptr && element < searchNode->payload) { searchNode = searchNode->left; @@ -66,26 +67,27 @@ namespace blt { BST_node* search(BST_node** parent, const T& element) const { BST_node* searchNode = m_root; + BST_node* parentNode = m_root; + + if (searchNode->left == nullptr && searchNode->right == nullptr) + return nullptr; + // basically we are iterating through the tree looking for a valid node to insert into. - while (true) { - if (searchNode->payload == element) - return searchNode; - if (searchNode->left == nullptr && searchNode->right == nullptr) + while (searchNode->payload != element) { + if (searchNode == nullptr) return nullptr; // check for left and right tree traversal if it exists - if (searchNode->left != nullptr && element < searchNode->left->payload) { - if (parent != nullptr) - *parent = searchNode; + if (element < searchNode->payload) { + parentNode = searchNode; searchNode = searchNode->left; - continue; - } - if (searchNode->right != nullptr && element > searchNode->right->payload) { - if (parent != nullptr) - *parent = searchNode; + } else { + parentNode = searchNode; searchNode = searchNode->right; - continue; } } + if (parent != nullptr) + *parent = parentNode; + return searchNode; } std::vector inOrderTraverse(BST_node* root) { @@ -109,6 +111,31 @@ namespace blt { return nodes; } + + BST_node* findMin(BST_node* root) { + while (root->left != nullptr) + root = root->left; + return root; + } + + BST_node* findMax(BST_node* root) { + while (root->right != nullptr) + root = root->right; + return root; + } + + BST_node* remove(BST_node*& root, const T& element) { + if (root->payload < element) // search left + root->left = delete(root->left, element); + else if (root->payload > element) // search right + root->right = delete(root->right, element); + else { + if (root->left != nullptr && root->right != nullptr) { + BST_node* rootCopy = root; + root = + } + } + } public: node_binary_search_tree() = default; @@ -125,8 +152,8 @@ namespace blt { return search(nullptr, element); } - void remove(const T& element) { - BST_node* parent{}; + /*void remove(const T& element) { + BST_node* parent = nullptr; BST_node* elementNode = search(&parent, element); BST_node*& parentChildSide = parent->left; @@ -134,20 +161,38 @@ namespace blt { parentChildSide = parent->right; if (elementNode->left != nullptr && elementNode->right != nullptr) { - parentChildSide = nullptr; - // reconstruct subtree. More efficient way of doing this... TODO - std::vector subNodes = inOrderTraverse(elementNode); - for (auto* node : subNodes) { - // insert will create a new node, we must delete old one to prevent memory leaks - if (node != elementNode) { - insert(parent, node->payload); - delete (node); + // root node special case: TODO: better way of doing this. + if (parent == elementNode) { + delete(m_root); + m_root = nullptr; + // reconstruct subtree. More efficient way of doing this... TODO + std::vector subNodes = inOrderTraverse(elementNode); + for (auto* node : subNodes) { + // insert will create a new node, we must delete old one to prevent memory leaks + if (node != elementNode) { + insert(node->payload); + delete (node); + } + } + } else { + parentChildSide = nullptr; + // reconstruct subtree. More efficient way of doing this... TODO + std::vector subNodes = inOrderTraverse(elementNode); + for (auto* node : subNodes) { + // insert will create a new node, we must delete old one to prevent memory leaks + if (node != elementNode) { + insert(parent, node->payload); + delete (node); + } } } } else { parentChildSide = elementNode->left != nullptr ? elementNode->left : elementNode->right; } delete (elementNode); + }*/ + void remove(const T& element) { + remove(m_root, element); } inline std::vector inOrderTraverse() { diff --git a/src/tests/binary_trees.h b/src/tests/binary_trees.h new file mode 100644 index 0000000..db45699 --- /dev/null +++ b/src/tests/binary_trees.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include +#include + +void printBinaryTree(blt::node_binary_search_tree& tree) { + auto nodes = tree.inOrderTraverse(); + for (auto n : nodes) + std::cout << n->payload << " "; + std::cout << "\n"; +} + +void binaryTreeTest(){ + + using namespace blt; + + node_binary_search_tree dataTree; + dataTree.insert(6); + dataTree.insert(3); + dataTree.insert(2); + dataTree.insert(4); + dataTree.insert(10); + dataTree.insert(13); + dataTree.insert(8); + dataTree.insert(16); + + printBinaryTree(dataTree); + + auto searchedNode = dataTree.search(10); + std::cout << "10's children: "<< searchedNode->left->payload << ", " << searchedNode->right->payload << "\n"; + + dataTree.remove(6); + + printBinaryTree(dataTree); + + +} \ No newline at end of file diff --git a/src/tests/main.cpp b/src/tests/main.cpp new file mode 100644 index 0000000..749b61c --- /dev/null +++ b/src/tests/main.cpp @@ -0,0 +1,6 @@ + +#include "binary_trees.h" + +int main() { + binaryTreeTest(); +} \ No newline at end of file