Troubled with this binary tree code (in c++)? - c++

This is the code I am writing for insertion and inorder traversal of a binary tree. However I am kind of messed up now. Could you please help me in correcting this? The while loop in the insert-code is not getting anything getting inside into it. Thanks for your help.
#include<iostream>
#include<string>
using namespace std;
class binarynode
{public:
string data;
binarynode *left;
binarynode *right;
};
class tree
{
binarynode *root;
public:
tree()
{
root=new binarynode;
root=NULL;
}
binarynode* createnode(string value)
{
binarynode * temp;
temp=new binarynode;
temp->data=value;
temp->left=NULL;
temp->right=NULL;
return temp;
}
void insert(string value)
{//cout<<"entered 1"<<endl;
binarynode * nroot;
nroot=root;
while(nroot!=NULL)
{//cout<<"here 2"<<endl;
if(value> nroot->data )
{
// cout<<"here 3"<<endl;
nroot=nroot->right;
}
else
if(value<nroot->data)
{//cout<<"here 4"<<endl;
nroot=nroot->left;
}
}
nroot=createnode(value);
}
void inorder()
{
binarynode *nroot;
nroot=root;
printinorder(nroot);
}
void printinorder(binarynode * nroot)
{
//cout<<"entered 5"<<endl;
if(nroot->left==NULL&&nroot->right==NULL)
{
cout<<nroot->data<<" ";
}
printinorder(nroot->left);
cout<<nroot->data<<" ";
printinorder(nroot->right);
}
};
int main()
{
tree a;
int n;
cin>>n;
for(int i=0;i<n;i++)
{
string value;
cin>>value;
a.insert(value);
}
a.inorder();
}

You are assigning NULL to root in the constructor:
root = NULL;
so your while loop will never be entered.

Note that nroot=createnode(value); won't append a node to the tree. You can use double pointers for this.
Edit: as requested by yeldar
void insert(const std::string& value) {
binarynode **node = &root;
while (*node) {
if (value >= (*node)->data) {
node=&(*node)->right;
} else {
node=&(*node)->left;
}
}
*node=createnode(value);
}
Edit: not using double pointers
void insert(const std::string& value) {
if (root == NULL) {
root = createnode(value);
return;
}
binarynode *node = root;
binarynode *parent = NULL;
while (node) {
parent = node; // we should store the parent node
node = value >= parent->data ? parent->right : parent->left;
}
if (value >= parent->data) {
parent->right = createnode(value);
} else {
parent->left = createnode(value);
}
}

Related

This tree implementation is not showing any output

