Skip to content

Commit

Permalink
Update binary_search_tree.cpp
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
arjunjain8887 committed Sep 27, 2024
1 parent 9374b00 commit db6f08b
Showing 1 changed file with 129 additions and 108 deletions.
237 changes: 129 additions & 108 deletions data_structures/binary_search_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,168 +7,189 @@
* utilize any of the C++ STL features.
*/
#include <iostream>
#include <memory>
#include <vector>
#include <queue>

struct node {
// Node structure representing each element in the binary tree
struct Node {
int val;
node *left;
node *right;
};
std::unique_ptr<Node> left; // Using unique_ptr for automatic memory management
std::unique_ptr<Node> 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<Node> 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<Node>(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<Node*> 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<Node>(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<Node>(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>& 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;
}

0 comments on commit db6f08b

Please sign in to comment.