【问题标题】:Deep copy queue recursively C++ (Implemented using a doubly linked list)递归深度复制队列 C++(使用双向链表实现)
【发布时间】:2021-06-05 19:29:40
【问题描述】:

我正在使用双向链表构建队列。我希望我的深拷贝构造函数递归地深拷贝整个队列,但是当我执行以下操作时出现分段错误:

// Recursive helper method for deep copy constructor
void queue::copyAllNodes(Node* og, Node *cpy) {
    if(og == nullptr) back = og;
    else {
        cpy->previous = og->previous;
        cpy->data = og->data;
        cpy->next = og->next;
        copyAllNodes(og->next, cpy->next);
    }
}

我的构造函数有另一个辅助函数,允许我传入原始节点和要复制的复制节点。

【问题讨论】:

  • 很可能cpy 不会按要求分配所有节点,还要考虑到新节点的创建。
  • 如果你可以回收队列的推送功能,似乎没有必要。
  • 嗯...看看你的代码。您没有看到递归调用实际上只是copyAllNodes(og->next, og->next);,因为它前面有一行吗?我敢问到底是什么力量让你以递归方式而不是迭代方式完成简单的枚举和复制任务?通常情况下,递归正好落在“仅仅因为你可以并不意味着你应该”的范围内。
  • 我只是想看看我能不能做到,但事实证明它并不像我想象的那么简单。我尝试了没有复制 cpy->next 但仍然有段错误
  • 我同意 WhozCraig 关于使用递归的观点。它不能很好地扩展(例如,假设你的列表有 100,000,000 个元素——你会得到堆栈溢出吗?)。我将从一个非递归函数开始,并首先使其工作[然后,if必须 递归解决方案]。您正在使用 queue 成员函数,但实际上并未更改它(例如 queue::push)。事实上,我认为即使对于迭代案例,您的解决方案也需要重构。您不需要为副本分配新节点(例如Node *dstnode = new Node(...);)吗?

标签: c++ queue doubly-linked-list recursive-datastructures


【解决方案1】:

首先,了解您实际上并没有在此处复制任何内容。您只是通过递归和分配指针进行枚举。 最好是浅拷贝;实际上,您的算法完全被破坏了。 种方法可以递归地复制链表,包括双向链表。这样做是否明智是另一回事。


单向列表

在进入双向链表的主题之前,请考虑单向链表的基本情况。假设您有一个包含如下节点的链表:

template<class T>
struct Node
{
    T data;
    Node *next;

    Node(T dat, Node *nxt = nullptr)
        : data(std::move(dat))
        , next(nxt)
    {
    }
};

现在假设你想递归地制作一个深拷贝。递归复制算法最简单的形式是:

Node *copyDeep(const Node *p)
{
    Node *res = nullptr;
    if (p)
        res = new Node(p->data, copyDeep(p->next));
    return res;
}


双向列表

引入双链接节点(nextprev 成员)使这更具挑战性,但难度不大。首先必须修改节点以包含新成员:

struct Node
{
    T data;
    Node *next;
    Node *prev;

    Node(T dat, Node *nxt = nullptr)
        : data(std::move(dat))
        , next(nxt)
        , prev(nullptr)
    {
    }
};

这样,copyDeep 可以修改为记住添加的节点,用作递归调用的添加参数。一种方法是:

Node *copyDeep(Node *p, Node *prev = nullptr)
{
    if (p)
    {
        Node *res = new Node(p->data);
        res->prev = prev
        res->next = copyDeep(p->next, res);
        return res;
    }
    return nullptr;
}

两种情况中,迭代地执行此操作更容易、更快且更不容易出错(包括堆栈溢出)。在回答您的问题时,是的,您可以递归地复制链接列表。这样做是否是个好主意,我留给你。

【讨论】:

    猜你喜欢
    • 2014-06-05
    • 2020-04-17
    • 1970-01-01
    • 2011-12-02
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 2018-04-27
    相关资源
    最近更新 更多