【问题标题】:How do you move between nodes of a linked list?如何在链表的节点之间移动?
【发布时间】:2011-08-31 19:05:28
【问题描述】:

这是一段尝试构建链表的代码。

struct node {
    char name[20];
    int age;
    int height;
    node* next; // Pointer to the next node
};
node* startPTR = NULL;

void addNode_AT_END() {
    node *temp1;
    node *temp2;

    temp1 = new node;  

    cout << "Enter the name : ";
    cin  >> temp1->name;
    cout << endl << "Enter the age : ";
    cin  >> temp1->age;
    cout << endl << "Enter height : ";
    cin  >> temp1->height;

    temp1->next = NULL;

    if( startPTR == NULL) {
       startPTR = temp1; 
    }  else {
       temp2 = startPTR;

       while( temp2->next != NULL )
           temp2 = temp2->next;

       temp2->next = temp1;
    }
 }

以下是对上述函数的 2 次背靠背调用后的示意图。

start = addr1;
|
V
(addr1) ----> (addr2) ----> (NULL)      at end
^
|
temp2

其中addr1和addr2分别是第一个和第二个节点的地址。

第三次通话后会发生什么?第三次调用的迭代将如何进行?我无法理解list 在第二次调用后如何链接。据我所知,所有已经建立起来的东西都会消失。那么将如何列出走得更远?第三次调用时节点如何放置?

【问题讨论】:

  • 什么?发布的代码是一个非常典型的链表实现。令人困惑的第三个电话的具体内容是什么?
  • @Chad 在第三次调用中迭代将如何进行?
  • 查看下面的正确答案。
  • 我发现找出指针的最佳方法是拿出铅笔和纸(还记得吗?它们在上个世纪非常流行)。然后逐行浏览代码并画出发生了什么。

标签: c++ list pointers linked-list


【解决方案1】:

这就是所有魔法发生的地方:

1. temp2 = startPTR;
2. while( temp2->next != NULL )
3.    temp2 = temp2->next;
4. temp2->next = temp1;

首先,temp2 将指向列表的开头。在第 2 行和第 3 行中,将temp2 更改为下一个节点,直到到达temp2-&gt;nextNULL 的节点。该节点是列表的最后一个节点,与列表的大小无关。

最后,在第 4 行中,您将 temp2-&gt;next 更改为 temp1,所以现在它指向新节点(即最后一个节点现在指向新节点)。 temp1-&gt;next 也是 NULL,所以 temp1 现在代表列表的结尾。

在第 1 行之后

start = addr1;
|
V
(addr1) ----> (addr2) ----> (NULL)
^
|
temp2

temp2-&gt;next 不是 NULL(它是 addr2),所以你迭代并执行第 3 行,你会得到:

start = addr1;
|
V
(addr1) ----> (addr2) ----> (NULL)
              ^
              |
              temp2

temp2-&gt;next 现在是 NULL。所以你停止循环并执行第 4 行,你会得到:

start = addr1;
|
V
(addr1) ----> (addr2) ----> (addr3) ----> (NULL)
              ^             ^
              |             |
              temp2         temp1

注意:你知道指针是如何工作的吗?想象一下:你有一个节点,它是内存中的一些数据。当内存中有变量时,这些变量就有地址。假设 addr1 为 10,addr2 为 150,addr3(即 newed 的节点)为 60。start 的值为 10。因此,“指向”列表的第一个节点(即使用此地址,您可以访问其数据)。这些数据之一是next 字段。第一个节点的next 字段的值为150,因此指向下一个节点。当你说temp2 = start时,你把数字10放在temp2中,此时temp2-&gt;next的值是150。当你说temp2=temp2-&gt;next时,你只是把值150放在temp2中,覆盖之前的值。这样,您就有效地将指针从指向第一个节点移动到现在指向第二个节点。现在temp2-&gt;nextNULL(即0)。当您现在说temp2-&gt;next=temp1 时,您将值60 放入temp2next 字段中。所以现在temp2-&gt;next 是 60。temp2-&gt;next-&gt;nextNULL

【讨论】:

  • 好的。但我在问你如何在迭代中遍历列表。因为在第三次调用期间你没有第二个节点的地址。那么当你写startPTR-&gt;next时它是如何指向第二个节点的。
  • 我刚刚编辑完我的答案。如果您在阅读说明后仍有疑问,请告诉我。
  • 问题是,内存就在那里。 第二个节点的地址存储在第一个节点的next字段中,所以通过第一个节点你可以访问第二个节点。同样,从第二个节点到第三个节点,从第三个节点到第四个节点,因此是 while 循环。
  • temp2-&gt;next = temp1是把第二个节点的地址分配给第一个节点的,实际上是存入内存的?
  • 当然。 next 字段只是一个变量,就像其他任何变量一样。当你说temp2-&gt;next = ... 时,内存中的那个变量(next)就被设置了。
【解决方案2】:

这很简单。 while 循环会将 temp2 移动到最后一个元素。然后将 temp1 指向的您创建的节点分配为 temp2 的下一个节点

【讨论】:

  • 你能告诉我循环如何将 temp2 移动到最后一个元素?我们在第 2 步之前建立的列表在哪里? temp2->next 如何指向下一个元素?
  • 下一个指针为 NULL 的唯一元素是最后一个元素。您只需要执行 p=p->next 直到到达 NULL next 指针
  • 我如何使用 p=p->next 到达那里?它怎么知道以前的地址?这是我该死的问题
  • 不需要。知道以前的地址是没有意义的,因为你只是在前进。基本上, p->next 是指向下一个元素的指针。执行 p=p->next 您只是使 p 指向以下元素。一旦 p->next 为 NULL,p 肯定指向最后一个元素
【解决方案3】:

我不明白你在困扰什么。在任何调用期间,while() 循环都会遍历列表中的所有节点,直到到达末尾,然后将最后一个中的指针设置为新分配的节点(temp1)。

temp1 和 temp2 是指针。它们不存储节点的数据,它们将地址存储在存储数据的内存中。所以在第一次迭代结束时,startPTR = temp1 startPTR 指向与 temp1 指向的地址相同的地址。 temp1 是否仍然存在并不重要,因为现在 startPTR 指向该节点。在第二次调用结束时temp2-&gt;next=temp1(此时temp2==startPTR)使节点的next字段指向新分配的temp1

【讨论】:

  • temp2 是一个指针。在 while() 循环期间,您“移动”它,因此它指向最后一个节点。所以当你设置temp2-&gt;next=temp1 你实际上是在设置"lastnode"-&gt;next=temp1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多