Switching to recursive delete. Fixed search
parent
33ee1f2dc7
commit
60c1371a9d
|
@ -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()
|
|
@ -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) {
|
||||||
|
@ -110,6 +112,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() {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
#include "binary_trees.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
binaryTreeTest();
|
||||||
|
}
|
Loading…
Reference in New Issue