Challenging the Node syntax - c

The following is a syntax, part of linked list in C programming language
struct tag-name
{
type member1;
type member2;
.......
.......
struct tag-name *next;
};
Why do we have to again write struct tag-name before the pointer variable next. Why can we not use void *next or int *next or something like that??

for a linked list the next entry (or whatever its named) must point to the next node. In your case the node type is tag-name.
so you need <type> next;
in C (different for c++) the way you ask for a pointer to a struct called x is to do struct x *. Hence the code you see that is confusing / upsetting you. Can you simplify it? Yes you can. C has typedef. You can do
typedef struct tag-name node;
and now you can have
struct tag-name
{
type member1;
type member2;
.......
.......
node *next;
};
You ask, can I have void* next. Yes but why do it? You will have to keep casting that pointer to a pointer to the struct (the compiler does not know implicitly what it points to), also a reader of the code will be surprised because they expect the next pointer to be a pointer to a node.
You ask can it be int next. No it cannot, the next object is a node, not an int

Think about the typical illustration of a linked list:
node node node
+------+------+ +------+------+ +------+------+
| data | next | --> | data | next | --> | data | next | --> ...
+------+------+ +------+------+ +------+------+
Each item in the list is a node of some type, and that node contains a next member that explicitly points to the next node in the list. In C, that typically translates to a struct type like
struct node
{
T data; // for some type T
struct node *next;
};
IOW, each struct node has a next member that points to another object of type struct node - not int, not void, etc., which is why we don't declare next as an int *, or a void *, or whatever.
However...
Depending on how you implement your list, you can use something other than a struct node * as your next item. Normally when we implement a list, we dynamically allocate each node using malloc as we need it. However, if you know that your list will never get bigger than some known, reasonably small value, you can set aside an array of struct node as your "heap", and your next member can be an array index value:
struct node
{
T data;
int next; // holds the *index* of the next element
} heap[SOME_SIZE];
You then initialize your "heap" so that each element explicitly points to the next in the array:
for ( int i = 0; i < SOME_SIZE-1; i++ )
{
heap[i].next = i+1;
}
heap[SOME_SIZE-1].next = -1; // use -1 to indicate "null"
Now, all you need is a couple of integers, one to point to the first available element in the array, and the other to point to the head of your list:
int avail = 0; // initially points to the first element in the "heap"
int head = -1; // initially "null"
"Allocating" a node then just becomes a matter of finding the first free node in the "heap":
int node = avail; // get the index of the next available node in the "heap";
avail = heap[avail].next; // update avail to point to the next available node
"Freeing" a node just means adding that index back to the head of the avail list:
heap[node].next = avail; // set this node point to the first free element
avail = node; // make this node the first free element;
Remember, node and avail are not node objects, they're simply indices into an array of node objects.
We typically don't do it this way because it's conceptually simpler for next to point to another struct node object directly, rather than be an index into an array. We can still use a fixed-sized array as our "heap", we just use the address of each element instead of its index.

Related

What is meant by struct node *next; in a linked list program made in c language?

