How to understand pointer 'next' in a linked list structure? - c

struct Node
{
int a;
struct Node *next;
};
How will next address point dynamically? I read malloc returns address value — is that right?
Please explain struct Node *next. Is this the default way of declaring a pointer in a struct?

If you have this declaration
struct Node
{
int a;
struct Node *next;
};
then you can define it like so:
struct Node node = {1, 0};
or
struct Node *node = (Node*) malloc(sizeof(struct Node));
When you want to attach a node to the next member then you can like so for example:
node.next = (Node*) malloc(sizeof(struct Node));
or
node->next = (Node*) malloc(sizeof(struct Node));
Example experiment:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
struct Node
{
int a;
struct Node *next;
};
struct Node node1;
struct Node *node2 = (Node*) malloc(sizeof(struct Node));
node1.a = 1;
node2->a = 2;
node1.next = node2;
node2->next = (Node*) malloc(sizeof(struct Node));
node2->next->a = 3;
printf("node1.a = %d, node1->next->a node2->a = %d, node2->next->a = %d\n", node1.a, node2->a, node2->next->a);
}

Yes your declaration is correct. To understand it, see it this way. When the compiler wants to know what kind of pointer it should compile the strcut's next field. The declaration type you gave is used. Since the compiler already parses the structure before coming to this line. It understands that the next pointer type is also of same structure type. I hope this helps in your understanding.

Start points to the top of the list and is available globally to your program. Whereas next just keeps track of the next item, and is available when referring to a specific 'node'. See this diagram it may help you understand with a visual!
link internally tracks the following item which keeps track of where the next component is as it is not necessarily contiguous the way arrays are.
+------+ +------+ +------+
| data | | data | | data |
+------+ +------+ +------+
| next |---->| next |---->| next |----> NULL
+------+ +------+ +------+
^
|
START (Keep track of the whole list.)
Hope that helps clarify.

Related

Double Pointers Queue, deQueue, enQueue

Currently preparing for exams and can't figure out the reasoning behind the queue[rear*] = new_node in this example code.
are you not putting the address of new_node in rather than the value?
Also, is the queue a Node ** queue because it is a pointer to a list of node pointers?
Thanks so much, I really appreciate it, no matter how many hours i spend on double pointers, they always crop up and retest my understanding i thought i finally had!
void enQueue(struct node **queue, int *rear, struct node *new_node)
{
queue[*rear] = new_node;
(*rear)++;
}
struct node *deQueue(struct node **queue, int *front)
{
(*front)++;
return queue[*front - 1];
}
Here queue is pointer to pointer to array of struct Node pointers.
Where each node pointer inside the array will point to NewNodes.
node 1 node2
^ ^
| .... |
+--------+---------+--------+
queue -->| node * | node * |node * |
+--------+---------+--------+
When you do
queue[*rear] = new_node;
You assign the node * at the *rear position inside the queue array to NewNode
Only reason I can think of for maintaining the Node * array is to avoid the copying the content of NewNode.
the variable rear is a pointer to an int. With *rear you get the value of that int. That value is then used as index.
It's equivalent to e.g.
int index = *rear;
queue[index] = new_node;
index++;
*rear = index;
It copies the value of the variable new_node (i.e. the address of where the pointer is pointing) into queue[index]. From this point onward, both new_node and queue[index] points to the same thing.
I hope that makes it clearer what's happening.

Link List Generation with malloc()

