![](/img/trans.png)
[英]Understanding code for creating a singly linked list using double pointer in C
[英]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;
}
为什么使用双指针? 我们可以使用单个指针完成同样的事情吗? 我在《算法设计手册》(第2版)第69页中看到了此示例。
列表基本上是节点,仅供参考。
我们可以使用单个指针完成同样的事情吗?
您可以使用单个指针进行较小的更新来完成此操作。
返回分配的指针,并确保正确更改了函数调用。
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;
}
并用作
list* l = NULL;
l = insert(l, 10);
这里使用双指针是合理的,因为在函数中您将节点插入到列表的标题中,因此变量l将使用新的标题*l=p;
进行更改*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
在这种情况下,函数的调用方式如下:
list *head;
insert(&head, 4);
对于您的问题:
我们可以使用单个指针完成同样的事情吗?
是的,该函数将如下所示:
list *insert(list *l, int x)
{
list *p;
p = malloc(sizeof(list));
p->item = x;
p->next = l;
return p;
}
您可以在这种情况下调用函数,如下所示:
list *head;
head = insert(head, 4);
C中的参数按值传递。 因此,为了对函数中的变量进行一些更改,我们必须告诉该函数变量的地址 。 这使得它可以通过将数据写入相应的存储器来间接更改变量的值。
结果,要修改一个int
,您必须传递一个int *
。 在您的情况下,要修改list *
( p->next
的类型),您必须传递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.
----------
[这里有个图表,可以让您清楚地知道如何使用双指针
在这里工作] [1] [1]: http : //i.stack.imgur.com/HQOaa.jpg
在此示例中,您需要使用双指针,因为您还想更改列表的起始节点。 因此,基本上,当您插入新元素时,您还希望使包含该元素的节点成为列表的第一个。 如果仅传递单个指针( list *l
)并将新创建的节点( p
)分配给它,则更改(并且通过更改,我的意思是它将成为列表的第一个节点)将仅可用在函数内部,并且不会在函数外部传播。
更清楚地说,如果您使用简单的指针( list *l
),则基本上是将函数外部的list*
变量存储的地址复制到新创建的指针( l
参数)中。 因此,函数内的l
变量是一个不同的指针(与函数外的指针变量相比,在内存中的位置不同),其地址与函数外的指针相同。 这就是为什么将新创建的元素分配给此l
单指针将仅使新插入的元素成为唯一的局部(函数作用域)。
与采用双指针( list **l
)时的替代方法相比,实际发生的情况是,通过将外部指针变量传递给函数,实际上是在传递外部指针的地址,而不是与指针包含的地址混淆。 (请注意,因为您将不得不调用如下函数: insert(&l, 2)
)。 这样,通过将其解引用并将其用作rvalue( p->next = *l
),您仍将拥有外部指针所包含的地址,并且同时具有外部变量的地址,因此当您进行*l = p
(注意, *l
在这里用作左值),实际上是在取消引用双指针,因此,您将获得实数变量(外部变量)的地址,并为其分配新创建的节点。 换句话说,您实际上是将新创建的节点设置为起始节点,但是这次也是在函数之外。
真希望这不会引起极大的混乱。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.