【问题标题】:Deep copy of doubly linked list [closed]双链表的深拷贝[关闭]
【发布时间】:2013-02-14 20:37:39
【问题描述】:

我无法对我的双向链表进行深层复制。这是一个家庭作业,所以我想知道为什么我的代码不工作,而不是得到我不理解的工作代码。

这是我的课:

#include "textAnalyzer.h"
#include <string>
#include <iostream>
#include <sstream>

TextAnalyzer::Node* TextAnalyzer::createNode(const string& word, const int wordFrequency, 
Node* const previous, Node* const next)
{
return new Node(word, wordFrequency, previous, next);
}
void TextAnalyzer::releaseNodes()
{
Node* del = tail;

while(tail != NULL)
{
    tail = tail->previous;
    tail->next = del;
    delete del;
    del = tail;
}

delete [] head;
delete [] tail;

head = tail = del = NULL;
}

void TextAnalyzer::copyNodes(Node* const copyHead)
{
head = new Node(*copyHead);
Node* iter = head->next;

for(Node* np = copyHead->next; np != NULL; np = np->next)
{
    iter->next = new Node(*np);
    iter = iter->next;
}

iter = NULL;
}

TextAnalyzer::TextAnalyzer():head(createNode("0",0,NULL,NULL)),tail(head)
{}

TextAnalyzer::TextAnalyzer(const TextAnalyzer& copyObject)
{
copyNodes(copyObject.head);
}

TextAnalyzer::~TextAnalyzer()
{
releaseNodes();
}

TextAnalyzer TextAnalyzer::operator=(const TextAnalyzer& assignObject)
{
return TextAnalyzer(assignObject);
}

void TextAnalyzer::insertWord(const string& word)
{
Node* iter = head->next;

while(iter != NULL)
{
    if(iter->word == word)
        iter->wordFrequency++;
    else if(iter->word[0] == word[0] && iter->next != NULL)
    {
        Node* temp = iter->next;
        iter->next = createNode(word, 1, iter, temp);
        iter = iter->next;
        temp->previous = iter;

        temp = NULL;
    }
    else if(iter->word[0] == word[0] && iter->next == NULL)
    {
        iter = createNode(word, 1, tail, NULL);
        tail = iter;
    }
    else
        iter = iter->next;
}

iter = NULL;
}

int TextAnalyzer::wordCount() const
{
Node* iter = head->next;
int count = 0;

while(iter != NULL)
    count++;

return count;
}

int TextAnalyzer::wordCountWithInitialCharacter(const char startsWith)
{
Node* iter = head->next;
int count = 0;

for(int i = 0; i < wordCount(); i++)
{
    if(startsWith == iter->word[0])
        count++;

    iter->previous = iter;
    iter = iter->next;
}

iter = NULL;

return count;
}

string TextAnalyzer::toString() const
{
Node* iter = head->next;
string desc = "List of words: \n";
ostringstream convert;

for(int i = 0; i < wordCount(); i++)
{
    convert << iter->word[0] << " words:\n"
            << iter->word    << "(" 
            << iter->wordFrequency
            << ")\n";
    iter->previous = iter;
    iter = iter->next;
}

iter = NULL;

return desc + convert.str();
}

界面如下:

#ifndef TEXTANALYZER_H
#define TEXTANALYZER_H

#include <iostream>
#include <string>

using namespace std;

class TextAnalyzer {
private:

/*
 * Class: Node
 *
 * This class represents a node in a sorted doubly linked list that stores a
 * list of words and their frequency of occurrence.
 */
class Node {
public:
    string word;
    int wordFrequency;
    Node* previous;
    Node* next;

