confused over the usage of free () in C - c

This is done by someone who is better in C programming than me.
confused over the usage of free () in C
below is the struct of linked list
typedef struct node {
int value;
struct node *next;
} ListNode;
typedef struct list {
ListNode *head;
} LinkedList;
after created a list with some nodes
his code does this when exit
void deleteList(LinkedList *ll) {
if (ll != NULL) {
ListNode *temp;
while (ll->head) {
temp = ll->head;
ll->head = temp->next;
free(temp);
}
free(ll);
}
}
The above is what I don't understand. Why he needs to create such complexity, why not just do free(ll).
Please help
thanks in advance.

Linked list is made up of individual objects that happen to point at each other. If you want to delete a list you have to delete all of its nodes. free() won't do that. It doesn't know that these objects make up a list. It doesn't even know that these objects contain pointers to anything. Therefore you need to iterate over the list and free each node by hand.

if you have a linked list, suposse that every "*" is a node.
0 1 2 3 4
head--> *--*--*--*--*
the first *, es the head, is you just do "free ll"
this will be on the memory
0 1 2 3 4
head-->nul *--*--*--*
the problem here, is, all the "memory" that you ask for those nodes will still be there, and now you can't know where is it (you have nothing poiting to that memory) for every malloc you need a free (not 100% true, but for simple things work).
What that algorithm do is:
get the reference to the next node (if you don't do this and you free the node, you won't be able to get the "next" node, becouse head will be pointing to nothing ).
free the head.
make head point to the reference that you get before.

You can do with the following struct alone
typedef struct node {
int value;
struct node *next;
} ListNode;
But every time you have to declare a global variable struct node *HEAD. In a bigger program it may confuse you. The author has done this so that you can create a linked list like a variable. Every time you have to create a new linked list all you have to do is declare
LinkedList *ll;
When there are two struct, one has to free the objects of both the struct.

That's because each pointer points to a memory location. You need to free all memory locations that were previously allocated. free(ll) would only remove the node pointed to by the ll pointer.

Related

How to print linked list node top to bottom

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);
}

Why use dynamic memory allocation(i.e. malloc()) when implementing linked list in c?

