leetcode#144 二叉树的前序遍历
题目:
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
示例:
输入:root = [1,null,2,3]
输出:[1,2,3]
思路:
递归。
迭代。
Morris遍历:
我们递归和迭代时,实际上用了一个栈去维护访问节点顺序,以便回溯。
我们可以这样,用空余指针指向回溯的下一个点,这样就不用存储序列了。
对于一个点,什么时候会回溯到当前点,显然,当我们遍历完左子树最后一个点时,会回到这个点,如果用栈,就把栈回退到当前点。然而我们可以用左子树的最后一个点的指针指向当前点,这样当遍历完成过后,根据指针可以直接回到当前点。
细节:
p1为当前点,p2为临时指针指向p2->left也就是左子树,用p2=p2->right的方式,一直遍历右子树,这样就可以得到p1的前驱节点,让前驱节点指向当前节点即可,代表左子树已经遍历完,这样当遍历到这个点时直接p1->right就能返回当前节点,返回当前节点后,再次遍历找前驱节点,前驱节点的下一个节点改为null即可。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution
{
public:
vector<int> preorderTraversal(TreeNode *root)
{
vector<int> ans;
if (!root)
return ans;
TreeNode *p1 = root, *p2 = NULL;
while (p1)
{
p2 = p1->left;
if (p2)
{
while (p2->right && 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;
}
return ans;
}
};