2013-03-01 281 views
2

我正在学习链接列表以及如何使用结构和指针在C中创建它们。我下面有一个例子。根据我的理解,被调用的push()传递了头节点所在结构的开始内存位置作为参数。我们的push()函数的参数将一个结构节点作为指针的指针,所以它作为引用传递,而不是实际的副本。所以我们的struct node ** headref的第一个指针只是一个指向我们头节点的内存位置的指针,而第二个指针指向的值是头节点指向的下一个内存位置。我们在struct节点内创建一个名为newnode的新节点,并为其分配一些内存。然后我们在这个节点里创建一个int类型的数据。结构和指针指针

好吧,假设我说的一切都是正确的,下一部分就是我所困惑的。

newNode->next= *headRef; 

从我能理解的这行中提取headref,这样只会让headref指向头节点。然后我们有一个指针操作,headref指向的内容也就是我们下一个指针所指向的内容。基于此,我们新节点(newnode)中的下一个指针将指向头指针。

下一行对此我也搞不清楚上:

*headRef = newNode; 

什么解除引用的headref指针指向,这是头节点,将现在指向我们的newnode。

基于此,应该有一个新的节点叫做newnode,它具有一个int数据和一个将我们的newnode链接到头部的下一个指针。那么headref指针(或者它是头节点?)将指向新节点。我知道这是不正确的,因为我们的newnode旁边的指针应该指向第二个节点,所以我们的newnode可以在结构中链接。我也不相信我在上述两行代码中理解指向指针的指针和取消引用。

代码:

void Push(struct node** headRef, int data) { 
    struct node* newNode = malloc(sizeof(struct node)); 

    newNode->data = data; 
    newNode->next = *headRef; 
    *headRef = newNode; 
} 

void PushTest(void) { 
    struct node* head = BuildTwoThree(); // suppose this returns the list {2, 3} 

    Push(&head, 1); 
    Push(&head, 13); 
    // head is now the list {13, 1, 2, 3} 
} 
+2

究竟是什么问题? – aaaaaa123456789 2013-03-01 09:15:36

+0

我很确定我可以阅读 - 如果不能开始阅读就很难写。这个问题得到解答,我问的是你对这些问题的疑问是 - 它只是一个“这是如何工作的?”事情,还是“它为什么不做X?”事情? – aaaaaa123456789 2013-03-01 09:19:42

+1

我的假设哪部分是错误的?我显然没有正确地阅读这两行,因为我在想的不是将头节点链接到newnode,而是将newnode的下一个指针链接到第二个节点(之前在创建要插入的newnode之前创建的)。对不起,粗鲁,只是恼火,我不明白这一点。 – user2122810 2013-03-01 09:22:14

回答

0
void Push(struct node** headRef, int data) { 

headRef包含struct节点所在地址。这是变量的PushTest函数的地址。

struct node* newNode = malloc(sizeof(struct node)); 

这里我们创建了一个newNode。它包含节点结构所在的内存地址。

newNode->data = data; 

newNode的数据设置为数据参数传递到函数的值 - 确定。

newNode->next = *headRef; 

设置newNode->下到位于可变结构的地址。例如,如果我们写

void Push(struct node* head, int data) { 
... 
newNode->next = head; 

接下来,我们需要将变量更改为newNode。如果变量是通过引用传递,我们可以简单地写这篇文章,就像在C++:

void Push(struct node* &head, int data) { 
... 
head = newNode; 

但在纯C,我们必须通过地方变量所在的地址,所以我们可以写成该地址的指针newNode我们在函数创建的结构:

*headRef = newNode; 

相当于写newNo德指针,其地址位于headRef变量

内并且在你的逻辑有问题的变量:

我们推的参数()函数接受一个结构节点作为指针 到指针,所以它作为参考传递,而不是实际的副本。

事实上,我们通过一个包含节点变量,而不是参考的地址临时变量的副本。在C++中有传递引用方法,它使用&符号声明传递给函数的变量是引用,而不是原始变量的副本。

+0

谢谢你的详细解答!我希望我能给大家最好的答案,但你的是最详细的答案。 – user2122810 2013-03-01 14:58:36

0

你实际上是正确和在同一时间不正确。 push函数在列表头部添加一个新节点。在调用此函数之后,新节点是新的节点head,并且之前的head节点现在是列表中的第二个(下一个)节点。所以你的观察是正确的,但你的结论不是。

我建议您在查看所有指针及其内容的同时,在调试器中单步执行代码,看看会发生什么。它可能会让事情变得更加清晰。

+0

所以我们可以认为: newNode-> next = * headRef; 接下来的指针指向头节点? 和 * headRef = newNode; 究竟是什么?头节点现在是新节点? 所以这只是翻转头和新节点,因为新节点的下一个指针连接到头(现在是旧头),那么新头(以前是新节点)指向第一个节点(旧头)? – user2122810 2013-03-01 09:31:40

+0

@ user2122810'newNode-> next'将指向'head',然后'* headRef = newNode'将使头指向'newNode'。调用此函数时,“head”指针现在指向添加的新节点。真的,在检查所有变量和指针的同时,在调试器中遍历代码。这是看到“行动中”会发生什么的好方法。 – 2013-03-01 09:57:22

+0

谢谢你的详细解答! – user2122810 2013-03-01 14:58:09

0

好的。我想我可以解释。

head是链表的头指针。 headRef点头。所以*headRef是头指针(通过引用传递)。

所以newNode->next现在将指向该结构的头(其值为2,这就是为什么节点插入前面)。

在这一行 *headRef = newNode; *headRef

现在被分配newNode所以head现在改为newNode在原来的结构中的价值。

再次当您通过&head时,您将传递包含值1的head

+0

我唯一感到困惑的是你说的是newNode-> next。我们正在解除headRef,所以现在它不指向2,而只指向头部。没有? – user2122810 2013-03-01 09:34:46

+0

headRef不指向结构,它只指向指向该结构的变量。当你解引用它时,你会得到指向该结构的变量。 – izogfif 2013-03-01 10:01:29

+0

@ user2122810是的。它指向头部。不2.要获得“2”,您必须做* headRef->数据 – dejavu 2013-03-01 10:33:35

0

让我们这这里,对于简单的参考副本:

1 void Push(struct node** headRef, int data) { 
2  struct node* newNode = malloc(sizeof(struct node)); 
3  newNode->data = data; 
4  newNode->next = *headRef; 
5  *headRef = newNode; 
6 } 

为了简单起见,我的编号行。

现在,headRef本身只是一个指向变量的指针,它保存了列表的标题 - 因此它本身不包含有用的信息。通过取消引用该指针,你获得进入内容变量本身(headPushTest())的。因此,*headRef基本上是你可以访问head的方式。现在,由于head是顶级节点,所以是*headRef - 他们持有相同的值,因为它们是同一个地址。什么线4所做的是,分配的*headRef值(即的head值)到新节点的下一个环节。以同样的方式,第5行将新节点分配给*headRef,这与将其分配给head相同,因为headRef是指向head的指针 - 这意味着*headRefhead的值。

这里的关键点在于,headRef是参考(指针)来head,所以*headRefhead是当量(范围规则除外)。

+0

谢谢您的详细解答! – user2122810 2013-03-01 14:57:16