Binary Search Tree implementation giving segmentation fault - c++

This is the c++ code to implement binary search tree where program gets seg. fault:
#include<iostream>
#include<cstdlib>
#include<stack>
struct BSTNode
{
int info;
struct BSTNode *left, *right;
};
class BST
{
private:
//BSTNode *root;
public:
void rpreorder(BSTNode*);
void rinorder(BSTNode*);
void rpostorder(BSTNode*);
BSTNode * search(BSTNode*, int);
BSTNode* insert(BSTNode*, int);
};
void BST:: rpreorder(BSTNode *root)
{
if(root == NULL)
return ;
std::cout<<" "<<root->info;
rpreorder(root->left);
rpreorder(root->right);
}
void BST:: rinorder(BSTNode *root)
{
if(root = NULL)
return ;
rinorder(root->left);
std::cout<<" "<<root->info;
rinorder(root->right);
}
void BST:: rpostorder(BSTNode *root)
{
if(root == NULL)
return ;
rpostorder(root->left);
rpostorder(root->right);
std::cout<<" "<<root->info;
}
BSTNode * BST:: search(BSTNode* root, int data)
{
if(root == NULL)
return root;
if(data < root->info)
return search(root->left, data);
else if(data > root->info)
return search(root->right, data);
return root;
}
BSTNode* BST:: insert(BSTNode *root, int data)
{
BSTNode* parent;
BSTNode* newNode = new BSTNode;
newNode->info = data;
newNode->right = NULL;
newNode->left = NULL;
if(root == NULL)
root = newNode;
else
{
parent = root;
while(parent != NULL)
{
if(data < parent->info)
{
if(parent->left == NULL)
parent->left = newNode;
parent = parent->left;
}
else if(data > parent->info)
{
if(parent->right == NULL)
parent->right = newNode;
parent = parent->right;
}
}
}
return root;
}
int main()
{
int choice, value;
BST obj;
BSTNode *root = NULL;
while(1)
{
std::cout<<"\n Enter the choice : \n 1. To insert \n 2. To search \n 3. recursive preorder \n 4. recursive inorder \n 5. recursive \
postorder \n 6. EXIT \n : ";
std::cin>>choice;
switch(choice)
{
case 1:
std::cout<<"\n Enter element to insert : ";
std::cin>>value;
root = obj.insert(root, value);
break;
case 2:
std::cout<<"\n Enter the element to search : ";
std::cin>>value;
{
BSTNode* temp;
temp = obj.search(root, value);
if(temp == NULL)
std::cout<<"\n Element not found "<<std::endl;
else
std::cout<<"\n The element found ";
}
break;
case 3:
obj.rpreorder(root);
break;
case 4:
obj.rinorder(root);
break;
case 5:
obj.rpostorder(root);
break;
case 6:
exit(0);
}
}
return 0;
}
The seg. fault is coming in this segment of above code :
void BST:: rinorder(BSTNode *root)
{
if(root = NULL)
return ;
rinorder(root->left); // <- this line gives seg. fault
std::cout<<" "<<root->info;
rinorder(root->right);
}
There is one more problem to this code :
After inserting only one element in BST I can't insert more elements into the BST.

Related

Binary Search Tree Using Classes

