问题打印出链表

时间:2010-07-30 07:09:36

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

我正在尝试创建自己的数据类型,就像向量或数组一样。

我的打印功能遇到了麻烦;当我打印列表时,它只打印列表中的最后一项。

// 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

*/

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

4 个答案:

答案 0 :(得分:4)

有三个重要错误:

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->next = currentNode;您预期下次更新currentNode时,它也会更新firstNode->next

这不起作用。

firstNode->next = currentNode;表示currentNode中存储的地址现在位于firstNode->next。因此,下次在currentNode = node;中存储内容时,您不会将其存储在firstNode->next 中。所以你有一个破碎的链表 - 这就是为什么你的输出不是很远。

另外,这真的很糟糕。通过在设置当前节点的currentNode=node指针next之前设置node ,您再次打破了列表。您应首先将currentNode->next指向node,然后将currentNode设置为nodenode作为您推送到列表中的节点。)< / p>

节点val =节点(i);

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

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

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

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

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

答案 1 :(得分:1)

以下导致未定义的行为:

  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 );

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

答案 2 :(得分:0)

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

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

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

  1. 在firstNode为NULL的情况下, 将firstNode设置为新节点和 设置firstNode-&gt;旁边的NULL(因为 它没有下一个元素)。您可以 还设置currentNode = firstNode 为方便起见。

  2. 在firstNode不是的情况下 NULL,我们需要从firstNode走 直到我们找到一个节点 其下一个字段为NULL,然后设置 它的新节点的下一个字段。 或者,我们可以使用它 currentNode指针访问 列表中的最后一个元素并执行相同的操作 确保设置currentNode 我们的时候指向新节点 完成。

  3. 你基本上完成了第1部分,但第2部分仍然需要实现。随意要求澄清/批评。 :)

答案 3 :(得分:0)

尝试

 Node* val=new Node(i) 
以前你在存储临时变量。所以没有将ndoe存储在动态内存中,因此可以给出单独的内存。 当你创建节点时,它是为了临时目的而创建的 存储临时地址,所以当你遍历临时存储器时,你会发现有些垃圾。值。