
本文详细阐述如何将二叉树原地扁平化为一种类似双向链表的结构,其中节点的左右指针分别模拟链表的prev和next指针。通过递归辅助函数,文章深入解析了在遍历过程中如何正确地调整节点指针,以实现左-中-右的顺序连接,并避免常见的循环引用问题。此教程旨在提供一个清晰、高效的二叉树扁平化解决方案。
二叉树扁平化是将一个标准的二叉树结构转换为一个类似双向链表的结构。在这个新的结构中,原二叉树的节点仍然存在,但它们的 left 和 right 指针被重新定义,分别扮演了双向链表中的 prev 和 next 角色。扁平化后的节点应遵循原二叉树的左-中-右(in-order)遍历顺序。此过程必须是“原地”(in-place)操作,即直接修改现有节点的指针,而不是创建新的节点或复制数据。最终,函数需要返回扁平化结构的最左侧节点(即原二叉树中in-order遍历的第一个节点)。
首先,我们定义二叉树的节点结构,它包含一个值、一个左子节点和一个右子节点。
class BinaryTree:
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right实现原地扁平化的关键在于使用递归辅助函数,它能够处理当前节点及其左右子树的扁平化,并将它们正确地连接起来。辅助函数通常需要返回扁平化子树的最左侧节点和最右侧节点,以便父节点能够将它们连接到自身。
在尝试实现时,一个常见的误区是对辅助函数返回值的初始化。例如,考虑以下初始化方式:
# 假设这是某个辅助函数内部 leftmostofleft = node rightmostofright = node leftmostofright = node # 潜在问题 rightmostofleft = node # 潜在问题
这种初始化方式在某些情况下会导致错误。具体来说,如果一个节点没有右子节点,而我们将其 leftmostofright 初始化为 node,那么当执行 node.right = leftmostofright 时,就会导致 node.right = node,从而形成一个循环引用。这显然不是我们期望的双向链表结构,因为链表不应该有节点指向自身作为其下一个节点。因此,在没有实际子树的情况下,对应的“最左侧”或“最右侧”节点指针应该保持为 None,直到它们被实际的子树扁平化结果填充。
为了避免上述问题并简化逻辑,我们可以采用一个更精炼的递归策略。核心思想是:
Krikey AI
113
查看详情
以下是优化后的 helper 函数实现:
def flattenBinaryTree(root):
# 如果根节点为空,则直接返回None
if root is None:
return None
# 调用辅助函数进行扁平化,并返回扁平化结构的最左侧节点
leftmost, _ = helper(root)
return leftmost
def helper(node):
# 递归终止条件:如果节点为空,则返回None, None
if node is None:
return None, None
# 初始化当前节点为扁平化结构的最左和最右节点,
# 假设它目前是独立的,没有左右子树连接
leftmost_of_flattened_subtree = node
rightmost_of_flattened_subtree = node
# 1. 扁平化左子树
# 如果存在左子节点
if node.left:
# 递归调用helper,获取左子树扁平化后的最左侧和最右侧节点
# 注意:这里将返回的最左侧节点赋给 leftmost_of_flattened_subtree,
# 因为整个扁平化结构的最左侧节点将来自最左侧的子树。
# 同时,将左子树扁平化后的最右侧节点赋给 node.left,
# 这样 node.left 现在指向了它在双向链表中的“前一个”节点。
leftmost_of_flattened_subtree, node.left = helper(node.left)
# 建立从左子树扁平化后的最右侧节点到当前节点的连接
# 即:前一个节点的 right 指针指向当前节点
node.left.right = node
# 2. 扁平化右子树
# 如果存在右子节点
if node.right:
# 递归调用helper,获取右子树扁平化后的最左侧和最右侧节点
# 注意:这里将右子树扁平化后的最左侧节点赋给 node.right,
# 这样 node.right 现在指向了它在双向链表中的“后一个”节点。
# 同时,将返回的最右侧节点赋给 rightmost_of_flattened_subtree,
# 因为整个扁平化结构的最右侧节点将来自最右侧的子树。
node.right, rightmost_of_flattened_subtree = helper(node.right)
# 建立从右子树扁平化后的最左侧节点到当前节点的反向连接
# 即:后一个节点的 left 指针指向当前节点
node.right.left = node
# 返回当前节点所代表的扁平化子树的最左侧和最右侧节点
return leftmost_of_flattened_subtree, rightmost_of_flattened_subtree
这种方法巧妙地利用了Python的多重赋值特性,直接将递归调用返回的最左/最右节点赋值给对应的变量和当前节点的 left/right 指针,从而避免了中间变量的复杂性,并确保了指针的正确连接。
为了验证扁平化过程,我们需要一个辅助函数来插入节点和遍历扁平化后的链表。
# 假设 BinaryTree 类定义如上
# 扁平化主函数和辅助函数定义如上
# 用于测试的 BinaryTree 辅助方法
class BinaryTree(BinaryTree): # 继承以添加辅助方法
def insert(self, values, i=0):
if i >= len(values):
return
queue = [self]
while len(queue) > 0:
current = queue.pop(0)
if current.left is None:
current.left = BinaryTree(values[i])
break
queue.append(current.left)
if current.right is None:
current.right = BinaryTree(values[i])
break
queue.append(current.right)
self.insert(values, i + 1)
return self
def leftToRightToLeft(self):
nodes = []
current = self
# 从左到右遍历
while current.right is not None:
nodes.append(current.value)
current = current.right
nodes.append(current.value) # 添加最右侧节点
# 从右到左遍历
while current is not None:
nodes.append(current.value)
current = current.left
return nodes
# 测试用例
if __name__ == "__main__":
# 构建一个示例二叉树
# 1
# / \
# 2 3
# / \ \
# 4 5 6
# / \
# 7 8
root = BinaryTree(1).insert([2, 3, 4, 5, 6])
root.left.right.left = BinaryTree(7)
root.left.right.right = BinaryTree(8)
print("原始树结构(in-order 遍历):")
# 模拟in-order遍历
def in_order_tr*ersal(node, result):
if node is None:
return
in_order_tr*ersal(node.left, result)
result.append(node.value)
in_order_tr*ersal(node.right, result)
in_order_result = []
in_order_tr*ersal(root, in_order_result)
print(in_order_result) # 期望扁平化后的顺序:[4, 2, 7, 5, 8, 1, 6, 3]
# 扁平化二叉树
leftMostNode = flattenBinaryTree(root)
# 验证扁平化后的链表
flattened_values = leftMostNode.leftToRightToLeft()
print("扁平化后从左到右再到左遍历结果:")
print(flattened_values)
# 期望结果 (leftToRightToLeft): [4, 2, 7, 5, 8, 1, 6, 3, 3, 6, 1, 8, 5, 7, 2, 4]
expected = [4, 2, 7, 5, 8, 1, 6, 3, 3, 6, 1, 8, 5, 7, 2, 4]
assert flattened_values == expected
print("测试通过!")二叉树原地扁平化为双向链表结构是一个经典的递归问题,它要求我们深入理解二叉树的遍历顺序以及如何精确地操纵节点指针。通过一个返回子树最左和最右节点的辅助函数,我们可以高效地在in-order遍历过程中建立起前后节点间的双向连接。关键在于正确处理递归返回值的赋值,确保 node.left 和 node.right 最终指向其在扁平化链表中的 prev 和 next 节点,同时避免循环引用。这种方法不仅实现了原地操作,而且逻辑清晰,易于理解和维护。
以上就是深入理解二叉树扁平化:原地转换为双向链表结构的详细内容,更多请关注其它相关文章!
# 是一个
# seo后期优化方案
# 营销型网站建设如何开展
# 关键词平台排名
# 推广门店营销
# 河间seo优化选哪家
# 专注网站推广联系人
# 重庆seo工作
# 织金营销抖音推广方案
# 深圳外贸独立网站推广
# 龙华seo哪家最好
# 这是
# python
# 转换为
# 它在
# 二叉树
# 链表
# 遍历
# 递归
# 扁平化
# 子树
# ai
# app
# node
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
《书耽》更换手机号方法
毒蘑菇VOLUMESHADER_BM官网首页登录入口 毒蘑菇VOLUMESHADER_BM官网首页登录入口说明
圆通快递官方入口不需要登录 在线查询入口快速查询
PHP动态导航按钮:根据用户登录状态切换链接与文本
发布小红书怎么屏蔽粉丝?屏蔽粉丝能看到吗?
顺丰快递单号查询寄件人 顺丰寄件人查询入口
怎样让Windows 11的开始菜单恢复经典样式_Open-Shell工具使用指南【怀旧】
Sublime怎么配置YAML文件格式化_Sublime YAML Formatter插件教程
苹果17 Pro如何启用分屏浏览_iPhone 17 Pro分屏浏览设置步骤
123网页端官方登录页 123邮箱网页版即时通讯服务
《咸鱼之王》新版孙坚技能解析
《火影忍者:木叶高手》快速升级攻略
J*aScript深度克隆:实现高效、健壮与安全的复杂对象复制
QQ邮箱PC端登录页面_QQ邮箱网页版登录界面
抖音作品被限流怎么办 抖音内容优化与流量恢复方法
《深林》冬季章节图文攻略
《健康大兴》注册方法介绍
Python实时数据流中高效查找最大最小值
使用TinyButStrong生成HTML并结合Dompdf创建PDF教程
《领英》查看屏蔽名单方法
苹果手机怎么合并照片_苹果手机合并多张照片的操作方法
QQ网站入口直接登录 QQ官方正版登录页面
构建可配置的J*aScript加权点击计数器与共享总计功能
京东快递包裹信息查询入口 京东快递官方查询平台入口
银信通自动开通原因揭秘
C#解析并修改XML后保存 如何确保格式与编码的正确性
抖音火山版注销账号抖音会注销吗 抖音火山版与抖音账号注销关系
在J*a中如何实现在线问答与评分系统_问答评分项目开发方法说明
OpenWeatherMap API:通过城市名称获取天气预报数据指南
小米civi如何设置锁屏时间
顺丰快递在线查询系统 顺丰快递官方查单入口
c++如何链接Boost库_c++准标准库的集成与使用
优化Leaflet弹出层图片显示:条件渲染策略
使用AI在VS Code中将代码从一种语言翻译成另一种
CSS动画如何实现图标旋转并放大_transform rotate scale @keyframes实现
国际经济与贸易就业方向解析
Win10锁屏时间怎么设置 Win10调整自动锁屏时间方法
OPPO A3 WiFi频繁断开怎么办 OPPO A3网络优化技巧
CSS如何使用outline-offset与颜色组合突出元素边框
斯宾塞称XGP云游戏“蒸蒸日上”:正在构建一个游戏从未如此唾手可得的未来
Excel怎么用XLOOKUP函数实现双向查找_ExcelXLOOKUP替代VLOOKUP+HLOOKUP的高级用法
如何在CSS中使用过渡制作按钮边框渐变_border-color transition实现
汽水音乐在线听歌网页版 汽水音乐在线听歌网页版入口
百度网盘如何设置上传限额
电脑开不了机怎么办 电脑无法开机的解决方法
《百度畅听版》关闭兴趣推荐方法
《飞猪旅行》购买汽车票方法
PDF如何批量加注释_PDF多文件批注高亮操作教程
多闪电脑版下载_多闪PC端模拟器使用
CSS过渡与滚动滚动事件结合应用_scroll与transition动画
2025-12-04
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。