From 01b505fe626af0cacf96c26bf6657439dd492f8f Mon Sep 17 00:00:00 2001 From: hmigl <88746406+hmigl@users.noreply.github.com> Date: Tue, 7 Nov 2023 09:30:19 -0300 Subject: [PATCH 1/3] refactor(cpp): rename 'BinaryTree' to 'BinarySearchTree' The 'Node *insert(Node *, int)' method makes the tree a Binary Search Tree, since it enforces these two properties: - Each node is greater than every node in its left subtree - Each node is less than every node in its right subtree --- src/cpp/{BinaryTree.cpp => BinarySearchTree.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/cpp/{BinaryTree.cpp => BinarySearchTree.cpp} (100%) diff --git a/src/cpp/BinaryTree.cpp b/src/cpp/BinarySearchTree.cpp similarity index 100% rename from src/cpp/BinaryTree.cpp rename to src/cpp/BinarySearchTree.cpp From 070e71c99594a0ca44a37265f4456466b2c04a6b Mon Sep 17 00:00:00 2001 From: hmigl <88746406+hmigl@users.noreply.github.com> Date: Tue, 7 Nov 2023 09:37:46 -0300 Subject: [PATCH 2/3] docs: update README --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 03dee087..c07dbef5 100644 --- a/README.md +++ b/README.md @@ -1698,8 +1698,8 @@ In order to achieve greater coverage and encourage more people to contribute to - - + + @@ -1756,8 +1756,8 @@ In order to achieve greater coverage and encourage more people to contribute to - - + + From dd0420ff0e775413c8fc97fd760894f2c62c7ecc Mon Sep 17 00:00:00 2001 From: hmigl <88746406+hmigl@users.noreply.github.com> Date: Tue, 7 Nov 2023 09:44:12 -0300 Subject: [PATCH 3/3] refactor(cpp): update 'BinarySearchTree', adding other operations... ...like 'delete', 'find min', 'find max'. In addition to that, in this version, object oriented code is present. `BinarySearchTree` is a class, and it has behaviour that operates on the state. --- src/cpp/BinarySearchTree.cpp | 322 ++++++++++++++++++++++++----------- 1 file changed, 221 insertions(+), 101 deletions(-) diff --git a/src/cpp/BinarySearchTree.cpp b/src/cpp/BinarySearchTree.cpp index 44324dbd..ddc01eb4 100644 --- a/src/cpp/BinarySearchTree.cpp +++ b/src/cpp/BinarySearchTree.cpp @@ -3,124 +3,244 @@ /* * Structure for a binary tree node */ - struct Node { - int data; // data value stored in the node - Node* left; // pointer to the left child node - Node* right; // pointer to the right child node - - /** - * Constructor to create a new node with the given data. - * - * @param value the data value for the new node. - */ - - Node(int value) : data(value), left(nullptr), right(nullptr) {} + int data; ///< The integer data value stored in the node. + Node *left; ///< Pointer to the left child node. + Node *right; ///< Pointer to the right child node. + + /** + * Constructor to create a new node with the given data. + * + * @param value the data value for the new node. + */ + Node(int data) : data(data), left(nullptr), right(nullptr) {} }; +class BinarySearchTree { + public: + BinarySearchTree() : root(nullptr) {} + Node *find(int x) const { return _find(this->root, x); } -/** - * Function to insert a new node into the binary tree. - * - * @param root pointer to the root of the binary tree. - * @param value the value to be inserted. - * - * @return pointer to the root of the modified binary tree. - */ - -Node* insert(Node* root, int value) { - if (root == nullptr) { - return new Node(value); - } - if (value < root->data) { - root->left = insert(root->left, value); - } - else if (value > root->data) { - root->right = insert(root->right, value); - } - return root; -} - - + void insert(int x) { _insert(&(this->root), x); } -/** - * Function for an in-order traversal of the binary tree (Left-Root-Right). - * - * @param root pointer to the root of the binary tree. - */ + void deleteNode(int x) { _delete(&(this->root), x); } -void inOrderTraversal(Node* root) { - if (root == nullptr) { - return; - } - inOrderTraversal(root->left); - std::cout << root->data << " "; - inOrderTraversal(root->right); -} + void preorderTraversal() const { _printPreorder(this->root); } + void inorderTraversal() const { _printInorder(this->root); } + void postorderTraversal() const { _printPostorder(this->root); } -/** - * Function for a pre-order traversal of the binary tree (Root-Left-Right). - * - * @param root pointer to the root of the binary tree. - */ + private: + Node *root; -void preOrderTraversal(Node* root) { - if (root == nullptr) { - return; + /** + * @brief Find a node with a specific value in the binary search tree. + * + * This function searches the binary search tree starting from the given root + * node for a node that contains the specified value `x`. If a node with the + * value `x` is found, a pointer to that node is returned. If no such node + * exists in the tree, the function returns `nullptr`. + * + * @param root A pointer to the root node of the binary search tree. + * @param x The value to search for in the tree. + * @return A pointer to the node containing the value `x`, or `nullptr` if not + * found. + */ + Node *_find(Node *root, int x) const { + if (!root || root->data == x) { + return root; } - std::cout << root->data << " "; - preOrderTraversal(root->left); - preOrderTraversal(root->right); -} - - - -/** - * Function for a post-order traversal of the binary tree (Left-Right-Root). - * - * @param root pointer to the root of the binary tree. - */ - -void postOrderTraversal(Node* root) { - if (root == nullptr) { - return; + if (x < root->data) { + return _find(root->left, x); + } else { + return _find(root->right, x); + } + } + + /** + * @brief Inserts a new node with the specified value into the binary search + * tree. + * + * This function inserts a new node containing the value `x` into the binary + * search tree. It traverses the tree starting from the given root node + * (passed as a pointer to a pointer) and inserts the new node at the + * appropriate position based on the value `x`. + * + * @param root A pointer to a pointer to the root node of the binary search + * tree. + * @param x The value to insert into the tree. + * @return A pointer to the updated root node of the tree after the insertion. + */ + Node *_insert(Node **root, int x) { + if (!(*root)) { + *root = new Node(x); + } else if (x <= (*root)->data) { + (*root)->left = _insert(&((*root)->left), x); + } else { + (*root)->right = _insert(&((*root)->right), x); + } + return *root; + } + + /** + * @brief Deletes a node with the specified value from the binary search tree. + * + * This function deletes a node containing the value `x` from the binary + * search tree. It traverses the tree starting from the given root node and + * removes the node with the specified value if it exists. + * + * After the deletion, the function may adjust the tree structure to maintain + * its binary search tree properties. + * + * @param root A pointer to a pointer to the root node of the binary search + * tree. + * @param x The value to delete from the tree. + * @return A pointer to the updated root node of the tree after the deletion. + */ + Node *_delete(Node **root, int x) { + if (!(*root)) { + return nullptr; } - postOrderTraversal(root->left); - postOrderTraversal(root->right); - std::cout << root->data << " "; -} - - -int main() { - Node* root = nullptr; + if (x < (*root)->data) { + (*root)->left = _delete(&((*root)->left), x); + } else if (x > (*root)->data) { + (*root)->right = _delete(&((*root)->right), x); + } else { + // Case 1: Leaf node + if (!((*root)->left) && !((*root)->right)) { + delete *root; + *root = nullptr; + } + + // Case 2: Only one child + else if (!((*root)->left)) { + Node *tmp = *root; + *root = (*root)->right; + delete tmp; + } else if (!((*root)->right)) { + Node *tmp = *root; + *root = (*root)->left; + delete tmp; + } + + // Case 3: Two children + else { + // Could've been <<< Node *tmp = _find_max((*root)->left); >>> + Node *tmp = _find_min((*root)->right); + (*root)->data = tmp->data; + (*root)->right = _delete(&((*root)->right), tmp->data); + } + } + return *root; + } + + /** + * @brief Find the minimum node value in the binary search tree. + * + * This function searches the binary search tree starting from the given root + * node and returns a pointer to the node with the minimum value. The minimum + * value is found by recursively traversing the left child nodes until the + * smallest value is located. + * + * @param root A pointer to the root node of the binary search tree. + * @return A pointer to the node with the minimum value in the tree. + */ + Node *_find_min(Node *root) const { + while (root && root->left) { + root = root->left; + } + return root; + } + + /** + * @brief Find the maximum node value in the binary search tree. + * + * This function searches the binary search tree starting from the given root + * node and returns a pointer to the node with the maximum value. The maximum + * value is found by recursively traversing the right child nodes until the + * largest value is located. + * + * @param root A pointer to the root node of the binary search tree. + * @return A pointer to the node with the minimum value in the tree. + */ + Node *_find_max(Node *root) const { + while (root && root->right) { + root = root->right; + } + return root; + } + + /** + * @brief Prints the elements of the binary search tree in preorder traversal. + * + * The preorder traversal visits the current node first, followed by its left + * and right children - recursively. + * + * @param root A pointer to the root node of the binary search tree. + */ + void _printPreorder(Node *root) const { + if (root) { + std::cout << root->data << '\n'; + _printPreorder(root->left); + _printPreorder(root->right); + } + } + + /** + * @brief Prints the elements of the binary search tree in inorder traversal. + * + * The inorder traversal visits the left child, followed by the current node, + * and then the right child recursively. + * + * @param root A pointer to the root node of the binary search tree. + */ + void _printInorder(Node *root) const { + if (root) { + _printInorder(root->left); + std::cout << root->data << '\n'; + _printInorder(root->right); + } + } + + /** + * @brief Prints the elements of the binary search tree in postorder + * traversal. + * + * The postorder traversal visits the left and right children first, followed + * by the current node. + * + * @param root A pointer to the root node of the binary search tree. + */ + void _printPostorder(Node *root) const { + if (root) { + _printPostorder(root->left); + _printPostorder(root->right); + std::cout << root->data << '\n'; + } + } +}; - // insert elements into the binary tree - root = insert(root, 50); - root = insert(root, 30); - root = insert(root, 20); - root = insert(root, 40); - root = insert(root, 70); - root = insert(root, 60); - root = insert(root, 80); +int main(int argc, char *argv[]) { + auto bst = BinarySearchTree(); - // in-order traversal - std::cout << "In-order traversal: "; - inOrderTraversal(root); - std::cout << std::endl; + int arr[] = {30, 20, 10, 50, 40, 45, 80, 90}; + for (const auto &e : arr) { + bst.insert(e); + } - // pre-order traversal - std::cout << "Pre-order traversal: "; - preOrderTraversal(root); - std::cout << std::endl; + std::cout << "inorder traversal:\n"; + bst.inorderTraversal(); + std::cout << "preorder traversal:\n"; + bst.preorderTraversal(); + std::cout << "postorder traversal:\n"; + bst.postorderTraversal(); - // post-order traversal - std::cout << "Post-order traversal: "; - postOrderTraversal(root); - std::cout << std::endl; + bst.deleteNode(50); + std::cout << "preorder traversal:\n"; + bst.preorderTraversal(); - return 0; + return 0; }