C programming free trie tree - c

I just started programming and I have a beginner question:
So I have a trie tree and I want to use it to store a large numbers of words from multiple files.
In order to do that everytime after I insert all the words from one file into the tree, I need to free the memory of the tree so that I can reuse the tree for the next file.
Should I use free to just free the root? Or I need to traverse the tree and delete all the node one by one?
Here's the node, I am already able to insert all the words into the tree.
struct node{
struct node * parent;
int noempty;
int isword;
int super;
int occurrence;
int leaf;
struct node * child[26];
};
Here is my insert function:
struct node* insert(struct node *root,char *c){
int i=0;
struct node *temp=root;
int l=length(c);
while(i!=l){
int index=c[i]-'a';
if(temp->child[index]==NULL){
//New Node
struct node *n=(struct node *)malloc(sizeof(struct node));
n->parent=temp;
temp->child[index]=n;
temp->noempty=1;
}
//Node Exist
if(i!=l&&temp->leaf==1){temp->leaf=0;}
temp=temp->child[index];
i++;
}
if(temp->noempty==0){
temp->leaf=1;}
temp->isword=1;
return root;
};

You must traverse the tree and free every node. Each node you created for the Trie has been dynamically allocated. If you just delete the root, then only the memory for the root will be freed, while the memory for every other node is taking up space in the heap. This means you have a memory leak. If you create a Trie for each of your files, the memory that you have not freed could add up to be a substantial amount.

Related

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.

C programming trie tree insert

I just started programming and have a beginner question,I am writing a trie insert function that insert a string into the trie tree. But when I add a string with more than two characters I'm getting heap buffer overflow. Here is my insert function:
struct node* insert(struct node *root,char *c){
int i=0;
struct node *temp=root;
while(c[i]){
int index=c[i]-'a';
//New Node
struct node *n=malloc(sizeof(*n));
n=malloc(sizeof(struct node));
temp->child[index]=n;
i++;
temp=temp->child[index];
}
return root;
};
The definition of the tree node
struct node
{
int isword;
int prefix;
int occurrence;
int leaf;
struct node * child[26];
};
and How I called them
char *c=malloc(3*sizeof(char));
c[0]='a';
c[1]='d';
c[2]='e';
struct node *root=malloc(sizeof(*root));
root=malloc(sizeof(struct node));
insert(root,c);
I think it's how I allocate space in the insert function for new node that went wrong, but I'm not sure what's the proper way to avoid heap buffer overflow, any advice please?
c is not ending with nul. So c[i] is undefined if i>=3(maybe coredump because access invalid memory address). while(c[i]) may run more than 3 times. This maybe the point.
char *c=malloc(3*sizeof(char));
c[0]='a';
c[1]='d';
c[2]='e';
btw, code below will cause memory leak:
struct node *root=malloc(sizeof(*root));
root=malloc(sizeof(struct node));

Freeing tree, but IDE gains a bit of memory over time

I am using the following free function for my tree:
void freeTree(struct node *tree) {
if (tree == NULL) return;
freeTree(tree->left);
freeTree(tree->right);
free(tree);
}
And I am creating a tree/operating on it like this:
struct node *root = NULL;
root = createTree(testNodes);
inOrderPrint(root);
freeTree(root);
Definition of node struct:
struct node {
int val;
int color;
struct node *parent;
struct node *left;
struct node *right;
};
I have noticed after running this enough (many hours), memory starts to build up (very little amount) in my IDE (I am using CLion). I am posting to ask if my freeTree function is implemented correctly to rule that out and to see if it could be something else causing this slow memory build up.
Supposing that your tree is in fact constructed in the manner implied by the names of the members of struct node, and that nodes' left and right pointers are set to NULL for nodes that do not have a left or right child, respectively, your freeTree() function will free all memory associated with the (sub) tree whose root node its argument points to. If you have a leak, it is elsewhere.

Nodes as a pointer

Why the nodes in a linked list are declared as pointers? Nodes contains the pointer part in it to link to another node. Then why the nodes are itself a pointer?
struct node
{
int data;
struct node *link;
} *start;
Now we introduce nodes as
struct node *tmp;
Now this is a node which is a pointer to data type struct node..but for linking we use the link pointer to link the other node
Why dindnt we coded node as
struct node tmp;
only...is this because of allocating dynamic memory..or something more?
Yes, this is because the nodes are allocated dynamically.
struct node tmp could be using tmp as a dummy or sentinel node, where it's data is not used, only it's next pointer to the actual first node of a list.
struct node *tmp would be using tmp as a pointer to the first node of a list or as a working pointer to some node in a list when scanning a list.
In some cases a list structure is also used:
struct list{
struct node *head // pointer to first node
struct node *tail // optional: pointer to last node
size_t size; // optional: number of items in a list
}
A circular list could be implemented using just a tail pointer to the last node, which in turn would have a next pointer to the head/first node.

Nodes data type

Why the nodes in a linked list are declared as pointers? Nodes contains the pointer part in it to link to another node. Then why the nodes are itself a pointer?
struct node
{
int data;
struct node *link;
} *start;
Now we introduce nodes as
struct node *tmp;
Now this is a node which is a pointer to data type struct node..but for linking we use the link pointer to link the other node Why dindnt we coded node as
struct node tmp;
only...is this because of allocating dynamic memory..or something more?
Nodes in linked lists in C always allocated in a heap to allow you manage their lifetime. Therefore for creating, destroying and adding nodes to list, you need to declare a pointer on a node:
struct node *tmp; // declaring
tmp = (node*) malloc(sizeof(node)); // creating (allocating memory)
// ... tmp initializing and processing
free(tmp); // removing (freeing memory)
tmp = NULL;
Otherwise, if you create a node on stack node tmp;, it's lifetime will be managed by the rules of language, not by your business logic.

Resources