在一个简单的链表中,为什么要在插入节点时传递双指针?与第二个代码有什么区别?
void push(struct node **headRef, int data);
void push(struct node *head, int data);
C 函数调用始终传递参数的值。当您在函数内部时,您将调用方的值的副本放置在新变量中。
您可以在函数中更改这些副本的值,但调用方具有的值将保持不变。
例:
void foo(int n)
{
n = 1;
printf("In foo: %dn", n); // Will print 1
}
void bar()
{
int n = 42;
printf("In bar: %dn", n); // Will print 42
foo(n);
printf("Back in bar: %dn", n); // Will still print 42
}
如您所见,对foo
内部n
所做的更改不会更改n
bar
内部。
那么,如果你真的想改变bar
内部n
呢?
这就是您传递n
传递指向n
的指针的地方。
喜欢:
void foo(int *n) // Note the *
{
*n = 1;
printf("In foo: %dn", *n); // Will print 1
}
void bar()
{
int n = 42;
printf("In bar: %dn", n); // Will print 42
foo(&n); // Note the & to get a pointer to n
printf("Back in bar: %dn", n); // Will now print 1
}
这也是代码行之间的区别:
void pushA(struct node **headRef, int data);
void pushB(struct node *head, int data);
struct node *head = NULL;
pushA(&head, 42); // head may be changed after this call
pushB(head, 42); // head is unchanged after this call
第一个版本可能是您想要的,即当将新元素推送到列表时,您希望将元素插入前面,因此需要更改 head 的值。
另一种方法是让函数返回指向新头的指针:
struct node* push(struct node *head, int data);
struct node *head = NULL;
head = push(head, 42);
在第一种情况下,您指向对head
节点的引用,而在第二种情况下,您指向指向链表的第一个节点的引用。
以示意图方式:
// Original List structure
head -> first node -> second node
// first case
void push(struct node **headRef, int data);
head -> first node -> second node
^
|
headRef
--------------------------------------
// second case
void push(struct node *headRef, int data);
head -> first node -> second node
^
|
headRef
你应该更喜欢一个而不是另一个吗?这要看情况。
如果您希望能够修改头节点的值,则应使用双指针,否则只需使用案例 2。
您还应该看看这里:在链表中添加节点时使用双指针的原因是什么?