diff --git a/Headers/0002_Tree/0001_BinarySearchTree.h b/Headers/0002_Tree/0001_BinarySearchTree.h new file mode 100644 index 0000000..6e4963d --- /dev/null +++ b/Headers/0002_Tree/0001_BinarySearchTree.h @@ -0,0 +1,40 @@ +#pragma once + +#include +using namespace std; +class Node +{ +public: + int data; + Node* parent; + Node* left; + Node* right; + + Node(int data, Node* parent, Node* left, Node* right); +}; + +class BinarySearchTree +{ +private: + Node* _root; + void _InsertNode(Node* node); + Node* _FindNode(int value); + Node* _FindMinimumValueNode(Node* node); + Node* _FindMaximumValueNode(Node* node); + Node* _FindSuccessorNode(Node* node); + Node* _FindPredecessorNode(Node* node); + void _Transplant(Node* nodeU, Node* nodeV); + void _DeleteNode(Node* node); + string _RecursiveInorderTraversal(Node* node); + string _RecursivePreorderTraversal(Node* node); + string _RecursivePostorderTraversal(Node* node); + string _MorrisInorderTraversal(Node* node); + string _MorrisPreorderTraversal(Node* node); + string _MorrisPostorderTraversal(Node* node); +public: + BinarySearchTree(); + void InsertNode(int value); + void DeleteNode(int value); + string GetRecursiveInorderTravesalResult(); + string GetMorrisInorderTraversalResult(); +}; \ No newline at end of file diff --git a/SourceCodes/0002_Tree/0001_BinarySearchTree.cc b/SourceCodes/0002_Tree/0001_BinarySearchTree.cc new file mode 100644 index 0000000..a29db5d --- /dev/null +++ b/SourceCodes/0002_Tree/0001_BinarySearchTree.cc @@ -0,0 +1,246 @@ +#include "../Headers/0002_Tree/0001_BinarySearchTree.h" +#include +using namespace std; + + +Node::Node(int data, Node* parent, Node* left, Node* right) +{ + this->data = data; + this->parent = parent; + this->left = left; + this->right = right; +} + +BinarySearchTree::BinarySearchTree() +{ + this->_root = nullptr; +} + + +void BinarySearchTree::_InsertNode(Node* node) +{ + Node* nodeY = nullptr; + Node* nodeX = this->_root; + while (nodeX != nullptr) + { + nodeY = nodeX; + if (node->data < nodeX->data) + { + nodeX = nodeX->left; + } + else + { + nodeX = nodeX->right; + } + } + node->parent = nodeY; + if (nodeY == nullptr) + { + this->_root = node; + } + else if (node->data < nodeY->data) + { + nodeY->left = node; + } + else + { + nodeY->right = node; + } +} + +Node* BinarySearchTree::_FindNode(int value) +{ + Node* node = this->_root; + while (node != nullptr) + { + if (value < node->data) + { + node = node->left; + } + else if(value > node->data) + { + node = node->right; + } + else + { + break; + } + } + return node; +} + +Node* BinarySearchTree::_FindMinimumValueNode(Node* node) +{ + while (node->left != nullptr) + { + node = node->left; + } + return node; +} + +Node* BinarySearchTree::_FindMaximumValueNode(Node* node) +{ + while (node->right != nullptr) + { + node = node->right; + } + return node; +} + +Node* BinarySearchTree::_FindSuccessorNode(Node* node) +{ + if (node->right != nullptr) + { + return this->_FindMinimumValueNode(node->right); + } + Node* nodeY = node->parent; + while (nodeY != nullptr && node == nodeY->right) + { + node = nodeY; + nodeY = nodeY->parent; + } + return nodeY; +} + +Node* BinarySearchTree::_FindPredecessorNode(Node* node) +{ + if (node->left != nullptr) + { + return this->_FindMaximumValueNode(node->left); + } + Node* nodeY = node->parent; + while (nodeY != nullptr && node == nodeY->left) + { + node = nodeY; + nodeY = nodeY->parent; + } +} + +void BinarySearchTree::_Transplant(Node* nodeU, Node* nodeV) +{ + if (nodeU->parent == nullptr) + { + this->_root = nodeV; + } + else if (nodeU == nodeU->parent->left) + { + nodeU->parent->left = nodeV; + } + else + { + nodeU->parent->right = nodeV; + } + + if (nodeV != nullptr) + { + nodeV->parent = nodeU->parent; + } +} + +void BinarySearchTree::_DeleteNode(Node* node) +{ + if (node->left == nullptr) + { + this->_Transplant(node, node->right); + } + else if (node->right == nullptr) + { + this->_Transplant(node, node->left); + } + else + { + Node* nodeY = this->_FindMinimumValueNode(node->right); + if (nodeY->parent != node) + { + this->_Transplant(nodeY, nodeY->right); + nodeY->right = node->right; + nodeY->right->parent = nodeY; + } + this->_Transplant(node, nodeY); + nodeY->left = node->left; + nodeY->left->parent = nodeY; + delete node; + } +} + +string BinarySearchTree::_RecursiveInorderTraversal(Node* node) +{ + if (node == nullptr) + { + return ""; + } + string leftSubTree = this->_RecursiveInorderTraversal(node->left); + string currentNode = to_string(node->data); + string rightSubTree = this->_RecursiveInorderTraversal(node->right); + + string result = leftSubTree; + if (!leftSubTree.empty()) + { + result += " "; + } + result += currentNode; + if (!rightSubTree.empty()) + { + result += " " + rightSubTree; + } + return result; +} + +string BinarySearchTree::_MorrisInorderTraversal(Node* node) +{ + string result = ""; + while (node != nullptr) + { + if (node->left == nullptr) + { + result += to_string(node->data) + " "; + node = node->right; + } + else + { + Node* predecessor = node->left; + while (predecessor->right != nullptr && predecessor->right != node) + { + predecessor = predecessor->right; + } + if (predecessor->right == nullptr) + { + predecessor->right = node; + node = node->left; + } + else + { + predecessor->right = nullptr; + result += to_string(node->data) + " "; + node = node->right; + } + } + } + if (!result.empty()) + { + result.pop_back(); + } + return result; +} + +void BinarySearchTree::InsertNode(int value) +{ + Node* node = new Node(value, nullptr, nullptr, nullptr); + this->_InsertNode(node); +} + +void BinarySearchTree::DeleteNode(int value) +{ + Node* node = this->_FindNode(value); + this->_DeleteNode(node); +} + +string BinarySearchTree::GetRecursiveInorderTravesalResult() +{ + return this->_RecursiveInorderTraversal(this->_root); +} + +string BinarySearchTree::GetMorrisInorderTraversalResult() +{ + return this->_MorrisInorderTraversal(this->_root); +} \ No newline at end of file diff --git a/SourceCodes/0002_Tree/CMakeLists.txt b/SourceCodes/0002_Tree/CMakeLists.txt index e69de29..cc7027a 100644 --- a/SourceCodes/0002_Tree/CMakeLists.txt +++ b/SourceCodes/0002_Tree/CMakeLists.txt @@ -0,0 +1,7 @@ +# Specify the source files +set(0002TREE_SOURCES + 0001_BinarySearchTree.cc +) + +# Create a library target +add_library(0002TREE ${0002TREE_SOURCES}) \ No newline at end of file diff --git a/Tests/0002_Tree/0001_BinarySearchTreeTest.cc b/Tests/0002_Tree/0001_BinarySearchTreeTest.cc new file mode 100644 index 0000000..dec2e0d --- /dev/null +++ b/Tests/0002_Tree/0001_BinarySearchTreeTest.cc @@ -0,0 +1,21 @@ +#include +#include +#include "../Headers/0002_Tree/0001_BinarySearchTree.h" + +// Demonstrate some basic assertions. +namespace BinarySearchTreeTest +{ + TEST(BSTTesting, ShowBSTResultTest) + { + BinarySearchTree bst; + bst.InsertNode(50); + bst.InsertNode(30); + bst.InsertNode(60); + + + string actualResult = bst.GetRecursiveInorderTravesalResult(); + string expectedResult = "30 50 60"; + + EXPECT_EQ(actualResult, expectedResult); + } +} \ No newline at end of file diff --git a/Tests/0002_Tree/CMakeLists.txt b/Tests/0002_Tree/CMakeLists.txt index e69de29..c662127 100644 --- a/Tests/0002_Tree/CMakeLists.txt +++ b/Tests/0002_Tree/CMakeLists.txt @@ -0,0 +1,29 @@ +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +# For Windows: Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) + + +enable_testing() + +add_executable( + 0002TreeTests + 0001_BinarySearchTreeTest.cc) + +target_link_libraries( + 0002TreeTests + GTest::gtest_main +) + +target_link_libraries( + 0002TreeTests + 0002TREE +) + + +include(GoogleTest) +gtest_discover_tests(0002TreeTests) \ No newline at end of file