enh(CPlusPlus): Binary Search Tree and Iterative Traversal (#434)

Co-authored-by: Arsenic <54987647+Arsenic-ATG@users.noreply.github.com>
pull/441/head
shinchancode 2021-08-30 18:24:52 +05:30 committed by GitHub
parent ad6073753a
commit 2c8c9c011c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 338 additions and 103 deletions

View File

@ -1,51 +1,52 @@
#include <iostream> #include <iostream>
#include <cmath> #include <cmath>
//Structure of the Tree //Structure of the Tree
struct TreeNode{ struct TreeNode{
int data; int data;
TreeNode* left; TreeNode* left;
TreeNode* right; TreeNode* right;
TreeNode(const int& data): data(data), left(nullptr), right(nullptr){} TreeNode(const int& data): data(data), left(nullptr), right(nullptr){}
}; };
TreeNode* find(TreeNode* root, const int& data){ TreeNode* find(TreeNode* root, const int& data){
/** /**
* Find the node that contains the given data and * Find the node that contains the given data and
* return that node * return that node
* *
* @params: `root` root/parent node of the tree * @params: `root` root/parent node of the tree
* @params: `data` data to be find in the tree * @params: `data` data to be find in the tree
* @return: tree node that contains the data * @return: tree node that contains the data
* *
* Average case Time Complexity: O(log(n)) * Average case Time Complexity: O(log(n))
* Worst case Time Complexity: O(n) * Worst case Time Complexity: O(n)
* *
*/ */
if(root == nullptr) { throw std::runtime_error("Error: find() cannot find the data. The data doesn't exist."); } if(root == nullptr) { throw std::runtime_error("Error: find() cannot find the data. The data doesn't exist."); }
else if(root->data == data) { return root; } else if(root->data == data) { return root; }
else if(root->data < data) { return find(root->right, data); } else if(root->data < data) { return find(root->right, data); }
else { return find(root->left, data); } else { return find(root->left, data); }
} }
void Insert(TreeNode*& root, const int& data){ void Insert(TreeNode*& root, const int& data){
/** /**
* Create and Insert the node in the appropriate place of the tree * Create and Insert the node in the appropriate place of the tree
* *
* @params: `root` root/parent node of the tree * @params: `root` root/parent node of the tree
* @params: `data` data to be inserted in the tree * @params: `data` data to be inserted in the tree
* @return: void * @return: void
* *
* Average case Time Complexity: O(log(n)) * Average case Time Complexity: O(log(n))
* Worst case Time Complexity: O(n) * Worst case Time Complexity: O(n)
* *
*/ */
if(root == nullptr) { root = new TreeNode(data); } if(root == nullptr) { root = new TreeNode(data); }
else if(root->data == data) { throw std::runtime_error("The node already exist. Duplicates not allowed"); } else if(root->data == data) { throw std::runtime_error("The node already exist. Duplicates not allowed"); }
else if(root->data < data) { Insert(root->right, data); } else if(root->data < data) { Insert(root->right, data); }
else { Insert(root->left, data); } else { Insert(root->left, data); }
} }
@ -107,7 +108,7 @@ bool perfect_recursive(TreeNode* cur, int depth, int level = 0){
if(cur->left != nullptr && cur->right != nullptr) { if(cur->left != nullptr && cur->right != nullptr) {
return perfect_recursive(cur->left, depth, level+1) && perfect_recursive(cur->right, depth, level+1); return perfect_recursive(cur->left, depth, level+1) && perfect_recursive(cur->right, depth, level+1);
} }
return false; return false;
} }
int count_nodes(TreeNode* cur){ int count_nodes(TreeNode* cur){
@ -117,7 +118,7 @@ int count_nodes(TreeNode* cur){
*/ */
if(cur != nullptr){ return 1 + count_nodes(cur->left) + count_nodes(cur->right); } if(cur != nullptr){ return 1 + count_nodes(cur->left) + count_nodes(cur->right); }
return 0; return 0;
} }
@ -129,7 +130,7 @@ int height(TreeNode* cur){
*/ */
if(cur != nullptr){ return 1 + std::max(height(cur->left), height(cur->right)); } if(cur != nullptr){ return 1 + std::max(height(cur->left), height(cur->right)); }
return 0; return 0;
} }
bool perfect(TreeNode* cur){ bool perfect(TreeNode* cur){
@ -158,83 +159,226 @@ bool isperfect(TreeNode* root){
//if(perfect(root)) { return true; } //if(perfect(root)) { return true; }
if(perfect_recursive(root, depth(root) - 1)) { return true; } if(perfect_recursive(root, depth(root) - 1)) { return true; }
return false; return false;
}
void leaf_nodes(TreeNode* root) //Print all leafnode in BST
{
/* * Node which does not have a child is called as LEAF Node.
* Printing the nodes whose left and right pointer are null.
* @params: `root` root/parent node of the tree
*/
if (!root)
return;
if (root->left==NULL && root->right==NULL)
{
std::cout<<root->data<< " ";
return;
}
if (root->left)
leaf_nodes(root->left);
if (root->right)
leaf_nodes(root->right);
}
TreeNode* f_min(TreeNode* root) //Find Minimum element from root
{
/**
* Print the minimum value of the tree
*
* @params: `root` root/parent node of the tree
* @return: void
*/
if(root==NULL)
{
std::cout<<"No value present in the tree"<< std::endl;
return NULL;
}
TreeNode* p=root;
while(p->left!=NULL)
{
p=p->left;
}
return p;
}
TreeNode* f_max(TreeNode* root) //Find Maximum element from root
{
/**
* Print the maximum value of the tree
*
* @params: `root` root/parent node of the tree
* @return: void
*/
if(root==NULL)
{
std::cout<<"No value present in the tree"<< std::endl;
return NULL;
}
TreeNode* p=root;
while(p->right!=NULL)
{
p=p->right;
}
return p;
}
TreeNode* bstdelete(TreeNode* root, int x)
{
TreeNode* m;
if(root==NULL)
{
std::cout<<"NOT FOUND!!";
return root;
}
if(x < root->data)
{
root->left=bstdelete(root->left,x);
return root;
}
if(x>root->data)
{
root->right=bstdelete(root->right,x);
return root;
}
if(root->left==NULL && root->right==NULL)
{
m=root;
delete m;
return (NULL);
}
else if(root->left==NULL)
{
m=root;
root=root->right;
delete m;
return (root);
}
else if(root->right==NULL)
{
m=root;
root=root->left;
delete m;
return (root);
}
m=f_min(root->right);
root->data=m->data;
root->right=bstdelete(root->right, m->data);
return (root);
} }
void print(TreeNode* root){ void print(TreeNode* root){
/** /**
* Print the tree in an inorder fashion * Print the tree in an inorder fashion
* *
* @params: `root` root/parent node of the tree * @params: `root` root/parent node of the tree
* @return: void * @return: void
*/ */
if(root != nullptr){ if(root != nullptr){
print(root->left); print(root->left);
std::cout << root->data << " "; std::cout << root->data << " ";
print(root->right); print(root->right);
} }
} }
void free(TreeNode* root){ void free(TreeNode* root){
/* /*
* Free up the memory in the heap * Free up the memory in the heap
* *
* @params: `root` root/parent node of the tree * @params: `root` root/parent node of the tree
*/ */
if(root != nullptr){ if(root != nullptr){
free(root->left); free(root->left);
free(root->right); free(root->right);
delete root; delete root;
root = nullptr; root = nullptr;
} }
} }
int main(){ int main(){
TreeNode* root = nullptr; TreeNode* root = nullptr;
Insert(root, 37); Insert(root, 37);
Insert(root, 19); Insert(root, 19);
Insert(root, 4); Insert(root, 4);
Insert(root, 22); Insert(root, 22);
Insert(root, 51); Insert(root, 51);
Insert(root, 55); Insert(root, 55);
Insert(root, 42); Insert(root, 42);
Insert(root, 20); Insert(root, 20);
Insert(root, 11); Insert(root, 11);
Insert(root, 2); Insert(root, 2);
print(root); print(root);
TreeNode* n = find(root, 19); TreeNode* n = find(root, 19);
std::cout << "\nValue of n: " << n->data << std::endl; std::cout << "\nValue of n: " << n->data << std::endl;
if(isfull(root)) { std::cout << "The binary tree is FULL" << std::endl; } if(isfull(root)) { std::cout << "The binary tree is FULL" << std::endl; }
else { std::cout << "The binary tree is not FULL" << std::endl; } else { std::cout << "The binary tree is not FULL" << std::endl; }
if(isperfect(root)) { std::cout << "The binary tree is PERFECT" << std::endl; } if(isperfect(root)) { std::cout << "The binary tree is PERFECT" << std::endl; }
else { std::cout << "The binary tree is not PERFECT" << std::endl; } else { std::cout << "The binary tree is not PERFECT" << std::endl; }
/* std::cout << "Leaf Nodes present in the binary tree are : ";
Tree structure leaf_nodes(root);
37 std::cout<< std::endl;
/ \
19 51 n = f_max(root);
/ \ / \ if(n)
4 22 42 55 {
/\ / std::cout<<"Maximum Value Present in the tree is : "<<n->data<< std::endl;
2 11 20 }
OUTPUT: n=f_min(root);
2 4 11 19 20 22 37 42 51 55 if(n)
Value of n: 19 {
The binary tree is not FULL std::cout<<"Minimum Value Present in the tree is : "<<n->data<< std::endl;
The binary tree is not PERFECT }
*/
// free the memory root = bstdelete(root, 19);
free(root); std::cout<<"Binary search Tree after Deletion is : "<<std::endl;;
return 0; print(root);
/*
Tree structure
37
/ \
19 51
/ \ / \
4 22 42 55
/\ /
2 11 20
OUTPUT:
2 4 11 19 20 22 37 42 51 55
Value of n: 19
The binary tree is not FULL
The binary tree is not PERFECT
Leaf Nodes present in the binary tree are : 2 11 20 42 55
Maximum Value Present in the tree is : 55
Minimum Value Present in the tree is : 2
Binary search Tree after Deletion is :
2 4 11 20 22 37 42 51 55
Tree structure after deletion
37
/ \
11 51
/ \ / \
4 22 42 55
/ /
2 20
*/
// free the memory
free(root);
return 0;
} }

View File

@ -1,4 +1,5 @@
#include<iostream> #include<iostream>
#include<stack>
#define endl "\n" #define endl "\n"
using namespace std; using namespace std;
@ -49,6 +50,82 @@ void post_order(struct Node* root){
} }
/* Pre, In and Post order Traversal of a Binary Tree using Iteration */
/* Complexity for each Traversal : O(n) */
void NRpreorder(struct Node* root) //Iterative Preorder Traversal
{
stack <Node*> s;
while(!s.empty() || root!=NULL)
{
while(root!=NULL)
{
cout<<root->data<<" ";
s.push(root);
root=root->left;
}
root=s.top();
s.pop();
root=root->right;
}
}
void NRinorder(struct Node* root) //Iterative Inorder Traversal
{
stack <Node*> s;
while(!s.empty() || root!=NULL)
{
while(root!=NULL)
{
s.push(root);
root=root->left;
}
root=s.top();
s.pop();
cout<<root->data<<" ";
root=root->right;
}
}
void NRpostorder(struct Node* root) //Iterative Postorder Traversal
{
stack <Node*> s1;
stack <int> s2;
while(root!=NULL)
{
s1.push(root);
s2.push(0);
root=root->left;
}
while(!s1.empty())
{
root=s1.top();
if(s2.top()==1)
{
s1.pop();
s2.pop();
cout<<root->data<<" ";
}
else
{
s2.top()=1;
root=root->right;
while(root!=NULL)
{
s1.push(root);
s2.push(0);
root=root->left;
}
}
}
}
int main(){ int main(){
Node* root = new Node(1); Node* root = new Node(1);
root->left = new Node(2); root->left = new Node(2);
@ -63,14 +140,28 @@ int main(){
2 3 2 3
/ \ \ / \ \
4 5 7 4 5 7
Expected-> pre-order : 1,2,4,5,3,7 Expected-> From Recursive calls :
in-order : 4,2,5,1,3,7 pre-order : 1 2 4 5 3 7
post-order: 4,5,2,7,3,1 in-order : 4 2 5 1 3 7
post-order : 4 5 2 7 3 1
From Non-Recursive/Iterative calls :
preorder : 1 2 4 5 3 7
inorder : 4 2 5 1 3 7
postorder : 4 5 2 7 3 1
*/ */
// Tree Traversal using recursive calls
cout<<"From Recursive calls : "; cout<<endl;
cout<<"pre-order : "; pre_order(root); cout<<endl; cout<<"pre-order : "; pre_order(root); cout<<endl;
cout<<"in-order : "; in_order(root); cout<<endl; cout<<"in-order : "; in_order(root); cout<<endl;
cout<<"post-order : "; post_order(root); cout<<endl; cout<<"post-order : "; post_order(root); cout<<endl<<endl;
// ~~~~~~ Tree Traversal using non-recusive/Iterative calls ~~~~~~
cout<<"From Non-Recursive/Iterative calls : "; cout<<endl;
cout<<"preorder : "; NRpreorder(root); cout<<endl;
cout<<"inorder : "; NRinorder(root); cout<<endl;
cout<<"postorder : "; NRpostorder(root); cout<<endl;
return 0; return 0;
} }