c++ - 双链表复制构造函数(不能尾对头复制)

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

所以,我正在尝试实现一个复制构造函数,在实例化对象时,我可以选择从头到尾(正常)或尾到头(反向)复制列表。现在,当我使用复制构造函数时,它总是从头到尾复制,即使它进入反向条件也是如此。

这是我的头文件:

#include <iostream>
#include "Student.h"
#include "Node.h"
using namespace std;

class List {

public:
    List(); // Default constructor
    List(const List&); // Copy constructor (2-in-1, see lab sheet)
    ~List(); // Destructor

    bool isEmpty(); // List is empty: TRUE or FALSE?
    int getNumNodes() {return numNodes;} // How many Nodes in List

    void append(Student *); // Append new Node to head or tail of List
    void insert(Student *); // Inserts new Node in the
                            // Appropriate location in List
    void deleteNode(string); //Search for and delete specific Node
    void displayAscending();// Display List HEAD to TAIL
    void displayDescending(); // Display List TAIL to HEAD

    // input Student::data into Student pointer.
    void input(Student*, string, string, string, string, string);

    Node *getHead() const {return head;} // ptr to head. 
    Node *getTail() const {return tail;} //ptr to tail.

private:
    void printer(Node *); //recursive function w/in displayDescending()
    Node *head;
    Node *tail;

    bool empty;
    bool forward; // forward = head-to-tail i.e. true
    int numNodes; // number of nodes in the list 
};

这是我的复制构造函数。

List::List(List &list) { // Copy constructor
    head = NULL; // Head pointer set to NULL initially
    tail = NULL; // Tail pointer set to NULL initially

    empty = true;
    forward = true; // Copies head-to-tail by default.
    numNodes = 0;

    string flag; // Stores prompt value.
    cout << "Copy from head to tail? (y/n): ";
    cin >> flag; // prompt for user.
    if(flag == "n")
        forward = false;

    Node *curr = NULL; //initialize curr in function scope.

    if(flag == "n") {
        forward = false;
        curr = list.getTail(); // curr points to list tail.
        cout << "Copying in reverse order...\n" << endl;
    } else { // forward == true
        curr = list.getHead(); // curr points to list head.
        cout << "Copying from head-to-tail...\n" << endl;
    } // end if/else 

    while(curr) {
        string f = ( curr->getData()->getFirst()  );
        string m = ( curr->getData()->getMid()    );
        string l = ( curr->getData()->getLast()   );
        string s = ( curr->getData()->getSocial() );
        string a = ( curr->getData()->getAge()    );

        Node *nodePtr = NULL; // a node that's pointing 
                              // using it to point to creation of
                              // a new node
        Student *stuPtr = new Student; // creates a stud pointer on
                                       // heap of Student class in
                                       // order to store stud info 
        input(stuPtr,f,m,l,s,a); // input Student::data into stuPtr.      
        append(stuPtr); // append the node with stuPtr to head or tail
                        // of list.

        if(!forward)
            curr = curr->getPrev();
        else
            curr = curr->getNext();
    }  // end while*/
    cout << "Done copying!\n" << endl;
} // end copy constructor

此外,如果您需要查看它是如何附加到列表的,这里是 append() 函数。

void List::append(Student *newStudent) {
    Node *newNode = new Node(newStudent); // new Node containing student arg.

    newNode->getData(); // get data of student arg.

    if(isEmpty()) {  // tail=NULL, no list.
        cout << "List is empty. Inserting first Node.\n" << endl;
        head = newNode;
        tail = newNode; // new Node becomes head & tail.
    } else { 
        if(forward) { // append to tail of list.
            tail->setNext(newNode); // NEXT ptr of tail points to newNode.
            newNode->setPrev(tail); // newNode's PREV points to former tail.
            tail = newNode; // newNode becomes the new tail.
        } else { // append to head of list.
            head->setPrev(newNode); // PREV ptr of head points to newNode.
            newNode->setNext(head); // newNode's NEXT points to former head.
            head = newNode; // newNode becomes the new head.
        } // end if/else
    } // end if/else
    numNodes++;
}

最佳答案

你似乎总是从头到尾复制的原因是你的代码是乱七八糟的,并且试图同时以不止一种方式做同样的事情。如果你试图从尾部复制从头到尾,您将新列表从尾部写到头部,您从尾部到头部读取旧列表。这两者相互抵消。想一想。

如果您尝试使参数 const 出现编译器错误的原因是您正在使用 getTail()getHead()< 查询它,您还没有将其设为 const

编辑:

让我们回到设计并思考尾对头复制应该如何工作。基本上有两种方法,头尾读取和尾对头写入:

|                |
v                v
A-B-C-D          A

  |            |
  v            v
A-B-C-D        B-A

    |        |
    v        v
A-B-C-D      C-B-A

      |    |
      v    v
A-B-C-D    D-C-B-A

或反之亦然:

      |    |
      v    v
A-B-C-D    D

    |        |
    v        v
A-B-C-D    D-C

  |            |
  v            v
A-B-C-D    D-C-B

|                |
v                v
A-B-C-D    D-C-B-A

但是,如果我们尝试两者,它们会抵消:

      |          |
      v          v
A-B-C-D          D

    |          |
    v          v
A-B-C-D        C-D

  |          |
  v          v
A-B-C-D      B-C-D

|          |
v          v
A-B-C-D    A-B-C-D

我们所要做的就是选择一个。如果我们选择第一个,我们更改复制构造器:

curr = list.getHead(); // curr points to list head.
cout << "Reading from head-to-tail...\n" << endl;

while(curr) {
  ...
  append(stuPtr); // append the node with stuPtr to head or tail of list.

  curr = curr->getNext();
}  // end while*/

而且它有效。如果我们选择第二个,我们就不用管构造函数并更改 append(...):

if(isEmpty()) {  // tail=NULL, no list.
  cout << "List is empty. Inserting first Node.\n" << endl;
  head = newNode;
  tail = newNode; // new Node becomes head & tail.
} else {
  tail->setNext(newNode); // NEXT ptr of tail points to newNode.
  newNode->setPrev(tail); // newNode's PREV points to former tail.
  tail = newNode; // newNode becomes the new tail.
} // end if/else

一般来说,避免此类问题的方法是从小而简单开始,一次增加一点点复杂性,每一步都进行测试,首先隔离测试新功能,永远不要添加不起作用的代码.找到不明显的错误的方法是对你的代码进行简化,逐步消除复杂性,直到你达到仍然表现出错误行为的最简单版本——或者更有可能的是,错误在这个过程中变得很明显.

关于c++ - 双链表复制构造函数(不能尾对头复制),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18263818/

相关文章:

为双向链表创建标题

c++ - 通过 boost::asio::tcp::ip 发送的大正文

c++ - 在 C++ 中乘法变量有问题。 (除非硬编码,否则 C++ 不想将它们相乘)

c++ - std::queue 初始化为 NULL

c++ - 在 C++ 中创建对象的拷贝

java - 使用尾递归的双向链表

c - 双向链表

c++ - 如何允许 64 位 Windows 上的 32 位应用程序执行 Windows\System32 中提供的 64 位应用程序

java - 复制构造函数的一个问题

java - 我应该为从 getter 返回的每个对象编写复制构造函数吗