这段代码实现了二叉树的前序遍历(Pre-order Traversal)的一种无递归算法,利用了莫里斯遍历的思想。我们逐行分析这段代码:
vector<int> ans;
TreeNode* p1 = root;
TreeNode* p2 = NULL;
vector<int> ans;
:定义一个整数向量ans
用于存储遍历结果。TreeNode* p1 = root;
:初始化指针p1
指向树的根节点root
,用于遍历树。TreeNode* p2 = NULL;
:定义一个指针p2
,用于找到当前节点的前驱节点。
while (p1 != NULL)
- 进入一个循环,只要
p1
不为空,就继续进行遍历。
{
p2 = p1->left;
- 将
p2
设置为当前节点p1
的左子树。
if (p2 != NULL)
- 检查当前节点是否有左子树。如果没有左子树,则直接访问右子树。
{
while (p2->right != NULL && p2->right != p1)
{
p2 = p2->right;
}
- 如果存在左子树,我们在其右侧找到最右边的节点(前驱),直到到达最右侧或者回到了当前节点(即将来要返回到的父节点)。
if (p2->right == NULL)
- 检查当前前驱节点的右指针是否为空。如果是空,说明我们还没有返回到父节点。
{
ans.emplace_back(p1->val);
p2->right = p1;
p1 = p1->left;
continue;
}
- 将当前节点的值添加到结果向量中,并设置前驱的右指针指向当前节点(建立回链),然后移动到左子树,继续处理下一个子树。这也使得下一次循环可以通过这个链接返回父亲。
else {
p2->right = NULL;
}
- 如果前驱已经链接到了当前节点,表示我们刚从它那里回来。因此需要断开这个连接,以恢复原状,从而避免无限循环。
}else {
ans.emplace_back(p1->val);
}
- 如果没有左子树,则直接将当前节点值添加到结果中,然后继续访问其右子树。
p1 = p1->right;
}
- 移动到右孩子结点开始新一轮的判断和操作。这个步骤会使得最终访问整个二叉树。
最后,通过以上步骤,实现了对二叉树的前序遍历且不使用栈或递归。每个步骤保证能准确访问每个节点一次,同时通过建立临时链接来控制遍历流程。
内容由零声教学AI助手提供,问题来源于学员提问