Skip to content

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

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

headers should be documented

#include <queue>

Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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 {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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) {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests should be in a separate function called tests

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;
}
Loading