Okay this question may sound stupid to the amateur programmers . But seriously this is bothering me and a solemn answer to this doubt of mine is welcomed. I have just started to take my first ever course in data structures. And what is bothering me is this:
Assuming C is used,
//Implementing a node
struct Node
{
int data;
struct *Node;
};
Now while creating a node why do we use the dynamic memory allocation technique where we use malloc(). Can't we just create a variable of type ' Struct Node '.
i.e. something like:
struct Node N1;
//First node - actually second where !st Node is assumed to be Head.
struct Node *Head = &N1;
struct Node N2;
N2.(*Node) = &N1;
Well some parts of my code may be incorrect because I am only a beginner and not well versed with C. But by know you may have understood what I basically mean. Why don't we create variables of type Node of an Array of type Node to allocate memory t new nodes why get into the complexity of dynamic memory allocation?
First off, you have an error in how you declare your struct. struct * by itself does not denote a type. You have to give the full type name:
struct Node
{
int data;
struct Node *Node;
};
You can certainly use local variables as above to make a linked list, however that limits you to a fixed number of list elements, i.e. the ones you explicitly declare. That would also mean you can't create a list in a function because those variables would go out of scope.
For example, if you did this:
struct Node *getList()
{
struct Node head, node1, node2, node3;
head.Node = &node1;
node1.Node = &node2;
node2.Node = &node3;
node3.Node = NULL;
return &head;
}
Your list would be restricted to 4 elements. What of you needed thousands of them? Also, by returning the address of local variables, they go out of scope when the function returns and thus accessing them results in undefined behavior.
By dynamically allocating each node, you're only limited by your available memory.
Here's an example using dynamic memory allocation:
struct Node *getList()
{
struct Node *head, *current;
head = NULL;
current = NULL;
// open file
while (/* file has data */) {
int data = /* read data from file */
if (head == NULL) { // list is empty, so create head node
head = malloc(sizeof(struct Node *));
current = head;
} else { // create new element at end of list
current->next = malloc(sizeof(struct Node *));
current = current->next;
}
current->data = data;
current->Node = NULL;
}
// close file
return head;
}
This is psedo-code that doesn't go into the details of reading the relevant data, but you can see how you can create a list of arbitrary size that exists for the lifetime of the program.
If these variables are local, defined inside a function's scope (i.e. stored on the stack), you shouldn't do this, because accessing them after leaving their scope will result in undefined behavior (their contents will likely be overwritten as you call other functions). In fact, any time you return a pointer to a local, stack based variable from your function, you are doing the wrong thing. Given the nature of C, this is problematic since nothing will warn you you are doing something wrong, and it will only fail later when you try to access this area again.
On the other hand, if they are declared as global variables (outside any other function), then you are simply limited by the number of variables declared that way.
You can potentially declare many variables, but keeping track of which one is "free" for use will be painful. Sure, you can even go a step further and say you will have a global preallocated array of nodes to prevent using malloc, but as you are doing all this you are only getting closer to writing your own version of malloc, instead of sticking to the existing, dynamic one.
Additionally, all preallocated space is wasted if you don't use it, and you have no way of dynamically growing your list in runtime (hence the name dynamic allocation).
Here is some good reasons to use dynamic memory
When you declare node struct Node N1;this node will store on stack memory. After scope of the node that will get destroy auto.But in case of dynamic you have handle to free the memory when you done.
When you have some memory limitation.
When you don't know the size of array then dynamic memory allocation will help you.
One issue could be that you cannot use another function to add a new node to your list.
Remember that automatic variables - like the ones created by struct Node node100; - have scope only inside the function in which they are defined. So when you do something like this:
int main()
{
struct Node *head;
/* Some code there you build list as:
head ---> node1 ---> node2 --> .. ---> node99
*/
/* Add a new node using add_node function */
add_node(head, 555);
/* Access the last node*/
}
void add_node(struct Node *head, int val)
{
/* Create new node WITHOUT using malloc */
struct Node new_node;
new_node.data = val;
/* add this node to end of the list */
/* code to add this node to the end of list */
/* last_element_of_list.next = &new_node*/
return;
}
Now you think that you have added a new node to the end of the list. But, unfortunately, its lifetime ends as soon as the add_node function returns. And when you try to access that last node in your main function your program crashes.
So, to avoid this situation you will have put all your code in one single function - so that the lifetime of those nodes do not end.
Having all your code in ONE function is bad practice and will lead to many difficulties.
This was one situation that asks for a dynamic memory allocation, because, a node allocated with malloc will be in scope untill it is freed using free, and you can put code that do different things in different functions, which is a good practice.
You don't have to use dynamic memory to create a linked list, although you definitely don't want to create separate variables for each node. If you want to store up to N items, then you'd need to declare N distinct variables, which becomes a real pain as N gets large. The whole idea behind using a linked list is that it can grow or shrink as necessary; it's a dynamic data structure, so even if you don't use malloc and free, you're going to wind up doing something very similar.
For example, you can create an array of nodes at file scope like so:
struct node {
int data;
struct node *next;
};
/**
* use the static keyword to keep the names from being visible
* to other translation units
*/
static struct node store[N]; /* our "heap" */
static struct node *avail; /* will point to first available node in store */
You the initialize the array so each element points to the next, with the last element pointing to NULL:
void initAvail( void )
{
for ( size_t i = 0; i < N - 1; i++ )
store[i].next = &store[i + 1];
store[N - 1].next = NULL;
avail = store;
}
To allocate a node for your list, we grab the node avail points to and update avail to point to the next available node (if avail is NULL, then there are no more available nodes).
struct node *getNewNode( void )
{
struct node *newNode = NULL;
if ( avail ) /* if the available list isn't empty */
{
newNode = avail; /* grab first available node */
avail = avail->next; /* set avail to point to next available node */
newNode->next = NULL; /* sever newNode from available list, */
} /* which we do *after* we update avail */
/* work it out on paper to understand why */
return newNode;
}
When you're done with a node, add it back to the head of the available list:
void freeNode( struct node *n )
{
n->next = avail;
avail = n;
}
We're not using dynamic memory in the sense that we aren't calling mallic or free; however, we've pretty much recapitulated dynamic memory functionality, with the additional limitation that our "heap" has a fixed upper size.
Note that some embedded systems don't have a heap as such, so you'd have to do something like this to implement a list on such systems.
You can write a singly linked list with out malloc , but make sure the implementation is done in main. but what about writing program for traversing , finding least number ,etc . these struct node variables will go out of scope .
struct node{
int a;
struct node* nextNode;
};
int main()
{
struct node head,node1,node2;
head.a=45;
node1.a=98;
node2.a=3;
head.nextNode=&node1;
node1.nextNode=&node2;
node2.nextNode=NULL;
if(head.nextNode== NULL)
{
printf("List is empty");
}
struct node* ptr=&head;
while(ptr!=NULL)
{
printf("%d ",ptr->a);
ptr=ptr->nextNode;
}
}

