Я пытаюсь внедрить конструктор копирования в свой круговой двусвязный список, но не могу заставить его работать. Файлы копируются, но не в правильном порядке. (НОТА: 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;
}
Спасибо.
Как я указал в комментарии, проблема, похоже, заключается в последней функции. Поэтому я пытаюсь написать это с нуля более читабельным способом:
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
}
пожалуйста, дайте мне знать, если это решит вашу проблему.
Других решений пока нет …