Extending a graph struct in c - c

My problem: I have a graph made of node struct
struct node {
node *n1;
node *n2;
}
And I want to add some members to make a new struct newNode
struct newNode {
newNode *n1;
newNode *n2;
newNode *n3; // new member
int a; // new member
}
I want to keep the original "node connections" in the graph so that I can do
newNode *n;
n->n1->n2...
just like
node *n;
n->n1->n2...
where n1 (or n2) of the two structs represent the same node in the graph, while I can also do
newNode *n;
n->n1->a...
n->n1->n3...
It's tricky to modify the node struct as it's defined in a big library.
My idea is to add one more member to newNode struct
struct newNode {
node *n; // added member
newNode *n1;
newNode *n2;
newNode *n3;
int a;
}
First, I create a newNode n_new for each node n. Then I traverse every pair of n_news, say n_new1 and n_new2, look at n_new1->n and n_new2->n to see whether there's a connection between them, that is, whether n_new1->n->n1 == n_new2->n, or n_new1->n->n2 == n_new2->n or vice versa. If so I make n_new1->n1 = n_new2, or n_new1->n2 = n_new2 or vice versa.
But the time complexity is O(#node^2). Inefficient.
Any other ideas?
P.S. The graph is a reduced-ordered binary decision diagram.

You have to copy recursively, creating a new new_node each time you encounter a new node (read that carefully). This will be a complete copy of the original graph, structurally identical but using different memory.
To determine if we have already copied a node, we keep a list of the ones we have copied (and their copies) in a BST that maps node* to new_node*.
You can find many BST implementations out there. There is one in the stl c++ library, for example and I think glibc, and so on.
The code will look like this:
struct node {
node *n1;
node *n2;
}
struct new_node {
node *n1;
node *n2;
newNode *n3; // new member
int a; // new member
}
new_node* GraphCopy (node* start)
{
new_node* n_new;
if(!start) return NULL;
n_new = malloc(sizeof(new_node));
//Add start.n1 and start.n2 to a bst here
//with keys of node* and vals of new_node*
TreeInsert(start, n_new)
if(IsInTree(start->n1))
n_new->n1 = TreeFind(start->n1);
else
n_new->n1 = GraphCopy(start->n1);
//repeat for n2
}
Complexity would be linear if there were no tree, so its still quite quick. (It would be more linear with a hash table, for example.)
(The tree would map node* to their copies.)

Related

Freeing dynamically allocated graph nodes in C

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).

How do I delete a doubly linked list in C?

I've created a doubly linked list, filled it with values and now I want to delete it and remove all the values to avoid memory leaks. Here's what I wrote as well as the structs that were used when creating the doubly linked list. Both those functions will be called towards the end of the main function.
struct node
{
struct node *next;
struct node *prev;
char *value;
};
// The type for a list.
typedef struct list
{
struct node head;
} List;
// The type for a list position.
typedef struct list_pos
{
struct node *node;
} ListPos;
void list_destroy(List *lst)
{
List p,q;
p = *lst;
while (p)
{
q = p.head->next;
free(p);
p = q;
}
*lst = NULL;
}
// Remove the value at the position and return the position of the next element.
ListPos list_remove(ListPos pos)
{
}
You appear to have the right general idea: you walk the list and free each node, making sure to grab any needed data from each node (in particular, the pointer to the next node) while the node holding it still exists. Your case differs from some that you might have seen, however, because instead of handling the overall list via a bare pointer to the head node, you have a separate object, of a separate type (List / struct list), to represent the list itself. This approach has much to recommend it, including, especially, the use of (apparently) a dummy head node, which provides for a variety of algorithmic simplifications. This is usually how I write a linked list.
But because struct list is not struct node, you cannot set a list pointer equal to a node pointer. Instead, create a struct node * to track your position. The first node to free would be the one referenced by struct node *to_free = lst->head.next, and the one after that would be the one referenced by to_free->next.
Note that you might need to free the struct list, too.

List of a List in C

