递归克隆图时的堆栈溢出
stackoverflow when cloning graph recursively
我收到错误"地址消毒器..运算符 new 中的堆栈溢出(无符号长(">使用此版本的代码,其中我使用复制>neighbors.push_back
class Node {
public:
int val;
vector<Node*> neighbors;
Node() {}
Node(int _val, vector<Node*> _neighbors) {
val = _val;
neighbors = _neighbors;
}
};
unordered_map<Node*, Node*> copies;
Node* cloneGraph(Node* node) {
if(!node) return node;
if(copies.find(node)==copies.end()){
Node *copy = new Node(node->val,{});
for(auto neighbor:node->neighbors){
copy->neighbors.push_back(cloneGraph(neighbor));//stackoverflow
}
copies[node]= copy;
}
return copies[node];
}
但它适用于我使用副本[节点]->neighbors.push_back的这个版本,为什么会这样?
唯一的区别是使用对全局映射元素的引用:副本[节点]与本地指针副本
Node* cloneGraph(Node* node) {
if(!node) return node;
if(copies.find(node)==copies.end()){
copies[node] = new Node(node->val,{});
for(auto neighbor:node->neighbors){
copies[node]->neighbors.push_back(cloneGraph(neighbor));
}
}
return copies[node];
}
在第一个实现中,您将为每个推送到堆栈的递归调用创建一个新的 Node。然而,在您的第二个实现中,它被放置在一个不属于局部递归变量的数组中(它看起来像一个全局变量(,因此堆栈不需要跟踪新创建的节点。
当递归函数导致堆栈溢出时,您应该寻找的第一件事就是无限递归。
考虑一个有两个节点的简单图:A
是B
的邻居,B
是A
的邻居(对于无向图来说非常标准(。当你打电话给cloneGraph(&A)
时会发生什么?
- 节点
A
不在映射中,因此会进行克隆。 - 作为克隆过程的一部分,
cloneGraph(&B)
被称为。
那么接下来会发生什么?
- 节点
B
不在映射中,因此会创建一个克隆。 - 作为克隆过程的一部分,调用
cloneGraph(&A)
。
好了,回到我们开始的地方。如果递归继续,这可能会变得丑陋。所以最大的问题是
- 此时,地图中是否
A
?
使用代码的第一个版本,它不是。因此,递归重复,直到堆栈溢出。使用代码的第二个版本,它是,所以递归在这一点上结束。
在第一个版本中,你有一个递归,它可以为带有循环的图生成无限循环。请注意,进入更深层次递归的条件是在映射copies
中找不到节点,但此映射仅在整个递归完成后更新。
如果你的图是 A->B 和 B->A,那么对cloneGraph(&A)
的调用将调用cloneGraph(&B)
,这将无限期地调用cloneGraph(&A)
等等,直到调用堆栈没有更多的空间。
仔细考虑你的算法。大概你的图有cylces。
由于您的第一个版本仅在递归到cloneGraph
后将新创建的节点添加到copies
,因此下一次调用将尝试再次克隆同一节点,这将递归等。
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 我的 int main() 中出现堆栈溢出错误
- C++ 对象数组堆栈溢出
- 有没有一种方法可以捕获进程中的堆栈溢出?C++Linux
- 对象接收堆栈溢出异常 c++ 的排序向量
- 将公共递归转换为尾递归,因为大型输入的堆栈溢出
- C++ 中递归期间的堆栈溢出
- 启动 dll 时 C# 环境堆栈溢出
- 在C++中使用数组时如何防止堆栈溢出?
- 如何修复递归函数导致的堆栈溢出错误?C++
- 当我尝试为结构分配新指针时出现堆栈溢出错误
- 为什么析构函数无休止地调用自己(导致堆栈溢出)?
- 为什么堆栈溢出?如有建议,不胜感激
- 主函数执行时C++堆栈溢出异常
- 如何在不导致堆栈溢出的情况下计算非常大的数字和很小的 HCF.我正在使用欧几里得算法
- 我正在尝试使用回溯来解决 N queen 问题,但在编译时它会给出运行时错误(动态堆栈缓冲区溢出)
- 如何在Windows上报告堆栈缓冲区溢出
- 如何抑制来自 gcc 中地址清理器的堆栈缓冲区溢出
- 声明大数组时堆栈/堆溢出
- c++中栈溢出和分段错误的危险