双链接列表复制构造函数(不能尾部复制)

时间:2013-08-15 23:58:18

标签: 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++;
}

2 个答案:

答案 0 :(得分:2)

你似乎总是从头到尾复制的原因是你的代码是蓬头垢面的,并尝试一次以多种方式做同样的事情。如果你试图从尾部复制你可以从头到尾编写新的列表从头到尾读取旧列表。这两个相互抵消了。想一想。

如果您尝试生成参数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(...)

它有效。如果我们选择第二个,我们会单独离开ctor并更改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

{{1}}

一般来说,避免这样的问题的方法是从小而简单开始,一次增加一点复杂性,在每一步测试,先隔离测试新功能,永远不要添加到不起作用的代码。找到非显而易见的错误的方法是采用你的代码和简化,逐步删除复杂性,直到你找到仍然表现出错误行为的最简单版本 - 或者更有可能的是,bug一路走来很明显

答案 1 :(得分:1)

通过使用const参数,您将在const对象上调用非const成员函数。非const函数不承诺不修改对象。您可以将这些成员函数声明为const以避免此错误:

Node *getHead() const

..等等

至于你的第一个问题,我不知道如何解决它(还),我有一些建议:

  • 使用nullptr代替NULL0
  • 使用list initialisation作为字符串:string f { curr->getData()->getFirst() };

我建议您使用一个好的调试工具(如Visual Studio)逐行调试代码 ;它可以帮助您在几分钟内解决您的问题。如果您仍然不确定,可以减少要测试的代码量,减少几行并发布。