链接列表替换前节点而不是弹出到后面

时间:2018-03-21 20:18:39

标签: c++ linked-list doubly-linked-list

我正致力于创建双向链表。我似乎遇到了pushBack函数的问题(应该将一个节点添加到列表的末尾)。不知何故,它只是替换了第一个节点,并将其指向上一个节点和下一个节点。当我去打印列表时,它会永远继续下去,因为下一个节点不是NULL(因为正如我所说,它出于某种原因指向自己)。以下是整个计划。我想我的范围可能有问题,或者我可能错误地使用指针。

#include <iostream>

class Node {
public:
  Node();
  Node(int *val, Node *nx = NULL, Node *prev = NULL) {
    value = val; next = nx; previous = prev;
  }

  void setPrev(Node* prev) { previous = prev; }
  void setNext(Node* nx) { next = nx; }
  void setVal(int* x) { value = x; }
  Node* getPrev() { return previous; }
  Node* getNext() { return next; }
  int* getVal() { return value; }

private:
  int* value;
  Node *next;
  Node *previous;
};

class LinkedList {
 public:
  LinkedList() : front(NULL), back(NULL) {}

  bool empty() { return front == NULL; }
  void pushBack(Node *nd) {
    if (back == NULL) {
      front = nd;
      back = nd;
    }
    else {
      back->setNext(nd);
      nd->setPrev(back);
      back = nd;
    }
    std::cout << "Front: " << *front->getVal() << std::endl;
    std::cout << "Back: " << *back->getVal() << std::endl;
  }
  Node* topFront() { return front; }
  void printFront() {
    int *x = front->getVal();
    std::cout << *x << std::endl;
  }

  void print() {
    if (empty()) {
      std::cout << "List is empty" << std::endl;
    }
    else {
      std::cout << "Print list" << std::endl;

      Node *x = front;
      int count = 1;

      // First just print the first element, then the rest
      int *y = front->getVal();
      std::cout << count << ": ";
      std::cout << *y << std::endl;

      x = x->getNext();

      while (x != NULL) {
        std::cout << count << ": ";
        int *z = x->getVal(); std::cout << *z << std::endl;

        x = x->getNext();
      }
    }
  }
 private:
  Node* front;
  Node* back;
};

int main() {
  LinkedList ll;
  char input;
  char const *menu = {"Options:\n\n" \
                      "0. Quit\n" \
                      "1. Print linked-list\n" \
                      "2. pushBack -- add to the end of the LinkedList\n"};

  while (input != '0') {
    std::cout << menu << std::endl;
    std::cout << ":";

    std::cin >> input;

    if (input == '1') {
      ll.print();
    }
    else if (input == '2') {
      std::cout << "Value: ";
      static int init;
      std::cin >> init;
      static Node x(&init);
      ll.pushBack(&x);
    }
  }

  return 0;
}

以下是我使用的输入。我打印了一些值来尝试调试程序。您会注意到,我只是尝试将值为1,2,3和4的节点放入列表中

Options:

0. Quit
1. Print linked-list
2. pushBack -- add to the end of the LinkedList

:2
Value: 1
Front: 1
Back: 1
Node Prev: 0
Node Next: 0
Options:

0. Quit
1. Print linked-list
2. pushBack -- add to the end of the LinkedList

:2
Value: 2
Front: 2
Back: 2
Node Prev: 0x602300
Node Next: 0x602300
Options:

0. Quit
1. Print linked-list
2. pushBack -- add to the end of the LinkedList

:2
Value: 3
Front: 3
Back: 3
Node Prev: 0x602300
Node Next: 0x602300
Options:

0. Quit
1. Print linked-list
2. pushBack -- add to the end of the LinkedList

:2
Value: 4
Front: 4
Back: 4
Node Prev: 0x602300
Node Next: 0x602300
Options:

0. Quit
1. Print linked-list
2. pushBack -- add to the end of the LinkedList

:0

2 个答案:

答案 0 :(得分:2)

这里有很多好的提示,但到目前为止都没有解决根本问题:你需要在堆上而不是堆栈上分配Node实例。

为了使这更容易,我建议你按值而不是指针存储int。将所有使用int *的地方改为普通的'int'。

然后更改代码以将背面的节点推送到此:

else if (input == '2') {
  std::cout << "Value: ";
  int init;
  std::cin >> init;
  Node *x = new Node(init);
  ll.pushBack(x);
}

我已经用你的代码对它进行了测试,它对我有用。

当你做这样的事情时:

    else if (input == '2') {
  std::cout << "Value: ";
  int init;
  std::cin >> init;
  Node x(init);
  ll.pushBack(&x);
}

您正在堆栈上分配一个节点,这意味着只要退出“else”块,节点“x”就会被销毁,而添加到列表中的指针将不再有效。您需要使用new运算符在堆上分配Node。这将使Node保持活动状态,直到你以后删除它为止。

说到删除 - 一旦你使这个部分工作,你就会想要编写一个遍历列表中所有节点的析构函数并删除它们。但是现在,我专注于让你的其他操作正确。

答案 1 :(得分:-1)

当您在下面的代码中使用静态变量时,您的所有节点都将具有您输入的第一个值。

static int init;
std::cin >> init;
static Node x(&init);

如下所示进行纠正,然后重试

int *init = new int;
std::cin >> *init;
Node *x = New Node(init);

你的pushBack方法对我来说很好看。只需进行上述更改即可。