How is malloc being used in linked list generation? I do not see how it is being used to generate new linked lists, rather than reserve memory for linked lists
Tip: press Ctrl + F and look for "(***)" (without quotes) to find the exact code location
Example 1:
#include <stdio.h>
#include <stdlib.h>
struct LinkedList {
int data; /* The data part of the linked list */
struct LinkedList *next; /* The pointer part of the linked list */
};
int main(void) {
/* Generate the 1st node ("head") */
struct LinkedList *head /* I am not sure what this pointer */
head = NULL; /* is doing to the struct*/
head = malloc(sizeof(struct LinkedList)); /* Head points to null. Now
* malloc() is being called
* and is assigned to head.
* Next line implies head is
* already pointing to a
* linked list, which means
* malloc() is making a new
* strucuture (***) */
/* Generate the second node */
head -> data = 1; // This implies head is already pointing to a linked list
head -> next = malloc(sizeof(struct LinkedList));
/* Generate the third node */
head -> next -> data = 2;
head -> next -> next = malloc(sizeof(struct LinkedList));
/* Generate the fourth node */
head -> next -> next -> data = 3;
head -> next -> next -> next = NULL;
return 0;
}
Example 2:
#include<stdio.h>
#include<stdlib.h>
struct LinkedList {
int data;
struct LinkedList *next;
}; // notice the semi-colon!
int main(void) {
struct LinkedList *head = NULL; /* why is it doing this? */
struct LinkedList *second = NULL;
struct LinkedList *third = NULL;
// Generate the node structure:
/* how does (struct LinkedList*) affect malloc? (***) */
head = (struct LinkedList*)malloc(sizeof(struct LinkedList));
second = (struct LinkedList*)malloc(sizeof(struct LinkedList));
third = (struct LinkedList*)malloc(sizeof(struct LinkedList));
// Now fill the first node with info:
head->data = 1; /* assign data to the first node */
head->next = second; /* Link the first node ("head") with the second
* node ("second") */
// Now fill the second node with info:
second->data = 2; /* assign data to the second node */
second->next = third; /* Link the second node to the third node */
// Now fill the second node with info:
third->data = 3; /* assign data to the second node */
third->next = NULL; /* Since node 3 is our last node to the link list,
* we give it the value of NULL */
return 0;
}
The textbook describes a link list as being a chain structure. Malloc() is used for dynamic memory management. However, malloc is being used to declare a new structure in these examples and I do not understand why. I thought it only reserves memory
For example, in example 1, malloc() reserves the space for the structure, but does not "create" it (struct LinkedList var would create a new linked list and store it in var)
For example, in example 2, it looks like malloc() is being affected by (struct LinkedList*) (i.e. (struct LinkedList*)malloc(sizeof(struct LinkedList));), but I am unsure
You can look at linked list like on boxes connected with each other:
______ ______ ______
| data | | data | | data |
|______| |______| |______|
| next | | next | | next |
|______|----->|______|----->|______|----->NULL
Where each box is your:
struct LinkedList
{
int data; /* The data part of the linked list */
struct LinkedList *next; /* The pointer part of the linked list */
};
The size of your "boxes" (depends on arch) let's take x64 Linux machine is equal
to 16 bytes. To create linked list data type you need to store this boxes in memory (stack/heap) and connect them.
As I noticed the size is 16 byte for one "box" and it should be store in memory. For memory managment in userspace you can use malloc(), important thing here there malloc() is not "declare" anything it only allocate part of memory for your one "box" on the heap and you ask for exactly 16 bytes for your "box" using sizeof() operator.
struct LinkedList *head = malloc(sizeof(struct LinkedList));
It allocate memory for your "box" and now it look like this:
______
| data |
|______|
| next |
|______|----->NULL
When you do this:
head->next = malloc(sizeof(struct LinkedList));
Your allocate memory for another "box" and connect them:
______ ______
| data | | data |
|______| |______|
| next | | next |
|______|----->|______|
When you do this one:
struct LinkedList *head = malloc(sizeof(struct LinkedList));
struct LinkedList *second = malloc(sizeof(struct LinkedList));
struct LinkedList *third = malloc(sizeof(struct LinkedList));
You create three "boxes" somewhere in memory 16 bytes each. And they not connected for now, they only located in memory;
head second third
______ ______ _____
| data | | data | | data |
|______| |______| |______|
| next | | next | | next |
|______| |______| |______|
And you connected them doing this one:
head->next = second;
second->next = third;
third->next = NULL;
head second third
______ ______ ______
| data | | data | | data |
|______| |______| |______|
| next | | next | | next |
|______|----->|______|----->|______|----->NULL
Usually second approach used in function like for ex add_node_front()
void add_node_front(struct LinkedList **head_ref, int data)
{
/* 1. allocate node */
struct LinkedList *new_node = malloc(sizeof(struct LinkedList));
/* 2. put in the data */
new_node->a = data;
/* 3. Make next of new node as head */
new_node->next = (*head_ref);
/* 4. move the head to point to the new node */
(*head_ref) = new_node;
}
In the second example you also could allocate the memory statically:
struct LinkedList head;
struct LinkedList second;
struct LinkedList third;
Then you need to access with the dot-operator:
head.data = 1; //assign data to the first node
head.next = &second;
You could also use an array
struct LinkedList nodes[3];
node[0].data = 1;
node[0].next = &node[1];
and so on.
So, the malloc command is not essential to the concept of linked list.
But for many applications you do not know before, how big your linked list will be. And elements and the order will change during runtime. So, in this case the dynamic memory allocation with malloc/free is really helpful.
How is malloc being used in linked list generation?
malloc is used for allocating memory dynamically. When you are creating linked list, you can use malloc for allocating memory for the nodes of the list.
Read more about malloc here.
From Example 1:
head = malloc(sizeof(struct LinkedList));
From Example 2:
head = (struct LinkedList*)malloc(sizeof(struct LinkedList));
The only difference is, in Example 2, you are explicitly casting the malloc result. The malloc return type is void * and void * can be cast to the desired type, but there is no need to do so as it will be automatically converted. So the cast is not necessary. In fact, its not desirable to cast malloc return. Check this.
Your both the examples are functionally same except the memory allocation sequence.
In Example 1, you are allocating memory to head pointer and then to head -> next pointer and then to head -> next -> next pointer.
In Example 2, you are allocating memory to head, second and third pointer and later assigning second to head -> next and third to head -> next -> next.
Additional:
Always check the malloc return, like this:
head = malloc(sizeof(struct LinkedList));
if (NULL == head) {
fprintf (stderr, "Failed to allocate memory");
exit(EXIT_FAILURE);
}
Also, make sure to free the dynamically allocated memory once you are done with it. Follow good programming practice.