I have been trying to implement binary search tree using classes. Every time I try to compile and run the program, the program ends. I have tried many things like making the *root public to access it in main so I can update the root, but somehow it becomes null every time.
Help will be appreciated.
This is for my university project.
#include <iostream>
using namespace std;
class tree;
class Node {
friend class tree;
private:
Node *lchild,*rchild;
int data;
public:
Node (int x) {
data = x;
lchild = rchild = NULL;
}
};
class tree {
protected:
Node* root;
void inorder(const Node* root)const;
public:
tree () {
root = NULL;
}
bool insert(int item);
void inorder() const {inorder(root);};
Node* getroot() {
return root;
}
};
bool tree :: insert(int item) {
if (root == NULL) {
Node *temp = new Node(item);
root = temp;
return (bool) root;
}
if (item < root -> data) {
insert(item);
}
if (item > root -> data) {
insert(item);
}
else if (item == root -> data) {
cout<<"Duplicate";
exit (0);
}
return (bool) root;
}
void tree :: inorder(const Node *root)const {
if (root != NULL) {
inorder(root -> lchild);
cout<<root -> data;
inorder(root -> rchild);
}
}
int main()
{
tree obj1;
obj1.insert(3);
//obj1.insert(4);
obj1.insert(1);
//obj1.insert(5);
obj1.inorder();
}
/* Program to implement Binary Search Tree in c++ using classes and objects */
#include<iostream>
#include<stdlib.h>
#include<cstdlib>
using namespace std;
struct Node {
int data;
Node* left;
Node* right;
};
class BinaryTree {
private:
struct Node* root;
public:
BinaryTree() {
root = NULL;
}
Node* createNode(int);
Node* insertNode(Node*, int);
Node* deleteNode(Node*, int);
void inOrder(Node*);
void preOrder(Node*);
void postOrder(Node*);
Node* findMinimum(Node*);
/* accessor function helps to
get the root node in main function
because root is private data member direct access is not possible */
Node* getRoot() {
return root;
}
/* mutator method helps to update root ptr after insertion
root is not directly updatable in the main because its private data member */
void setRoot(Node* ptr) {
root = ptr;
}
};
/* Helper function to create a new node in each function call of insertNode */
Node* BinaryTree :: createNode(int n) {
Node* newNode = new struct Node();
newNode->data = n;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
/* Helps to get inorder predessor to delete the node from tree */
Node* BinaryTree :: findMinimum(Node* rootPtr) {
while(rootPtr->left != NULL) {
rootPtr = rootPtr->left;
}
return rootPtr;
}
/* insertion of the Node */
Node* BinaryTree :: insertNode(Node* rootPtr, int n) {
if(rootPtr == NULL) {
return createNode(n);
}
if(n < rootPtr->data) {
rootPtr->left = insertNode(rootPtr->left, n);
}
if(n > rootPtr->data) {
rootPtr->right = insertNode(rootPtr->right, n);
}
return rootPtr;
}
/* function to delete the Node */
Node* BinaryTree :: deleteNode(Node* rootPtr, int n) {
if(rootPtr == NULL) {
cout<<"Node to be deleted is not present.!"<<endl;
return rootPtr;
}
else if(n < rootPtr->data) {
rootPtr->left = deleteNode(rootPtr->left, n);
} else if(n > rootPtr->data) {
rootPtr->right = deleteNode(rootPtr->right, n);
} else {
if(rootPtr->left == NULL && rootPtr->right == NULL) {
delete rootPtr;
rootPtr = NULL;
}
else if(root->left == NULL) {
struct Node* temp = rootPtr;
rootPtr = rootPtr->right;
delete temp;
}
else if(rootPtr->right == NULL) {
struct Node* temp = rootPtr;
rootPtr = rootPtr->left;
delete temp;
} else {
Node* temp = findMinimum(rootPtr->right);
rootPtr->data = temp->data;
rootPtr->left = deleteNode(rootPtr->right, temp->data);
}
}
return rootPtr;
}
/* all traversal technique */
void BinaryTree :: inOrder(Node* root) {
if(root == NULL) {
return;
}
inOrder(root->left);
cout<<root->data<<"\t";
inOrder(root->right);
}
void BinaryTree :: preOrder(Node* root) {
if(root == NULL) return;
cout<<root->data<<"\t";
preOrder(root->left);
preOrder(root->right);
}
void BinaryTree :: postOrder(Node* root) {
if(root == NULL) return;
postOrder(root->left);
postOrder(root->right);
cout<<root->data<<"\t";
}
int main() {
BinaryTree l1;
int ch, ele, res;
Node* ptr;
do {
cout<<"1 - Insert Node\n";
cout<<"2 - IN-ORDER Traversal\n";
cout<<"3 - PRE-ORDER Traversal\n";
cout<<"4 - POST-ORDER Traversal\n";
cout<<"Enter choice\n";
cin>>ch;
switch(ch) {
case 1:
cout<<"Entre element to insert to the List\n";
cin>>ele;
/* calling insertNode function by passing root ptr to the function,
root ptr can be obtained by accessor function getRoot() */
ptr = l1.insertNode(l1.getRoot(), ele);
/* updating the root ptr*/
l1.setRoot(ptr);
break;
case 2:
cout<<"---IN-ORDER TRAVERSAL---"<<endl;
l1.inOrder(l1.getRoot());
cout<<endl;
break;
case 3:
cout<<"---PRE-ORDER TRAVERSAL---"<<endl;
l1.preOrder(l1.getRoot());
cout<<endl;
break;
case 4:
cout<<"---POST-ORDER TRAVERSAL---"<<endl;
l1.postOrder(l1.getRoot());
cout<<endl;
break;
case 5:
cout<<"Enter node to be deleted."<<endl;
cin>>ele;
ptr = l1.deleteNode(l1.getRoot(), ele);
l1.setRoot(ptr);
default: cout<<"Invalid choice"<<endl;
}
} while(ch >=1 && ch <= 5);
return 0;
}
The reason why root gets NULL again and again is that it actually never changes its value to something else than NULL.
Maybe you have introduced this behaviour in your code in the course of fixing some other issues; yet you assign root=NULL in the constructor; afterwards, you assign only obj.root1 = ..., while you return root in getroot() { return root; }. Further, you pass Node *root as parameter in you insert function; Note that this local variable named root hides data member root, such that root->... in these functions will always address the local variable and not the data member.
Before diving around in code that's interface needs a redesign, I'd suggest to adapt the design and then adapt the code; I'm pretty sure the errors will simply go away. I'd suggest to adapt the interface of class tree as follows and write the code around it.
Member function inorder() should be const to indicate that it does not alter the object's state. Note that const-member functions can - in contrast to other non-static member functions - be called on const-objects.
class Node {
friend class tree;
private:
Node *lchild,*rchild;
int data;
public:
Node (int x) {
data = x;
lchild = rchild = NULL;
}
};
class tree {
public:
tree () { root = NULL; }
bool insert(int item) { return insert(item,root); };
void inorder() const { inorder(root);};
protected:
Node* root;
void inorder(const Node* curr) const;
bool insert(int item, Node* curr);
};
bool tree :: insert(int item, Node *currNode) {
if (root == NULL) {
root = new Node(item);
return true;
}
else if (item < currNode->data) {
if (currNode->lchild == NULL) {
currNode->lchild = new Node(item);
return true;
}
else {
return insert(item, currNode->lchild);
}
}
else if (item > currNode->data) {
if (currNode->rchild == NULL) {
currNode->rchild = new Node(item);
return true;
}
else {
return insert(item, currNode->rchild);
}
}
else // item == currNode->data
return false; // duplicate; do not insert
}
The biggest problem with your code are the following lines:
if (item < root -> data) {
insert(item);
}
if (item > root -> data) {
insert(item);
}
Basically you are saying that if the item is larger or smaller than the root data you will call the function again with the same item, you never changed the item and you will basically do this an infinity amount of times.....

What's wrong with this code for BST insertion?

So I wrote this code for Insertion of a node in BST (Binary Search Trees) but the program always prints that the tree is empty. I guess there's a problem with the function call I've made. Can you explain the problem.
#include <bits/stdc++.h>
#include <conio.h>
using namespace std;
struct node
{
int key;
node* left;
node* right;
};
void insert(node* root, int item)
{
if(root == NULL)
{
node* temp = new node();
temp->key = item;
temp->left = NULL;
temp->right = NULL;
root = temp;
}
else
{
if((root->key)>item)
{
insert(root->left,item);
}
else
{
insert(root->right,item);
}
}
}
void inorder(node* root)
{
if(root!=NULL)
{
inorder(root->left);
cout<<" "<<root->key<<" ";
inorder(root->right);
}
else cout<<"The tree is empty.";
}
int main()
{
// cout<<endl<<" Here 5 ";
node* root = NULL;
int flag = 1 , item;
while(flag == 1)
{
cout<<"Enter the number you want to enter : ";
cin>>item;
// cout<<endl<<" Here 6";
insert(root, item);
cout<<"Do you want to enter another number (1 -> YES)?";
cin>>flag;
}
cout<<"The final tree is :";
inorder(root);
getch();
return 0;
}
First, the insertion is slightly incorrect. The root pointer must be passed by reference. Just some such as:
void insert(node *& root, int item)
{
if(root == NULL)
{
node* temp = new node();
temp->key = item;
temp->left = NULL;
temp->right = NULL;
root = temp;
}
else
{
if ((root->key) > item)
{
insert(root->left,item);
}
else
{
insert(root->right,item);
}
}
}
which is structurally identic to your code (except for the reference to the root)
Also, your inorder traversal is bizarre because it will print out the message "The tree is empty." each time that the traversal detects a null node. I would modify thus:
void inorder(node* root)
{
if (root == NULL)
return;
inorder(root->left);
cout<<" "<<root->key<<" ";
inorder(root->right);
}
Finally, I would slightly modify main() for managing the case when the tree is empty (instead of doing it inside inorder traversal):
int main()
{
node* root = NULL;
int flag = 1 , item;
while(flag == 1)
{
cout<<"Enter the number you want to enter : ";
cin>>item;
insert(root, item);
cout<<"Do you want to enter another number (1 -> YES)?";
cin>>flag;
}
cout<<"The final tree is :";
if (root == NULL)
cout << "The tree is empty.";
else
inorder(root);
cout << endl;
return 0;
}

BST remove/delete node - root

I got a problem when I delete root node for example if I add to tree 2, 1, 3 and remove 2 (root) something goes wrong when I want to see my tree in preorder and program fails.
Could You explain what's going wrong?
#include <iostream>
#include <string>
using namespace std;
struct BST {
int data;
BST* left;
BST* right;
};
BST* GetNewNode (int data)
{
BST* newNode = new BST ();
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
//******************************BST******************************************************
BST * insertBST (BST * root, int data);
BST * search (BST* root , int data);
BST* FindMin(BST* root);
BST* Delete (BST* root, int data);
BST* DeleteAll(BST* root);
void Inorder(BST *root);
void Preorder(BST *root);
void Postorder(BST *root);
//****************************MAIN***********************************
int main()
{
BST* root = NULL;
string menu= " ";
int f ;
while(menu!="k")
{
cout<<"Chose function (i, r, in ,pre, post, del, f)"<<endl
<<"Want to quit tap k"<<endl;
cin>>menu;
if(menu== "i" )
{
cout<<"If you want to end inserting write 0"<<endl;
cin>>f;
while(f)
{
root = insertBST (root,f );
cin>>f;
}
}
else if(menu == "r" )
{
cout<<"Insert data of node to delete"<<endl;
cin>>f;
Delete(root , f);
}
else if(menu == "in")
Inorder (root);
else if(menu == "pre")
Preorder (root);
else if(menu == "post")
Postorder (root);
else if(menu == "del")
root = DeleteAll(root);
else if(menu == "find")
{
cin>> f;
search(root , f);
}
}
DeleteAll (root);
return 0;
}
///---------------------------------------
BST* insertBST (BST* root, int data)
{
if (root == NULL)
{
root = GetNewNode (data);
}
else if (data <= root->data)
{
root->left = insertBST (root->left, data);
}
else
{
root->right = insertBST (root->right, data);
}
return root;
}
BST* search (BST* root , int data)
{
if (root == NULL) {cout <<"Not found "<<endl; return NULL;}
else if (root->data == data){ cout<<"Found "<<root->data <<endl ;return root;}
else if (data<= root->data) return search (root->left, data);
else return search (root->right, data);
}
BST* Delete (BST* root, int data)
{
if(root == NULL) return root;
else if(data < root->data) root->left = Delete(root->left,data);
else if(data > root->data) root->right = Delete(root->right, data);
else
{
if(root->left == NULL && root->right == NULL)
{
delete root;
root = NULL;
} else if(root->left == NULL)
{
struct BST *temp = root;
root = root->right;
delete temp;
} else if(root->right == NULL)
{
struct BST *temp = root;
root = root->left;
delete temp;
} else{
struct BST *temp = FindMin(root->right);
root->data = temp->data;
root->right = Delete(root->right, temp->data);
}
}
return root;
}
void Inorder(BST *root)
{
if(root == NULL) return;
Inorder(root->left);
cout<<root->data<<" ";
Inorder(root->right);
}
void Preorder(BST *root)
{
if (root != NULL)
{
cout<< root->data<<" ";
Preorder (root->left);
Preorder (root->right);
}
else if (root == NULL)
return;
}
void Postorder(BST *root)
{
if (root == NULL)
return;
Postorder (root->left);
Postorder (root->right);
cout<< root->data<<" ";
}
BST* FindMin(BST* root)
{
while(root->left != NULL) root = root->left;
return root;
}
BST* DeleteAll(BST* root)
{
if (root!=NULL)
{
DeleteAll(root->left);
DeleteAll(root->right);
delete(root);
root = NULL;
}
return root;
}
What you are doing is called inorder. below you can check preorder
Preorder:
do stuff with the node // pre means before
recurse left
recurse right
void Preorder(BST *root)
{
if (root == NULL)
return;
cout<< root->data<<" ";
Preorder (root->left);
Preorder (root->right);
}

I would like not to use root as global

Hello I am writing an avl tree and I have one issue . I am currently having a root as global since I use it in the class as well as in main , how can I write it without having it global?
struct avl_node {
int data;
struct avl_node *left;
struct avl_node *right;
}*root;
class avlTree {
public:
int height(avl_node *temp)
{
int h = 0;
if (temp != NULL)
{
int l_height = height (temp->left);
int r_height = height (temp->right);
int max_height = max (l_height, r_height);
h = max_height + 1;
}
return h;
}
int diff(avl_node *temp)
{
int l_height = height (temp->left);
int r_height = height (temp->right);
int b_factor= l_height - r_height;
return b_factor;
}
avl_node *rr_rotation(avl_node *parent)
{
avl_node *temp;
temp = parent->right;
parent->right = temp->left;
temp->left = parent;
return temp;
}
avl_node *ll_rotation(avl_node *parent)
{
avl_node *temp;
temp = parent->left;
parent->left = temp->right;
temp->right = parent;
return temp;
}
avl_node *lr_rotation(avl_node *parent)
{
avl_node *temp;
temp = parent->left;
parent->left = rr_rotation (temp);
return ll_rotation (parent);
}
avl_node *rl_rotation(avl_node *parent)
{
avl_node *temp;
temp = parent->right;
parent->right = ll_rotation (temp);
return rr_rotation (parent);
}
avl_node* balance(avl_node *temp)
{
int bal_factor = diff (temp);
if (bal_factor > 1)
{
if (diff (temp->left) > 0)
temp = ll_rotation (temp);
else
temp = lr_rotation (temp);
}
else if (bal_factor < -1)
{
if (diff (temp->right) > 0)
temp = rl_rotation (temp);
else
temp = rr_rotation (temp);
}
return temp;
}
avl_node* insert(avl_node *root, int value)
{
if (root == NULL)
{
root = new avl_node;
root->data = value;
root->left = NULL;
root->right = NULL;
return root;
}
else if (value < root->data)
{
root->left = insert(root->left, value);
root = balance (root);
}
else if (value >= root->data)
{
root->right = insert(root->right, value);
root = balance (root);
}
return root;
}
void display(avl_node *ptr, int level)
{
int i;
if (ptr!=NULL)
{
display(ptr->right, level + 1);
printf("\n");
if (ptr == root)
cout<<"Root -> ";
for (i = 0; i < level && ptr != root; i++)
cout<<" ";
cout<<ptr->data;
display(ptr->left, level + 1);
}
}
void inorder(avl_node *tree)
{
if (tree == NULL)
return;
inorder (tree->left);
cout<<tree->data<<" ";
inorder (tree->right);
}
void preorder(avl_node *tree)
{
if (tree == NULL)
return;
cout<<tree->data<<" ";
preorder (tree->left);
preorder (tree->right);
}
void postorder(avl_node *tree)
{
if (tree == NULL)
return;
postorder ( tree ->left );
postorder ( tree ->right );
cout<<tree->data<<" ";
}
avlTree()
{
root = NULL;
}
};
int main()
{
int choice, item;
avlTree avl;
while (1)
{
cout<<"\n---------------------"<<endl;
cout<<"AVL Tree Implementation"<<endl;
cout<<"\n---------------------"<<endl;
cout<<"1.Insert Element into the tree"<<endl;
cout<<"2.Display Balanced AVL Tree"<<endl;
cout<<"3.InOrder traversal"<<endl;
cout<<"4.PreOrder traversal"<<endl;
cout<<"5.PostOrder traversal"<<endl;
cout<<"6.Exit"<<endl;
cout<<"Enter your Choice: ";
cin>>choice;
switch(choice)
{
case 1:
system("cls");
cout<<"Enter value to be inserted: ";
cin>>item;
root = avl.insert(root, item);
break;
case 2:
system("cls");
if (root == NULL)
{
cout<<"Tree is Empty"<<endl;
continue;
}
cout<<"Balanced AVL Tree:"<<endl;
avl.display(root, 1);
break;
case 3:
system("cls");
cout<<"Inorder Traversal:"<<endl;
avl.inorder(root);
cout<<endl;
break;
case 4:
system("cls");
cout<<"Preorder Traversal:"<<endl;
avl.preorder(root);
cout<<endl;
break;
case 5:
system("cls");
cout<<"Postorder Traversal:"<<endl;
avl.postorder(root);
cout<<endl;
break;
case 6:
exit(1);
break;
default:
system("cls");
cout<<"Wrong Choice"<<endl;
}
}
return 0;
}
You should not explicitly use the tree's root in main(), and generally outside the tree's methods. To achieve this just make the method
avl_node* insert(avl_node *where, int value)
private (or protected, at least) in a class and add a public interface:
void insert(int value)
{
root = insert(root, value);
}
Then in main you add items simply by calling
avlTree tree;
....
tree.insert(item);
EDIT to answer a question asked in a comment.
Functions like display, inorder etc. should be handled in the same way as insert: declare a public, parameterless function to launch the action and a protected method with a parameter to recursively perform it:
public:
void display() { display(root, 0); }
void inorder() { inorder(root); }
.....
protected:
void display(avl_node *node, int level)
{
if (node!=NULL)
{
display(node->right, level + 1);
if (node == root)
cout << "Root -> ";
else
cout << " ";
cout << setw(5*level) << "" << node->data << endl;
display(node->left, level + 1);
}
}
void inorder(avl_node *node)
{
if (node)
{
inorder (node->left);
cout << node->data << " ";
inorder (node->right);
}
}
then use:
tree.display();
tree.inorder();

I'm having trouble with cpp code to insert elements in a binary tree

I've tried this way to insert elements in a binary tree in code blocks. The program got compiled but got a run time error and the program stopped running. Could some one please help me out in this issue.
Thanks in advance.
#include <iostream>
#include <cstdlib>
using namespace std;
class bst;
class node
{
public:
int data;
node *lc;
node *rc;
};
class bst
{
public:
node *root;
bst()
{
root = NULL;
}
void search(int, node **, node **);
void insert(int);
void display(node *, int);
};
void bst::search(int item, node **par, node **loc)
{
node *current;
node *ptr;
if(root == NULL)
{
*par = NULL;
*loc = NULL;
return;
}
if(item == root->data)
{
*par = NULL;
*loc = root;
return;
}
if(item < root->data)
current = root->lc;
else
current = root->rc;
ptr = root;
while(current != NULL)
{
if(item == current->data)
{
*par = ptr;
*loc = current;
return;
}
ptr = current;
if(item < current->data)
current = current->lc;
else
current = current->rc;
}
*par = current;
*loc = NULL;
}
void bst::insert(int item)
{
node *parent;
node *location;
node *temp;
search(item, &parent, &location);
temp = new node;
temp->data = item;
temp->lc = NULL;
temp->rc = NULL;
if(item < parent->data)
parent->lc = temp;
else
parent->rc = temp;
}
void bst::display(node *ptr, int level)
{
if(ptr != NULL)
{
display(ptr->rc, level+1);
cout<<"\n";
for(int i=0;i<level;i++)
cout<<" ";
cout<<ptr->data;
display(ptr->lc, level+1);
}
}
int main()
{
int ch, num;
bst b;
while(1)
{
cout<<"1. INSERT ; 2. DISPLAY ; 3. EXIT "<<endl;
cout<<"Enter your choice"<<endl;
cin>>ch;
switch(ch)
{
case 1: cout<<"Enter the number to insert"<<endl;
cin>>num;
b.insert(num);
break;
case 2: b.display(b.root, 1);
break;
case 3: exit(0);
}
}
return 0;
}
In this line search(item, &parent, &location); you are calling the function search with arguments of types int, node** and node**. It in fact expects int, node* and node*. You should change the function declaration to search(int, node**, node**).