三种方法。
方法一:递归遍历。 Time:O(n); space:O(n);
方法二:使用stack。Time:O(n); space:O(n);
方法三:使用stack。Time:O(n); space:O(n);
方法四:Morris遍历。Time:O(n); space:O(1);
方法一代码如下:
/**
* Definition for binary tree
* 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> result;
if(root == NULL)
return result;
result.push_back(root->val);
vector<int> left = preorderTraversal(root->left);
vector<int>right = preorderTraversal(root->right);
result.insert(result.end(), left.begin(), left.end());
result.insert(result.end(), right.begin(), right.end());
return result;
}
};
方法二使用栈,模拟递归的过程,每次将访问到的节点压栈,然后访问其左子树,直到左子树为空,然后从栈中弹出最后一个访问的节点,然后访问右子树。在同一层中,不可能有两个节点同时在栈里,栈空间的大小为O(h),h为二叉树的高度。二叉树中的每个节点入栈一次,出栈一次,访问一次,时间复杂度为O(n)。
class Solution {
public:
vector<int> preorderTraversal(TreeNode *root) {
vector<int> result;
stack<TreeNode*> s;
TreeNode *p = root;
while(p != NULL || !s.empty())
{
if(p != NULL)
{
result.push_back(p->val);
s.push(p);
p = p->left;
}
else
{
p = s.top();
s.pop();
p = p->right;
}
}
return result;
}
};
方法三也使用栈,先入栈右子节点,再入栈左子节点。栈中最多h-1个右节点和一个左节点,空间为O(h),时间为O(n)。代码如下:
class Solution {
public:
vector<int> preorderTraversal(TreeNode *root) {
vector<int> result;
stack<TreeNode*> s;
const TreeNode* p;
if(root != NULL)
s.push(root);
while(!s.empty())
{
p = s.top();
s.pop();
result.push_back(p->val);
if(p->right != NULL) s.push(p->right);
if(p->left != NULL) s.push(p->left);
}
return result;
}
};
方法四:Morris遍历。
Morris遍历的过程中即使已经计算出了最终结果,也要把整棵树都遍历完,否则树的结构将被破坏。
class Solution {
public:
vector<int> preorderTraversal(TreeNode *root) {
vector<int> result;
TreeNode *cur = root, *prev = NULL;
while(cur != NULL)
{
if(cur->left == NULL)
{
result.push_back(cur->val);
cur = cur->right;
}
else
{
prev = cur->left;
while(prev->right != NULL && prev->right != cur)
prev = prev->right;
if(prev->right == NULL)
{
result.push_back(cur->val); //here is different from inorder traversal
prev->right = cur;
cur = cur->left;
}
else
{
prev->right = NULL;
cur = cur->right;
}
}
}
return result;
}
};
参考:http://www.cnblogs.com/TenosDoIt/p/3416824.html
http://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html (Morris遍历方法)