我正在学习链表操作,并且有一个与参数传递有关的问题。
问题1: 我正在创建一个简单的链表,其中包含三个值1-> 2-> 3。我正在尝试打印它。 以下是我的代码。我正在我的主要创建一个节点“第一”,并将其传递给方法“createlinkedlist”。我正在使用指针“head”并在方法中更新它。但是我看到“head”的值在“createlinkedlist”方法之外被正确保留。我不明白这是怎么回事。我在想我应该像
一样使用参考传递参数 void createLinkedList(struct node * & head)
或void createLinkedList(struct node ** head)
而不是
void createLinkedList(struct node * head)
获取在函数外部反映的正确值。我在这里错过了什么?为什么我能够在printList方法中看到正确的值?
struct node
{
int data;
struct node * next;
};
void createLinkedList(struct node * head)
{
struct node * second = (node *)malloc(sizeof(node));
struct node * third = (node *)malloc(sizeof(node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
}
void printList(struct node * first)
{
struct node * current = first;
while(current)
{
printf("%d",current->data);
current = current->next;
}
}
void main()
{
struct node * first = (node *)(malloc(sizeof(node)));
createLinkedList(first);
printList(first);
}
问题2:我使用的是与上面相同的程序,但添加了推送功能
void push(struct node *& first, int data)
{
struct node * newnode = (node*)malloc(sizeof(node));
newnode->data = data;
newnode->next = first;
first = newnode;
}
现在我看到了,除非我使用“&”对于push()中的第一个参数,我无法在printList方法中看到更新。这对我来说很有意义,因为我们通常需要使用referncial参数来使函数外部看到局部函数更改。因此,如果列表在此处需要参考参数,为什么它在问题1的情况下表现不同。 PLS。让我知道。
答案 0 :(得分:2)
关于问题1)
您没有在createLinkedList方法中更改指针头部;您正在更改头指向的节点的内容。所以你在调用createLinkedList之后会看到这种变化。
关于问题2)
在第二种情况下,您实际上是在添加一个新节点,并且您需要将头指针更改为指向链表的新头,而在第一种情况下,您可以保持列表的头部稳定并添加列表尾部的新节点。因此,您不需要将列表头部的新地址返回给调用者,因为头部的地址没有改变。
我还会创建一个节点构造函数:
struct node * make_node(int data) { struct node * tmp = (node *)malloc(sizeof(node)); if (!tmp) { /* error handling for malloc failure */ } tmp->next = NULL; tmp->data = data; return tmp; }
另一点:
如果我是你,如果我写了一个将节点添加到列表头部的推送功能,我会明确地返回列表的新头部:
struct node * push(const struct node * head, int data) { struct node * fresh = make_node(data) fresh->next = head; return fresh; }
这样称呼:
struct node * head = make_node(1); head = push(head, 2);
这比理解push(head,1)改变头部更容易理解。但这是一个风格问题。
答案 1 :(得分:1)
更改
struct node * first = (node *)(malloc(sizeof(node)));
struct node * second = (node *)(malloc(sizeof(node)));
struct node * third = (node *)(malloc(sizeof(node)));
部分
struct node * first = (struct node *)(malloc(sizeof(struct node)));
struct node * second = (struct node *)(malloc(sizeof(struct node)));
struct node * third = (struct node *)(malloc(sizeof(struct node)));
。由于您在没有“typedef”的情况下初始化了“node”,因此每次使用“node”之前都需要编写“struct”。
答案 2 :(得分:0)
既然你在谈论引用,我会假设你正在使用C ++。
如果您要将指针修改为struct node *& head
,则需要传递head
,但在您的示例中,您只想修改头节点本身,而不是指向它的指针,这就是为什么你只是传递一个指向它的指针,让你查找地址。当您通过head->...
取消引用指针时,您正在查找内存中head
的位置,然后移至其data
或next
字段。或者,您可以将头部作为引用传递:struct node & head
,并直接修改head.data
之类的内容。
您的push
需要 first
指针的引用(struct node *& first
)或指向“first
”指针(struct node **first
)的指针,以便您可以实际修改pointer itself
。这是正在发生的事情:
first = newnode;
或者,如果您使用struct node **first
,则可以执行以下操作:
*first = newnode;
此处push
的两种情况都在修改指向struct node
的指针,而不是修改struct node
本身。