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. :)
Related
Why is head is going to some random value?
// Simple insertion at the starting of link list
#include<iostream>
using namespace std;
struct node{
int d;
node *next;
}; // creation of node
node *head=new node; // is there any problem?
void insert(int x)
{
if (head==NULL) { // is there something wrong?
head->d=x;
haad->next=NULL;
} else {
node *t=new node;
t->d=x;
t->next=head;
head=t;
}
}
int main() {
insert(1); // function calling
insert(2); // function calling
insert(3); // function calling
while(head!=NULL) {
cout<<head->d<<" ";
head=head->next;
} // this is going on to infinity
return 0;
}
This code is lopping till infinity and I am not able to understand why?
Why is head going to some random value after 3 2 1? Is there any problem in declaring head globally?
head is going to some random value because the last element in your list is pointing with next to a random value.
This last element is the first node you created in this line:
node *head=new node;
By doing that, you are allocating memory for this node on the heap, however, you're not setting any values to the node's fields, including next. Then in the loop, when head is pointing to the last node (that was allocated first) head->next is not NULL and therefore the loop continues.
Three side notes:
Using head itself to iterate over the list elements is not a good idea since you're losing the pointer to the head of the list.
head can be declared globally but usually you should have a good reason for that. In your program I'd define it in main() and pass it to the functions that need it.
This code:
if (head==NULL) { // is there something wrong?
head->d=x;
haad->next=NULL;
doesn't make lots of sense: it will never run, and in case it will --> segmentation fault (because if head is NULL you cannot refer to its fields.
Hope it helps.
Hi I read this logic over internet and tried implementing the level order tree traversal in c++
void levelorder(struct node* root)
{
struct node* temp = (struct node*)malloc(sizeof(struct node));
std::queue<node*> qq;
if(root==NULL)
{
return;
}
qq.push(root);
while(!qq.empty())
{
temp=qq.front();
qq.pop();
printf("%d",temp->data);
qq.push(temp->left);
qq.push(temp->right);
}
}
But the above is giving me an error segmentation fault which I think is happening because
temp->left
does not exist. Or should i need llQueue for this implementation.Anybody has any idea about this ?
Ths posted code does not take into account the null pointers at the leaves of the tree. It can be fixed along these lines:
void levelorder(struct node* root)
{
std::queue<node*> qq;
qq.push(root);
while(!qq.empty())
{
struct node* node = qq.front();
qq.pop();
if (node) {
printf("%d",temp->data);
qq.push(temp->left);
qq.push(temp->right);
}
}
}
On the other hand, the memory allocation to temp is lost: This space is not freed and, moreover, will leak, as temp is assigned to somethig else.
Two problems:
the memory allocated for temp is leaked and non-necessary
null pointer at leaf nodes not checked
The implementation proposed by #anumi is correct. But I'd prefer this:
void levelorder(struct node* root)
{
if(!root) return;
std::queue<node*> qq;
qq.push(root);
while(!qq.empty())
{
struct node* node = qq.front();
qq.pop();
printf("%d", node->data);
if(node->left) qq.push(node->left);
if(node->right) qq.push(node->right);
}
}
Edit: handle empty tree according to comments.
Your idea seems correct, however this is impossible to tell without knowing the actual data. In your code, it might be possible that the left and right members are NULL or point to undefined locations, which means that following the left or right pointers might result in errors.
I'm attempting to print the nodes in a linked list (forwards direction).
It's defined as follows:
struct Node {
string val;
Node* next;
Node* prev;
};
struct Stew {
Node* first;
Node* last;
};
Where Stew has two special pointers, one pointing to the first element, and one to the last.
I'm positive that what I attempted is correct, but it's actually not.
void print (const Stew& q, char direction) {
assert (!isEmpty(q));
{
Node* current = new Node;
current = q.first;
cout << current -> val;
while((current -> next) != NULL)
{
current = current -> next;
cout << (current -> val);
}
delete current;
}
I know there's a logic mistake in there, but I can't seem to pinpoint it. Any help would be appreciated.
Why do you do not read answers on your question? I already showed you how to print the list in the direct and reverse order. See here.
Implementing a push function in c++
I think your problem might be that you are treating your current pointer like it is an object. Current is a pointer that simply points to another object in memory. Hence your line Node *current = new Node is meaningless and you are losing that Node in memory. Your problem is probably the last line where you delete current. Current is pointing to the last item in your list and when you call delete you are freeing the memory current points to. Hence you are deleting the last object in your list. You only need to use delete when you are creating an object in memory, and current should not be a new item it should be a pointer to existing memory.
First:
Node* current = new Node;
That is totally unnecessary. You don't want to create a new node from the heap. All you want to do is point current node to the head node:
Node* current = q.first;
Then assuming that current is a valid node, and the next pointer will either point to the next valid node or NULL to denote the end of the list, your while() loop is starting off wrong. It should be something like this:
while(current != NULL)
{
cout << current->val;
current = current->next;
}
And of course, remove the call to "delete" at the end.
I have a basic linked list problem that I have attempted to solve below. I would appreciate any inputs on my approach, correctness of the algorithm (and even coding style). The problem calls for a function that deletes all occurrences of an int in a circular linked list and returns any node from the list or NULL (when the list is null).
Here's some C++ code that I have so far:
struct Node{
Node* next;
int data;
};
Node* deleteNode(Node* &node, int num){
if(!node){
return NULL;
}
Node* given = node;
Node* del;
while(node->next != given){
if(node->next->data == num){
del = node->next;
node->next = node->next->next;
delete del;
}
node = node->next;
}
//Check if the first node needs to be deleted, with variable node pointing to last element
if(given->data == num){
node->next = given->next;
delete given;
}
return node;
}
The delete node; should be delete del;.
Also, use Node* node as parameter, instead of Node* &node which will prevent non-lvalues from passing in.
p.s. Forgot a semicolon after struct definition? :)
Without following all your logic I can see at a glance this code cannot work.
You are checking for the input list being empty and that's the only case in which your code returns NULL. But what happens if you are passed a list in which all elements must be deleted?
This problem also has a subtlety in it. To check if you completed a circular list you need to compare to the first address to see if you got linked back to the start. However if this element has been deleted then by C++ standard you're not even allowed to use its address in a comparison.
To avoid making two passes over the elements to be deleted one possible trick is to "break the loop" when starting iteration so you can check for NULL instead of checking for the address of the starting node.
// Variables
typedef struct node
{
int value;
struct node *next;
}mynode;
// Globals (not required, though).
mynode *head, *tail, *temp;
// Functions
void add(int value);
// Function to add new nodes to the linked list
void add(int value)
{
temp = (mynode *) malloc(sizeof(struct node));
temp->next=(mynode *)0;
temp->value=value;
if(head==(mynode *)0)
{
head=temp;
tail=temp;
}
else
{
tail->next=temp;
tail=temp;
}
}
// The main() function
int main()
{
head=(mynode *)0;
// Construct the linked list.
add(1);
add(2);
add(3);
return(0);
}
If I only have a pointer to a node, whose value is 3(The Last node as seen in the aforementioned code) , Can we delete it and make a node whose value is 2(aforementioned code) as the last node.
No you can not. Unless you have some reference to previous node. like head pointer. If you have other reference than its pretty much easier. In fact if you don't have any pointers you will loose the list itself
No, but if you know what you are doing, you can modify the last node in-place. Deleting the last node requires access to the second-to-last node, and specifically its link to the last node.
The answer is no.
You can call free on that pointer to the last node, but that just means that the memory occupied by that node is no longer claimed. The data will most likely stay there unchanged for a while. And that means that the next-to-last node's pointer to it is still valid, even though it should not be.
To delete the node in a way that is meaningful to the list, that pointer contained in the next-to-last node has to be nullified. And that can't be done unless that next-to-last node can be accessed, either by a direct pointer to it, or by traversing the list from a preceding node.
You can use a doubly linked list to access the previous node. Or iterate through the entire list.
Yes you can.. Try the following code:
void deleteNode()
{
mynode *temp1;
for(temp1 = head; temp->next!= tail; temp1 = temp1->next);
tail = temp1;
free(tail->next);
}
It will delete the last node.