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);
Related
I'm trying to traverse a binary tree inorder and the problem I'm trying to solve requires me to return one value at a time. The problem with binary tree traversal is that you get everything at once using recursion.Don't get me wrong, I want everything but not at once.
What I tried implementing an array to store every value and then loop through and get each value.
But this too does not seem to work, CPP is complaining that "undefined reference to `IPAddressAnalyzer::nodesArray'"
Here's a snippet of my code:
struct node
{
int address;
int count;
node* left;
node* right;
};
class IPAddressAnalyzer{
private:
node* root;
static node *nodesArray;
int arrayIndex = 0;
void destroy_tree(node *leaf);
void insert(int ip, int count, node *leaf);
void inorder_print(node *leaf);
And here's where I'm trying to use the array:
void IPAddressAnalyzer::inorder_print(node* leaf)
{
if(leaf != NULL)
{
inorder_print(leaf->right);
nodesArray[arrayIndex].address = leaf->address;
nodesArray[arrayIndex].count = leaf->count;
updateArrayIndex();
inorder_print(leaf->left);
}
}
Here's where I create the array, access the elements in the array and try to write to a file.
//Create the array
tree->createArray(intCounter);
tree->inorder_print();
//Traverse tree and write to a file
int rank =1;
int counter = 0;
int valueHolder = 0;
int nodeIndex = 0;
while (rank<=n){
node element = nodesArray[nodeIndex];
printf("Popped ip: %s count: %d\n", IPAddressToString(element.address), element.count);
if(counter == 0) {
fprintf(outFileStream, "%d, %s, %d\n", rank, IPAddressToString(element.address), element.count);
valueHolder = element.count;
counter++;
}
else if(element.count == valueHolder)
{
fprintf(outFileStream, "%d, %s, %d\n", rank, IPAddressToString(element.address), element.count);
}
else{
rank++;
if(rank>n)
break;
fprintf(outFileStream, "%d, %s, %d\n", rank, IPAddressToString(element.address), element.count);
valueHolder = element.count;
}
nodeIndex++;
}
Please note that I set the size of the array size in the main function before I use it.
Or, to put it simply, here's an example of what I want;
#include <iostream>
using namespace std;
struct node
{
int value;
node *left;
node *right;
};
class btree
{
public:
btree();
~btree();
void insert(int key);
void destroy_tree();
void inorder_print();
private:
void destroy_tree(node *leaf);
void insert(int key, node *leaf);
void inorder_print(node *leaf);
node *root;
};
btree::btree()
{
root = NULL;
}
btree::~btree()
{
destroy_tree();
}
void btree::destroy_tree(node *leaf)
{
if(leaf != NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
delete leaf;
}
}
void btree::insert(int key, node *leaf)
{
if(key < leaf->value)
{
if(leaf->left != NULL)
{
insert(key, leaf->left);
}
else{
leaf->left = new node;
leaf->left->value = key;
leaf->left->left = NULL;
leaf->left->right = NULL;
}
}
else if(key >= leaf->value)
{
if(leaf->right != NULL)
{
insert(key, leaf->right);
}
else
{
leaf->right = new node;
leaf->right->value = key;
leaf->right->right = NULL;
leaf->right->left = NULL;
}
}
}
void btree::insert(int key)
{
if(root != NULL)
{
insert(key, root);
}
else
{
root = new node;
root->value = key;
root->left = NULL;
root->right = NULL;
}
}
void btree::destroy_tree()
{
destroy_tree(root);
}
void btree::inorder_print()
{
inorder_print(root);
cout << "\n";
}
void btree::inorder_print(node *leaf)
{
if(leaf != NULL)
{
inorder_print(leaf->left);
cout << leaf->value << ",";
inorder_print(leaf->right);
}
}
int main(){
//btree tree;
btree *tree = new btree();
tree->insert(10);
tree->insert(6);
tree->insert(14);
tree->insert(5);
tree->insert(8);
tree->insert(11);
tree->insert(18);
tree->inorder_print();
delete tree;
}
This produces the following output at once:
5,6,8,10,11,14,18,
How can I get 5, then 6, then 8 etc, but each at a time, instead of all at once?
Any help offered will be appreciated!
CPP is complaining that "undefined reference to IPAddressAnalyzer::nodesArray"
This is probably because nodesArray is a static member variable, but you never declared storage for it. In some .cpp file, preferably one related to IPAddressAnalyzer, you should add the following line:
node *IPAddressAnalyzer::nodesArray;
But maybe just making it a non-static member would be even better.
I suggest you make use of the standard library instead of implementing your own tree structure, and use std::map and/or std::set instead. Your example of what you want can be rewritten like so:
#include <iostream>
#include <set>
int main(){
std::set<int> tree;
tree.insert(10);
tree.insert(6);
tree.insert(14);
tree.insert(5);
tree.insert(8);
tree.insert(11);
tree.insert(18);
for (auto &element: tree) {
std::cout << element << ',';
}
std::cout << '\n';
}
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).
I am learning c++ and tried a creating a Linked-List Data structure.
Here is the program-
main.cpp
#include <iostream>
using namespace std;
class LinkedList
{
public:
int data;
LinkedList *nextNode;
void init(int value,LinkedList *root)
{
root->data=value;
root->nextNode=NULL;
}
void add(int value,LinkedList *root)
{
LinkedList *temp=new LinkedList;
if(root->nextNode==NULL)
{
//cout<<"IF ADD()"<<endl;
temp->data=value;
temp->nextNode=NULL;
root->nextNode=temp;
}
else
{
//cout<<"else ADD()"<<endl;
while(root->nextNode!=NULL)
{
root=root->nextNode;
}
temp->data=value;
temp->nextNode=NULL;
root->nextNode=temp;
}
}
void display(LinkedList *root)
{
if(root->nextNode==NULL)
{
cout<<root->data<<endl;
}
else
{
while(root->nextNode!=NULL)
{
cout<<root->data<<endl;
root=root->nextNode;
}
}
}
void free(LinkedList *root)
{
if(root->nextNode==NULL)
{
delete root;
}
else
{
while(root->nextNode!=NULL)
{
LinkedList *temp=root->nextNode;
delete root;
root=temp;
}
}
}
};
int main()
{
LinkedList *root=new LinkedList;
root->init(1,root);
root->add(2,root);
root->add(3,root);
root->add(4,root);
root->add(5,root);
root->add(6,root);
root->add(7,root);
root->add(8,root);
root->add(9,root);
root->add(10,root);
root->display(root);
root->free(root);
//root->display(root);
//delete root;
return 0;
}
Output-
1
2
3
4
5
6
7
8
9
My question is why it doesn't print the last item i.e 10.
And one more question, as you can see I am commenting in the following line
//delete root
inside my main method.
What if I don't call my free() method and uncomment this? Would it free the whole LinkedList?
Thanks
Porblem is with this function in else statement it does not go to last node because last node's next will be NULL. One more thing is you are modifying the root in display function is should be a const function. It should not modify the root.
void display(LinkedList *root)
{
if(root->nextNode==NULL)
{
cout<<root->data<<endl;
}
else
{
while(root->nextNode!=NULL)
{
cout<<root->data<<endl;
root=root->nextNode;
}
}
}
Actual implementation should be like this.
void display(LinkedList *root) const
{
LinkedList * temp = root;
while(temp!=NULL)
{
cout<<temp->data<<endl;
temp=temp->nextNode;
}
}
Regarding your second question-> It won't clear the memory. But because its a small code after application close memory will be freed. It's always best practice to free memory otherwise you will have memory leaks and if this data structure is used heavily it can take all memory and crash the application.
Also implementation of your free function is not correct. It should be like this
void free(LinkedList *root)
{
LinkedList * temp = root;
LinkedList * nodeToFree = root;
while(temp!=NULL)
{
temp=temp->nextNode;
delete nodeToFree;
nodeToFree = temp;
}
}
while(root->nextNode!=NULL)
{
cout<<root->data<<endl;
root=root->nextNode;
}
should be
while(root!=NULL)
{
cout<<root->data<<endl;
root=root->nextNode;
}
change Condition of display
#include <iostream>
using namespace std;
class LinkedList
{
public:
int data;
LinkedList *nextNode;
void init(int value,LinkedList *root)
{
root->data=value;
root->nextNode=NULL;
}
void add(int value,LinkedList *root)
{
LinkedList *temp=new LinkedList;
if(root->nextNode==NULL)
{
//cout<<"IF ADD()"<<endl;
temp->data=value;
temp->nextNode=NULL;
root->nextNode=temp;
}
else
{
//cout<<"else ADD()"<<endl;
while(root->nextNode!=NULL)
{
root=root->nextNode;
}
temp->data=value;
temp->nextNode=NULL;
root->nextNode=temp;
}
}
void display(LinkedList *root)
{
if(root->nextNode==NULL)
{
cout<<root->data<<endl;
}
else
{
while(root !=NULL) // Change this condition
{
cout<<root->data<<endl;
root=root->nextNode;
}
}
}
void free(LinkedList *root)
{
if(root->nextNode==NULL)
{
delete root;
}
else
{
while(root->nextNode!=NULL)
{
LinkedList *temp=root->nextNode;
delete root;
root=temp;
}
}
}
Here you can display it one time only as you are changing its root value so it would be better if you use temp variable to display as done by #sanjay in above case.
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);
}
}
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.