Deleting first node of linked list

I have to print a list of a set in c using linked lists (hence pointers). However,when I delete the first element of the list and try to print the list, it just displays a lot of addresses under each other. Any suggestions of what the problem might be? Thanks!
Delete function:
int delete(set_element* src, int elem){
if (src==NULL) {
fputs("The list is empty.\n", stderr);
}
set_element* currElement;
set_element* prevElement=NULL;
for (currElement=src; currElement!=NULL; prevElement=currElement, currElement=currElement->next) {
if(currElement->value==elem) {
if(prevElement==NULL){
printf("Head is deleted\n");
if(currElement->next!=NULL){
*src = *currElement->next;
} else {
destroy(currElement);
}
} else {
prevElement->next = currElement->next;
}
// free(currElement);
break;
}
}
return 1;
}
void print(set_element* start)
{
set_element *pt = start;
while(pt != NULL)
{
printf("%d, ",pt->value);
pt = pt->next;
}
}
If the list pointer is the same as a pointer to the first element then the list pointer is no longer valid when you free the first element.
There are two solutions to this problem:
Let all your list methods take a pointer to the list so they can update it when neccesary. The problem with this approach is that if you have a copy of the pointer in another variable then that pointer gets invalidated too.
Don't let your list pointer point to the first element. Let it point to a pointer to the first element.
Sample Code:'
typedef struct node_struct {
node_struct *next;
void *data;
} Node;
typedef struct {
Node *first;
} List;
This normally happens when you delete a pointer (actually a piece of the memory) which doesn't belong to you. Double-check your function to make sure you're not freeing the same pointer you already freed, or freeing a pointer you didn't create with "malloc".
Warning: This answer contains inferred code.
A typical linked list in C looks a little something like this:
typedef struct _list List;
typedef struct _list_node ListNode;
struct _list {
ListNode *head;
}
struct _list_node {
void *payload;
ListNode *next;
}
In order to correctly delete the first element from the list, the following sequence needs to take place:
List *aList; // contains a list
if (aList->head)
ListNode *newHead = aList->head->next;
delete_payload(aList->head->payload); // Depending on what the payload actually is
free(aList->head);
aList->head = newHead;
The order of operations here is significant! Attempting to move the head without first freeing the old value will lead to a memory leak; and freeing the old head without first obtaining the correct value for the new head creates undefined behaviour.
Addendum: Occasionally, the _list portion of the above code will be omitted altogether, leaving lists and list nodes as the same thing; but from the symptoms you are describing, I'm guessing this is probably not the case here.
In such a situation, however, the steps remain, essentially, the same, but without the aList-> bit.
Edit:
Now that I see your code, I can give you a more complete answer.
One of the key problems in your code is that it's all over the place. There is, however, one line in here that's particularly bad:
*src = *currElement->next;
This does not work, and is what is causing your crash.
In your case, the solution is either to wrap the linked list in some manner of container, like the struct _list construct above; or to rework your existing code to accept a pointer to a pointer to a set element, so that you can pass pointers to set elements (which is what you want to do) back.
In terms of performance, the two solutions are likely as close so as makes no odds, but using a wrapping list structure helps communicate intent. It also helps prevent other pointers to the list from becoming garbled as a result of head deletions, so there's that.

pointer to pointers for singly linked list in C [duplicate]

