Suppose I have 3 nodes already in the list (i.e. 10 , 20). And I want to insert 30. So wrote as below
struct node *p,*temp;
p=start;
temp=(struct node*)malloc(sizeof(struct node));
temp->info=30;
temp->link=NULL;
while(p-link!=NULL)
{
p=p->link;
}
p->link=temp;
It worked perfectly until I do this: while(p!=NULL) rest is same..
Similarly in case of showing the node I wrote as follows
while(p!=NULL)
{
printf("%d \n",p->info);
p=p->link;
}
This also worked fine until I changed it to: while(p->link!=NULL)
I want to know what is happening why is not working? Give me the reason why we are using while(p!=NULL) in case of showing the all the data and while(p->link!=NULL) in case of inserting any node?
Before the first while loop, you've got something like this. Two nodes (not three as you state) in a linked-list, pointed to by start and a new node, pointed to by temp:
start-->+---------+ +-->+---------+ +---------+<--temp
|info:10 | | |info:20 | |info:30 |
|link:xxxx|--+ |link:NULL| |link:NULL|
+---------+ +---------+ +---------+
To add the new node to the end of the list, you need to advance p from the first node (pointed to by start) until p points at the node whose link is NULL (i.e., until p->link!=NULL fails to be true):
start-->+---------+ +-->+---------+ +---------+<--temp
|info:10 | | |info:20 | |info:30 |
|link:xxxx|--+ |link:NULL| |link:NULL|
+---------+ +---------+ +---------+
^
|
p -+
Once you have found the last node, you then "plumb" in your new node to get a three-element list:
start-->+---------+ +-->+---------+ +-->+---------+
|info:10 | | |info:20 | | |info:30 |
|link:xxxx|--+ |link:yyyy|--+ |link:NULL|
+---------+ +---------+ +---------+
However, when you're printing all of the nodes, you start p at the first node (i.e. start) and print the details of every node until p has been set to NULL (i.e. p!=NULL fails to be true). If you stopped when p->link was NULL, you would not have printed the last node.
A linked list, in C is a struct that contains data and a pointer to the next element (and maybe a pointer to the previous element, but that doesn't seem to be your case). It would be something like this:
struct node {
int data; //could be any type
struct node *next;
};
To insert elements in the end of the list, you need to go to the end of it - when there is no next element. To do that, you check node->next == NULL. Then you make node->next = new_node
To find an element in the list, you need to loop for all elements until you find it. If the element doesn't exists in the list, you need to prevent the user from accessing an invalid element, so you test node == NULL to finish the loop safely. This case is also applicable if you want to just print all data in the list - you need to reach all elements, the test would be the same (if you were testing node->next == NULL, you would skip the last element).
Related
I've just recently gotten into linked lists and I'm adding my own "add to end" function.
void insert_at_end(Node** head, Node* node)
{
Node* temp;
temp = *head;
if (temp == NULL) // linked list is empty
{
*head = node;
}
else
{
while (temp->pNext != NULL)
{
temp = temp->pNext;
}
temp->pNext = node;
}
}
Originally I was doing temp != NULL instead of temp->pNext != NULL because I thought that way it would take me to the very LAST node, since it stops looping when temp still has data before it reaches NULL. Wouldn't temp->pNext != NULL stop at the 2nd to last node? Since it stops looping when it realizes that the last nodes next pointer is NULL, it does not travel to that node?
Thanks guys, If I need to clear anything up from that word vomit let me know.
Wouldn't temp->pNext != NULL stop at the 2nd to last node?
No. Here is the pictorial representation for ease of understanding.
With temp != NULL, temp will be pointing to NULL:
+---+ +---+ +---+
| 1 |--->| 2 |--->| 3 |---> NULL
+---+ +---+ +---+ ^
|
temp
As you see temp is iterating until it becomes NULL, at which point you cannot attach anything to the final node because you're past it.
With temp->pNext != NULL, temp will be pointing to last node.
+---+ +---+ +---+
| 1 |--->| 2 |--->| 3 |---> NULL
+---+ +---+ +---+
^
|
temp
Here temp will iterate till its next node is NULL. That means you're pointing to the final node and you can use that pointer to adjust that node to point to a new one with temp->pNext = node:
+---+ +---+ +---+ +---+
| 1 |--->| 2 |--->| 3 |--->| 4 |---> NULL
+---+ +---+ +---+ +---+
^
|
temp
As an aside, you may also want to add the extra safety of ensuring the node you're given points to NULL, on the off chance the caller may forget to do that. That's as simple as adding this line to the start of the function:
node->pNext = NULL;
Let's make some analogy.
Each node is a station.
NULL is your stop station.
while (temp->pNext != NULL) { temp = temp->pNext; } means drive and visit each station until reach the stop station.
When you reach the stop station, an additional station is needed to be added by temp->pNext = node;
Now the former stop station followed by the new added stop station(implicitly the new NULL) is not a stop station, but the penultimate station to be visited.
have a reference for simple linked list concept
let us take an example
consider
struct node
{
int data;// data which you want to feed.
struct node *next;// gona hold the address of the next data, so that link can be established
}*root,*p; // root is the starting reference to your linked list
case 1: you dont insert any element and your linked list is empty. Now when you insert a new data 10.it will check for any data in the global pointer reference to your linked list, if, the pointer seems to be NULL, then it means your liked list is empty.The memory stack will be created like this.
10
1000
10 is the data, 1000 is its address.
case 2: adding an element at its back.you want to add, data 20 to your linked list.you will be looking whether the linked list is empty or not first, using your global linked list address reference(it will be a pointer variable, holding your linked list 1st address, as per your code)
now when we see root->data is not null 1000->data is 10
we go for root->next which is null, which we come to know that this is the last node. 1000->next is NULL
and we insert the new node address to the root->next so that a link is created to the newly inserted node.
stack will be created like this
10 20
1000 1004
case3: now you want to add another data say 30 to the end of list again. just follow the same as case 2.
check for the node which is currently null, i.e root->next == NULL,
for this you use a loop to find the node which is currently in last, like this.
struct node *temp; // creating a temp node which will be the new node we will insert
temp = (struct node *)malloc(sizeof(struct node));// allocating the size for the temp node, same as the size of previous nodes.
p = root;// i am giving my starting address to pointer p, i traverse the node with pointer p only, since i dont want to loose my root starting address.
while(p->next != NULL)// checking for the last node
p = p->next;// if last node not found, just move to next node, and see whether it is last node or not
p->next = temp;// if last node is found, put the address of newly created temp node to the node previously found last in the linked list.
temp->data = element;// feeding data to the temp node.
temp->next = NULL;// keeping temp node as last, it is necessary to say temp wont has any more node connected.
NOTE dont think this is just a temp node, and will disappear once we come out of function, it is playing with pointer, so it wont destroyed until, the owner wont destroy it.
flow will be
newly created temp address is 1008
1000->next is 1004
1004->next is NULL
so, 1004->next will hold 1008 now
then,1008->data will be 30
then, 1008->next will be NULL
stack will be created like this
10 20 30
1000 1004 1008
I have some questions regarding the definition of a linked list as it was defined in my class.
This is what was used:
typedef struct node_t {
int x;
struct node_t *next;
} *Node;
Now, I understand that this way we created a shorter way to use pointers to the struct node_t. Node will be used as struct node_t*.
Now, say we want to create a linked list. For example:
Node node1 = malloc(sizeof(*node1));
Node node2 = malloc(sizeof(*node2));
Node node3 = malloc(sizeof(*node3));
node1->x = 1;
node1->next = node2;
node2->x = 4;
node2->next = node3;
node3->x = 9;
node3->next = NULL;
This is roughly how I imagine this (The circles represent the structures):
Now I know it's wrong, but I can't understand why. We have a pointer, node1, that points to our structure. Then, we point at node2, which points at another structure and so and so on.
Another things is, I can't understand how is it possible to have the longer arrows in the picture. Shouldn't we only be able to point to a structure from each lower part of the circle, and not to a pointer to a structure? How is this possible?
If anyone here could make things a little clearer it would be hugely appreciated. Thank a lot.
You have three linked nodes, and additional local pointers pointing to them.
The nodes don't know anything about those local pointers though, even if it is often convenient to use their names to refer to the nodes.
Instead, they know the next node in the sequence, respectively the last node knows none.
Put another way, your image is flat-out wrong.
+---+------+
node1 --> | 1 | next |
+---+-|----+
|
v
+---+------+
node2 --> | 4 | next |
+---+-|----+
|
v
+---+------+
node3 --> | 9 | NULL |
+---+------+
Assignment is a transitive operation. So,
node1->next = node2;
would mean that node1->next points to whatever node2 was pointing to. And, in particular, node1->next does not point to node2 itself.
Each of node1, node2, and node3 name a variable that is a pointer.
node1 node2 node3
+---+ +---+ +---+
| * | | * | | * |
+ | + + | + + | +
v v v
+---+---+ +---+---+ +---+---+
| 1 | * --> | 4 | * --> | 9 | * --> NULL
+---+---+ +---+---+ +---+---+
typedef struct node_t {
int x;
struct node_t *next;
} *Node; /* <-- don't typedef pointers */
Simply use Node instead of Node * and then allocate with:
Node *node1 = malloc(sizeof(*node1));
Why? Somebody looking at your code 100 lines below the declaration of your typedef will not inherently know whether Node is a type, or whether it is a pointer-to-type. This type of confusion will only grow as your code grows in size. Review: Is it a good idea to typedef pointers?.
(note: good job using the dereferenced pointer to set the typesize in sizeof)
A Linked List
A linked list is simply a clever data structure that allows you to iterate over a number of independently allocated nodes. Each node contains some data and then a pointer to the next node in the list, or NULL if that node is the final node in the list.
(for a doubly-linked list, you simply add a prev pointer that also points to the node before the current node in the list. You also have circular lists where the last node points back to the first allowing iteration from any node to any other node in the list regardless of which node you begin iterating with. For a doubly-linked circular list, you can iterate the entire list in both directions from any node)
In your case, your list is simply:
node1 +-> node2 +-> node3
+------+ | +------+ | +------+
| data | | | data | | | data |
|------| | |------| | |------|
| next |--+ | next |--+ | next |---> NULL
+------+ +------+ +------+
Where your data is a single integer value and your next pointer simply holds the address of the next node in your list, or NULL if it is the final node in the list. Adding your data, your list would be:
node1 +-> node2 +-> node3
+------+ | +------+ | +------+
| 1 | | | 4 | | | 9 |
|------| | |------| | |------|
| next |--+ | next |--+ | next |---> NULL
+------+ +------+ +------+
When creating a list, the first node is usually referred to as the head of the list and the last node the tail of the list. You must always preserve a pointer to the head of your list as that pointer holds the beginning list-address. For efficient insertions into the list, it is also a good idea to keep a pointer to the tail node so you can simply insert the new node without iterating over the list to find the last node each time, e.g.:
Node *newnode = malloc(sizeof(*newnode)); /* allocate */
newnode->next = NULL; /* initialize next NULL */
tail->next = newnode; /* assign to tail */
tail = newnode; /* set new tail at newnode */
Lists are fundamental to C, there are many used in the Linux kernel itself. Take the time to understand them and how to write them in the differing variants. You'll be glad you did. Lastly, don't forget to write a simple function to free your list when you are done (and free the data as well if it is allocated). A simple free_list function would be:
void free_list (Node *list)
{
while (list) {
Node *victim = list; /* separate pointer to node to free */
list = list->next; /* can you see why you iterate next... */
free (victim); /* before you free the victim node? */
}
}
Let me know if you have further questions.
I am having big problems understanding linked lists and I would be very thankful if someone could explain me the following.
Element_t *pushfront(Element_t *list)
{
if(list==0)
return allocate();
list->prev=allocate();
list->prev->next=list;
list=list->prev;
return list;
}
What here means list->prev->next=list ?
What means this: f->next->prev=f->prev?
I know that this is just a part from program code, but I hope someone can give me general meaning of these as simpliest as can?
The list has nodes that have references to the previous node and to the next node in the list.
The function gets the first node of the list. So this first node does not have a previous node.
In this statement
list->prev=allocate();
a previous node is created because as it follows from the function name it push a new node at the beginning of the list.
In this statement
list->prev->next=list;
expression list->prev yields the address of the new created node. This created node shall point to the current first node of the list. Thus its data member next shall contain the address of the node list.
And this statement
list->prev->next=list;
does this.
It can be imagined simpler if to introduce an intermediate variable.
For example
Element_t *new_node = allocate();
list->prev = new_node; // list->prev=allocate();
new_node->next = list; //list->prev->next=list;
list = new_node; //list=list->prev;
return list;
As for this question
What means this: f->next->prev=f->prev?
then it looks like that the node f is removed from the list. Now its next node (f->next) will not point to f but will point to the preceding node of f.
Again it will be more clear if to introduce intermediate variables.
Element_t *previous_node_of_f = f->prev;
Element_t *next_node_of_f = f->next;
next_node_of_f->prev = previous_node_of_f; // f->next->prev=f->prev
If to add also a statement like this
previous_node_of_f->next = next_node_of_f;
then the node f will be fully removed from the list.
--------------------------------------------------------
| prev ^
| |
---------------------- ---------------------- ----------------------
| previous_node_of_f | | f | | next_node_of_f |
---------------------- ---------------------- ----------------------
| ^
| next |
-------------------------------------------------------
Here is your code with comments, which tell you what is happening.
Element_t *pushfront(Element_t *list)
{
if(list==0) // If the list is emtpy
return allocate(); /* then you simply create a new node, which
represents your list and return it. The size of your list grew from 0 to 1.*/
list->prev=allocate(); /*If the list is not empty, you add a new node by creating it,
and then the prev pointer of the first element in the list (list->prev)
is set to this new element, as you want it to be first.*/
list->prev->next=list; /*Then you need to set the next pointer
to the element you just added. The new element is at list->prev,
so by list->prev->next, you just say, that the next element of the one
you just created is the element that was first before you added the new one*/
list=list->prev; /* Here you just set the new element as the head of the list*/
return list; /*And here you return the new list*/
}
Note, that your list is always passed just as a pointer to the first element, as that's all you need. You can then access all of the elements by next pointer, which is set for each element in the list.
Firstly the linked lists are linked each others with pointers. They are not in order in fact they are distributed on memory.
Let me get on your question-1 list->prev->next=list;
Here you are linking the previous node with the current node. This code means that link the next of previous to the current node. Then the previous node now linked with next pointer which is defined in structure.
Get the question-2 f->next->prev=f->prev;
I dont know where this is defined but here you are doing that a circled linked list. The last node linked to the first node by this code.
Element_t is a probably a typedef similar to the following:
typedef struct Element {
struct Element * next;
struct Element * prev;
void * data;
} Element_t;
Assuming this, your linked list basicly works like this:
(list)
A B C
+----------+ +----------+ +----------+
| next=B |--->| next=C |--->| next=0 |
| prev=0 |<---| prev=A |<---| prev=B |
| data="A" | | data="B" | | data="C" |
+----------+ +----------+ +----------+
So now you want to add a new node N in front of A
(list)
N A B C
+----------+ +----------+ +----------+ +----------+
| next=A |--->| next=B |--->| next=C |--->| next=0 |
| prev=0 |<---| prev=N |<---| prev=A |<---| prev=B |
| data="N" | | data="A" | | data="B" | | data="C" |
+----------+ +----------+ +----------+ +----------+
so, 1. A->prev needs to be set to N and 2. N->next needs to set to A.
list->prev=allocate(); this allocates the new N and already assigns A->prev=N.
Next in line: list->prev->next=list: Read list->prev as the new node that just got alloced. Then it's N->next=A - the second step.
And your new element is linked in the list. Obviously, allocate() needs to initialize next and prev to NULL.
What means this: f->next->prev=f->prev?
Depends on where it's written. Here, it's probably part of a function, that removes a node from the list.
I am new to C, i am trying to learn linked lists, can some one explain me the code below.
I understand some part of it but not all of it.
void deletefrombeginning( node **head, node **tail)
{
node *temp;
if(*head==NULL)
return;
temp=*head;
if(*head==*tail)
*head=*tail=NULL;
else
{
(temp->next)->prev=NULL; <-- there is where i get lost.
*head=temp->next;
}
free(temp);
}
(temp->next)->prev=NULL;
This line is making the prev pointer of what will be your new head NULL. So that when the second item in your linked list becomes the new head with:
*head = temp->next;
it has no prev pointer and is therefore the new head.
------ ------
| | <--prev--- | |
NULL <----- | temp | | node | -----> ...
| | ---next--> | |
------ ------
Short answer:
(temp->next)->prev=NULL; makes sure that node->prev doesn't
access invalid memory.
*head=temp->next; makes temp the new head of the list.
Long answer:
You are currently at temp.
You cannot delete temp first because you then would have broken links (what would node->prev point to?).
This means you have to first remove the links related to temp.
Since temp is the first node, temp->prev should point to NULL.
So (temp->next)->prev=NULL; is equivalent to node->prev = NULL;.
We cannot directly do node->prev = NULL; because we do not know node exists at this point.
*head=temp->next makes sure that the new list head is node (in my above ascii demonstration).
The next step then frees the memory used by temp.
Tip: In case you're nitpicky like me, you might want to assign temp to NULL right after you free it. This makes sure that you can never mistakenly access temp in the rest of your code. Memory can still be accessed in error even after freeing it.
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.