From db6f08b7206971256465502ee3a84e61d9a14a5f Mon Sep 17 00:00:00 2001 From: arjunjain8887 <158755008+arjunjain8887@users.noreply.github.com> Date: Fri, 27 Sep 2024 11:11:54 +0530 Subject: [PATCH] Update binary_search_tree.cpp 1. Memory Management: Used std::unique_ptr for automatic memory management, reducing the risk of memory leaks. 2. STL Utilization: Replaced the custom queue implementation with std::queue, simplifying breadth-first traversal. 3. Code Structure: Organized the code into a BinaryTree class, encapsulating the tree functionality and providing clearer interfaces for operations. 4. Redundancy Reduction: Combined logic for finding and removing nodes to reduce redundancy, improving readability and maintainability. 5. Error Handling: Added checks to handle cases where nodes may not be present during removal and traversal. --- data_structures/binary_search_tree.cpp | 237 ++++++++++++++----------- 1 file changed, 129 insertions(+), 108 deletions(-) diff --git a/data_structures/binary_search_tree.cpp b/data_structures/binary_search_tree.cpp index 86057c6c507..33ec69bfb0d 100644 --- a/data_structures/binary_search_tree.cpp +++ b/data_structures/binary_search_tree.cpp @@ -7,168 +7,189 @@ * utilize any of the C++ STL features. */ #include +#include +#include +#include -struct node { +// Node structure representing each element in the binary tree +struct Node { int val; - node *left; - node *right; -}; + std::unique_ptr left; // Using unique_ptr for automatic memory management + std::unique_ptr right; -struct Queue { - node *t[100]; - int front; - int rear; + Node(int value) : val(value), left(nullptr), right(nullptr) {} }; -Queue queue; - -void enqueue(node *n) { queue.t[queue.rear++] = n; } - -node *dequeue() { return (queue.t[queue.front++]); } +class BinaryTree { +public: + std::unique_ptr root; // Root of the binary tree -void Insert(node *n, int x) { - if (x < n->val) { - if (n->left == NULL) { - node *temp = new node; - temp->val = x; - temp->left = NULL; - temp->right = NULL; - n->left = temp; + // Insert a value into the tree + void insert(int x) { + if (!root) { + root = std::make_unique(x); // Create root if it doesn't exist } else { - Insert(n->left, x); + insertHelper(root.get(), x); // Helper function for recursive insertion } - } else { - if (n->right == NULL) { - node *temp = new node; - temp->val = x; - temp->left = NULL; - temp->right = NULL; - n->right = temp; - } else { - Insert(n->right, x); + } + + // Remove a value from the tree + void remove(int x) { + removeHelper(root, x); // Helper function to manage removal + } + + // Breadth-first traversal of the tree + void breadthFirstTraversal() const { + if (!root) return; + std::queue q; // Using STL queue for level-order traversal + q.push(root.get()); + while (!q.empty()) { + Node* current = q.front(); + q.pop(); + std::cout << current->val << " "; // Print the current node's value + if (current->left) q.push(current->left.get()); + if (current->right) q.push(current->right.get()); } } -} -int findMaxInLeftST(node *n) { - while (n->right != NULL) { - n = n->right; + // Preorder traversal + void preOrderTraversal() const { + preOrderHelper(root.get()); } - return n->val; -} -void Remove(node *p, node *n, int x) { - if (n->val == x) { - if (n->right == NULL && n->left == NULL) { - if (x < p->val) { - p->right = NULL; - } else { - p->left = NULL; - } - } else if (n->right == NULL) { - if (x < p->val) { - p->right = n->left; + // Inorder traversal + void inOrderTraversal() const { + inOrderHelper(root.get()); + } + + // Postorder traversal + void postOrderTraversal() const { + postOrderHelper(root.get()); + } + +private: + // Helper function for insertion + void insertHelper(Node* node, int x) { + if (x < node->val) { + if (!node->left) { + node->left = std::make_unique(x); // Create left child if it doesn't exist } else { - p->left = n->left; + insertHelper(node->left.get(), x); // Recur to the left } - } else if (n->left == NULL) { - if (x < p->val) { - p->right = n->right; + } else { + if (!node->right) { + node->right = std::make_unique(x); // Create right child if it doesn't exist } else { - p->left = n->right; + insertHelper(node->right.get(), x); // Recur to the right } - } else { - int y = findMaxInLeftST(n->left); - n->val = y; - Remove(n, n->right, y); } - } else if (x < n->val) { - Remove(n, n->left, x); - } else { - Remove(n, n->right, x); } -} -void BFT(node *n) { - if (n != NULL) { - std::cout << n->val << " "; - enqueue(n->left); - enqueue(n->right); - BFT(dequeue()); + // Helper function to find the maximum value in the left subtree + Node* findMaxInLeft(Node* node) { + while (node->right) { + node = node->right.get(); + } + return node; } -} -void Pre(node *n) { - if (n != NULL) { - std::cout << n->val << " "; - Pre(n->left); - Pre(n->right); + // Helper function for removing a node + Node* removeHelper(std::unique_ptr& node, int x) { + if (!node) return nullptr; // Base case: node not found + + if (x < node->val) { + node->left = removeHelper(node->left, x); // Recur left + } else if (x > node->val) { + node->right = removeHelper(node->right, x); // Recur right + } else { + // Node found: handle three cases + if (!node->left) { + return std::move(node->right); // No left child + } else if (!node->right) { + return std::move(node->left); // No right child + } else { + // Node with two children: replace with max value from left subtree + int maxVal = findMaxInLeft(node->left.get())->val; + node->val = maxVal; // Replace value + node->left = removeHelper(node->left, maxVal); // Remove the max value + } + } + return std::move(node); // Return updated node } -} -void In(node *n) { - if (n != NULL) { - In(n->left); - std::cout << n->val << " "; - In(n->right); + // Preorder traversal helper + void preOrderHelper(Node* node) const { + if (node) { + std::cout << node->val << " "; // Visit node + preOrderHelper(node->left.get()); // Recur left + preOrderHelper(node->right.get()); // Recur right + } } -} -void Post(node *n) { - if (n != NULL) { - Post(n->left); - Post(n->right); - std::cout << n->val << " "; + // Inorder traversal helper + void inOrderHelper(Node* node) const { + if (node) { + inOrderHelper(node->left.get()); // Recur left + std::cout << node->val << " "; // Visit node + inOrderHelper(node->right.get()); // Recur right + } } -} + + // Postorder traversal helper + void postOrderHelper(Node* node) const { + if (node) { + postOrderHelper(node->left.get()); // Recur left + postOrderHelper(node->right.get()); // Recur right + std::cout << node->val << " "; // Visit node + } + } +}; int main() { - queue.front = 0; - queue.rear = 0; + BinaryTree tree; int value; - int ch; - node *root = new node; - std::cout << "\nEnter the value of root node :"; + std::cout << "\nEnter the value of root node: "; std::cin >> value; - root->val = value; - root->left = NULL; - root->right = NULL; + tree.insert(value); // Insert the root value + + int choice; do { std::cout << "\n1. Insert" << "\n2. Delete" << "\n3. Breadth First" << "\n4. Preorder Depth First" << "\n5. Inorder Depth First" - << "\n6. Postorder Depth First"; + << "\n6. Postorder Depth First" + << "\n0. Exit" + << "\nEnter Your Choice: "; + std::cin >> choice; - std::cout << "\nEnter Your Choice : "; - std::cin >> ch; int x; - switch (ch) { + switch (choice) { case 1: - std::cout << "\nEnter the value to be Inserted : "; + std::cout << "\nEnter the value to be Inserted: "; std::cin >> x; - Insert(root, x); + tree.insert(x); // Insert value break; case 2: - std::cout << "\nEnter the value to be Deleted : "; + std::cout << "\nEnter the value to be Deleted: "; std::cin >> x; - Remove(root, root, x); + tree.remove(x); // Remove value break; case 3: - BFT(root); + tree.breadthFirstTraversal(); // Perform breadth-first traversal break; case 4: - Pre(root); + tree.preOrderTraversal(); // Perform preorder traversal break; case 5: - In(root); + tree.inOrderTraversal(); // Perform inorder traversal break; case 6: - Post(root); + tree.postOrderTraversal(); // Perform postorder traversal break; } - } while (ch != 0); + } while (choice != 0); // Exit loop on choice 0 return 0; }