What is wrong in my min method (Binary Search Tree)? - c++

This is a binary search tree implementation, I cant figure out why my min method (for finding the minimum element in a tree) is not returning the correct answer, but an arbitrary memory address.
I am creating a tree by this constructor BST(3);, now I run min(), it returns correctly 3, but after inserting 1(insert(1) method), min() returns some hex address.
class node{
public:
int key;
node *left;
node *right;
node *parent;
};
class BST{
node *root;
public:
BST(){}
BST(int a){
root=new node();
root->left=NULL;
root->right=NULL;
root->parent=NULL;
root->key=a;
}
void insert(int n)
{
if(search(n))return;
node *p=root;
node *m=new node;
m->key=n;
m->left=NULL;
m->right=NULL;
while(1)
{
if(p->key > n)
{
//look left
if(p->left==NULL)
{
p->left=m;
m->parent=p;
return;
}
else
p=p->left;
}
else
{
//look right
if(p->right==NULL)
{
p->right=m;
m->parent=p;
return;
}
else
p=p->right;
}
}
}
bool search(int n)
{
node *p=root;
while(1)
{
if(p->key > n)
{
//look left
if(p->left==NULL)
return false;
else
p=p->left;
}
else if(p->key==n)return true;
else
{
//look right
if(p->right==NULL)
return false;
else
p=p->right;
}
}
}
int min()
{
node *p=root;
if(p->left == NULL)
return (p->key);
p=p->left;
}
};

Because you run into undefined behaviour by not returning on all control paths:
int min()
{
node *p=root;
if(p->left == NULL)
return (p->key);
p=p->left;
//no return here
}
Which means that if p->left is not NULL, anything can happen. Anything!
It looks like you want a loop there instead:
int min()
{
node *p=root;
while (p->left != NULL)
p=p->left;
return (p->key);
}

If p->left != NULL, you don't return anything.

Related

How to implement complete binary in c++?

I want to try make insertion of complete binary tree using recursion . I make a piece of code and I cannot catch problem why value not inserted. I make height function and count nodes function with help of these function and recursive call I want to insert new node in Complete binary tree. In main get root by using get root function then send to insert function
#include<iostream>
#include<math.h>
using namespace std;
struct node{
int data;
node *left,*right;
};
class cbt{
node *root;
public:
cbt()
{
root=NULL;
}
node* get_node()
{
return root;
}
node* newNode(int key)
{
node* temp1 = new node;
temp1->data = key;
temp1->left = temp1->right = NULL;
return temp1;
}
void CBT_inseration(node* temp,int data)
{
node *ptr;
ptr=newNode(data);
if(root==NULL)
{
root=ptr;
return;
}
else
{
height = f_height(temp->left);
int excepted_node = pow(2,height)-1;
int left_tree_node_count = countNumNodes(temp->left);
int right_tree_node_count = countNumNodes(temp->right);
if(left_tree_node_count==right_tree_node_count)
{
CBT_inseration(temp->left,data);
}
else if(excepted_node != left_tree_node_count)
{
if(temp->left == NULL)
{
temp->left = ptr;
return;
}else
{
CBT_inseration(temp->left,data);
}
}
else if(temp->right == NULL)
{
temp->right=ptr;
return;
}
else if(excepted_node != left_tree_node_count)
{
if(temp->left == NULL)
{
temp->left=ptr;
return;
}
else
{
CBT_inseration(temp->right,data);
}
}
}
}
void print(node *root) {
if (root == NULL)
return;
print(root->left);
cout << root->data << " ";
print(root->right);
}
};
int main()
{
cbt obj;
node *r=NULL;
obj.CBT_inseration(obj.get_node(),4);
obj.CBT_inseration(obj.get_node(),3);
obj.CBT_inseration(obj.get_node(),5);
obj.CBT_inseration(obj.get_node(),8);
obj.print(obj.get_node());
return 0;
}
You would need to go through a debugger to see what is wrong with your code. I will tell you how I would do this:
First, you need a function to check if the tree is full. We will reuse your functions to do this:
bool isTreeFull(node* head) {
return head != NULL && countNumNodes(head) == (1 << find_height(head)) - 1;
}
Then for inserting I have to check if the number of nodes on each side are the same. This tells me that I am allowed to move one level deeper on the left side. If the number of nodes aren't the same, then I only move on to insert on the right subtree if the left subtree is full:
void CBT_inseration(int data) {
root = insert(root, data);
}
node* insert(node* head, int data) {
if (head == NULL) {
head = newNode(data);
} else {
int leftCount = countNumNodes(head->left);
int rightCount = countNumNodes(head->right);
if (leftCount == rightCount) {
head->left = insert(head->left, data);
} else {
if (isTreeFull(head->left)) {
head->right = insert(head->right, data);
} else {
head->left = insert(head->left, data);
}
}
}
return head;
}
Then you would call it like:
cbt obj;
obj.CBT_inseration(4);
obj.CBT_inseration(3);
obj.CBT_inseration(5);
obj.CBT_inseration(6);
obj.CBT_inseration(8);
obj.print(obj.get_node()); // 6 3 8 4 5

