简体   繁体   中英

Insertion into a Linked list using double pointer in C

void insert(list **l, int x)
{
       list *p;
       p = malloc(sizeof(list));
       p->item = x;
       p->next = *l;
       *l=p;
}

Why did we use double pointer? Could we have done the same thing using single pointer? I saw this example in the book "The Algorithm Design Manual" page 69 2nd Edition.

List is basically node, just for refernce.

Could we have done the same thing using single pointer?

You could have done that using a single pointer with a minor update.

Return the pointer that was allocated and make sure that the function call is changed appropriately.

list* insert(list *l, int x)
{
   // list = *p
   // What was that? That is not valid code.

   list* p = malloc(sizeof(list));
   p->item = x;
   p->next = l;
   return p;
}

and use it as

list* l = NULL;
l = insert(l, 10);

using double pointer is justified here because in the function you insert node in the header of list, so the variable l will be changed with the new header *l=p;

*l->|node1|->|node2| //initial value
p->|nodeP| //after p = malloc(sizeof(list)); p->item = x;
p->|nodeP|->|node1|->|node2| //p->next = *l;
*l->|nodeP|->|node1|->|node2| //after *l=p

in this case function is called like this:

list *head;
insert(&head, 4);

For your question:

Could we have done the same thing using single pointer?

Yes, the function will look like this:

list *insert(list *l, int x)
{
       list *p;
       p = malloc(sizeof(list));
       p->item = x;
       p->next = l;
       return p;
}

you can call function in this case like this:

list *head;
head = insert(head, 4);

Parameters in C are passed by value. So in order to make some changes to a variable in a function, we have to tell that function the address of the variable. This enables it to change the value of the variable indirectly by writing data to the corresponding memory.

As a result, to modify an int , you have to pass an int * . In your case, to modify a list * (the type of p->next ), you have to pass a list ** .

Basically u might be calling the insert function using insert(&head,x);
Previously head would have stored the address of your first node in the
linked list and u give the address of the head node to l and to access the
address of a u need to dereference it once and to change its value u need to 
dereference it twice.

and obviously u can do it without double pointers just giving the value of   
head to l  insert(head,x)....and in the function declaring insert(int *l,int 
x) 
suppose

address of a(first node)=123

value of head=123

address of head =456

l(storing address of head)=456

In order to get the address of the first node dereference once

*l=123
in order to change value or to go to the next node you dereference it twice
for visual satisfaction have a look at the diagram image i tried to figure
out for your better understanding.


----------

[Here's an diagram which will give you a clear idea abt how the double pointer
is working here][1] [1]: http://i.stack.imgur.com/HQOaa.jpg

You need to use double pointer in this example because you would like to also change the starting node of your list. So basically when you're inserting a new element, you also want to make the node that contains it the first one of your list. If you pass only a single pointer( list *l ) and you assign to it the newly created node ( p ), the changes (and by changes I mean the fact that it will be the first node of the list) would only be available inside your function, and would not be propagated outside it.

To make it more clear, if you're taking in a simple pointer ( list *l ) you're basically copying the address stored by the list* variable that's sitting outside your function, in the newly created pointer (the l parameter). So the l variable inside your function is a different pointer (a different location in memory compared to the pointer variable outside your function) containing the same address as the pointer outside the function. So that's why assigning the newly created element to this l single-pointer would only make the the newly inserted element the first only local (function scope).

Compared to the alternative method when you're taking in a double pointer (so list **l ), what really happens is that by passing the outer pointer variable to the function, you're actually passing the address of the outside pointer, not to be confused with the address that the pointer is containing. (take care since you will have to call the function something like this: insert(&l, 2) ). This way you will still have the address contained by the outer pointer by dereferencing it and using it as rvalue ( p->next = *l ) and at the same time you have the address of the outside variable, so when you're making *l = p (notice *l is used as lvalue here), you're actually dereferencing the double pointer and in consequence you will obtain the the address of the real variable (the outside one), assigning to it the newly created node. In other words you're actually setting the newly created node as the starting node but this time also outside the function.

Really hope this is not extremely confusing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM