题目描述
给定一棵二叉树,返回它的前序遍历。
进一步: 递归方法很容易,能否使用非递归方法?
样例
输入:[1,null,2,3]
1
\
2
/
3
输出:[1,2,3]
算法
(Morris-traversal) $O(n)$
用Morris-traversal算法遍历二叉树。Morris-traversal算法详见Recover Binary Search Tree。
算法步骤:
从根节点开始遍历,直至当前节点为空为止:
- 如果当前节点没有左儿子,则打印当前节点的值,然后进入右子树;
- 如果当前节点有左儿子,则找当前节点的前驱。
(1) 如果前驱节点的右儿子为空,说明左子树没遍历过,则先将前驱节点的右儿子置成当前节点,方便回溯,然后打印根节点,并进入左子树遍历;
(2) 如果前驱节点的右儿子为当前节点,说明左子树已被遍历过,则将前驱节点的右儿子恢复为空,然后进入右子树继续遍历;
时间复杂度分析:Morris-traversal算法的时间复杂度是 $O(n)$,空间复杂度是 $O(1)$。
C++ 代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
while (root)
{
if (!root->left)
{
res.push_back(root->val);
root = root->right;
}
else
{
TreeNode *pre = root->left;
while (pre->right && pre->right != root) pre = pre->right;
if (pre->right) pre->right = 0, root = root->right;
else
{
pre->right = root;
res.push_back(root->val);
root = root->left;
}
}
}
return res;
}
};