返回
递归调用深拷贝的栈空间风险
前端
2024-02-06 04:01:19
爆栈引起的对深拷贝理解
面对庞大数据,递归式深拷贝极易爆栈,风险在于函数调用栈帧无限扩张 。每一次递归调用都会在栈中创建新的栈帧,而递归深度与数据规模正相关。当数据量超出栈容量,就会发生爆栈错误。
如何避免爆栈?
解决爆栈的关键在于控制递归调用深度 。以下方法可行:
- 迭代代替递归: 将递归算法转换为迭代算法,避免函数调用栈的增长。
- 限制递归深度: 通过外部变量或参数对递归调用深度设置上限。
对深拷贝的理解
爆栈问题凸显了深拷贝与浅拷贝的本质区别。
- 浅拷贝: 仅复制对象引用,浅拷贝后的对象与原对象共享底层数据。修改副本会同时影响原对象。
- 深拷贝: 复制整个对象及其所有子对象,深拷贝后的对象独立于原对象,修改副本不会影响原对象。
递归式深拷贝 是一种利用递归算法遍历对象并生成新对象的深拷贝方法。
示例:
考虑一个包含嵌套列表的列表:
original_list = [[1, 2], [3, 4, [5, 6]]]
递归式深拷贝:
import copy
def deep_copy(obj):
if isinstance(obj, list):
return [deep_copy(x) for x in obj]
else:
return copy.copy(obj)
new_list = deep_copy(original_list)
避免爆栈:
为了避免爆栈,可以通过以下方式限制递归深度:
- 设置递归深度上限:
def deep_copy(obj, depth=0):
if depth > 10: # 设置递归深度上限为 10
return copy.copy(obj)
if isinstance(obj, list):
return [deep_copy(x, depth + 1) for x in obj]
else:
return copy.copy(obj)
- 使用迭代器:
def deep_copy(obj):
stack = [obj]
visited = set()
new_objects = []
while stack:
current_obj = stack.pop()
if current_obj in visited:
continue
visited.add(current_obj)
if isinstance(current_obj, list):
new_list = []
new_objects.append(new_list)
stack.append(new_list)
for item in current_obj:
stack.append(item)
else:
new_objects.append(copy.copy(current_obj))
return new_objects[0]