Skip to content

Commit db6f08b

Browse files
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.
1 parent 9374b00 commit db6f08b

File tree

1 file changed

+129
-108
lines changed

1 file changed

+129
-108
lines changed

data_structures/binary_search_tree.cpp

Lines changed: 129 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -7,168 +7,189 @@
77
* utilize any of the C++ STL features.
88
*/
99
#include <iostream>
10+
#include <memory>
11+
#include <vector>
12+
#include <queue>
1013

11-
struct node {
14+
// Node structure representing each element in the binary tree
15+
struct Node {
1216
int val;
13-
node *left;
14-
node *right;
15-
};
17+
std::unique_ptr<Node> left; // Using unique_ptr for automatic memory management
18+
std::unique_ptr<Node> right;
1619

17-
struct Queue {
18-
node *t[100];
19-
int front;
20-
int rear;
20+
Node(int value) : val(value), left(nullptr), right(nullptr) {}
2121
};
2222

23-
Queue queue;
24-
25-
void enqueue(node *n) { queue.t[queue.rear++] = n; }
26-
27-
node *dequeue() { return (queue.t[queue.front++]); }
23+
class BinaryTree {
24+
public:
25+
std::unique_ptr<Node> root; // Root of the binary tree
2826

29-
void Insert(node *n, int x) {
30-
if (x < n->val) {
31-
if (n->left == NULL) {
32-
node *temp = new node;
33-
temp->val = x;
34-
temp->left = NULL;
35-
temp->right = NULL;
36-
n->left = temp;
27+
// Insert a value into the tree
28+
void insert(int x) {
29+
if (!root) {
30+
root = std::make_unique<Node>(x); // Create root if it doesn't exist
3731
} else {
38-
Insert(n->left, x);
32+
insertHelper(root.get(), x); // Helper function for recursive insertion
3933
}
40-
} else {
41-
if (n->right == NULL) {
42-
node *temp = new node;
43-
temp->val = x;
44-
temp->left = NULL;
45-
temp->right = NULL;
46-
n->right = temp;
47-
} else {
48-
Insert(n->right, x);
34+
}
35+
36+
// Remove a value from the tree
37+
void remove(int x) {
38+
removeHelper(root, x); // Helper function to manage removal
39+
}
40+
41+
// Breadth-first traversal of the tree
42+
void breadthFirstTraversal() const {
43+
if (!root) return;
44+
std::queue<Node*> q; // Using STL queue for level-order traversal
45+
q.push(root.get());
46+
while (!q.empty()) {
47+
Node* current = q.front();
48+
q.pop();
49+
std::cout << current->val << " "; // Print the current node's value
50+
if (current->left) q.push(current->left.get());
51+
if (current->right) q.push(current->right.get());
4952
}
5053
}
51-
}
5254

53-
int findMaxInLeftST(node *n) {
54-
while (n->right != NULL) {
55-
n = n->right;
55+
// Preorder traversal
56+
void preOrderTraversal() const {
57+
preOrderHelper(root.get());
5658
}
57-
return n->val;
58-
}
5959

60-
void Remove(node *p, node *n, int x) {
61-
if (n->val == x) {
62-
if (n->right == NULL && n->left == NULL) {
63-
if (x < p->val) {
64-
p->right = NULL;
65-
} else {
66-
p->left = NULL;
67-
}
68-
} else if (n->right == NULL) {
69-
if (x < p->val) {
70-
p->right = n->left;
60+
// Inorder traversal
61+
void inOrderTraversal() const {
62+
inOrderHelper(root.get());
63+
}
64+
65+
// Postorder traversal
66+
void postOrderTraversal() const {
67+
postOrderHelper(root.get());
68+
}
69+
70+
private:
71+
// Helper function for insertion
72+
void insertHelper(Node* node, int x) {
73+
if (x < node->val) {
74+
if (!node->left) {
75+
node->left = std::make_unique<Node>(x); // Create left child if it doesn't exist
7176
} else {
72-
p->left = n->left;
77+
insertHelper(node->left.get(), x); // Recur to the left
7378
}
74-
} else if (n->left == NULL) {
75-
if (x < p->val) {
76-
p->right = n->right;
79+
} else {
80+
if (!node->right) {
81+
node->right = std::make_unique<Node>(x); // Create right child if it doesn't exist
7782
} else {
78-
p->left = n->right;
83+
insertHelper(node->right.get(), x); // Recur to the right
7984
}
80-
} else {
81-
int y = findMaxInLeftST(n->left);
82-
n->val = y;
83-
Remove(n, n->right, y);
8485
}
85-
} else if (x < n->val) {
86-
Remove(n, n->left, x);
87-
} else {
88-
Remove(n, n->right, x);
8986
}
90-
}
9187

92-
void BFT(node *n) {
93-
if (n != NULL) {
94-
std::cout << n->val << " ";
95-
enqueue(n->left);
96-
enqueue(n->right);
97-
BFT(dequeue());
88+
// Helper function to find the maximum value in the left subtree
89+
Node* findMaxInLeft(Node* node) {
90+
while (node->right) {
91+
node = node->right.get();
92+
}
93+
return node;
9894
}
99-
}
10095

101-
void Pre(node *n) {
102-
if (n != NULL) {
103-
std::cout << n->val << " ";
104-
Pre(n->left);
105-
Pre(n->right);
96+
// Helper function for removing a node
97+
Node* removeHelper(std::unique_ptr<Node>& node, int x) {
98+
if (!node) return nullptr; // Base case: node not found
99+
100+
if (x < node->val) {
101+
node->left = removeHelper(node->left, x); // Recur left
102+
} else if (x > node->val) {
103+
node->right = removeHelper(node->right, x); // Recur right
104+
} else {
105+
// Node found: handle three cases
106+
if (!node->left) {
107+
return std::move(node->right); // No left child
108+
} else if (!node->right) {
109+
return std::move(node->left); // No right child
110+
} else {
111+
// Node with two children: replace with max value from left subtree
112+
int maxVal = findMaxInLeft(node->left.get())->val;
113+
node->val = maxVal; // Replace value
114+
node->left = removeHelper(node->left, maxVal); // Remove the max value
115+
}
116+
}
117+
return std::move(node); // Return updated node
106118
}
107-
}
108119

109-
void In(node *n) {
110-
if (n != NULL) {
111-
In(n->left);
112-
std::cout << n->val << " ";
113-
In(n->right);
120+
// Preorder traversal helper
121+
void preOrderHelper(Node* node) const {
122+
if (node) {
123+
std::cout << node->val << " "; // Visit node
124+
preOrderHelper(node->left.get()); // Recur left
125+
preOrderHelper(node->right.get()); // Recur right
126+
}
114127
}
115-
}
116128

117-
void Post(node *n) {
118-
if (n != NULL) {
119-
Post(n->left);
120-
Post(n->right);
121-
std::cout << n->val << " ";
129+
// Inorder traversal helper
130+
void inOrderHelper(Node* node) const {
131+
if (node) {
132+
inOrderHelper(node->left.get()); // Recur left
133+
std::cout << node->val << " "; // Visit node
134+
inOrderHelper(node->right.get()); // Recur right
135+
}
122136
}
123-
}
137+
138+
// Postorder traversal helper
139+
void postOrderHelper(Node* node) const {
140+
if (node) {
141+
postOrderHelper(node->left.get()); // Recur left
142+
postOrderHelper(node->right.get()); // Recur right
143+
std::cout << node->val << " "; // Visit node
144+
}
145+
}
146+
};
124147

125148
int main() {
126-
queue.front = 0;
127-
queue.rear = 0;
149+
BinaryTree tree;
128150
int value;
129-
int ch;
130-
node *root = new node;
131-
std::cout << "\nEnter the value of root node :";
151+
std::cout << "\nEnter the value of root node: ";
132152
std::cin >> value;
133-
root->val = value;
134-
root->left = NULL;
135-
root->right = NULL;
153+
tree.insert(value); // Insert the root value
154+
155+
int choice;
136156
do {
137157
std::cout << "\n1. Insert"
138158
<< "\n2. Delete"
139159
<< "\n3. Breadth First"
140160
<< "\n4. Preorder Depth First"
141161
<< "\n5. Inorder Depth First"
142-
<< "\n6. Postorder Depth First";
162+
<< "\n6. Postorder Depth First"
163+
<< "\n0. Exit"
164+
<< "\nEnter Your Choice: ";
165+
std::cin >> choice;
143166

144-
std::cout << "\nEnter Your Choice : ";
145-
std::cin >> ch;
146167
int x;
147-
switch (ch) {
168+
switch (choice) {
148169
case 1:
149-
std::cout << "\nEnter the value to be Inserted : ";
170+
std::cout << "\nEnter the value to be Inserted: ";
150171
std::cin >> x;
151-
Insert(root, x);
172+
tree.insert(x); // Insert value
152173
break;
153174
case 2:
154-
std::cout << "\nEnter the value to be Deleted : ";
175+
std::cout << "\nEnter the value to be Deleted: ";
155176
std::cin >> x;
156-
Remove(root, root, x);
177+
tree.remove(x); // Remove value
157178
break;
158179
case 3:
159-
BFT(root);
180+
tree.breadthFirstTraversal(); // Perform breadth-first traversal
160181
break;
161182
case 4:
162-
Pre(root);
183+
tree.preOrderTraversal(); // Perform preorder traversal
163184
break;
164185
case 5:
165-
In(root);
186+
tree.inOrderTraversal(); // Perform inorder traversal
166187
break;
167188
case 6:
168-
Post(root);
189+
tree.postOrderTraversal(); // Perform postorder traversal
169190
break;
170191
}
171-
} while (ch != 0);
192+
} while (choice != 0); // Exit loop on choice 0
172193

173194
return 0;
174195
}

0 commit comments

Comments
 (0)