Structure In C for linked list - c

Sorry for asking such a stupid question but I am really confused.
struct Amit
{
int a;
struct Amit *link;
}
*start;
Here both *link and *start are used to point to a node of a linked list, but what's the difference between these two and why can't we put *start inside the structure body?

The link is a member of the structure type. Every structure of type struct Amit has one.
The start is a variable of type 'pointer to struct Amit'. At any given time, there can be at most one variable called start visible.
You could put start inside the structure, but it would become a member of the structure (like link), and you would still need to declare variables of the structure type, or pointers to them.
The idea is that each structure on a list except the last contains a link pointer to the next structure on the list. Normally, the last structure on the list has a link pointer that is NULL (0). When searching down a list, you look at the values, and when you need the next item, you follow the link to it, stopping when the link is NULL.
struct Amit *item = start;
while (item != NULL && item->a != value_wanted)
item = item->link;
It is possible to build a circular linked list instead, which has a different stop criterion.
Looking at the comments, and explaining a bit more...
One way to create a list is:
struct Amit root = { 0, NULL };
struct Amit *start = &root;
The variable root is a structure initialized with root.a == 0 and root.link == NULL (or, equivalently, root.link == 0). The pointer variable start points to (stores the address of) root. Given a new node:
struct Amit next = { 1, NULL };
we can add that to the front of the list which start points to:
next.link = start;
start = &next;
A more plausible way to create a list is by dynamically allocating nodes, including the root node. Consistency is crucial because you have to free the dynamically allocated nodes, and having some nodes dynamically allocated and others not is messy. (I'm assuming that function void *emalloc(size_t nbytes); is a cover function for malloc() that never returns a null pointer - so it does the error checking for me.)
// Create the empty list
start = emalloc(sizeof(*start));
start->a = 0;
start->link = NULL;
// Create a node
struct Amit *node = emalloc(sizeof(*node));
node->a = 42;
node->link = NULL:
// Add the node to the font of the list
node->link = start;
start = node;
You'd normally package this stuff up into functions which manage the allocation, initialization and linking of the nodes.
struct Amit *add_node(struct Amit *start, int value)
{
struct Amit *node = emalloc(sizeof(*node));
node->a = value;
node->link = start;
return start;
}
start = add_node(start, 42);
start = add_node(start, 30);
start = add_node(start, 18);
for (node = start; node->link != 0; node = node->link)
printf("Node: %d (%p)\n", node->a, node->link);
Etc.

This basically defines three things:
a struct (don't capitalize it as Struct, by the way)
a member variable within the struct, named link
a variable outside the struct named start
You can reduce the confusion by separating the definition of the struct from the declaration of the start variable, like this:
struct Amit
{
int a;
struct Amit *link;
};
struct Amit *start;

If you rename "link" to "next" it might help you get a better sense of it. A linked list is like a chain - your "start" (or as usually called, the list "head") is the first ring of the chain, and the next ring of the chain is linked to it through your "next" pointer (in your case, your "link" pointer). You know you got to the last item on your chain when there are no other rings (link is NULL).

Start points to the top of the list and is available globally to your program. Whereas link 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 |
+------+ +------+ +------+
| link |---->| link |---->| link |----> NULL
+------+ +------+ +------+
^
|
START (Keep track of the whole list.)
Hope that helps clarify.

Related

Challenging the Node syntax

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.

Pointer to a pointer, how do I get values?

Lets say I have the following code,
typedef struct WordNode WordNode;
struct WordNode {
int freq; // The frequency of the the word.
char *word; // The word itself.
WordNode *next; // The next word node in the list.
};
struct WordSet {
int size; // The number of elements in the set.
WordNode *head; // The starting node in the set.
};
After this, I've got some functions that initialize these structs. To prevent too much code in this post, I'm going to avoid posting those functions here.
Now, lets say I have the following,
WordNode **p = wset->head; // can't change this line
Here, p is basically a pointer pointing to a pointer, correct?
And then, if I do this:
(*p) == NULL
This would return true if p is pointing to NULL, right?
Now, how would I get the word stored in wset->head?
Can I do this?
(*(*p))->word
And if I want p to point to the next WordNode, can I do this?
p = (*(*p))->next
I just want to know if all this is valid syntax so that I know I'm using pointers correctly.
Not really. (*(*p))->word is a total dereferenciation. So it would either be (*(*p)).word or (*p)->word.
You can imagine it that way, that the ->-Operator takes away one reference for you.
obj->field is the same as (*obj).field
Just for the sake of simplicity, whenever I have to deal with double pointer and I need the value I all the time go via an intermediate variable
e.g.
WordNode **ptr2ptr = wset->head;
WordNode *ptr = *ptr2Ptr;
WordNode value = *ptr;
or to get the head:
WordNode head = ptr->head;
Now I'm just answering the question which is, how to access the value of a pointer to pointer. You must be careful that your wset->head contains actually a pointer to pointer which is normally not the case in a linked list the way I understand you are trying to do. This is also not the way you have defined your head member...

Changing nodes in linked list

This is somewhat mind-boggling
i will try to explain my doubt.
Check this function for example:
void snoc(Lint *l, int val){
Lint i, new;
new = (Lint) malloc(sizeof(Nodo));
new->value = val;
new->next = NULL;
i=(*l);
while(i->next!=NULL){
i=i->next;
}
i->next = new;
}
I understand the concept behind and i have no trouble working with lists, taking in consideration that i can't iterate through the list using the list initial pointer itself (if i do this, i would lose the initial pointer right)
The thing is, making i=(*l) and afterwards iterating through the list using i=i->next, is making the i variable becoming in constant change.
In this particular example, the original list will not change until i find the end of the linked list, and then i make an attribution and voilá! I insert an element at the end.
My doubt is, if by changing the i, and making i->next = new at the end, wouldn't that mean that everytime i make i=i->next, change ALL the nodes in the original list?
Another example would be init:
void init (Lint *l){
Lint i, prev;
i=(*l);
prev=NULL;
while(i!=NULL){
if( (i->next)->next==NULL){
i->next = NULL;
}
i=i->next;
}
}
if i do this, the last element will be removed, by changing the i->next to NULL, at the right moment. But before that, i've been making changes to the i itself again, by telling i=i->next
If i were to make this change to the (*l) itself (by doing (*l)=(*l)->next) i would be ruining the original list .
I really hope you guys can understand my doubt.
Yes, we do understand your confusion, and it comes from not working out the list pointers on a piece of paper so you can visualize what is taking place. Always use a diagram when you are working node link issues. For example in your case with your singly linked-list, current node called i (dubious choice of name) and your new node called new a helpful diagram would be:
Singly Linked-List (non-circular)
Tail Current Head
(list start) i new
+------------+ +------------+ +------------+
| Payload | | Payload | | Payload |
+------------+ +------------+ +------------+
| Next |------->| Next |------->| Next |--->NULL
+------------+ +------------+ +------------+
Now, I bet you can tell what:
changing i, and making i->next = new at the end
would do. This isn't a dig or meant to be condescending, it is really the way you need to work out linked-list issues until you have done it enough you can visualize the pointer wiring in your head. This is even more important when you get to circular or doubly-linked list insertions and deletions. No matter what the problem, if you just write it down and label all the connections that are being made or broken, you can then code it cleanly in your editor.
with some minors modifications your code is like this
void snoc(Lint *l, int val)
{
Lint i, new;
new = (Lint) malloc(sizeof(Nodo));
new->value = val;
new->next = NULL;
i = *l;
if(!(*l))
{
*l = new;
return;
}
while(i->next) i = i->next; // (1)
i->next = new; // (2)
}
and, this is its explanation:
In (1) we walk throught the linked list until its end. We know we are at the end because i->next (which point after each loop step to the next nodo item) is null so in that case, we make i->next point to the newly created nodo item in (2). But l never changed during the function, l is always pointing to the begining of our linked list so the purpose of this function is to add a new element at the end without changing the value of l.
but also we can initialize our linked list with this function...for example:
Lint l = NULL;
snoc(&l, 10); // l will be initialized with a new nodo item with 10 as the value its value member
(0) checks if l is null in that case we make *l point to the newly allocated nodo item and return...so initialization done.
I add another way for the code above
void snoc(Lint *l, int val)
{
Lint now, new, previous;
new = (Lint) malloc(sizeof(Nodo));
new->value = val;
new->next = NULL;
if(!(*l)) // (0)
{
*l = new;
return;
}
for(now = *l; now; now = now->next)previous = now;
previous->next = new;
}
I am not sure I understand your question, but why don't you simply copy the pointer? You can keep a pointer to the initial element and use a second one to traverse though it.

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.

How to remove a node any integer data

I am working on my homework but I really don't know how to remove a node with an integer data I already have a code for adding of nodes, I just need to remove nodes, or can you give me atleast an algorithm of it goes like this
addnode(root,5);
addnode(root,2);
addnode(root,6);
display(root);
removenode(root,5);
display(root);
removenode(root,6);
do you guys need code for my addition code? but our proff already gave us the code for showing the display of nodes ;
void display(struct node *head)
{
struct node *traverser;
traverser = head;
while(traverser!=NULL)
{
printf("%d\n",traverser->x);
traverser=traverser->next;
}
}
struct node
{
int data;
struct node *next
};
a question though what does traverser=traverser->next;
I assume you are dealing with a linked list. These are usually built up of entries that contain data and a link to the following name (thus the name):
struct node {
int data;
struct node *next;
}
As you can see, the link is a pointer in C. Which should point to the next entry. To start traversing a list, you usually have got a head.
If you want to remove an entry, you need to traverse the list and once you found the entry you want to remove, simply rearrange the pointers:
void removeEntry(int data, struct node *head) {
struct node *prev = NULL, *current = head;
while(current->data != data) {
prev = current; // current will always point to the entry in front of current
current = current->next;
if(current == NULL) // end of list and no match
return;
}
// now current is pointing to the entry you want to remove
// remove it just by rearrangeing pointers
prev->next = current->next;
free(current); // I assume you malloc'ed the memory
}
Note: Please note that I omitted errorchecking here. Also, sometimes the head is a fixed item in which no data is stored (would work in my case), sometimes head can contain data itself (in this case you need to check if the element you want to remove is the first element and relink head accordingly)
1)
you can delete the node from the linked list like(considering head is not dummy node i.e head also contains data)...
int flag=0;
if(head->data==data_todel) head=head->next; //if head contains the data
ptr=head;
while(ptr->next!=NULL && flag==0)
{
if(ptr->next->data!=data_todel)
ptr=ptr->next;
else
{
flag=1;
break;
}
}
if(flag) ptr->next=ptr->next->next;
you need to use two pointers to free the deleted node.
2)
+------+-------+ +------+-------+
| data1| next | | data2| next |
+------+-------+ +------+-------+
^ | ^
| | |
| +--------------+
+---------+
|traverser|
+---------+
after traverser=traverser->next
+------+-------+ +------+-------+
| data1| next | | data2| next |
+------+-------+ +------+-------+
| ^ ^
| | |
+--------------+ |
|
+---------+
|traverser|
+---------+
that means it is assigning the address of of the next node currently pointed by traverser.
a question though what does traverser=traverser->next;
It sets the pointer to the next element in the queue. Iterating in your while cicle until it reaches a null pointer (end of the queue).
(You didn't post the node structure declaration, so i'm just guessing)
The next field is the key in the linked list. Each element has a successor, that way the list is linked. So, when you traverse the list, you start at the first element head and move from one element to the next until there is no next element.
To remove an entry, you need to cycle through the list until you find that entry. Then, set the next variable of the previous entry to the next entry. That way, the element is removed from the list.

Resources