// Linked list implementation in C
#include <stdio.h>
#include <stdlib.h>
// Creating a node
struct node {
int value;
struct node *next; //What is this, what are we doing here?
};
// print the linked list value
void printLinkedlist(struct node *p) {
while (p != NULL) {
printf("%d ", p->value);
p = p->next;
}
}
int main() {
// Initialize nodes
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;
// Allocate memory
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));
// Assign value values
one->value = 1;
two->value = 2;
three->value = 3;
// Connect nodes
one->next = two;
two->next = three;
three->next = NULL;
// printing node-value
head = one;
printLinkedlist(head);
}
I want to ask what are we doing here with this line of code?
it's in the creating a node part of the code (top).
struct node *next;
Are we assigning a pointer type struct variable for the sturct node but its inside of the same struct, assigning a variable named *next inside the same struct? But that isn't allowed, right?
we can either declare the variable out side the } and between ; or in the main()
function part of the code only, Isn't it?
Like
main()
{
struct node *next;
}
Again, then I came across a post mentioning it as a pointer to the structure itself, can anyone explaine how can we do this inside the same struct?
The next member points to another instance of struct node. Graphically, we usually represent it like this:
+–––––––+––––––+ +–––––––+––––––+
| value | next |––––> | value | next |
+–––––––+––––––+ +–––––––+––––––+
A struct type cannot contain an instance of itself - we can’t create a type like
struct node {
int value;
struct node next;
};
for two reasons:
The type definition isn’t complete until the closing }, and you cannot create an instance of an incomplete type;
The type would require infinite storage (struct node contains a member next of type struct node which contains a member next of type struct node which contains a member next of type struct node...);
However, we can declare next as a pointer to struct node, since we can create pointers to incomplete types. The size and representation of a pointer is independent of the size and representation of the type it points to.
What it means
The line struct node *next; is read as "next is a pointer to another struct node".
This is just a recursive structure declaration (definition):
struct node {
int value;
struct node *next; //What is this, what are we doing here?
};
It says a node consist of two parts:
an integer value
a pointer to another node.
The wiki article on linked lists has a nice visualization showing how one node points to another (or to NULL to end the chain).
How does it work?
As you noted, the interesting part is how the declaration can include a reference back to itself. The compiler handles this in two steps:
It sizes the struct as consisting of an int and a pointer (they're all the same size regardless of what they are pointing to).
Later it type checks the assignment and generates the appropriate assembly. When you write one->value = 1;, it makes sure the 1 is an integer and generates code to move 1 to the integer slot. And when your write one->next = two;, it verified that two is a pointer to a node and generates code to move that pointer to the second slot for the struct node pointer.

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;

What is self-referencing structure in C?

struct LinkedList
{
int data;
struct LinkedList *next;
};
In the code, within the definition of struct LinkedList there is a pointer to the structure itself.
How does it work?
So, the code
struct LinkedList
{
int data;
struct LinkedList *next;
};
defines a struct type containing two members named data and next, with the next member storing the address of a different object of the same type. Given the code:
struct LinkedList Node1 = { .data = 1, .next = NULL };
struct LinkedList Node0 = { .data = 0, .next = &Node1 };
you get something that sort of looks like this:
Node0 Node1
+---+--------+ +---+------+
| 0 | &Node1 |--->| 1 | NULL |
+---+--------+ +---+------+
(Note that you would never create a linked list this way, this is just for illustration).
This is possible for two reasons:
C allows you to declare pointers to incomplete types;
Pointers to struct types all have the same size and representation.
This is an example of a self-referential data type, which simply means that the type stores a reference (pointer) to a different object of the same type.
What you talk about are recursive data structrues and the question is how to let a data structure reference itself.
In C this can be done by declaring a pointer to itself in the definition of the data structure, "self" meaning a thing of its own type.
Note that when you write the expression, the data structure is not yet complete. Therefore it is not possible to let a data structue contain an occurence of itself, for once because the definition is not yet completely known and for two because the data strutcure would be never ending containing an occurrence of itself, itself,...
But you can declare a pointer to itself. The compiler now only allocates storage for the pointer and if you later assign/dereference the pointer it knows the storage pointed to contains an occurrence of itself. That is what you do in your example.
A self-referential pointer which points to the address of whatever it is a part of. So for example,
typedef struct node {
char data[30];
struct node *this;
struct node *next;
} Node;
*this is a self-referential pointer if it is assigned to whatever is applied to.
,and
Clearly a Cell cannot contain another cell as it becomes a never-ending recursion.
However a Cell CAN contain a pointer to another cell.
Refer this post as well.

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.

Linked-list is confusing

I am stuck, as I don't understand what is this code doing:
struct node
{
int info; /* This is the value or the data
in the node, as I understand */
struct node *next; /* This looks like a pointer. But
what is it doing in real life? */
} *last; /* What is this and why is it
outside the body? What is this
thing doing? */
I know that when a node is created, it has a value, and it is pointing to some other node
but I don't understand the syntax.
Is this a better way of writing the code above?
Is there a simpler way of writing the same struct for better understanding?
In my lectures they presume that the student has understanding of what they teach.
Well, we can explain this to you, but we can't understand it for you.
Code snippet you've provided is definition of variable last, being pointer to newly defined structure type node. It can be written other way as:
typedef struct _node_t {
int info;
node_t *next;
} node_t;
node_t *last;
This way we define typedef, which is, say, alias of type definition to some short name — in this particular case, it aliases structure of two fields as the name node_t. Wherever you define something as being of type node_t, you tell compiler that you mean 'this should be aforementioned structure of two fields', and node_t *last means 'variable last should be pointer to node_t type'.
So, back to syntax:
struct foo {
int a;
float b;
void *c;
} bar, *baz;
means 'Define structure type foo, and make it contain three fields — integer a, float-point b and untyped pointer c, then make variable bar to be of this structure type, and make variable baz to point to this structure type'.
Now to pointer. What you see is called 'recursive definition', e.g. type mentions itself in it's own definition. They are okay, if language supports them (C does), but one could avoid recursive definitions in linked list node structure by specifying next node pointer to be just untyped:
struct node_t {
int info;
void *next;
};
This way you no longer reference node_t type from node_t type, but that adds you some inconveniences when using this type (you have to explicitly cast next to node_t type, like ((*node_t)(last->next))->info instead of just last->next->info).
If you feel you need additional reference, consider taking a look at interactive online tutorials, like http://www.learn-c.org/ (I'm not affiliated).
that is the simplest way to write a linked list node , but why name it last ? name it node instead , this makes it more understandable , but here's how it works.
when a linked list is first created it contains only the root node (the first node in a linked list) , when you add a node , you fill the info field with the data that node will hold (note that info may be any kind of data , character , string , int ...) then set next to NULL , since that node is the last node in the list.
when you add another node , you change the value of next to point to the node you just added and you set the value of next to NULL in the node you just created because now that is the last node in the list .
you can repeat this to add as many nodes as your memory allow you to.
this link may help you to better understand structures
typedef struct marks {
int m;
struct marks *next;
} marks_t;
This way we define a structure so that a Linked List can be formed. Now we have defined the last variable next as a "structure pointer" which gives us the address of the next element in the list (i.e. as structure only)!
The last element does not point to any node (here marks structure) and hence the pointer variable has NULL value.
Now to define the first element:
marks_t *list;
if (list == NULL) {
list = (marks_t *) malloc(sizeof(marks_t));
}
list->m = 15;
list->next = NULL;
Now if we want to add an element next to this (i.e. second element):
marks_t *next1;
next1 = (marks_t *) malloc(sizeof(marks_t));
next1->m = 27;
next1->next = NULL;
list->next = next1; // Storing address of next1 structure in list

Resources