Displaying elements of a Generic Tree - c++

I am trying to display all elements of this Generic Tree, in the fashion -
NodeData --> (list of all the children data)
According to the input given, my output should be-
10-->5,6
5-->4,1
6-->
4-->
1-->
I am unable to figure out what is going wrong, my o/p is only 10--> for some reason.
I've written a recursive code for printing the generic tree. Please help me out..
My code is :
using namespace std;
class Node
{
public:
int data;
vector<Node> children;
};
void printTree(Node *node)
{
cout<<node->data<<"-->";
for(auto x:node->children)
cout<<x.data<<",";
cout<<endl;
for(auto x:node->children)
printTree(&x);
}
int main()
{
int a[]={10,5,4,-1,1,-1,-1,6,-1};
int n=sizeof(a)/sizeof(a[0]);
stack<Node> s;
Node root;
for(int i=0;i<n;i++)
{
if(a[i]==-1)
s.pop();
else
{
Node temp;
temp.data=a[i];
if(s.size()==0)
{
root=temp;
}
else
{
s.top().children.push_back(temp);
}
s.push(temp);
}
}
printTree(&root);
return 0;
}````

To print your tree you need to have a pointer to the top of the tree which is what root is meant to be. To fix root so that it can reference the top of the top tree, make root to a pointer type (Node *). Then when you set root = &temp, root will point to the top of your tree rather than just a copy of the top node.
Your code declares root as an un-instantiated object. As such, root = temp triggers a shallow copy of temp into root at the time of execution. After the copy is done, changes to temp are not reflected in root because they are distinctly separate objects. Although it should be noted that if the objects were to have pointer type properties, then the pointers would be copied and thus both object would have a separate pointer to the same memory space.

Related

Why do I need to use queue<TreeNode**>q and cannot use queue<TreeNode*>q?

I am moderately new to coding so I would appreciate some help especially when I have no one to ask and only have books and YouTube to consult.
This is my code for a function that makes a binary tree in level order from the given string. I did a lot of trial and error to figure this out.
My question is why does this code only work when the queue contains addresses of pointers i.e. queue is queue<TreeNode**>q and not when it is made up of pointers i.e. queue<TreeNode*>q.
NOTE: While using queue<TreeNode*>q I will obviously use the necessary practices of storing root in it instead of &root.
I feel like the second case (queue<TreeNode*>q) should also work since it is pointers and not the actual object being stored. So it should work with the same logic of storing left and right.
TreeNode* deserialize(string data) {
if(data=="#,"){return {};}
stringstream a(data);
string temp;
vector<string>token;
while(getline(a, temp, ','))
{token.push_back(temp);}
TreeNode* root=NULL;
queue<TreeNode**>q;
q.push(&root);
for(int i=0;i<token.size();i++)
{
if(token[i]!="#")
{
(*q.front())=new TreeNode(stoi(token[i]));
q.push(&(*q.front())->left);
q.push(&(*q.front())->right);
}
q.pop();
}
return root;
}
};
With the current code and using queue<TreeNode**>q;, what happens essentially is that I am taking a number and storing it in the TreeNode and then pushing that TreeNodes left and right child in the queue. The end result is a connected tree.
When done with queue<TreeNode*>q, the same thing DOES NOT result in the nodes connecting.
what you have done is, you are pushing the address of root in the queue in line q.push(&root) ,instead of only root. That's why it requires double pointer. Refer to the code below:
TreeNode* deserialize(string data) {
if(data=="#,"){return {};}
stringstream a(data);
string temp;
vector<string>token;
while(getline(a, temp, ','))
{token.push_back(temp);}
TreeNode* root=NULL;
queue<TreeNode*>q;
q.push(root);
for(int i=0;i<token.size();i++)
{
if(token[i]!="#")
{
(q.front())=new TreeNode(stoi(token[i]));
q.push(q.front()->left);
q.push(q.front()->right);
}
q.pop();
}
return root;
}
};
Change these lines also:
if(token[i]!="#")
{
(*q.front())=new TreeNode(stoi(token[i]));
q.push(&(*q.front())->left);
q.push(&(*q.front())->right);
}
q.pop();
Refer the code above

