I want to build a graph that creates a new parent node by merging two child nodes. The code below is supposed to merge node a and b into a parent node c. Then, nodes a and c to create a parent node d:
a b
|---|
|
a c
|---|
|
d
When I try to free the graph starting at node d I get a segmentation fault and I don't know why. Somehow it works if I don't use the same node twice in the graph. However, I want to be able to use the same node more than once. Can someone please tell me what am I missing here?
#include <stdlib.h>
struct Node {
int data;
struct Node *child1;
struct Node *child2;
};
struct Node *NewNode(double data) {
struct Node *node = NULL;
node = malloc(sizeof(*node));
if (node == NULL) {
return node;
}
node->data = data;
node->child1 = NULL;
node->child2 = NULL;
return node;
}
struct Node* merge(struct Node *self, struct Node *other) {
struct Node *node = NewNode(-1);
node->child1 = self;
node->child2 = other;
return node;
}
void free_graph(struct Node **node) {
if (*node != NULL) {
free_graph(&(*node)->child1);
free_graph(&(*node)->child2);
free(*node);
*node = NULL;
}
}
int main(void){
struct Node *a = NewNode(1);
struct Node *b = NewNode(2);
struct Node *c = merge(a, b);
struct Node *d = merge(a, c);
free_graph(&d);
}
It does not work because your "tree" does not match your illustration, and is in fact technically not a tree. What you have looks like this:
You need to make a copy instead of reusing a node if you want a tree.
In order to free everything in a graph like this, I'd suggest having a separate linked list to keep track of everything you need to free.
If you don't want to do that, or cannot do that for some reason, it gets more complicated. Performing an operation an all nodes in a tree is trivial, but for a general directed graph it's slightly more complicated. I guess this answer could help, and if not, it at least gives you an idea about what to search for:
Finding list of all nodes in a directed graph
I assume you could do something like this pseudo:
getAllNodes(root, nodes)
if root // NULL check
if not node in nodes // If it's the first time we visit the node
// Add this node to the list of visited nodes
nodes = nodes + [root]
// And then call this function recursively on the children
getAllNodes(root->left, nodes)
getAlLNodes(root->right, nodes)
nodes = []
getAllNodes(root, nodes)
for node in nodes
free(node)
Trees have the nice feature that they never contain loops. But directed graphs do, so you have to have some check to see if a node is already visited. Note that in order for this to work, it has to be called from the root. Or to be more precise, every node needs to be reachable from the node. But that's not so different from a tree.
I guess you could somehow move the free inside to create a freeAllNodes() function, but this is more flexible. Maybe you want a list for other purposes. So my suggestion in that case is to just make freeAllNodes() call getAllNodes().
I could write an implementation for the above, but since C does not provide library functions for linked lists, that would mean including a lot of extra code.
You put a into the intended tree twice, so free_graph attempts to free it twice. Calling free twice on the same address from the same original allocation is improper.
If you want to have a true tree, do not put any node into it twice. If you want to have a data structure that can have the same node in it twice, either use separate copies of the node (e.g., two different allocations for struct Node with the same value for data) or make provisions in the data structure to avoid freeing it twice (for example, add a reference count to struct node to count how many times it is currently in the tree, and free the node only when its reference count reaches zero).
Related
Write function in C that for given binary (ordered) tree returns pointer to node that is the closest to the root and divisible by 3.
Here is what I have tried:
Node* find_closest(Node* root) {
if(root == NULL)
return NULL;
if(root->number % 3 == 0)
return root;
if(root->left != NULL)
return find_closest(root->left);
if(root->right != NULL)
return find_closest(root->right);
}
But this doesn't seem to be working. Can someone please help me with this problem?
There are two basic ways to search a binary tree. DFS (depth-first search), and BFS (breadth-first search). DFS searches a tree by going as deep as it can in one direction, only going back up and trying other routes when it finds a dead-end. BFS searches the entire first layer of the tree, then the entire second layer of the tree and so on until it finds what it's looking for.
DFS is very easy to implement with recursion, and appears to be what you were trying to do with your code, but based on the problem you're trying to solve, BFS is a more appropriate algorithm to use, however it is a bit harder to implement because it involves a queue.
Here's an example implementation of BFS that should serve your purposes:
struct nodeQueue{ //This struct lets us store Node pointers in a queue
Node *node;
struct nodeQueue *next;
};
Node* find_closest(Node *root){
if(!root)
return NULL; //Just in case
//Head and tail let us manage the queue of nodes that need to be searched next
struct nodeQueue *head = malloc(sizeof(struct nodeQueue));
struct nodeQueue *tail = head;
*head = (struct nodeQueue){.node = root,.next = NULL}; //root is first in line
while(head){ //As long as there are nodes to check
Node *check = head->node; //Let's pull the next node out of the queue
if(check->number % 3 == 0){ //It is divisible by three so we're done
while(head){ //Free queue to prevent memory leak
struct nodeQueue *hold = head->next;
free(head);
head = hold;
}
return check; //return the node we found
}
//...otherwise
//We need to add the left and right nodes to the queue so they can wait their turn
if(check->left){ //If there is a node to the left put it at the end of the queue
tail->next = malloc(sizeof(struct nodeQueue));
tail = tail->next;
*tail = (struct nodeQueue){.node = check->left,.next = NULL};
}
if(check->right){ //If there is a node to the right put it at the end of the queue
tail->next = malloc(sizeof(struct nodeQueue));
tail = tail->next;
*tail = (struct nodeQueue){.node = check->right,.next = NULL};
}
struct nodeQueue *hold = head->next;
free(head);
head = hold; //Remove the node we just checked so the loop starts with the node next in line
} //If this loop breaks it means none of the nodes' numbers are divisible by three
return NULL;
}
Ensure stdlib.h is included for malloc() and free() and you must be using at least C99 for compound literals to work.
Algorithmically, using a breadth-first search instead of a depth-first search is the most natural solution for finding the node closest to the root (in terms of depth in the tree) that meets a particular criterion. That means testing all the nodes at each depth before testing any deeper nodes, which allows you to test the smallest number of nodes. Read up on breadth-first search if you want to consider this.
Alternatively, you can do it with a depth-first search such as you are presently using, but to do so, you need to track and report back additional data. Specifically, the depth at which the returned result was found, or an equivalent. For example, consider this:
/*
* Finds and returns one of the nodes among those whose number is evenly
* divisible by three and that share a minimum distance from the specified
* root, or returns null if the tree does not contain any nodes with numbers
* divisible by three
*
* root: a pointer to the root node of the tree
* result_depth: a pointer to a `size_t` wherein the depth of the result node
* should be written
*/
Node *find_closest_helper(Node *root, size_t *result_depth);
That can be implemented as a recursive depth-first search, with the result_depth argument used to pass the information between calls that is necessary to favor the nodes closer to the root. The "_helper" part of the function name is meant to convey that you can preserve the function signature presented in the question by making that function a (non-recursive) wrapper around this one.
I am trying to make linked list. I can add node one by one but I could not print the linked list as i wanted. How to print linked list node from top to bottom
#include<stdio.h>
#include<stdlib.h>
struct node{
int N;
struct node *next;
};
struct node* newNode(int number, struct node *next) {
struct node *new = malloc(sizeof(*new));
new->N = number;
new->next = next;
return new;
}
void show(struct node *head){
struct node *c;
c = head;
while (c!=NULL){
printf("%d\n",c->N);
c = c->next;
}
}
int main (void ) {
struct node *head = NULL;
head = newNode(10, head);
head = newNode(20, head);
head = newNode(30, head);
head = newNode(40, head);
show(head);
return 0;
}
Output
40
30
20
10
I am trying to print node like below
10
20
30
40
How to get above output ?
Since I understand this is probably part of an excercise, I will attempt to answer it in the style of assistance, while still giving a comprehensive answer.
I let aside the fact that you insert your elements in the head - which I am not sure it is what you want to do, and I consider the question as "How to print it backwards, once I have entered the elements correctly?".
We have to examine possible solutions on this:
1) Create a method void addToTail(Node* head, int value); That traverses the list and adds elements to the tail of the list instead of the head. Side note: this operation is time costly, as it requires O(N) time complexity. About complexities, read more here. Se also this StackOverflow question.
2) You mention the term "linked list". By what you say, you do not specify if it is a singly linked, or a doubly linked. And since you have access to the node implementation, I suggest that you add a pointer to each node that points to the previous element, thus converting your singly-linked list to a doubly-linked one.
struct node{
int N;
struct node *next;
struct node *prev;
};
And, of course, you need to update this node respectively in the operations of your list - otherwise it will not work - I let this to you.
That way, you will be able to easily iterate the list backwards then in order to print the number in the order desired.
3) You could implement a function Node * reverseList(Node* head); that "reverses" a list via iteration, and then use it to print the list reversed.
And again, I let the implementation to you. Of, course, you need to consider the list state on each time, as also if you need to reverse the list in-place or return a pointer to a new, reversed list (as the function contract above indicates).
What you need to do now, is re-read your excercise brief, stop for a moment and think: "Do I really need these solutions? Is this what is requested from me?".
If you are just entering the data in the wrong order, probably not.
But if it is specifically required from you to print the list elements backwards, then you have some good hints on how to proceed.
Recursive approach works great here:
void show(struct node *c){
if (c == NULL)
return;
show(c->next);
printf("%d\n", c->N);
}
I'm having trouble understanding a piece of C code that represents a linked list structure. The skeleton of the struct looks like this:
struct r{
r *next;
r **prev;
data *d;
}
struct r *rlist;
rlist can be filled by calling the following function: (skeleton only)
r* rcreate(data *d){
struct r *a = xmalloc(sizeof(*r))
a->d = d;
a->next = rlist;
a->prev = &rlist;
if (rlist)
rlist->prev = &a->next;
rlist = a;
return a;
}
How do I go about using this data structure? e.g. how to traverse rlist ?
Edit: here is the function for deleting a node in the linked list
void rdestroy(struct r *a){
if (a->next){
a->next->prev = a->prev;
}
*a->prev = a->next;
destroy(a->d); /* destroy is defined elsewhere */
}
Double prev pointer seems to allow traversing list in one direction only, while allowing easy deletion (because even though you can't access the previous element (easily), you can access the next pointer of previous element, and set it to new correct value when deleting a node.
Without seeing other related functions, it's hard to see why it is done this way. I've not seen this done, and can't immediately think of any really useful benefit.
I think this allows having simpler node deletion code, because node does not need to care if it first or not, because node's prev pointer will always have non-NULL value to a pointer it needs to modify when deleting itself. And same simplicity for insertion before a current node. If these operations are what dominate the use pattern, then this could be seen as minor optimization, I suppose, especially in older CPUs where branches might have been much more expensive.
How to traverse list
This was the question, right? You can only traverse it forward, in a very simple manner, here's a for loop to traverse entire list:
struct r *node;
for (node = rlist ; node ; node = node->next) {
// assert that prev points to pointer, which should point to this node
assert(*(node->prev) == node);
// use node
printf("node at %p with data at %p\n", node, node->d);
}
Example insertion function
This example insertion function demonstrates how insertion before a node needs no branches (untested):
struct r *rinsert(struct r *nextnode, data *d) {
// create and initialize new node
struct r *newnode = xmalloc(sizeof(struct r));
newnode->d = d;
newnode->next = nextnode;
newnode->prev = nextnode->prev;
// set next pointer of preceding node (or rlist) to point to newnode
*(newnode->prev) = newnode;
// set prev pointer of nextnode to point to next pointer of newnode
nextnode->prev = &(newnode->next);
return newnode;
}
There's no good reason to have r ** next in that structure. It's for a double linked list.
So if this thing is created you have it assigned
thisList = rcreate("my data")
now you could start with traversing it
while (thisList->next)
thisList = thisList->next.
...
Your code has many syntactical errors in it, probably because (as you say) it is a "skeleton," so it is hard to parse what the author (whether it was you or someone else) actually intended this code to do.
A simple (doubly) linked list structure looks like this:
struct node {
struct node *next, *prev; // pointers to the adjacent list entries
int data; // use whatever datatype you want
};
struct node *list = NULL; // the list starts empty
void add_entry(int new_data) {
struct node *new_entry = malloc(sizeof(struct node));
// note that in the above line you need sizeof the whole struct, not a pointer
new_entry->data = new_data;
new_entry->next = list; // will be added to the beginning of the list
new_entry->prev = NULL; // no entries currently front of this one
// in general a NULL pointer denotes an end (front or back) of the list
list->prev = new_entry;
list = new_entry; // now list points to this entry
// also, this entry's "next" pointer points to what used to
// be the start of the list
}
Edit: I'll say that if you want us to help you understand some code that is part of a larger program, that you did not write and can't modify, then please post the relevant code in a format that is at least syntactical. As others have said, for example, the use of prev in the code you posted is indecipherable, and it isn't clear (because there are other similarly confusing syntactical problems) whether that was in the original code or whether it is an error introduced in transcription.
Yang, I am not sure how comfortable you are with pointers in general. I suggest taking a look at few other linked-list implementations, it might just do the trick.
Take at look at this Generic Linked List Implementation.
As part of an assignment that is now past due, I was to read a list of search terms from a text file and store these in memory for searching. I decided to use a linked list to store the terms and my implemenation of struct node (stored in myheader.h) looks like this:
struct Node{
char * term;
int termLength;
struct Node *next;};
To save the rootNode as the head of my list, I had a separate function for creating it called startList that is defined as such:
struct Node * startList(char * sterm){
struct Node * rootNode;
rootNode=(struct Node *)malloc(sizeof(struct Node));
assert(rootNode != NULL);
memset(rootNode,0,sizeof(struct Node));
rootNode->term=sterm;
rootNode->termLength = strlen(sterm);
rootNode->next=NULL;
return rootNode;
}
This seems to work fine, the trouble arises when I try to add a new node onto this rootNode, which is supposed to be done with this function:
void insert_another_node( struct Node * headNode, char * sterm){
struct Node * newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->term=sterm;
newNode->next=NULL;
newNode->termLength=strlen(sterm);
while (headNode->next != NULL){
headNode=headNode->next;}
headNode->next=newNode;
}
These functions are all called in this for loop:
while ((fgets(search_wrd,41,list)) != NULL){
strtok(search_wrd, "\n");
if (count==0){
rootNode=startList(search_wrd);}
else{
insert_another_node(rootNode,search_wrd);}
count++;
}
fclose(list);
}
Say I am trying to store a list of planets in this list, the last planet being Neptune. The insert_another_node function will update the terms stored in ALL of the nodes to the most recent term (including the rootNode). The result is the right number of nodes, but they all store "Neptune" at someNode->term.
All of the insert to the end of a linked list implementations I've seen for a linked list in c follow my logic, so I can't understand how this weird update is happening let alone a way to fix it. Any help would be greatly appreciated!
You are just assigning sterm each time, all the assignments point to the same original buffer. You need to make a copy each time.
Use strdup like this:
rootNode->term=strdup(sterm)
and
newNode->term= strdup(sterm);
You need to allocate new memory for each sterm. If you reuse the same memory location they will all have the same value and if you change one you will change them all (because they are the same).
I have a n-ary tree structure with only parents and children. The spantree itself holds only one node, the root. Then there are created nodes which are linked with other nodes or the root. Each node(root included) are allowed to have up to MAXCHILDREN children nodes.
Here's the structure:
typedef struct node{
unsigned int id; //every node has different id
struct node* parent; //points to parent node
struct node* children[MAXCHILDREN]; //pointers to all children of this node
}node;
typedef struct spantree{
node root; //root node
}spantree;
Visual picture:
root
___O
/ / \
O O O
/ \
O O
After I have created my tree I want to deallocate the whole thing but I am unsure on which way to do it. I can't start deallocating from the root because then the tree will get broken. So I imagine that I have to start from the leaves and going up to the root?
But that means that I have to find the deepest leaves first, right? I feel quite confused on how to start.
I don't think it's neccesary but for insurance here's what I use everytime I need to make a new node:
node *newNode;
newNode=(node*)malloc(sizeof(node));
//then I modify it to my preferences
You need to check if the node you're freeing has children, and free them first if it does.
void free_node( node *n ) {
if(n) {
for(int i=0; i<MAXCHILDREN; i++)
free_node(n->children[i]);
free(n);
}
}
Recurse through the tree, call the recursive function first, then free memory.
void deleteNode(node * Node) {
for (int i = 0; i < MAXCHILDREN; ++i) {
if (node->children[i]) {
deleteNode(node->children[i]);
free(node->children[i]);
}
}
}
You're correct, you need to use your favorite traversal function to find the leaves, and then free those before freeing the parent nodes. Once the children have been freed, you basically have another leaf node that you can then free.
You'll need to use recursion. Enjoy!
You heard anything about POST-ORDER Traversing? You use the same technique to delete all of the nodes. This automatically deletes the parents after all their children are deleted.