Skip to content

Commit dd0420f

Browse files
committed
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.
1 parent 070e71c commit dd0420f

File tree

1 file changed

+221
-101
lines changed

1 file changed

+221
-101
lines changed

src/cpp/BinarySearchTree.cpp

+221-101
Original file line numberDiff line numberDiff line change
@@ -3,124 +3,244 @@
33
/*
44
* Structure for a binary tree node
55
*/
6-
76
struct Node {
8-
int data; // data value stored in the node
9-
Node* left; // pointer to the left child node
10-
Node* right; // pointer to the right child node
11-
12-
/**
13-
* Constructor to create a new node with the given data.
14-
*
15-
* @param value the data value for the new node.
16-
*/
17-
18-
Node(int value) : data(value), left(nullptr), right(nullptr) {}
7+
int data; ///< The integer data value stored in the node.
8+
Node *left; ///< Pointer to the left child node.
9+
Node *right; ///< Pointer to the right child node.
10+
11+
/**
12+
* Constructor to create a new node with the given data.
13+
*
14+
* @param value the data value for the new node.
15+
*/
16+
Node(int data) : data(data), left(nullptr), right(nullptr) {}
1917
};
2018

19+
class BinarySearchTree {
20+
public:
21+
BinarySearchTree() : root(nullptr) {}
2122

23+
Node *find(int x) const { return _find(this->root, x); }
2224

23-
/**
24-
* Function to insert a new node into the binary tree.
25-
*
26-
* @param root pointer to the root of the binary tree.
27-
* @param value the value to be inserted.
28-
*
29-
* @return pointer to the root of the modified binary tree.
30-
*/
31-
32-
Node* insert(Node* root, int value) {
33-
if (root == nullptr) {
34-
return new Node(value);
35-
}
36-
if (value < root->data) {
37-
root->left = insert(root->left, value);
38-
}
39-
else if (value > root->data) {
40-
root->right = insert(root->right, value);
41-
}
42-
return root;
43-
}
44-
45-
25+
void insert(int x) { _insert(&(this->root), x); }
4626

47-
/**
48-
* Function for an in-order traversal of the binary tree (Left-Root-Right).
49-
*
50-
* @param root pointer to the root of the binary tree.
51-
*/
27+
void deleteNode(int x) { _delete(&(this->root), x); }
5228

53-
void inOrderTraversal(Node* root) {
54-
if (root == nullptr) {
55-
return;
56-
}
57-
inOrderTraversal(root->left);
58-
std::cout << root->data << " ";
59-
inOrderTraversal(root->right);
60-
}
29+
void preorderTraversal() const { _printPreorder(this->root); }
6130

31+
void inorderTraversal() const { _printInorder(this->root); }
6232

33+
void postorderTraversal() const { _printPostorder(this->root); }
6334

64-
/**
65-
* Function for a pre-order traversal of the binary tree (Root-Left-Right).
66-
*
67-
* @param root pointer to the root of the binary tree.
68-
*/
35+
private:
36+
Node *root;
6937

70-
void preOrderTraversal(Node* root) {
71-
if (root == nullptr) {
72-
return;
38+
/**
39+
* @brief Find a node with a specific value in the binary search tree.
40+
*
41+
* This function searches the binary search tree starting from the given root
42+
* node for a node that contains the specified value `x`. If a node with the
43+
* value `x` is found, a pointer to that node is returned. If no such node
44+
* exists in the tree, the function returns `nullptr`.
45+
*
46+
* @param root A pointer to the root node of the binary search tree.
47+
* @param x The value to search for in the tree.
48+
* @return A pointer to the node containing the value `x`, or `nullptr` if not
49+
* found.
50+
*/
51+
Node *_find(Node *root, int x) const {
52+
if (!root || root->data == x) {
53+
return root;
7354
}
74-
std::cout << root->data << " ";
75-
preOrderTraversal(root->left);
76-
preOrderTraversal(root->right);
77-
}
78-
79-
80-
81-
/**
82-
* Function for a post-order traversal of the binary tree (Left-Right-Root).
83-
*
84-
* @param root pointer to the root of the binary tree.
85-
*/
86-
87-
void postOrderTraversal(Node* root) {
88-
if (root == nullptr) {
89-
return;
55+
if (x < root->data) {
56+
return _find(root->left, x);
57+
} else {
58+
return _find(root->right, x);
59+
}
60+
}
61+
62+
/**
63+
* @brief Inserts a new node with the specified value into the binary search
64+
* tree.
65+
*
66+
* This function inserts a new node containing the value `x` into the binary
67+
* search tree. It traverses the tree starting from the given root node
68+
* (passed as a pointer to a pointer) and inserts the new node at the
69+
* appropriate position based on the value `x`.
70+
*
71+
* @param root A pointer to a pointer to the root node of the binary search
72+
* tree.
73+
* @param x The value to insert into the tree.
74+
* @return A pointer to the updated root node of the tree after the insertion.
75+
*/
76+
Node *_insert(Node **root, int x) {
77+
if (!(*root)) {
78+
*root = new Node(x);
79+
} else if (x <= (*root)->data) {
80+
(*root)->left = _insert(&((*root)->left), x);
81+
} else {
82+
(*root)->right = _insert(&((*root)->right), x);
83+
}
84+
return *root;
85+
}
86+
87+
/**
88+
* @brief Deletes a node with the specified value from the binary search tree.
89+
*
90+
* This function deletes a node containing the value `x` from the binary
91+
* search tree. It traverses the tree starting from the given root node and
92+
* removes the node with the specified value if it exists.
93+
*
94+
* After the deletion, the function may adjust the tree structure to maintain
95+
* its binary search tree properties.
96+
*
97+
* @param root A pointer to a pointer to the root node of the binary search
98+
* tree.
99+
* @param x The value to delete from the tree.
100+
* @return A pointer to the updated root node of the tree after the deletion.
101+
*/
102+
Node *_delete(Node **root, int x) {
103+
if (!(*root)) {
104+
return nullptr;
90105
}
91-
postOrderTraversal(root->left);
92-
postOrderTraversal(root->right);
93-
std::cout << root->data << " ";
94-
}
95-
96-
97106

98-
int main() {
99-
Node* root = nullptr;
107+
if (x < (*root)->data) {
108+
(*root)->left = _delete(&((*root)->left), x);
109+
} else if (x > (*root)->data) {
110+
(*root)->right = _delete(&((*root)->right), x);
111+
} else {
112+
// Case 1: Leaf node
113+
if (!((*root)->left) && !((*root)->right)) {
114+
delete *root;
115+
*root = nullptr;
116+
}
117+
118+
// Case 2: Only one child
119+
else if (!((*root)->left)) {
120+
Node *tmp = *root;
121+
*root = (*root)->right;
122+
delete tmp;
123+
} else if (!((*root)->right)) {
124+
Node *tmp = *root;
125+
*root = (*root)->left;
126+
delete tmp;
127+
}
128+
129+
// Case 3: Two children
130+
else {
131+
// Could've been <<< Node *tmp = _find_max((*root)->left); >>>
132+
Node *tmp = _find_min((*root)->right);
133+
(*root)->data = tmp->data;
134+
(*root)->right = _delete(&((*root)->right), tmp->data);
135+
}
136+
}
137+
return *root;
138+
}
139+
140+
/**
141+
* @brief Find the minimum node value in the binary search tree.
142+
*
143+
* This function searches the binary search tree starting from the given root
144+
* node and returns a pointer to the node with the minimum value. The minimum
145+
* value is found by recursively traversing the left child nodes until the
146+
* smallest value is located.
147+
*
148+
* @param root A pointer to the root node of the binary search tree.
149+
* @return A pointer to the node with the minimum value in the tree.
150+
*/
151+
Node *_find_min(Node *root) const {
152+
while (root && root->left) {
153+
root = root->left;
154+
}
155+
return root;
156+
}
157+
158+
/**
159+
* @brief Find the maximum node value in the binary search tree.
160+
*
161+
* This function searches the binary search tree starting from the given root
162+
* node and returns a pointer to the node with the maximum value. The maximum
163+
* value is found by recursively traversing the right child nodes until the
164+
* largest value is located.
165+
*
166+
* @param root A pointer to the root node of the binary search tree.
167+
* @return A pointer to the node with the minimum value in the tree.
168+
*/
169+
Node *_find_max(Node *root) const {
170+
while (root && root->right) {
171+
root = root->right;
172+
}
173+
return root;
174+
}
175+
176+
/**
177+
* @brief Prints the elements of the binary search tree in preorder traversal.
178+
*
179+
* The preorder traversal visits the current node first, followed by its left
180+
* and right children - recursively.
181+
*
182+
* @param root A pointer to the root node of the binary search tree.
183+
*/
184+
void _printPreorder(Node *root) const {
185+
if (root) {
186+
std::cout << root->data << '\n';
187+
_printPreorder(root->left);
188+
_printPreorder(root->right);
189+
}
190+
}
191+
192+
/**
193+
* @brief Prints the elements of the binary search tree in inorder traversal.
194+
*
195+
* The inorder traversal visits the left child, followed by the current node,
196+
* and then the right child recursively.
197+
*
198+
* @param root A pointer to the root node of the binary search tree.
199+
*/
200+
void _printInorder(Node *root) const {
201+
if (root) {
202+
_printInorder(root->left);
203+
std::cout << root->data << '\n';
204+
_printInorder(root->right);
205+
}
206+
}
207+
208+
/**
209+
* @brief Prints the elements of the binary search tree in postorder
210+
* traversal.
211+
*
212+
* The postorder traversal visits the left and right children first, followed
213+
* by the current node.
214+
*
215+
* @param root A pointer to the root node of the binary search tree.
216+
*/
217+
void _printPostorder(Node *root) const {
218+
if (root) {
219+
_printPostorder(root->left);
220+
_printPostorder(root->right);
221+
std::cout << root->data << '\n';
222+
}
223+
}
224+
};
100225

101-
// insert elements into the binary tree
102-
root = insert(root, 50);
103-
root = insert(root, 30);
104-
root = insert(root, 20);
105-
root = insert(root, 40);
106-
root = insert(root, 70);
107-
root = insert(root, 60);
108-
root = insert(root, 80);
226+
int main(int argc, char *argv[]) {
227+
auto bst = BinarySearchTree();
109228

110-
// in-order traversal
111-
std::cout << "In-order traversal: ";
112-
inOrderTraversal(root);
113-
std::cout << std::endl;
229+
int arr[] = {30, 20, 10, 50, 40, 45, 80, 90};
230+
for (const auto &e : arr) {
231+
bst.insert(e);
232+
}
114233

115-
// pre-order traversal
116-
std::cout << "Pre-order traversal: ";
117-
preOrderTraversal(root);
118-
std::cout << std::endl;
234+
std::cout << "inorder traversal:\n";
235+
bst.inorderTraversal();
236+
std::cout << "preorder traversal:\n";
237+
bst.preorderTraversal();
238+
std::cout << "postorder traversal:\n";
239+
bst.postorderTraversal();
119240

120-
// post-order traversal
121-
std::cout << "Post-order traversal: ";
122-
postOrderTraversal(root);
123-
std::cout << std::endl;
241+
bst.deleteNode(50);
242+
std::cout << "preorder traversal:\n";
243+
bst.preorderTraversal();
124244

125-
return 0;
245+
return 0;
126246
}

0 commit comments

Comments
 (0)