ZBLOG

vector ans; TreeNode* p1 = root; TreeNode* p2 = NULL; while (p1 != NULL) { p2 = p1->left; if (p2 != NULL) { while (p2->right != NULL && p2->right != p1) ...

这段代码实现了二叉树的前序遍历(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助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=20513

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?