Data Structure in C++. insertion in the beginning of the node in linked list

I am learning data structures in C++. This is a simple program for insertion
using links and nodes. The insertion takes place at the beginning of the node.
I do not understand some parts of the code.
In the function display() the pointer np points to the inserted info and then takes the value of the previous info using the next node. The next pointer is pointing to the previous info using the insert_beginning() function.
Displaying is done using the while loop. How does the next pointer change its value during each loop?
PS: The program runs fine.
#include<iostream>
#include<process.h>
#include<cstdlib>
using namespace std;
struct node
{
int info;
node *next;
}*start,*newptr,*save,*ptr;
node *create_new_node(int);
void insert_beg(node*);
void display(node*);
/*----------------------------------------------------------------------------------------------------------------------------
The pointer 'start' points to the beginning of the list.
Function 'create_new_node()' takes one integer argument , allocates memory to create new node and returns
the pointer to the new node.(return type: node*)
Function 'insert_beg()' takes node* type pointer as an argument and inserts this node in the beginning of the list.
Function display takes node* type pointer as an argument and displays the list from this pointer till the end of the list
------------------------------------------------------------------------------------------------------------------------------
*/
int main()
{
start=NULL;
int inf;
char ch='y';
while(ch=='y'||ch=='Y')
{
system("cls");
cout<<"enter information for the new node ";
cin>>inf;
cout<<"\ncreating new node. Press enter to continue ";
system("pause");
newptr = create_new_node(inf);
if(newptr!=NULL)
{
cout<<"\nnew node created successfully. Press enter to
continue. ";
system("pause");
}
else
{
cout<<"\nCannot create new node. ABORTING!! ";
exit(1);
}
cout<<"\nnow inserting this node in the beginning of the list.
Press enter to continue ";
system("pause");
insert_beg(newptr);
cout<<"\nNow the list is \n";
display(start);
cout<<"\nPress 'Y' to enter more nodes, 'N' to exit\n";
cin>>ch;
}
return 0;
}
node *create_new_node(int n)
{
ptr=new node;
ptr->info=n;
ptr->next=NULL;
}
void insert_beg(node *np)
{
if(start==NULL)
start=np;
else
{
save=start;
start=np;
np->next=save;
}
}
void display(node *np)
{
while(np!=NULL)
{
cout<<np->info<<" ->";
np=np->next;
}
cout<<"!!!\n";
}
To cut the long story short - per my understanding, your basic question is:-
display is done using the while loop. how does the next pointer change
its value during each loop??
This happens precisely in this line:-
np=np->next;
You are basically advancing the pointer to the node structure to another node structure whose address is in next member of the first node structure. This is text book stuff and any basic algo book should cover this thoroughly
HTH!
Your question is somewhat unclear. Especially because you state that:
PS:the program runs fine.
which it for sure does not. There is a bug that simply means this program will not work.
The problem is that create_new_node is not returning the pointer value
node *create_new_node(int n)
{
ptr=new node;
ptr->info=n;
ptr->next=NULL;
return ptr; // This line is missing
}
Besides that it is a really bad idea to use global pointer variables!
Here
struct node
{
int info;
node *next;
}*start,*newptr,*save,*ptr;
you define the struct node but you also define 4 variables, i.e. 4 pointers to node. These variables will be global, i.e. available in all your code. Something that you should never do.
Instead make local variables as needed - for instance:
node *create_new_node(int n)
{
node *ptr; // Local variable instead of global
ptr=new node;
ptr->info=n;
ptr->next=NULL;
return ptr;
}
Then for the insert_beg change it so that it returns a new start pointer - like:
node* insert_beg(node* start, node *np)
{
np->next=start;
return np;
}
and use it in main like:
node* start = NULL;
...
...
start = insert_beg(start, newptr);
BTW - In modern C++ you would never use raw pointers and you would never write your own list. Use smart pointers instead of raw pointer. Use the standard containers instead of writing your own.

Geting Data from a Tree Structure