I have implemented a tree using classes in C++, but the program is not showing any output when I called display function. Can anyone spot the reason?
Output
#include<iostream>
using namespace std;
class TreeNode //node for tree
{
public:
int data;
TreeNode* left;
TreeNode* right;
TreeNode(int val)
{
data=val;
left=NULL;
right=NULL;
}
};
class Tree //class for tree
{
public:
TreeNode *r;
Tree()
{
r=NULL;
}
void insert(int data)
{
TreeNode* new_node=new TreeNode(data);
TreeNode*trav=r;
while(trav!=NULL)
{
if(data>trav->data)
{
if(trav->right==NULL)
{
trav->right=new_node;
break;
}
trav=trav->right;
}
else
{
if(trav->left==NULL)
{
trav->left=new_node;
break;
}
trav=trav->left;
}
}
}
void display()
{
print(r);
}
void print(TreeNode *node)
{
if(node!=NULL)
{
print(node->left);
cout<<node->data<<" ";
print(node->right);
}
}
};
int main() //main function
{
Tree T;
T.insert(10);
T.insert(1);
T.insert(2);
T.insert(100);
T.display();
}
At beginning, 'r' is not assigned, that is, 'r' is NULL pointer.
So In 'Insert' function, no values can be insert to Tree.
I think it is likely that the first input value is to be set as a default value. And then 'r' must be initialized at this point.
class Tree //class for tree
{
public:
TreeNode *r;
Tree()
{
r = NULL;
}
~Tree()
{
release(r);
}
void release(TreeNode * node)
{
if (node != NULL)
{
release(node->left);
release(node->right);
delete node;
node = NULL;
}
}
void insert(int data)
{
if (r == NULL)
{
r= new TreeNode(data);
return;
}
...
And you need to add logic to releasing the all memories allocated to 'r' in the destructor of the 'Tree' class.
Change the Tree constructor to something like this:
Tree(int root_data) {
r = new TreeNode(root_data);
r->left=NULL;
r->right=NULL;
}
And replace
Tree T;
with
int some_value;
Tree T(some_value);

Inserting into a Binary Tree (geeksforgeeks) recursively

I'm trying to implement the insertion function used on geeksforgeeks.com but am running into some problems trying to work it into my current code.
I have a vector with the data I need to put into the binary tree. I use this function to pass the numbers into the insertion function:
void populateTree(vector<string> dataVec) {
for (int i = 0; i < dataVec.size(); i++) {
insert(stoi(dataVec[i]), root);
}
}
This is the insertion function:
node* insert(int x, node* node) {
if (node == nullptr)
return newNode(x);
if (x < node->data)
node->left = insert(x, node->left);
else
node->right = insert(x, node->right);
return root;
}
New node function:
node* newNode(int num) {
node* temp = new node;
temp->data = num;
temp->left = temp->right = nullptr;
temp->level = 1;
return temp;
}
Root is a private member within the class which is initialized to nullptr. I'm not sure how I should go about making the first node that comes in from the vector as the root and then keep inserting things beginning from there recursively. Thanks!
The problem in your is related to use of pointer.
Instead of using node* insert(int x, node* node) you should use node* insert(int x, node** node) or node* insert(int x, node*& node) and adopt your code accordingly.
Following is corrected sample code. See it in execution here:
#include <iostream>
#include <vector>
using namespace std;
struct Node
{
int val;
Node* left;
Node* right;
Node(int v)
{
val = v;
left = right = nullptr;
}
};
class Tree
{
Node* root;
Tree()
{
root = nullptr;
}
public:
static void insert(int x, Node*& node)
{
if (node == nullptr)
{
node = new Node(x);
}
else
{
if (x < node->val)
insert(x, node->left);
else
insert(x, node->right);
}
}
static Tree* populateTree(vector<string> dataVec)
{
Tree* t= new Tree();
for (int i = 0; i < dataVec.size(); i++)
{
insert(stoi(dataVec[i]), t->root);
}
return t;
}
static void printTree(Node* node, string s)
{
if(node == nullptr) return;
cout<<s<< "+"<<node->val <<endl;
s += "----";
printTree(node->left,s);
printTree(node->right, s);
}
static void printTree(Tree* t)
{
if(t)
{
printTree(t->root, "");
}
}
};
int main() {
Tree* t = Tree::populateTree({"70", "2", "7", "20", "41", "28", "20", "51", "91"});
Tree::printTree(t);
return 0;
}

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

Search function returns the same regardless of item present in the binary search tree

Here is my code:
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
#include<process.h>
struct tree_node
{
tree_node *left;
tree_node *right;
int data;
char r;
} ;
class bst
{
tree_node *root;
public:
bst()
{
root=NULL;
}
int isempty()
{
return(root==NULL);
}
void insert(int item);
void inordertrav();
void inorder(tree_node *);
void postordertrav();
void postorder(tree_node *);
void preordertrav();
void preorder(tree_node *);
int search(tree_node * ,int);
};
void bst::insert(int item)
{
tree_node *p=new tree_node;
tree_node *previous;
p->data=item;
p->left=NULL;
p->right=NULL;
previous=NULL;
if(isempty())
root=p;
else
{
tree_node *current;
current=root;
while(current!=NULL)
{
previous=current;
if(item<current->data)
current=current->left;
else
current=current->right;
}
if(item<previous->data)
previous->left=p;
else
previous->right=p;
}
}
int bst::search(tree_node* root,int data) {
int r;
if(root == NULL) {
// r='f';
return 0;
}
else if (root != NULL){
if(root->data == data) {
// r='t';
return 1;
}
}
else if(data <= root->data) {
return search(root->left,data);
}
else {
return search(root->right,data);
}
}
void main()
{
int digit;
bst b;
tree_node *root;
/*b.insert(52);
b.insert(25);
b.insert(50);
b.insert(15);
b.insert(40);
b.insert(45);
b.insert(20); */
cout<<"insert the nodes in the BT";
cout<<"enter integer: to quit enter 0";
cin>>digit;
while (digit!=0)
{
b.insert(digit);
cin>>digit;
}
cout<<"inorder"<<endl;
b.inordertrav();
cout<<endl<<"postorder"<<endl;
b.postordertrav();
cout<<endl<<"preorder"<<endl;
b.preordertrav();
int number;
cout<<"Enter number be searched\n";
cin>>number;
//If number is found, print "FOUND"
int c;
c=b.search(root,number);
cout<<"returned value"<<c;
if (c==1) cout<<"Found\n";
else cout<<"Not Found\n";
getch();
}
The search function is always returning the same value whether it is in the BST or not.
Please help me to figure out the error.
The above code has no compilation error.
All other functions except search function are working fine.
But the search function is not working as required to search whether the element is in the Binary Search tree or not.
Your code invoke UB.
tree_node *root;
...
c=b.search(root,number); // root is uninitialized
To solve this add a new function:
class bst
{
...
int search(tree_node * ,int);
int search(int v) {
return search(root, v);
}
};
Also in bst::search function:
else //if (root != NULL){ Comment this condition
if(root->data == data) {
// r='t';
return 1;
}
//} Comment this line
This condition is not only redundant but also make some code flow paths return without value.

Making a template for BST class(different types of keys) in C++

I have written an implementation of BST-Tree but the key can be only string type. I would like to use that tree with other types of keys. I know that I would have to define a template, but do not know how to do it so the key will have T type. The examples show all but not important stuff.
using namespace std;
int ASCENDING = 0, DESCENDING = 1;
class Node {
public:
string key; //I would like to change type to T
Node* left;
Node* right;
Node(string key) {
this->key = key;
left = NULL;
right = NULL;
}
};
class BST {
public:
Node* root;
BST(string key) {
root = new Node(key);
}
void insert(string value){
if(root == NULL)
root = new Node(value);
else
insertHelper(root, value);
}
void insertHelper(Node* node, string value){
if(value < node->key){
if(node->left == NULL)
node->left = new Node(value);
else
insertHelper(node->left, value);
}
else{
if(node->right == NULL)
node->right = new Node(value);
else
insertHelper(node->right, value);
}
}
void print(int order){
show(order, root);
}
~BST(){
//delete all nodes
}
private:
void show(int order, Node* n){
Node* pom = n;
if(order == ASCENDING){
if(pom != NULL){
show(order, n->left);
cout<<n->key<<endl;
show(order, n->right);
}
}else{
if(pom != NULL){
show(order, n->right);
cout<<n->key<<endl;
show(order, n->left);
}
}
}
};
This should cover the basic setup and the rest of the changes should be similar:
template <typename T>
class Node {
public:
T key; //I would like to change type to T
^^^^^ Type now T
Node<T>* left;
Node<T>* right;
Node(T key) {
this->key = key;
left = NULL;
right = NULL;
}
};
template <typename T>
class BST {
public:
Node<T>* root;
^^^^^^^ Node now will become Node<T> in the rest of the code as well
BST(T key) {
root = new Node<T>(key);
}
// rest of code
};