Switching to recursive delete. Fixed search

v1
Brett 2023-01-11 18:56:42 -05:00
parent 33ee1f2dc7
commit 60c1371a9d
4 changed files with 127 additions and 25 deletions

View File

@ -6,6 +6,7 @@ set(CMAKE_CXX_STANDARD 17)
option(BUILD_STD "Build the BLT standard utilities." ON) option(BUILD_STD "Build the BLT standard utilities." ON)
option(BUILD_PROFILING "Build the BLT profiler extension" ON) option(BUILD_PROFILING "Build the BLT profiler extension" ON)
option(BUILD_TESTS "Build the BLT test set" OFF)
if(${BUILD_STD}) if(${BUILD_STD})
file(GLOB_RECURSE STD_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/blt/std/*.cpp") 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}) add_library(BLT ${STD_FILES} ${PROFILING_FILES})
target_include_directories(BLT PUBLIC include/) target_include_directories(BLT PUBLIC include/)
target_link_libraries(BLT phmap) target_link_libraries(BLT phmap)
message("BLT ${CMAKE_PROJECT_VERSION} Successfully included!") 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()

View File

@ -7,6 +7,7 @@
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include <blt/std/queue.h> #include <blt/std/queue.h>
#include <iostream>
#ifndef BLT_BINARY_TREE_H #ifndef BLT_BINARY_TREE_H
#define 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. // basically we are iterating through the tree looking for a valid node to insert into.
while (true) { while (true) {
if (element == searchNode->payload) 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 // check for left and right tree traversal if it exists
if (searchNode->left != nullptr && element < searchNode->payload) { if (searchNode->left != nullptr && element < searchNode->payload) {
searchNode = searchNode->left; searchNode = searchNode->left;
@ -66,26 +67,27 @@ namespace blt {
BST_node* search(BST_node** parent, const T& element) const { BST_node* search(BST_node** parent, const T& element) const {
BST_node* searchNode = m_root; 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. // basically we are iterating through the tree looking for a valid node to insert into.
while (true) { while (searchNode->payload != element) {
if (searchNode->payload == element) if (searchNode == nullptr)
return searchNode;
if (searchNode->left == nullptr && searchNode->right == nullptr)
return nullptr; return nullptr;
// check for left and right tree traversal if it exists // check for left and right tree traversal if it exists
if (searchNode->left != nullptr && element < searchNode->left->payload) { if (element < searchNode->payload) {
if (parent != nullptr) parentNode = searchNode;
*parent = searchNode;
searchNode = searchNode->left; searchNode = searchNode->left;
continue; } else {
} parentNode = searchNode;
if (searchNode->right != nullptr && element > searchNode->right->payload) {
if (parent != nullptr)
*parent = searchNode;
searchNode = searchNode->right; searchNode = searchNode->right;
continue;
} }
} }
if (parent != nullptr)
*parent = parentNode;
return searchNode;
} }
std::vector<BST_node*> inOrderTraverse(BST_node* root) { std::vector<BST_node*> inOrderTraverse(BST_node* root) {
@ -109,6 +111,31 @@ namespace blt {
return nodes; 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: public:
node_binary_search_tree() = default; node_binary_search_tree() = default;
@ -125,8 +152,8 @@ namespace blt {
return search(nullptr, element); return search(nullptr, element);
} }
void remove(const T& element) { /*void remove(const T& element) {
BST_node* parent{}; BST_node* parent = nullptr;
BST_node* elementNode = search(&parent, element); BST_node* elementNode = search(&parent, element);
BST_node*& parentChildSide = parent->left; BST_node*& parentChildSide = parent->left;
@ -134,20 +161,38 @@ namespace blt {
parentChildSide = parent->right; parentChildSide = parent->right;
if (elementNode->left != nullptr && elementNode->right != nullptr) { if (elementNode->left != nullptr && elementNode->right != nullptr) {
parentChildSide = nullptr; // root node special case: TODO: better way of doing this.
// reconstruct subtree. More efficient way of doing this... TODO if (parent == elementNode) {
std::vector<BST_node*> subNodes = inOrderTraverse(elementNode); delete(m_root);
for (auto* node : subNodes) { m_root = nullptr;
// insert will create a new node, we must delete old one to prevent memory leaks // reconstruct subtree. More efficient way of doing this... TODO
if (node != elementNode) { std::vector<BST_node*> subNodes = inOrderTraverse(elementNode);
insert(parent, node->payload); for (auto* node : subNodes) {
delete (node); // 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<BST_node*> 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 { } else {
parentChildSide = elementNode->left != nullptr ? elementNode->left : elementNode->right; parentChildSide = elementNode->left != nullptr ? elementNode->left : elementNode->right;
} }
delete (elementNode); delete (elementNode);
}*/
void remove(const T& element) {
remove(m_root, element);
} }
inline std::vector<BST_node*> inOrderTraverse() { inline std::vector<BST_node*> inOrderTraverse() {

40
src/tests/binary_trees.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include <blt/std/binary_tree.h>
#include <blt/std/random.h>
#include <blt/std/time.h>
#include <blt/std/string.h>
#include <iostream>
void printBinaryTree(blt::node_binary_search_tree<long>& 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<long> 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);
}

6
src/tests/main.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "binary_trees.h"
int main() {
binaryTreeTest();
}