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.
Related
First post but I have been a lurker for some time now :)
First, I am attempting to execute this skeleton code in Visual Studio 2015 and it should work as is according to my teacher so I am not sure what else could be wrong client side that may be causing that.
Finally, the overall issue here is I am not sure how to complete the remain commands. I understand the basic concepts of how the pointer to pointers work as well as the linked lists but not completely. My first issue is not helping either.
Any help would be greatly appreciated.
Thanks,
Several
#include <stdio.h>
#include <stdlib.h>
typedef struct _node {
int value;
struct _node *next;
} node;
void append(node**, int);
void prepend(node**, int);
void lprint(node*);
void destroy(node*);
int main(int argc, char **argv)
{
node *head = NULL;
append(&head, 1);
append(&head, 2);
append(&head, 3);
prepend(&head, 0);
prepend(&head, -1);
prepend(&head, -2);
lprint(head);
destroy(head);
return 0;
}
void append(node **head, int value)
{
if (*head == NULL)
{
*head = (node*)calloc(0, sizeof(node));
(**head).value = value;
}
else
{
node *temp;
for (temp = *head; (*temp).next != NULL; temp = temp->next);
(*temp).next = (node*)calloc(0, sizeof(node));
(*temp).(*next).value = value;
}
}
void prepend(node **head, int value)
{
}
void lprint(node *head)
{
node *temp;
for (temp = head; temp != NULL; temp = temp->next)
{
printf("%d ", temp->value);
}
printf("\n");
}
void destroy(node *head)
{
}
I was able to compile and run your code after changing this line:
(*temp).(*next).value = value;
to this:
(*temp).next->value = value;
When I ran it, it printed out:
1 2 3
... which is what I would expect, given that prepend() isn't implemented.
I could write an implementation of prepend() and post it here, but I don't want to risk doing your homework for you; instead I'll just describe how prepend() ought to work.
For the case where head is NULL, prepend() can do the exact same thing that append() does: allocate a node and set head to point to that node.
For the other case, where head is non-NULL (because the list is non-empty), it's pretty easy too -- even easier than the append() implementation. All you need to do is allocate the new node, set the new node's next pointer to point to the existing head node (*head), and then set the head pointer (*head) to point to the new node.
The destroy() function can work with a loop very similar to the one in your lprint() function, with one caveat -- you have to grab the next pointer out of a given node (and store it into a local variable) before you free() the node, because if you free the node first and then try to read the next-pointer from the already-freed node, you are reading already-freed memory which is a no-no (undefined behavior) and will cause bad things (tm) to happen.
I want to say that I just started learning C++ and I'm having a fairly good grip on just insertion, deletion, reversing, finding the element and element in a position. I've tried to sort using Bubble Sort(?) and the program is crashing. Please help me.
struct node
{
int data;
struct node* link;
};
typedef struct node* NODE;
NODE rearr(NODE root)
{
NODE temp=root;
while(temp!=NULL)
{
NODE curr=temp;
while(curr!=NULL)
{
if(curr->data>(curr->link)->data)
{
int temp1=curr->data;
curr->data=(curr->link)->data;
(curr->link)->data=temp1;
}
curr=curr->link;
}
temp=temp->link;
}return root;
}
There are insert and delete functions too, but I haven't copied here. If you want, I'll post the whole program.
You never test to see if curr->link is null or not. Which causes a fault when you check its data memeber.
if(curr->link != NULL && curr->data>(curr->link)->data)
I am writing a function to delete the last node in a linked list. This is what I have, and other code I've found online searching for a solution is very similar (I have found several), but when I execute it it creates some sort of infinite loop when deleting the last element of a linked list (it deletes other elements just fine though).
Here is the code I imagine is causing a problem:
void delete_final(Node* head){
if(head == NULL) {
return; }
if(head->next == NULL) {
delete head;
head = NULL;
return;
}
//other code
}
I imagine it's an issue with the memory (particularly after the delete head; statement), but I'm really stuck and would appreciate any help or an explanation for why this doesn't work (I possibly don't have a very good understanding of pointers and memory in C++, I'm just starting with it)
Here is my Node code for reference:
struct Node {
int key;
Node* next;
};
Thanks for any help!
Original code:
void delete_final(Node* head){
if(head == NULL) {
return; }
if(head->next == NULL) {
delete head;
head = NULL;
return;
}
//other code
}
The "other code" is not specified, but if the list has exactly one node then the above code will
delete that first node, and
update the local pointer head, which doesn't update the actual argument since it was passed by value.
As a result the calling code will be left with a dangling pointer in this case, a pointer pointing to a destroyed object, or to where such an object once was. Any use of such a pointer is Undefined Behavior. It might appear to work, or crash, or just silently cause dirty words tattoo to appear on your forehead – anything…
One fix is to pass the first-pointer by reference:
void delete_final(Node*& head){
if(head == nullptr) {
return; }
if(head->next == nullptr) {
delete head;
head = nullptr;
return;
}
//other code
}
A nice helper function for dealing with linked lists, is unlink:
auto unlink( Node*& p )
-> Node*
{
Node* const result = p;
p = p->next;
return result;
}
The implementation is perhaps a bit subtle, but all you need to remember to use it is that it updates the pointer you pass as argument, which should be either a first-node pointer or a next pointer in the list, and returns a pointer to the unlinked node.
So e.g. you can do
delete unlink( p_first );
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. :)
I have a function that creates a binary tree(*build_tree)* (Huffman).
I also need a function that free's the memory that build tree allocated.
It's my first time working with binary trees so I'm kind of confused.
Should I create a loop that goes through each node in the tree and deletes it?
Should I consider if the node is a leaf or a parent node?
void free_memory(NodePtr root)
{
delete root;
}
struct HuffmanNode
{
//some stuff
HuffmanNode *left;
HuffmanNode *right;
};
Would appreciate it if someone could help me get started :)
If you use smart pointers the problem will solve itself. If each node contains a private SP to it's children and you delete a node all it's children will also be freed. Obviously your class destructor, which will get called by the SP when it cleans up will need to free any other non RIIA allocated resources if any exist.
class Node
{
private:
std:unique_ptr<Node> left;
std:unique_ptr<Node> right;
}
I'm using std::unique_ptr<> here because I'm assuming that these are private and not exposed to other parts of your program. If you want other things to reference nodes using these pointers then you should use std::shared_ptr<>.
If you're not using SP then the class destructor needs to do the work itself and you have to be much more careful about memory leaks. Each class destructor deletes its children, which in turn will call the destructor in each child.
class Node
{
private:
NodePtr left;
NodePtr right;
~Node()
{
delete left;
delete right;
// Delete any other resources allocated by the node.
}
}
You can also do as #OldProgrammer suggests and traverse the tree bottom up deleting nodes as you go. Remember you have to do this bottom up. If you did it top down then you would loose the reference to the (as yet) undeleted child nodes and leak memory. As you can see the code for recursive deletion (as referenced in #unluddite's answer) is a lot more complex.
There is a memory overhead for doing (anything) recursively. See: Is a recursive destructor for linked list, tree, etc. bad?. If your tree is very large then you should consider this and test accordingly.
My recommendation would be for the first solution if you are OK with using SP.
If you implement a post-order tree traversal and delete the node and data at the process step, you will ensure that each node of your tree is visited and the data deleted.
You can see a recursive and iterative example here with the relevant code reproduced below.
Recursive solution:
void postOrderTraversal(BinaryTree *p) {
if (!p) return;
postOrderTraversal(p->left);
postOrderTraversal(p->right);
// this is where we delete
delete p->data;
delete p;
}
One possible iterative solution:
void postOrderTraversalIterative(BinaryTree *root) {
if (!root) return;
stack<BinaryTree*> s;
s.push(root);
BinaryTree *prev = NULL;
while (!s.empty()) {
BinaryTree *curr = s.top();
if (!prev || prev->left == curr || prev->right == curr) {
if (curr->left)
s.push(curr->left);
else if (curr->right)
s.push(curr->right);
} else if (curr->left == prev) {
if (curr->right)
s.push(curr->right);
} else {
// this is where we delete
delete curr->data;
delete curr;
s.pop();
}
prev = curr;
}
}