【问题标题】:Problem printing out linked-list打印出链表的问题
【发布时间】:2010-07-30 07:09:35
【问题描述】:

我正在尝试创建自己的数据类型,类似于向量或数组。

我的打印功能有问题;当我去打印列表时,它只打印列表中的最后一项。

// LinkedListClass.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include <iostream>

class Node
{
public:
 int value;
 Node* next;

 Node::Node(int val)
 {
  value = val;
 };
};

class List
{
public:
 Node* firstNode;
 Node* currentNode;
 int size;

 List::List()
 {
  firstNode = NULL;
  currentNode = firstNode;
  size = 0;
 };

 void push(Node* node)
 {
  if(firstNode == NULL)
  {
   firstNode = node;
   firstNode->next = currentNode;
   size++;
  }
  else
  {
   currentNode = node;
   currentNode = currentNode->next;
   size++;
  }
 };

 void print()
 {
  if(firstNode != NULL)
  {
   Node* printNode = firstNode;
   while(printNode->next != NULL)
   {
    std::cout << "List Item " << printNode->value << std::endl;
    printNode = printNode->next;
   }
  }
 };
};

int _tmain(int argc, _TCHAR* argv[])
{
 List ll = List();
 for(int i = 0; i < 10; ++i)
 {
  Node val = Node(i);
  ll.push(&val);
 }
 std::cout << ll.firstNode->value << std::endl;
 ll.print();
 std::cout << "Size " << ll.size << std::endl;
 std::cin.ignore();
 return 0;
}

/* Output

9
Size 10

*/

我知道这还远未完成,但如果您有任何其他建议(笑),请随时提出建议。

【问题讨论】:

标签: c++ data-structures linked-list


【解决方案1】:

有三个重要的错误:

push() --- 固定

void push(Node* node)
 {
  if(firstNode == NULL)
  {
   firstNode = node;
   currentNode = node;
   // firstNode->next = currentNode; --> this does nothing useful!
   size++;
  }
  else
  {
   currentNode->next = node;
   currentNode = node;
   //currentNode = node;               -|
   //currentNode = currentNode->next;  -|----> why? what? Do explain.
   size++;
  }
 }

我认为通过分配firstNode-&gt;next = currentNode;,您预计下次更新currentNode 时,它也会更新firstNode-&gt;next

这样不行。

firstNode-&gt;next = currentNode; 意味着存储在currentNode 中的地址现在在firstNode-&gt;next 中。因此,下次您将某些内容存储在 currentNode = node; 中时,您不会将其存储在 firstNode-&gt;next 中。所以你有一个损坏的链表 --- 这就是你的输出没有走得很远的原因。

另外,这真的很糟糕。通过设置currentNode=node 之前 将当前节点的next 指针设置为node,你又破坏了列表。您应该首先将currentNode-&gt;next 指向node,然后将currentNode 设置为nodenode 是您要推送到列表中的节点)。

节点值 = 节点(i);

val 的范围仅在循环的该迭代内。一旦你循环,它就会脱离堆栈并且不再存在。但是您已将 val 的指针复制到您的列表中 --- 所以现在使用正确的 push 方法,您只是添加了一个悬空指针。

Node *val = new Node(i);
ll.push(val);

你需要把它放在堆上,这样它就会一直保持到你不再需要它为止。

...这将我们引向你的析构函数!

由于您已经分配了一个节点,因此您需要解除分配它。所以在你的析构函数中这样做——遍历你的列表并释放所有这些节点。

【讨论】:

    【解决方案2】:

    以下导致未定义的行为:

      Node val = Node(i);
      ll.push(&val); // take address of temporary
      ...
      firstNode = node; // store address of temporary here
      ...
      ll.print(); // temporary `val` was destroyed, but all nodes are point to it
    

    您可以按如下方式更改您的代码:

      Node* val = new Node(i);
      ll.push( val );
    

    并且不要忘记稍后删除所有节点。

    【讨论】:

      【解决方案3】:

      您的 push() 方法不正确。第一次推送一个节点时,它会正确地将其分配给 firstNode,但随后的每个 push() 只是将 currentNode 设置为新节点,然后将 currentNode 设置为 NULL——实际上并没有向列表中添加任何内容。

      我认为值得一提的是,指针在 C++ 中不是按名称引用的。例如,设置 firstNode->next = currentNode 不会使 currentNode 成为列表中的下一个元素;它只是让 firstNode->next 指向与 currentNode 相同的地址(在本例中为 NULL)。

      我不打算为您编写代码,但这是您的 push() 函数应该如何工作的。关键是您应该将现有节点的“下一个”字段设置为新节点,而不是将 currentNode 设置为新节点:

      1. 在 firstNode 为 NULL 的情况下, 将 firstNode 设置为新节点和 将 firstNode->next 设置为 NULL(因为 它没有下一个元素)。你可以 还设置 currentNode = firstNode 这里是为了方便。

      2. 在没有firstNode的情况下 NULL,我们需要从 firstNode 开始 沿着链向下直到我们找到一个节点 其下一个字段为 NULL,然后设置 它的下一个字段到新节点。 或者,我们可以使用 currentNode 指针访问 列表中的最后一个元素并执行相同操作 事情,一定要设置 currentNode 当我们指向新节点时 完成。

      您基本上已经完成了第 1 部分,但第 2 部分仍然需要实施。随时要求澄清/给予批评。 :)

      【讨论】:

      • 我确信所有关于临时变量的答案都适用,但我认为这不是您问题的主要根源。
      【解决方案4】:

      试试看

       节点* val=new 节点(i) 
      以前你正在存储临时变量。所以不要将 ndoe 存储在动态内存中,因此可以提供单独的内存。 当您创建节点时,它是出于临时目的而创建的 &临时地址已存储,因此当您回溯临时内存已被释放时,您会发现那里有一些垃圾。价值。

      【讨论】:

        猜你喜欢
        • 2021-09-21
        • 1970-01-01
        • 1970-01-01
        • 2022-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多