This question already has answers here:
What is the reason for using a double pointer when adding a node in a linked list?
(15 answers)
Closed 9 years ago.
I have a question about signly linked lists in C. I've created a linked list with the code shown below :
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node* next;
};
struct node *mknode(int data)
{
struct node* np=malloc(sizeof(struct node));
np->data=data;
np->next=NULL;
return np;
}
struct node * insert (struct node* list,int data)
{
struct node *np;
struct node*curr=list;
struct node* prev=NULL;
np=mknode(data);
for(;curr &&data<curr->data;curr=curr->next )
prev=curr;
np->next=curr;
if(prev)
prev->next=np;
else
list=np;
return list;
}
int main()
{
struct node* head;
head=malloc(sizeof(struct node));
head=insert(head,7);
head=insert(head,2);
head=insert(head,4);
printf("%d",head->data);
printf("%d",head->next->data);
printf("%d",head->next->next->data);
return 0;
}
However,While I search on internet, I've realized that, the double pointer is used for creating linked list instead of a normal pointer.I mean, struct node **list , not struct node * list . I wonder why ? Which one is correct , and If both of them is true , what is the differences between them, I used my implementation with the sample main I wrote here, and it works fine but I dont know why should I use pointer to pointers ? Thanks in advance.
The reason some people use a pointer to a pointer is so that the nodes can be updated without returning a new pointer. In your example, if you wanted to change the head pointer, you would have to create a new pointer and then make head equal to that pointer. With the double pointer, you only have to free the space that the second pointer points to, and then update the second pointer to your new data structure, which keeps your original head pointer
I just use the single pointer in my implementations.
Read here, In this way you can change elements without creating new ones.
What is the reason for using a double pointer when adding a node in a linked list?
Given
struct node { int x; };
struct node **pplist;
struct node *plist;
pplist is a pointer to a pointer to a struct node, while plist is a pointer to a struct node. To change x, you would need to write
*pplist->x = 3;
plist->x = 4;
You would use a pointer to a pointer if you wanted the same variable to point to, say, different lists, or if you wanted to pass a pointer to a function with a side-effect of changing that pointer.
This looks perfectly fine to me.
All a pointer is, is a memory address to somewhere. A double pointer is just a memory address to another memory address which points to some data.
Maybe you can post where you saw node **list and we can explain it better but for now, your code looks good.
it is a bit of naturally, if you call "head = NULL; insert(&head, data);" that then head points to the first element. All functions, that supose to change the content, should be called indirectly.
BUT: this is a matter of coding convention. Some like it hot, some like it cold. The problem with head=insert(head, data); is, that head is unusable, when you forget "head="

Allocate a consecutive linked list in c

Im trying to create a linked list in c. The twist is that I want to allocate the memory for the list so that all the nodes are consecutively stored in memory.
Maybe an array structure is the way to go.
Any ideas?
The obvious way would be to allocate a number of nodes in a block, then link them together into a free list. When you need to add a node to your linked list, you'll grab the one from the head of your free list. When you want to delete a node, you link it back onto the free list:
struct node {
struct node *next;
// other data here.
};
node *free_list;
#define block_size 1024
void initialize() {
free_list = malloc(block_size * sizeof(struct node));
for (i=0; i<block_size-1; i++)
free_list[i].next = &free_list[i+1];
free_list[block_size-1].next = NULL;
}
struct node *alloc_node() {
struct node *ret;
if (free_list == NULL)
return NULL;
ret = free_list;
free_list = free_list->next;
return ret;
}
void free_node(struct node *n) {
n->next = free_list;
free_list = n;
}
If you're looking at a linked list, don't worry about where in memory they are. That's what the pointers on the nodes are for.
If you want them sequential, allocate an array.
Yes, use an array. More interesting is why you want this. If your program requires this to work, then you'll need to make sure your array is big enough to store all the nodes that might be allocated. If not, you can allocate batches of nodes.
FYI. I've seen this strategy used in the past on the assumption that sequentially allocated nodes would result in fewer cache misses when searching the list. In the system of interest, that didn't actually give much a performance improvement. [ Not enough profiling of course!.]
You could do something like this
struct node
{
int data;
struct node *next;
};
struct node linkedlist[50];
This would allocate space for linked list structure in contiguous locations.

Resources