解法
- 前序------根-左-右
- 中序------左-根-右
- 后序------左-右-根
递归法、迭代法、莫里斯法
解法1递归法
这是经典的方法,直截了当。我们可以定义一个辅助函数来实现递归。
- 时间复杂度:O(n)O(n)。递归函数 T(n) = 2 \cdot T(n/2)+1T(n)=2⋅T(n/2)+1。
- 空间复杂度:最坏情况下需要空间O(n)O(n),平均情况为O(\log n)O(logn)。
牢记如下:
前序:
void fun(tree){
tree->val;
fun(tree->left);
fun(tree->right);
}
中序:
void fun(tree){
fun(tree->left);
tree->val;
fun(tree->right);
}
后序:
void fun(tree){
fun(tree->left);
fun(tree->right);
tree->val;
}
作者:183-3
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/zhe-ti-ying-gai-shu-yu-di-gui-de-ji-chu-ti-ba-by-1/
1、前序遍历递归
前序遍历即访问顺序按照: root -> left -> rightroot−>left−>right的顺序,直至访问到空结点。按照这个思路很容易写出递归实现。代码如下:
作者:007havegone
链接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/qian-xu-bian-li-by-007havegone/
/**
* 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> ret;
vector<int> preorderTraversal(TreeNode* root) {
pre_travel(root);
return ret;
}
void pre_travel(TreeNode* root)
{
if(root)//当前结点非空
{
ret.push_back(root->val);//访问根节点
pre_travel(root->left);//递归左子树
pre_travel(root->right);//递归右子树
}
}
};
2、后序遍历递归
https://leetcode.com/problems/binary-tree-postorder-traversal/discuss/45550/C%2B%2B-Iterative-Recursive-and-Morris-Traversal
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> nodes;
postorder(root, nodes);
return nodes;
}
private:
void postorder(TreeNode* root, vector<int>& nodes) {
if (!root) {
return;
}
postorder(root -> left, nodes);
postorder(root -> right, nodes);
nodes.push_back(root -> val);
}
};
3、中序遍历递归
/**
* 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> inorderTraversal(TreeNode* root) {
vector<int> res;
helper(root,res);
return res;
}
void helper(TreeNode* root,vector<int>& res){
if(root==NULL) return;
helper(root->left,res);
res.emplace_back(root->val);
helper(root->right,res);
}
};
作者:24shi-01fen-_00_01
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/die-dai-di-gui-by-24shi-01fen-_00_01-2/
解法2 迭代法
这里把前序、中序、后序的解法都列出来。内容来自如下链接:
https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/die-dai-fa-by-jason-2/
- 时间复杂度:O(n)O(n)。
- 空间复杂度:O(n)O(n)。
解题思路
1、前序遍历迭代算法
当然还可以通过自己用栈来完成递归的功能。即我们访问根节点后,然后访问其左子树,当左子树遍历完成后,我们需要访问右子树,此时我们就需要拿到父节点的信息,通过父节点我们从而访问其右子树。这样整棵树完成遍历后,继续回退到上一层。直至当前子树访问完成,同时栈为空。
作者:007havegone
链接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/qian-xu-bian-li-by-007havegone/
/**
* 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) {
if(!root)return vector<int>();//空树,直接返回
stack<TreeNode*> st;
vector<int> ret;
TreeNode* p=root;//p指向当前访问结点
while(p||!st.empty())
{
while(p){//若当前结点非空
ret.push_back(p->val);//访问该结点
st.push(p);//记录该结点到栈,后面回退
p=p->left;//进入左子树访问
}
// while条件的设置,保证下面st非空
//若p非空,那么一定会压入新元素,此时st非空。若p为空,则st一定非空
//按先序的,此时父节点已经访问,通过它拿到右孩子后就可以移除
p=st.top();st.pop();
p=p->right;//进入右子树访问
}
return ret;
}
};
2、后序遍历迭代算法
我们可以用与前序遍历相似的方法完成后序遍历。
后序遍历与前序遍历相对称。
思路: 每到一个节点 A,就应该立即访问它。 然后将左子树压入栈,再次遍历右子树。
遍历完整棵树后,结果序列逆序即可。
作者:jason-2
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/die-dai-fa-by-jason-2/
思路:
栈S;
p= root;
while(p || S不空){
while(p){
访问p节点;
p的左子树入S;
p = p的右子树;
}
p = S栈顶弹出;
}
结果序列逆序;
/**
* 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> postorderTraversal(TreeNode* root) {
stack<TreeNode*> S;
vector<int> v;
TreeNode* rt = root;
while(rt || S.size()){
while(rt){
S.push(rt->left);
v.push_back(rt->val);
rt=rt->right;
}
rt=S.top();S.pop();
}
reverse(v.begin(),v.end());
return v;
}
};
3、中序遍历迭代算法
思路:每到一个节点 A,因为根的访问在中间,将 A 入栈。然后遍历左子树,接着访问 A,最后遍历右子树。
在访问完 A 后,A 就可以出栈了。因为 A 和其左子树都已经访问完成。
作者:24shi-01fen-_00_01
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/die-dai-di-gui-by-24shi-01fen-_00_01-2/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> sk;
vector<int> res;
while(root || sk.size()){
while(root){
sk.push(root);
root=root->left;
}
root=sk.top();sk.pop();
res.emplace_back(root->val);
root=root->right;
}
return res;
}
};
解法3 莫里斯法
C++ 二叉树Morris法前、中、后遍历全集,见如下链接:
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/c-er-cha-shu-morrisfa-qian-zhong-hou-bian-li-quan-/