how to reset the pointer in BST?

I am trying to implement a Binary search tree with functionalities such as Deleting a node, finding the minimum node, maximum node, etc. But I am not able to Delete a node nor find Maximum or Minimum value in the tree. My take is that when I am inserting the nodes, the pointer to the node references to the last node hence my program cannot iterate from the root node. Any suggestion?
#include<iostream>
using namespace std;
struct BstNode
{
BstNode* left;
BstNode* right;
int data;
};
BstNode* GetnewNode(int data)
{
BstNode* newNode=new BstNode();
newNode->data=data;
newNode->left=NULL;
newNode->right=NULL;
return newNode;
}
BstNode* Insert(BstNode* root ,int data)
{
if(root==NULL)
{
root=GetnewNode(data);
}
else if(data<=root->data)
{
root=Insert(root->left,data);
}
else
{
root=Insert(root->right,data);
}
return root;
}
bool Search(BstNode* root, int data)
{
if(root==NULL)
{
return false;
}
else if(data==root->data)
{
return true;
}
else if(data<=root->data)
{
return Search(root->left,data);
}
else
{
return Search(root->right,data);
}
}
int FindMin(BstNode* root)
{
if(root==NULL)
{
return -1;
}
else
{
while(root->left!=NULL)
{
root=root->left;
}
}
return root->data;
}
bool IsBstUtil(BstNode* root, int minvalue, int maxvalue)
{
if(root==NULL)
return true;
if(root->data<minvalue && root->data >maxvalue && IsBstUtil(root->left,minvalue,root->data) && IsBstUtil(root->right,root->data,maxvalue))
{
return true;
}
else
{
return false;
}
}
bool IsBinarySearchTree(BstNode* root)
{
return IsBstUtil(root, INT_MIN, INT_MAX);
}
int FindMax(BstNode* root)
{
if(root==NULL)
{
return -1;
}
else
{
while(root->right!=NULL)
{
root=root->right;
}
}
return root->data;
}
BstNode* del(BstNode* root, int data)
{
if(root==NULL)
return root;
else if(data<=root->data)
root->left=del(root->left,data);
else if(data>root->data)
root->right=del(root->right,data);
else
{
if(root->left==NULL && root->right==NULL)
{
root=NULL;
delete root;
}
else if(root->left==NULL)
{
BstNode* temp=root;
root=root->right;
delete temp;
return root;
}
else if(root->right==NULL)
{
BstNode* temp=root;
root=root->left;
delete temp;
return root;
}
}
}
int main()
{
BstNode* root=NULL;
root=Insert(root,1);
root=Insert(root,3);
root=Insert(root,4);
}
Just instead of doing root = Insert(root->left,data); you should do set it as left to the root i.e
root->left = Insert(root->left,data);
Insert function:
BstNode* Insert(BstNode* root ,int data)
{
if(root==NULL)
{
root=GetnewNode(data);
}
else if(data<=root->data)
{
// setting the left to root
root->left=Insert(root->left,data);
}
else
{
// setting the right to root
root->right=Insert(root->right,data);
}
// returning the root itself
return root;
}

I can't figure out the reason for abnormal termination while executing levelOrder function?

