我正在尝试创建自己的数据类型,就像向量或数组一样。
我的打印功能遇到了麻烦;当我打印列表时,它只打印列表中的最后一项。
// 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
*/
我知道这远未完成,但如果您有任何其他指针(笑),请随时提出建议。
答案 0 :(得分:4)
有三个重要错误:
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
设置为node
(node
作为您推送到列表中的节点。)< / 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设置为新节点:
在firstNode为NULL的情况下, 将firstNode设置为新节点和 设置firstNode-&gt;旁边的NULL(因为 它没有下一个元素)。您可以 还设置currentNode = firstNode 为方便起见。
在firstNode不是的情况下 NULL,我们需要从firstNode走 直到我们找到一个节点 其下一个字段为NULL,然后设置 它的新节点的下一个字段。 或者,我们可以使用它 currentNode指针访问 列表中的最后一个元素并执行相同的操作 确保设置currentNode 我们的时候指向新节点 完成。
你基本上完成了第1部分,但第2部分仍然需要实现。随意要求澄清/批评。 :)
答案 3 :(得分:0)
尝试
Node* val=new Node(i)以前你在存储临时变量。所以没有将ndoe存储在动态内存中,因此可以给出单独的内存。 当你创建节点时,它是为了临时目的而创建的 存储临时地址,所以当你遍历临时存储器时,你会发现有些垃圾。值。