XNB's Not a Beginner 2024-02-09 02:59 采纳率: 0%
浏览 6

《递归调用。。拷贝构造函数,克隆二叉树》

先贴代码

img


意中写出来的反直觉的逆天东西。

正常来说,想要深度克隆一颗二叉树,安全做法应该写一个辅助的函数接口,再递归调用。

而这里用到了成员初始化列表和三目运算符。。通过对当前节点的子节点做是否为空的判断。用new关键字再次触发拷贝构造,从未形成构造函数的递归调用。这里每一层都能够平行的拷贝当前节点,并且由于new返回一个自适配指针。也不会发生父节点和子节点的指针丢失问题。

所以几行代码就实现了。深度拷贝二叉树的功能。已经做了测试,暂时没有出问题。

我对cpp的类的内存模型和对象实例化机理不是很了解。但是从我已经掌握的基本原理来看,这么做又说得通,却觉得哪里有些怪怪的。总觉得,一定会有哪里存在不安全。

这样做比传统做法简洁很多,而且在拷贝构造的实现体内可以做其他逻辑,真正的对象深拷贝只用成员初始化列表就完成了功能。

思索了一阵后,我得出了一些想法
如果原二叉树中存在循环引用,即 某个节点的子节点指向了该节点的父节点或祖 先节点,那么简单的深拷贝可能会导致无限递 归,最终导致栈溢出或无法正常结束。在拷贝 二叉树时,需要确保没有循环引用的存在。某些线索二叉树或者三叉链表,亦或者ac后缀自动机的failed失配回跳指针,都会这么做,形成循环引用现象。
然后有些树结构,在实现外部节点和子节点时不一定是空指针,可能是一个dummy占位节点,stl的rbtree就是采用这种策略。那这里递归出口的实现就不一致了。一旦递归出口没有设置好,比如没有判断叶子节点也会造成循环递归。
但是因为没有仔细研究过类对象模型和一些具体的内存分配和对象实例化机制。所以我没法系统的解释这里可能存在的内存泄露问题。
不过这种克隆多叉数的方法。好像还挺常用的,虽然我看过大量的树结构的库代码实现,这里面并没有这么做。

  • 写回答

5条回答 默认 最新

  • 叫兽-郭老师 新星创作者: Java技术领域 2024-02-09 03:00
    关注

    参考通义千问和郭老师的小迷弟雅思莫了-编写提供,主要是为了帮助您快速解决问题,如下回答,您可以参考下,如有问题,评论区留言。

    您提到的代码片段和实现方式确实非常简洁,它利用了C++的构造函数成员初始化列表以及递归调用拷贝构造函数的方式来深度克隆二叉树。这种方式在没有循环引用、所有空节点都已适当地处理为nullptr的前提下是有效的。然而,正如您所担忧的,这种方法存在一定的风险:

    1. 循环引用问题:如果二叉树中存在循环引用,即某个节点的子节点或父节点形成了一个闭环,那么简单的深度拷贝确实可能导致无限递归,从而栈溢出。

    2. 特殊节点处理:对于使用占位节点(dummy node)而不是nullptr表示空节点的情况,上述方法可能无法正确处理这些特殊节点,需要针对这类情况进行特殊处理。

    3. 内存泄露:由于直接在构造函数内部通过new分配内存创建新的节点,并依赖于析构函数来释放内存,如果在程序运行过程中出现异常或其他未预见的情况导致对象析构不完整时,可能会造成内存泄露。

    因此,虽然这种方法在特定场景下简洁且有效,但在实际编程中为了保证代码的健壮性和可维护性,通常会采用辅助函数递归的方式来深度克隆二叉树,并在函数内显式地处理各种边界条件和特殊情况。同时,可以考虑采用智能指针(如std::unique_ptrstd::shared_ptr)来管理动态分配的内存,以降低内存泄露的风险。

    评论

报告相同问题?

问题事件

  • 创建了问题 2月9日