【问题标题】:Circular Doubly Linked List Copy Constructor C++循环双向链表复制构造函数 C++
【发布时间】:2017-04-11 15:58:44
【问题描述】:

我正在尝试在我的循环双向链接列表中实现一个复制构造函数,但我无法使其工作。文件会复制,但顺序不正确。 (注意:plate 定义为template<typename T>,我会尽量只包含相关功能)

类:

plate class CircularDoubleDirectedList : public ICircularDoubleDirectedList<T> {
private:
    plate class Node {
    public:
        T data;
        Node *next;
        Node *prev;
    };
    Node<T> *current;
    int nrOfElements;
    direction currentDirection;
public:
    CircularDoubleDirectedList() { nrOfElements = 0; currentDirection = FORWARD; current = nullptr; }
    virtual ~CircularDoubleDirectedList();
    CircularDoubleDirectedList(const CircularDoubleDirectedList<T>& origObj);
    CircularDoubleDirectedList& operator=(const CircularDoubleDirectedList<T>& origObj);
    void addAtCurrent(const T& element);
    T getElementAtCurrent() const;
    void removeAtCurrent();
    int size() const;
    void changeDirection();
    void moveCurrent();
    direction getCurrentDirection() const;
}; 

我对复制构造函数的尝试:

plate CircularDoubleDirectedList<T>::CircularDoubleDirectedList(const CircularDoubleDirectedList<T>& origObj) {
    current = nullptr;
    nrOfElements = 0;
    Node<T> *tmp = origObj.current;
    currentDirection = origObj.currentDirection;

    while (nrOfElements < origObj.nrOfElements) {
        addAtCurrent(tmp->data);
        tmp = tmp->next;
    }
}

加法器:

plate void CircularDoubleDirectedList<T>::addAtCurrent(const T& element) {
    Node<T> *tmp = new Node<T>;
    tmp->data = element;
    tmp->next = nullptr;
    tmp->prev = nullptr;

    if (current == nullptr) {
        tmp->next = tmp;
        tmp->prev = tmp;
        }

    else if (nrOfElements == 1) {
        tmp->next = current;
        tmp->prev = current;
        current->next = tmp;
        current->prev = tmp;
    }

    else {

        if (currentDirection == FORWARD) {
            tmp->prev = current;
            tmp->next = current->next;
            current->next->prev = tmp;
            current->next = tmp;
        }

        else if (currentDirection == BACKWARD) {
            tmp->prev = current->prev;
            tmp->next = current;
            current->prev->next = tmp->prev;
            current->prev = tmp;
        }
    }

    nrOfElements += 1;
    current = tmp;
}

谢谢。

【问题讨论】:

  • 听起来你可能需要学习如何使用调试器来单步调试你的代码。使用好的调试器,您可以逐行执行您的程序,并查看它与您期望的偏差在哪里。如果您要进行任何编程,这是必不可少的工具。延伸阅读:How to debug small programs
  • 问题似乎出在 addAtCurrent 方法的最后一个 else 中。您正在以错误的顺序更新节点。仅举一个“向后”方向的示例: current->prev->next = tmp->prev 依次是 current->prev.. 因此 current->prev 之后的元素是 current->prev 本身。
  • @NathanOliver Okey 我修复了我的编译器,但我没有收到任何错误,除了最大警告级别,我被告知我错过了几个我已经知道的内联。我在这里发帖是因为我觉得熟练的程序员能够找到一些编译器无法找到的问题。但我会保留链接。
  • @RobertoTrani Okey 谢谢。我去看看。
  • @Henke 我没有说任何关于编译器的事情。我说使用你的调试器。调试器是一个单独的工具,它允许您在代码执行时遍历代码,并让您观察正在发生的事情。如果您想成为一名程序员,这是一项重要的学习工具/技能。

标签: c++ copy-constructor doubly-linked-list circular-list


【解决方案1】:

正如我在评论中指出的,问题似乎出在最后一个函数中。所以我尝试以一种更易读的方式从头开始编写它:

plate void CircularDoubleDirectedList<T>::addAtCurrent(const T& element) {
    Node<T> *tmp = new Node<T>;
    tmp->data = element;

    if (current == nullptr) {
        tmp->next = tmp;
        tmp->prev = tmp;
    } else {
        Node<T> * before, after;
        if (currentDirection == FORWARD) {
            before = current;
            after = current->next;
        } else {  // BACKWARD
            before = current->prev;
            after = current;
        }

        before->next = tmp;
        tmp->prev = before;
        after->prev = tmp;
        tmp->next = after;
    }

    nrOfElements += 1;
    current = tmp;
}

我在复制构造函数中看到了另一个问题:如果 currentDirection 是 Backward,那么您正在从左到右读取元素,但是以“后来”的方式添加元素,从而导致顺序丢失。 有两种解决方案:可以在扫描过程中尊重顺序,或者将 currentDirection 设置为 FORWARD,然后将其设置为正确的值。

plate CircularDoubleDirectedList<T>::CircularDoubleDirectedList(const CircularDoubleDirectedList<T>& origObj) {
    current = nullptr;
    nrOfElements = 0;
    currentDirection = FORWARD;  // set the scan direction temporarily

    for (Node<T> *tmp = origObj.current; nrOfElements < origObj.nrOfElements; tmp = tmp->next) {
        addAtCurrent(tmp->data);
    }
    if (nrOfElements > 0)
        current = current->next;  // align with the current of the copyed list
    currentDirection = origObj.currentDirection;  // set the right direction
}

如果它解决了您的问题,请告诉我。

【讨论】:

  • 是的,它有效,谢谢!我一直在努力解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-20
  • 1970-01-01
  • 2020-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多