I have a tree structure that i am creating the following way. The tree is created correctly as far as i know. But when i want to get the data from a node, i get some weird acsii symbols.
How I set the data.Lets say its empty. Doesn't matter at the moment. I have a value in my program. The function feeds itself until i get to the end of the data.
struct Node {
char Data;
Node* Left;
Node* Right;
};
Node maketree(0,s,split)
{
Node node;
node.Data=' ';
Node n1=subsplit(0,s,splitingat);
Node n2= subsplit(1,splitingat+1,e);
node.Left=&n1;
node.Right=&n2;
return node;
}
This is how i get data from the tree.
char decode(Node node,string text)
{
int currentindex=0;
Node sub=node;
{
}
if(text[currentindex]=='0')
{
sub=*sub.Left;
cout<<" x "<<sub.Data<<endl;
}
else if(text[currentindex]=='1')
{
sub=*sub.Right;
cout<<" x "<<sub.Data<<endl;
}
// cout<<sub.Data<<endl;
}
I think that the mistake is that I am printing out the pointer and not the node. But I don't know where I went wrong.
The source of your problem appears to be here:
Node node;
node.Data=' ';
Node n1=subsplit(0,s,splitingat);
Node n2= subsplit(1,splitingat+1,e);
node.Left=&n1; // danger Will Robinson!
node.Right=&n2;
return node;
You're taking the addresses of local, temporary, automatic variables and storing them in pointers that you return through node. As soon as that return executes, n1 and n2 are destroyed and node.Left and node.Right are left pointing to garbage. You may be able to fix this like so:
Node* n1=new Node(subsplit(0,s,splitingat));
Node* n2=new Node(subsplit(1,splitingat+1,e));
// side note: probably better to have subsplit() return dynamically-allocated Node*s to avoid the copy
node.Left=n1;
node.Right=n2;
but you may still have issues crop up if similar things are being done elsewhere.
Kind of along the same lines, in your second block of code, you are making a copy of each node you examine and storing it into sub. It would probably make more sense to have sub be a Node*.
And finally, to avoid memory management issues (almost) altogether, use shared_ptr<Node> instead of Node* in all of the above. :)

Use Binary-Tree in Template as Priority queue

So i want to make a code, that creates a binary tree, that holds data, for example ints like 1,6,2,10,8 and on pop i get the biggest number, and after that it gets deleted from the tree, and on push i can insert a new element. And this should be in a template so i can easy change the data type i want to hold in the tree. Now i got the tree so far, without template it is working fine thought, i can add items, and i can print them, but when i try to put it in a template, i get the following error: use of class template requires template argument list . What could be the problem? Maybe i am doing it totally wrong. Any suggestions are welcome.
This was my first question it got fixed by avakar ty. (i will post the code at the end of my question)
I just read trough the project request , and its like, i have to make this thing i above in the first part of question described, but its like the binary tree should represent a priority queue. And that is why in the request is written that i have to use push to put a new element in the tree by priority order and with pop i will get the element with the highest priority and then that element will be deleted. So how could i use my Tree as a Priority queue, or is he already one(i think not but who knew)? I hope i could explain it.
And here is the code as promised:
#include <iostream>
using namespace std;
template<class T>
class BinaryTree
{
struct Node
{
T data;
Node* lChildptr;
Node* rChildptr;
Node(T dataNew)
{
data = dataNew;
lChildptr = NULL;
rChildptr = NULL;
}
};
private:
Node* root;
void Insert(T newData, Node* &theRoot)
{
if(theRoot == NULL)
{
theRoot = new Node(newData);
return;
}
if(newData < theRoot->data)
Insert(newData, theRoot->lChildptr);
else
Insert(newData, theRoot->rChildptr);;
}
void PrintTree(Node* theRoot)
{
if(theRoot != NULL)
{
PrintTree(theRoot->lChildptr);
cout<< theRoot->data<<" ";;
PrintTree(theRoot->rChildptr);
}
}
public:
BinaryTree()
{
root = NULL;
}
void AddItem(T newData)
{
Insert(newData, root);
}
void PrintTree()
{
PrintTree(root);
}
};
int main()
{
BinaryTree<int> *myBT = new BinaryTree<int>();
myBT->AddItem(1);
myBT->AddItem(7);
myBT->AddItem(1);
myBT->AddItem(10);
myBT->AddItem(4);
myBT->PrintTree();
}
If you want to use the binary tree as a priority queue, you extract the maximum element by stepping only through right child pointers. Any left child would be smaller than the current element. So you record the value of that node and then remove it -- you would still have to write a node deletion routine.
The problem with a simple BST is that it can become unbalanced and send your complexities to O(n). You can use a self-balancing BST, but it's unusual for priority queues. Instead of BSTs they are usually heaps, as Kerrek said.
The simplest heap implementation that I know personally is the binary heap. The binary heap is theoretically a type of binary tree although not stored as such. So, depending on whether you had to implement a BST or just a binary tree, it might fit your requirements.
On this line:
BinaryTree<int> *myBT = new BinaryTree();
You need to also specify the type of template you want to instantiate on the right side of the assignment:
BinaryTree<int> *myBT = new BinaryTree<int>();
Because BinaryTree is not a BinaryTree<int>; one is the name of a template (BinaryTree) and one is the name of a specific type of that template (BinaryTree<int>). You can't create instances of plain templates, you have to give it the type of template you want to use all the time.