why a pointer to List can also point to Node?

I am a primer to c programming and reading c primer: 5th edition. What confuse me is why plist as a pointer to List can also point to Node?
sorry, I did not paste function ListItemCount to the code block. In this function, Node * pnode = *plist;, Does that mean plist was converted as a ponter point to Node ? If so, why does the program need to convert to a pointer to node instead of assigning plist->head to pnode(a pointer to Node)?
typedef struct film {
char title[TSIZE];
int rating;
} Item;
typedef struct node{
Item item;
// typical usage
struct node * next;
} Node;
/*
* Note: to manage a linked list, we need a pointer to its beginning,
* and we've used typedef to make List the name for a pointer of this
* type.
*/
typedef struct list{
// should point to linked list Node
Node * head;
int size;
} List;
// TODO why `plist` as a pointer to List can also point to Node?
/* returns number of nodes */
unsigned int ListItemCount(const List * plist)
{
unsigned int count = 0;
Node * pnode = *plist; /* set to start of list */
while (pnode != NULL)
{
++count;
pnode = pnode->next; /* set to next node */
}
return count;
}
The compiler should shout warnings at you for that code.
However lets take a look at how it works...
The memory layout of the List structure is something like
+------+------+
| head | size |
+------+------+
(The above illustration ignores possible padding.)
The variable plist points to the beginning of that structure:
+------+------+
| head | size |
+------+------+
^
|
plist
As you can see it points to the location where head is stored. So by dereferencing plist we can get the head member.
But it is bad code and you should never write code like that. It makes code hard to read, understand and maintain. Be explicit and use
Node * pnode = plist->head; /* set to start of list */
instead.
So you know that this doesn't work.
How should it work?
Node * pnode = *plist;
This was intended to get the first node. It actually tries to assign the list type as the first node. To make it work, we need to get the head node out of that.
Node * pnode = (*plist).head;
This now actually returns a Node*
To write this more succinctly:
Node * pnode = plist->head;

C Confusion about pointer to pointers memory allocation?