I am trying to dynamically allocate list of pointers to pointers of structs which each contain a list of structs with the following definition:
struct node {
char *text;
struct node *next; };
I am also using a typedef:
typedef struct node Node;
I am creating a list of nodes to hold each list by declaring the following:
Node **list;
list = (struct node**) malloc(sizeof(struct node*) * arraySize);
At each of the nodes of list I will have another list which I am creating as follows:
list[i] = malloc(sizeof(struct node*) * subArraySize);
I have several questions:
Is this the correct implementation for such a problem?
How can I access the text data member of the first node of each list within the larger list?
If my question is vague please let me know. My confusion on this topic makes it difficult to word my question properly.
Assuming your memory is allocated and filled up correctly, you'd access the text data member of the first node of each node* array within the larger node** array via:
list[i]->text
But, to answer your question about the implementation being correct, it's not really. You'd probably be happier doing this:
struct node **list;
list = (struct node**) calloc(sizeof(struct node*) * arraySize);
for (int i=0; i<arraySize; ++i) {
list[i] = (struct node*) malloc(sizeof(struct node));
list[i]->text = ""; // or whatever you want to start with
list[i]->next = NULL;
}
This creates a node** array (called list, since you wanted to call it that, but I would call it something else indicates it's an array of node-based linked lists), then instantiates a block of memory for each head node so that list is full of valid node*s and you can start working with them.
When you go to append something to each of your linked lists, you'd do something like this (this appends to the end, it's up to you to implement insertion based on comparing values if you want sorted data, etc.):
int i = index_where_you_want_to_insert;
struct node *currNode = list[i];
struct node *newNode = (struct node*) malloc(sizeof(struct node));
newNode->text = ""; // or whatever you want to start with
newNode->next = NULL;
while(currNode->next != NULL) {
currNode = currNode->next;
}
currNode->next = newNode;
It may also help you to see this question about using typedef with linked lists.
If I've made any syntactic or semantic errors in my code, I apologize, it's been a while since I wrote C and I may be rusty with how to refer to structs. I welcome corrections.

How to add a list of structures to an existing structure

I am designing a basic XML parser in C and am trying to figure out a way to add nodes (both child and parents). So my idea as of now is to have one datatype,node, which looks like this
struct node{
char* name;
char* value;
struct node* parent; // if is a child set this to the parent node
//how to make a list of child nodes
int numChildren;
struct node* nextParent;// allow me to iterate through top level parent level nodes
};
So if a node is a parent it will have its Parent pointer set to NULL.
I know how to add nodes to my linked list, but I don't get how to add child nodes to a "node list". So any ideas on how I would do that
One common way to create a tree structure is the following:
struct node {
//additional values...
struct node *parent; //optional
struct node *firstChild;
struct node *nextSibling;
};
Essentially, each node contains a linked list of its children. The first child is theNode->firstChild, the second child is theNode->firstChild->nextSibling, and so on, until nextSibling==NULL for the last child.
Leaf nodes will have firstChild==NULL, and the root node has parent==NULL.
Adding a child to a node will then be done in the same manner as adding a node to a linked list. For example, to add a child in front of the other children:
allocate newNode and initialize its fields.
newNode->parent = parentNode;
newNode->nextSibling = parentNode->firstChild;
parentNode->firstChild = newNode;
#define MAXCHILD N
struct node{
char* name;
char* value;
struct node* parent;
//int numChildren; if fixed number of children for each node then use macro
struct node* nextParent[MAXCHILD];
};
Or,
try using malloc() and make nextParent as struct node** nextParent pointer to pointer.Allocate according to number of each node's children. Like this below.
struct node *treenode;
treenode = malloc(sizeof(*treenode));
treenode -> numChildren = 2; // It must be initialized with value otherwise may
// take any garbage value.
treenode -> nextParent = malloc((treenode -> numChildren) * sizeof(struct node*));
But numChildren should be initialized

Freeing linked structs in C

Okay so I have a Binary Search Tree built using only C structs and pointers because I'm insane and didn't want to use C++. Anyways, I've got some serious memory leaks since I'm assuming free(tree), tree being an instance of the struct below, doesn't free all the children of that tree.
Here is my node:
struct node{
struct node* parent;
struct node* left;
struct node* right;
int key; //the value of the node
};
and here is my bst:
struct bst{
struct node* root;
int elements; //number of nodes in the bst
};
So my question, is there any better way of doing this than recursively calling a delete function? for instance (writing this on the spot):
void delete_tree(struct node* n){
if(n == NULL) return;
struct node* left = n->left;
struct node* right = n->right;
free(n);
delete_tree(left);
delete_tree(right);
}
I see absolutely nothing wrong with a recursive delete. You could use an iterative approach, but it wouldn't have any discernible benefits and would be harder to write.
By the way, you can simplify the code a little and remove the two local variables as so:
void delete_tree(struct node* n){
if(n == NULL) return;
delete_tree(n->left);
delete_tree(n->right);
free(n);
}
You are making the recursive calls but never actually call free. You probably need to verify if a node is a leaf node (maybe asking if both children are null) and call free on that node.

Resources