实现链接列表

时间:2013-02-14 18:41:24

标签: c++ linked-list

我正在使用C ++实现链接列表。虽然我以前在java中已经完成了这个,但我不明白如何在C ++中使用指针来实现它,因为代码编译但是当我运行它时它给了我一个Segmentation Fault。我做错了什么?

我的node.h文件

#ifndef NODE_H
#define NODE_H

#include <string>
using namespace std;

class Node
{
public:

    Node(const string, const int) ;
    ~Node() { }
    void setNext(Node *); // setter for the next variable
    Node * getNext();     // getter for the next variable
    string getKey();      // getter for the key variable
    int getDistance();    // getter for the dist variable

private:
   Node *next;
   int dist;
   string key;
};

#endif

我的Node.cpp文件

#include "node.h"
#include <string>

Node::Node(string key, int dist){
    key = key;
    dist = dist;
}

void Node::setNext(Node * next){
    next->next;
}

Node * Node::getNext(){
    return this->next;
}

string Node::getKey(){
    return key;
}

int Node::getDistance(){
    return dist;
}

我的main.cpp文件

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

using namespace std;

int main(){
    Node* nptr1 = new Node("Test1", 2);
    Node* nptr2 = new Node("Test2", 2);
    Node* temp;

    nptr1->setNext(nptr2);
    temp = nptr1->getNext();
    cout << temp->getKey() << "-" << temp->getDistance() << endl;
}

非常感谢任何帮助。 感谢。

2 个答案:

答案 0 :(得分:2)

您应该将所有成员初始化为定义的值。您不应该将参数和成员命名为相同,这几乎总是导致混淆,或者更可能导致错误

Node::Node(string key_val, int distance)
    : next(0)
{
    key = key_val;
    dist = distance;
}

更好的是,使用成员初始化

Node::Node(string key_val, int distance)
    : next(0),
      key(key_val),
      dist(distance)
{
}

正如评论者已经指出的那样,您必须将next中的setNext()指针设置为给定参数,并且修改参数,但是{{1}会员

this->next

答案 1 :(得分:0)

使用指针/动态内存分配的语言中链接列表和其他数据结构的关键是为每个操作映射所有可能的状态(个案)。您必须确保代码在每种情况下都能正确处理指针和内存。这可能就是为什么要求你实现它的原因:教你如何来思考出现的陷阱。因此,我不会简单地给你一个直接的解决方案,而是概述你如何抓住这个机会来理解将帮助你和其他人解决这个问题和未来问题的基本概念。

即使在看似是带尾部插入的stage1(极端基本)链表中,您也应该开发某种映射方案。我个人的经验是main()中的每一行:

  1. 为每个对象绘制一个框
  2. 列出方框中的所有数据变量
  3. 列出非指针变量旁边的任何初始化/分配值
  4. 从指针变量向指向
  5. 的对象绘制箭头
  6. 将箭头从指针变量绘制到空白区域以获取未指定的指针
  7. 要知道的一件事是,未初始化的数据和指针显示未定义的属性,这些属性因os /编译器而异,因此使用合适的初始值定义大多数属性通常至关重要。我发现始终初始化为声明的安全默认值对我有用(有些情况下它不可能或产生性能问题,但可以根据需要处理 - 例如 Lazy Initialization ) 。与Java不同,基本C ++默认情况下不会引发空指针异常,提供初始值或垃圾收集(它高度依赖于编译器/库和传递选项)。最好的情况是,你的程序会出现段错误(更常见的例外,通常意味着你已经访问过你不应该访问的内存),在更糟糕的情况下,它仍然会工作但行为不可预测或崩溃而没有反馈。因此,您应该使用映射方案来验证您没有对指向NULL的指针执行操作,或者指向对其执行free / delete的对象的指针。此外,您需要确保它们指向的位置。与任何链接方案一样,您可能会遇到悖论,例如将节点链接到自身或以其他方式创建循环链接。

    因此,如上所述,跟踪每个操作的所有可能情况也很重要。如果这个程序是一种学习数据结构或指针的方法,正如我怀疑的那样,毫无疑问会要求你实现更高级的列表。更高级的列表可能很棘手,因此您应该尽早养成尝试确定特定操作的执行可能需要额外注意(角落情况)的习惯。对于列表,您应该考虑列表为空,有1个元素,有2个元素或2个以上元素的情况。您可能还需要考虑是否从开头,结尾或其间的某个位置插入/删除元素。再次,广泛使用映射来理解这些情况将如何发挥作用。您真的应该尝试通过使用上述方法来考虑这一点,但您也可以查看wikipedia或数据结构教科书以获取更多信息。

    正如Raymond所提到的,BTW可以使用调试器来帮助您查看问题。实际上,如果您之前没有使用过C / C ++调试器,那么这是学习的最佳时机。完成此工作后,查找适用于您的平台的C / C ++调试器上的文档。尝试使用它来逐步查看非工作代码的main(),看看数据值是否与映射中的期望相符。这种技能将在以后证明是非常宝贵的。

    另请注意,this在C ++中通常为a pointer,因此不要将其与Java / Python中的使用方式混淆:使用this->somedata 访问成员数据有些人建议不要 this.somedata。话虽如此,您可能希望在参数名称与成员变量相同的位置使用this->somedata = somedata的约定,以增加清晰度。当然,使用不同参数名称的建议也适用。