-
-
Notifications
You must be signed in to change notification settings - Fork 7.4k
feat: use smart pointer in binary search tree #2741
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,168 +7,189 @@ | |
* utilize any of the C++ STL features. | ||
*/ | ||
#include <iostream> | ||
#include <memory> | ||
#include <vector> | ||
#include <queue> | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should be inside the datastructures namespace |
||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should probably try to avoid recursion |
||
} | ||
} 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instead of removeHelper why not _remove()? |
||
} | ||
|
||
// 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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please use snake_case |
||
postOrderHelper(root.get()); | ||
} | ||
|
||
private: | ||
// Helper function for insertion | ||
void insertHelper(Node* node, int x) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this could be inlined |
||
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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tests should be in a separate function called |
||
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; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
headers should be documented