This code is for Implementing binary tree.
It consist of insertNode(function which inserts node in the tree) and levelOrder(function which traverse the binary tree at level order).
insertNode function works fine but while executing levelOrder it successfully displays the data but after that it stops working and displays program has stopped working.
I can't find where i am going wrong?
Thanks in advance{ : )
#include<iostream>
using namespace std;
struct Node
{
Node *left;
Node *right;
int data;
}*root;
struct Queue
{
Node *p[1000];
int index=-1;
Node *add(Node *ptr)
{
p[++index]=ptr;
return ptr;
}
Node *peek()
{
if(index==-1)
return NULL;
return p[0];
}
Node *pop()
{
if(index==-1)
return NULL;
Node *temp=p[0];
for(int i=0;i<index;i++)
p[i]=p[i+1];
index--;
return temp;
}
};
Node * createNode(int data)
{
Node *p=new Node();
p->data=data;
p->left=p->right=NULL;
return p;
}
///////Insertion Of Node////////
int insertNode(int val)
{
if(root==NULL)
{
root=createNode(val);
return val;
}
bool found=false;
Node *p;
Queue q;
q.add(root);
while(found==false)
{
Node *l=(q.peek())->left;
Node *r=(q.peek())->right;
if(l==NULL)
{
(q.peek())->left=createNode(val);
found=true;
return val;
}
else
q.add(l);
if(r==NULL)
{
q.peek()->right=createNode(val);
found=true;
return val;
}
else
q.add(r);
q.pop();
}
return val;
}
/////////Traversal's///////////
void levelOrder(Node *p)
{
if(p==NULL)
return;
Queue q;
q.add(p);
while(true)
{
cout<<q.peek()->data<<" ";
if(q.peek()->left!=NULL)
q.add(q.peek()->left);
if(q.peek()->right!=NULL)
q.add(q.peek()->right);
if(q.pop()==NULL)
return;
}
}
int main()
{
root=NULL;
insertNode(1);
insertNode(2);
insertNode(3);
insertNode(4);
levelOrder(root);
return 0;
}
After you have popped the last element from the queue, you q.peek()->data on the next iteration, when q.peek() is not a valid pointer.
Change your termination condition:
while (q.peek())
{
cout<<q.peek()->data<<" "<< endl;;
if(q.peek()->left!=NULL)
q.add(q.peek()->left);
if(q.peek()->right!=NULL)
q.add(q.peek()->right);
q.pop();
}
On a side note, this is one situation where a "loop-local" variable can improve readability - all those peeks add clutter:
while(Node *next = q.pop())
{
cout<<next->data<<" "<< endl;;
if(next->left != nullptr)
q.add(next->left);
if(next->right != nullptr)
q.add(next->right);
}

In my BST implementation,my findNode function not returning parent location to its calling function

While implementing Binary search tree, i tried to have a custom find member function (findNode), which can provide me node location as well as parent location, But it failed to return it to calling function.
While implementing Binary search tree, i tried to have a custom find member function (findNode), which can provide me node location as well as parent location.
If i check inside findNode, it is able to find parent location. But it failed to return it to calling function.
#include<iostream>
using namespace std;
struct node
{
struct node* left;
int data;
struct node* right;
};
typedef struct node myNode;
class myTree
{
myNode* root;
void inorderUtil(myNode* rt);
public:
myNode* createNode(int num);
myTree():root(NULL){};
void inorder();
//void postorder();
//void preorder();
void findNode(int num,myNode* par,myNode* loc);
void insertNode(int num);
void displayroot(){cout<<root->data<<endl;}
};
void myTree::inorder()
{
inorderUtil(root);
}
void myTree::inorderUtil(myNode* rt)
{
if(rt != NULL)
{
inorderUtil(rt->left);
cout<<rt->data<<endl;
inorderUtil(rt->right);
}
}
myNode* myTree::createNode(int num)
{
myNode* nd= new myNode();
nd->data=num;
nd->left=NULL;
nd->right=NULL;
return nd;
}
void myTree::findNode(int num,myNode* par,myNode* loc)
{
cout<<"Searching for "<<num<<endl;
if(root==NULL)
{
par=NULL;
loc=NULL;
//cout<<"tree is empty"<<endl;
return;
}
if(root->data==num)
{
par=NULL;
loc=root;
return;
}
//cout<<"tree is non empty and data not at root"<<endl;
myNode* r=root;
par=root;
loc=NULL;
while((r->left != NULL) || (r->right != NULL))
{
if(r->left!=NULL && (r->left->data ==num))
{
par=r;
loc=r->left;
break;
}
else if(r->right!=NULL && (r->right->data ==num))
{
par=r;
loc=r->right;
break;
}
else
{
par = r;
if(num < r->data)
r = r->left;
else
r = r->right;
}
}
cout<<"parent is ="<<par->data<<endl;
}
void myTree::insertNode(int num)
{
myNode* par=NULL;
myNode* loc=NULL;
findNode(num,par,loc);
if(par !=NULL)
{
cout<<"in insert parent is ="<<par->data<<endl;
}
if(loc != NULL)
{
cout<<num<<" is already in tree, Aborting insertion "<<endl;
}
else
{
myNode *nd= createNode(num);
if(par == NULL)
{
root=nd;
}
else
{
if(par->left == NULL && par->data >num)
par->left =nd;
if(par->right == NULL && par->data <num)
par->right =nd;
}
}
}
int main()
{
myTree tr;
tr.insertNode(50);
tr.displayroot();
myNode* par=NULL;
myNode* loc=NULL;
tr.findNode(40,par,loc);
if(par!=NULL)
{
cout<<"parent from main is=="<<par->data<<endl;
}
return 0;
}
It should print below line as well:-
parent from main is==
You seem to have forgotten that arguments in C++ by default are passed by value. That means the value of the argument is copied into the local variable of the function.
If you want to give back a value to the caller, either return it (like e.g. std::pair<myNode*, myNode*>) or pass the pointers by reference (e.g. myNode*& par).

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.....