这段代码实现的是一种遍历二叉树的方法,具体来说,它是前序遍历的 Morris 遍历算法。Morris 遍历是一种不使用栈或递归,且只使用常数空间复杂度的树遍历方法。下面对代码进行详细解释,并举例说明其运行步骤。
代码解释
初始化:
- 创建一个
vector<int> ans
用于存储遍历结果。 - 使用两个指针
p1
和p2
。p1
初始指向树的根节点,p2
初始化为 NULL。
- 创建一个
主循环:
- 当
p1
不为 NULL 时,执行以下操作:
- 当
寻找右子树最右侧节点:
- 将
p2
设置为p1->left
(当前节点的左子树)。 - 如果左子树存在(即
p2 != NULL
),进入内部循环以找到左子树最右侧的节点(即最深的右叶子节点):while (p2->right != NULL && p2->right != p1)
- 一旦找到这个最右侧节点,将其的右指针指向当前节点
p1
,并将当前节点值加入到答案中,然后将当前指针移动到左孩子继续处理。 - 如果找到的是回到父亲节点的情况(即
p2->right == p1
),则将p2->right = NULL
断开这种连接。
- 将
如果没有左孩子:
- 直接将当前节点值添加到结果列表中,然后移动到右子树。
返回结果:
- 最终返回填充好的结果数组
ans
.
- 最终返回填充好的结果数组
举例说明
假设有如下二叉树:
1
/ \
2 3
/ \
4 5
步骤:
初始状态:
- 当前指针:
p1 = 1
- 当前指针:
第一轮迭代 (
p1 = 1
):- 左孩子是
2
, 找到它的最右侧是5
. - 将从
5.right = null -> p1
. - 将输出 1.
- 移动到左儿子:
p1 = 2
- 左孩子是
第二轮迭代 (
p1 = 2
):- 左孩子是
4
, 它没有右边,所以输出 [1, 2]. - 移动: 到它的儿子: -> p1=4.
- 左孩子是
第三轮迭代 (
p1 = 4
):- 没有左边,所以直接输出 [0,0,0] 为
[3,4]
.
- 没有左边,所以直接输出 [0,0,0] 为
… (继续按照相同逻辑)
最终运行完毕后,这个程序会返回一个包含 [4, 2,5 ,3 ,0 ]
.
这个过程保证了每个结点都被访问并通过更新边而不是通过 stack或者 recursion 保持空间复杂度。
内容由零声教学AI助手提供,问题来源于学员提问