链接列表引用指针

时间:2011-03-07 20:44:27

标签: linked-list

我正在学习链表操作,并且有一个与参数传递有关的问题。

问题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。让我知道。

3 个答案:

答案 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的位置,然后移至其datanext字段。或者,您可以将头部作为引用传递: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本身。