Basic C++ programming question

I am in process of learning c++. I am working on creating a linkedlist data structure. One of the functions that displays the values of nodes in the structure does not work. For some reason the while loop that traverses through nodes doesn't work in the display function, hence I can't see the values in those nodes. Does anyone see what the problem is? I've been staring at the code for a while and not sure what is wrong here.
Thanks for your help in advance.
Header:
// linklist.h
// class definitions
#ifndef LINKLIST_H
#define LINKLIST_H
class linklist
{
private:
// structure containing a data part and link part
struct node
{
int data;
node *link;
}*p;
public:
linklist();
void append(int num);
void addatbeg(int num);
void addafter(int loc, int num);
void display();
int count();
void del(int num);
~linklist();
};
#endif
.cpp file
// LinkedListLecture.cpp
// Class LinkedList implementation
#include"linklist.h"
#include<iostream>
using namespace std;
// initializes data member
linklist::linklist()
{
p =NULL;
}
// adds a node at the end of a linked list
void linklist::append(int num)
{
node *temp, *r;
// if the list is empty, create first node
if(p==NULL)
{
temp = new node;
temp->data = num;
temp->link = NULL;
}
else
{
// go to last node
temp = p;
while(temp->link!=NULL)
temp = temp->link;
// add node at the end
r = new node;
r->data=num;
r->link=NULL;
temp->link=r;
}
}
// displays the contents of the linked list
void linklist::display()
{
node *temp = p;
cout<< endl;
// traverse the entire linked list
while(temp!=NULL) // DEBUG: the loop doesn't work
{
cout<<temp->data<<" ";
temp = temp->link;
}
void main()
{
linklist l;
l.append(14);
l.append(30);
l.append(25);
l.append(42);
l.append(17);
cout<<"Elements in the linked list:";
l.display(); // this function doesn't work
system("PAUSE");
}
You never set p to a non NULL value.
if(p==NULL)
{
p = new node;
p->data = num;
p->link = NULL;
}
I think GWW has highlighted the issue, but part of learning to program it to learn how to identify the mistakes.
If you do something and don't get the expected result you could:
Use the visual c++ debugger to step through and see the values of your variables.
Put in log lines to report information you think is important
inspect the code - if you think something is right but it doesn't work, then go to an earlier step and check it does the right thing.
Add unit tests, or follow design by contract adding pre/post conditions and class invariants.
Learning to program C++ by writing a linked list is like learning math by adding 1 + 1. It is old fashioned thinking, slow and mostly boring without having any context.
Math isn't calculating, like C++ programming isn't pointer manipulation. At some stage you might need to know about it, but your better off learning other important things like stl and boost.
If it was understood that append() ment create something, find the end of the list, add it. you could then see that in you append function you have create something mixed uyp with move to the end of the list, but you never add it.