I apologize if this might be viewed as a duplicate, but I cannot seem to find a conclusive answer that satisfies my question.
So I have a struct with a self referential pointer to pointers.
struct Node {
int id;
int edge_count;
struct Node **edges;
}
static struct Node s_graph[MAX_ID+1];
I then have a function that allocates some memory.
int add_edge(int tail, int head)
{
struct Node *ptail, *phead;
ptail = &s_graph[tail];
phead = &s_graph[head];
ptail->edges = realloc(ptail->edges, ++ptail->edge_count * sizeof(struct Node *));
if (ptail->edges) {
*(ptail->edges + ptail->edge_count - 1) = phead;
return 0;
}
return -1;
}
The above seems to work just fine. However, I keep seeing posts about pointer to pointers that lead me to wonder if I need to do something like the following in add_edge:
struct Node *phead = malloc(sizeof(struct Node *));
However, this does not seem logical. There should be enough memory for ptail->edges to store this pointer after the realloc call. I am fairly confident that I did the allocation correctly (albeit, inefficiently), but it is kind of sending me on a mind trip ... So when people declare pointer to pointers (e.g., **ptr) and then allocate memory for both ptr and *ptr, wouldn't that technically make ptr a pointer to pointers to pointers (and maybe clearer to declare as ***ptr)? Or maybe I am wrong and missing something conceptually?
Thank you in advance!
It depends on the situation, there is no general answer. If you have a pointer to pointer, eg Node**, and you want to store new data into it, then you need to have two levels of allocations, otherwise one is enough.
struct Node** nodes = calloc(AMOUNT, sizeof(struct Node*));
Now you have an array of struct Node* elements, so each element is a pointer to a struct Node.
Now how do you fill this array? You could want to insert new nodes inside it. Then you wouold require to allocate them, eg
nodes[0] = calloc(1, sizeof(struct Node)); // <- mind Node, not Node*
But in your situation you just want to set the address to an element of an array of the static variable s_graph, so you don't need to allocate a second level, you directly set the value.
So:
struct Node** nodes = calloc(AMOUNT, sizeof(struct Node*));
nodes -> | 0 | 1 | 2 | 3 |
nodes[0] = calloc(1, sizeof(struct Node))
nodes -> | 0 | 1 | 2 | 3 |
|
|
v
| NODE |
But if you have s_graph you already have them allocated, so it's something like:
static struct Node s_graph[MAX_ID+1];
struct Node** nodes = calloc(AMOUNT, sizeof(struct Node*));
nodes -> | 0 | 1 | 2 | 3 |
s_graph -> | N1 | N2 | N3 |
nodes[0] = &s_graph[0];
nodes -> | 0 | 1 | 2 | 3 |
|
|----|
v
s_graph -> | N1 | N2 | N3 |

what is the purpose of adding "struct name *next" inside "struct name" in linked list. I mean i actually cant process what exactly happens

#include<stdio.h>
#include<stdlib.h>
typedef struct employ
{
int reg;
int sal;
char *name;
struct employ *next; // I want to know the purpose of this line
}EMP;
int main(void)
{
EMP *first,*emp1,*emp2,*emp3,*ans;
first = (EMP *)malloc(sizeof(EMP));
first->next = NULL;
/////first///////
emp1 = (EMP *)malloc(sizeof(EMP));
if(emp1 == NULL)
{
perror("malloc error");
exit(1);
}
emp1->reg = 100;
emp1->sal = 30000;
emp1->name = "james";
emp1->next = first;
first = emp1;
/* I havent completed the program bcoz its not necessary here */
In a linked list, each node contains a pointer to the next node.
struct employ *next;
is used to achieve that effect
+---------+ +---------+
| Node1 |------->| Node2 |----> ...
+---------+ +---------+
if you are in node1, next is a pointer to node2, that way you can accesss next element from the current element
A linked list is a data structure consisting of a group of nodes which together represent a sequence. Here the reg, sal and *name represent your data structure and *next will hold the link to next element in the list.
Consider the following data structure
struct sample {
int number;
struct sample *next;
};
The pictorial representation for this structure would be
The above example has 3 elements, every element is an individual structure variable. In the above example the variable 1 has members number and *next. Here, the number contains 12 and the *next contains the address of the structure variable holding the data 99. Since the type of the variable holding the data 99 is of type struct sample that is why we take *next type as struct sample type.

Resources