如何在双向链表上执行深层复制?

时间:2012-12-02 10:04:32

标签: c++ linked-list

我很难绕过指针。我可以想象这里有人可以更直观地概念化复制构造函数。我知道你不能简单地指定彼此的指针(浅拷贝),但我实际上很难复制对象。

以下是我的代码示例:

class LList {
    /* stuff */

    private:
        struct node {
            node   *next;
            node   *prev;
            int    *o;
        };

        node   *first; // The pointer to the first node (NULL if none)
        node   *last;  // The pointer to the last node (NULL if none)
}

感谢您的帮助!

3 个答案:

答案 0 :(得分:3)

当您为对象X(const T& other)编写复制构造函数时,X包含动态分配的T* p(在您的情况下可能是Node*),你最终可能会写这样一句话:

p = new T(*other.p);

这将创建您正在复制的对象所指向的对象的副本,从而为您提供该对象的深层副本。在您的情况下,这将最终导致列表的递归深度复制。

答案 1 :(得分:1)

创建链表的深层副本相当于创建具有相同数据值的新链表。

所以,你可以

  • 浏览当前列表
  • 从每个节点提取信息
  • 将其传递给新节点(基本上复制除列表指针以外的所有内容)
  • 将其添加到新列表(深层副本)。

在您的情况下,您需要尊重o,提取数据,分配新块,分配数据,然后将其添加到新节点。

答案 2 :(得分:1)

未经测试,但这可能表达了您所获得的想法的一部分。我尝试使用std::list代替:) 您应该添加一个复制赋值运算符和一个适当分配/解除分配的析构函数。请参阅here

template<typename T>
struct ListNode {
    ListNode *next, *prev;
    T value;

    ListNode(const T &val): value(val), next(0), prev(0) {}

    // copy constructor
    ListNode(const ListNode &other): value(other.value) {
        if(other.next)
           append(new ListNode(*other.next));
    }

    void append(ListNode &n) {
        next = &n; n.prev = this;
    }
};

如果您的value是一个指针,那么您将要复制它,就像上面复制next指针成员一样,即:

    // copy constructor
    ListNode(const ListNode &other): value(new T(*other.value)) {
        if(other.next)
           append(new ListNode(*other.next));
    }

因此,对于上面的示例列表,您可以尝试这样的事情:

class LList {
    LList(): first(0), last(0) {}

    // copy constructor
    LList(const LList &other):
        first(0),
        last(0)
    {
        if(other.first) {
          first = new node(*other.first);
          // find last item
          last = first;
          while(last->next) last = last->next;
        }
    }

    ~LList() {
       if(first) delete first;
    }

    // TODO: copy assignment operator

private:
    struct node {
        node(int val): next(0), prev(0), o(new int(val)) {}
        // copy constructor
        node(const node &other): next(0), prev(0), o(*other.o)
        {
            if(other.next) {
               next = new node(*other.next);
               next->prev = this;
            }   
        }

        ~node() {
          delete o;
          if(next) delete next;
        }
        // TODO: copy assignment operator

        node   *next;
        node   *prev;
        int    *o;
    };

    node   *first; // The pointer to the first node (NULL if none)
    node   *last;  // The pointer to the last node (NULL if none)
};

未经测试但是这个想法......构造函数通过操作下一个项目来递归地工作。正如链接所解释的那样,“TODO”项很重要。您可能还想查看智能指针 - 它们不需要记住删除内容,提高异常安全性,并且通常比原始指针更安全。