enh(CPlusPlus): Binary Search Tree and Iterative Traversal (#434)
Co-authored-by: Arsenic <54987647+Arsenic-ATG@users.noreply.github.com>pull/441/head
parent
ad6073753a
commit
2c8c9c011c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue