morris前序遍历通过临时利用空右指针构建线索实现o(1)空间复杂度:若当前节点无左子树则访问后向右;若有,则找左子树最右节点,首次建立线索并访问当前节点后向左,回溯时恢复结构并向右。

如果您需要在不使用栈或递归的情况下实现二叉树的前序遍历,Morris遍历提供了一种仅用常数额外空间的解决方案。以下是该算法的深度解析与具体实现步骤:
一、Morris前序遍历核心思想
Morris遍历通过临时修改树中节点的空右指针(或左指针),构建线索化路径,遍历完成后恢复原始结构。前序遍历的关键在于:每次到达某节点时,若其左子树存在,则先访问该节点本身;随后利用右指针线索进入左子树最右节点,建立回溯链接;若左子树不存在,则直接向右移动。
1、初始化当前节点为根节点。
2、当当前节点非空时,执行以下判断:
3、若当前节点无左子节点,则输出当前节点值,并将当前节点更新为其右子节点。
4、若当前节点有左子节点,则查找其左子树的最右节点(即中序前驱)。
5、若最右节点的右指针为空,则将其右指针指向当前节点,输出当前节点值,并移动到左子节点。
6、若最右节点的右指针已指向当前节点,则将右指针置空以恢复树结构,并将当前节点更新为其右子节点。
二、C++代码实现细节说明
实现需严格区分“首次访问”与“回溯访问”两种状态,通过检查左子树最右节点的右指针是否指向当前节点来判别。所有指针操作必须确保不造成内存泄漏或非法解引用。
1、定义二叉树节点结构体,包含val、left、right三个成员。
2、声明函数preorderTraversal,参数为TreeNode* root,返回std::vector
3、在函数内声明空结果容器result和当前节点指针curr初始化为root。
4、进入while循环,条件为curr不为空。
5、若curr->left为空,则将curr->val加入result,并令curr = curr->right。
6、否则,声明predecessor指向curr->left,执行while循环找到其最右节点。
7、若predecessor->right为空,则设置predecessor->right = curr,将curr->val加入result,再令curr = curr->left。
8、否则(即predecessor->right == curr),将predecessor->right置为nullptr,令curr = curr->right。
三、关键边界情况处理
算法必须正确应对空树、单节点树、完全右斜树、完全左斜树等极端结构,避免无限循环或访问空指针。所有指针赋值前均需校验非空性。
1、在进入左子树搜索前,先判断curr是否为空,若为空则立即跳出外层循环。
2、在查找predecessor时,while循环条件应为predecessor->right != nullptr && predecessor->right != curr。
3、当curr->left存在且predecessor->right为空时,必须在设置线索后立即记录curr->val,确保前序顺序。
4、当检测到predecessor->right == curr时,必须先恢复树结构(置空右指针),再向右推进,防止重复访问。
5、对每个curr节点,仅在其左子树被线索化前或无左子树时输出值,绝不于回溯路径上重复输出。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