    Node(const string& word,
         const int wordFrequency,
         Node* const previous,
         Node* const next)
    : word(word),
      wordFrequency(wordFrequency),
      previous(previous),
      next(next)
    {}
}; // end ListNode
/*********************************************************************/

Node* head;
Node* tail;


/*
 * Releases all the memory allocated to the list.
 */
void releaseNodes();

/*
 * Makes a deep copy of the object.
 */
void copyNodes(Node* const copyHead);

/*
 * Returns a populated Node.
 * Throws a bad_alloc exception if memory is not allocated.
 */
Node* createNode(const string& word,
                 const int wordFrequency,
                 Node* const previous,
                 Node* const next);

public:
/* 
 * Initializes head and tail, each to a dymmy node.
 */
TextAnalyzer();

/*
 * Makes a deep copy of the object passed in.
 * Calls copyNodes() to do the actual work.     
 */
TextAnalyzer(const TextAnalyzer& copyObject);

/* 
 * Releases all the memory allocated to the object.
 * Calls the releaseNodes() method to do the actual work.
 */
~TextAnalyzer();

/* 
 * Makes a deep copy of the rhs object.
 */
TextAnalyzer operator =(const TextAnalyzer& assignObject);

/*
 * Inserts the word in a sorted order into the list. 
 *
 * If no Node exists with that initial character, one is added in
 * sorted order. If one does exist (same word), then the word frequency
 * of that word is incremented by one.
 */
void insertWord(const string& word);

/*
 * Returns a count of all the words in the list.
 */
int wordCount() const;

/* 
 * Returns a count of all the words with the initial character.
 */
int wordCountWithInitialCharacter(const char startsWith);

/*
 * Returns a description of the object. The string is formatted as:
 * [A words:]
 *     [<word>(<count>)]
 *     [<word>(<count>)]
 *     ...
 *
 * [B words:]
 *     [<word>(<count>)]
 *     [<word>(<count>)]
 *     ...
 *
 *...
 */
string toString() const;

};

#endif 

我需要使用上面给出的界面。我的问题是我的复制构造函数中出现错误,说“对象具有不兼容的限定符”或类似的东西。我假设这是因为copyObject 是不变的。但是,我不知道如何做到这一点,有人可以告诉我我在这里缺少什么吗?我对 C++ 相当陌生,我对 Java 更有经验,所以这可能就是我感到困惑的原因。

编辑:

感谢您的回复。我想我正要弄清楚如何成功地进行深拷贝。我已经更新了我的代码以显示我到目前为止完成的内容。现在我已经编译了代码,我得到了一个新的错误。每次我运行它时都会出现“未处理的异常 0xc0000005”。我用谷歌搜索它并认为这是由于尝试取消引用空指针而导致的错误。调试器显示它是在我的releaseNodes() 方法中抛出的。

void TextAnalyzer::releaseNodes()
{
Node* del = tail;

while(tail != NULL)
{
    tail = tail->previous; //error on this line
    tail->next = del;
    delete del;
    del = tail;
 }

delete [] head;
delete [] tail;

head = tail = del = NULL;
}

以上只是我的releaseNodes() 方法,带有注释,显示调试器所说的错误源自何处。我想看看我的其余代码是否有效,因为我是 C++ 新手,而且很可能我的逻辑在其他地方也存在缺陷,不幸的是,在解决此错误之前我无法测试任何东西。我仍在跟踪我的代码,试图找出可能导致它的原因。如果有人能指出我正确的方向,将不胜感激。

【问题讨论】:

  • 好吧,没关系!就像这里指出的那样好:stackoverflow.com/questions/890535/… 以前从未见过!
  • 您非常接近自己找出问题所在。这确实是因为copyObject 是常量。你确定你在正确的实例上调用copyNodes() 方法吗?
  • ...您不应该将参数传递给copyNodes吗?
  • delete [] head; delete [] tail; 这些应该是什么意思?
  • 我已经更新了代码以反映当前的变化,并希望能在我的新问题上得到帮助。 @arrows 删除 [] 头;并删除 [] 尾;释放列表的内存。我的想法可能是错误的,也许只有在使用数组进行动态分配时才需要这些?

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


【解决方案1】:

我假设这是它所说的那一行

void TextAnalyzer::copyNodes(Node* const copyHead)
{
    head->next = new Node(*copyHead);   
}

您只是将 head 中的 next 指针分配给一个新的 Node 对象。基本上,您只复制一个节点,即跟随头的节点,而不是整个列表。您已经对使用 while 循环在 releaseNodes 中应该做什么有了正确的想法。

您在复制构造函数中也错误地调用了它。你在定义中给了它一个参数,但你在构造函数中调用了一个不接受的参数。

【讨论】:

  • 不一定。我看到的代码中没有复制构造函数,但完全有能力创建整个列表的副本(甚至可能递归地保持代码简短)。
  • 我看到了,它是 cpp 文件中的最后 3 行。 OP 正在调用 copyNodes(),我认为他的意思是调用 copyNodes(Node* const head);。
  • 我的意思是 Node 类的复制构造函数。它应该是这样的:用其他节点的数据初始化数据,创建其他节点的next 的新实例,并将这个新对象链接到next(并记住将其更新为previous)。大约 4 行代码来做深拷贝。
猜你喜欢
  • 2018-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
  • 2021-12-29
  • 1970-01-01
  • 2011-06-08
  • 1970-01-01
相关资源
最近更新 更多