【Leetcode】144.二叉树的前中后序遍历 递归法 迭代法

这道题掌握了基本概念后,代码很简单,但是一般大厂面试标明了只接受非递归法

迭代法解释
三种解法C++
迭代法

首先分享一个图示法快速写出三种遍历的方法

在这里插入图片描述

任何算法的递归版本都可以改成非递归版本,因为函数递归调用其实质就是压栈的过程,那么我们完全可以使用堆栈来模拟这个过程。二叉树的遍历(递归法)很容易实现,本质是采用了栈帧的实现方式,函数调用就是压栈,函数求解就是出栈的过程,那么我们完全可以手动创建栈来模拟这个过程,按照指定遍历顺序迭代的访问二叉树的所有结点。

因为前序、中序、后序三种遍历方式在当前函数体内都是先调用f(root.left),再调用f(root.right),函数再往下逐层调用,直到f(root.left)返回为空时。所以三种遍历方式的切入点都是要先遍历到二叉树的最左子结点(root.left == null),在遍历的过程中将根节点入栈,出栈的时候访问当前根节点以及其右子二叉树。创建栈的作用主要就是能够让我们存储访问顺序的那些根节点,可以回溯的对二叉树进行访问。

关于递归和迭代的区别

请参考我的另外一篇博客
递归和迭代的区别
这里简述一下

  • 递归是自身调用自身函数。递归一般是单个变量的不断使用
  • 递归需要不断进栈出栈,内存消耗大

前序遍历

递归法

递归法重要的是写好递归函数
递归函数的三大要素
1.函数的返回类型及参数列表
2.函数的终止条件,不然会有栈溢出的危险
3.单层递归的逻辑
class Solution {
    
    
public:
 
    void traversal(TreeNode *cur,vector<int>& res){
    
    //需要注意这里是引用类型 不然返回空值
        if(cur==NULL)
        return;
        res.push_back(cur->val);
        traversal(cur->left,res);
        traversal(cur->right,res);
    }
    vector<int> preorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        traversal(root,result);
        return result;
    }

};

迭代法

class Solution {
    
    
public:
 
    vector<int> preorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode * p = root;
        while(p||!st.empty()){
    
    //当这两个都为空时表示遍历结束
        while(p){
    
    //结点不为空继续访问其左孩子 对于前序搜索先打印  
        result.push_back(p->val);
        st.push(p);
        p=p->left;
        }
        while(p==NULL&&!st.empty()){
    
    
            p=st.top();//返回上一级 
            st.pop();//弹出
            p=p->right;
        }

        }
        return result;
    }

};

中序遍历

递归法

class Solution {
    
    
public:
    void traversal(TreeNode* p,vector<int>& res){
    
    
    if(p==NULL)
    return;
    traversal(p->left,res);
    res.push_back(p->val);
    traversal(p->right,res);
    }
    vector<int> inorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        traversal(root,result);
        return result;        
    }
};

迭代法

class Solution {
    
    
public:
  
    vector<int> inorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* p=root;//赋初值
        while(p||!st.empty()){
    
    
            while(p){
    
    
                st.push(p);
                p=p->left;
                
            }
            while(!p&&!st.empty()){
    
    
                p=st.top();
                result.push_back(p->val);
                st.pop();
                p=p->right;
            }
        }
        return result;        
    }
};

后序遍历

递归法

lass Solution {
    
    
public:
    void traversal(TreeNode* p,vector<int> &res){
    
    
        if(p==NULL)
        return;
        traversal(p->left,res);
        traversal(p->right,res);
        res.push_back(p->val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        traversal(root,result);
        return result;
    }
};

迭代法

class Solution {
    
    
public:

    vector<int> postorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        TreeNode* p=root;
        TreeNode* preVisite=NULL;
        stack<TreeNode*> st;
        while(p||!st.empty()){
    
    
            if(p){
    
    
                st.push(p);
                p=p->left;
            }
           else{
    
    
                 p=st.top();
            if(p->right==NULL||p->right==preVisite){
    
    
                result.push_back(p->val);
                preVisite=p;
                st.pop();
                p=NULL;
            }
            else{
    
    
                p=p->right;
            }
           }
            
        }
        return result;
    }
};

层序遍历

102. 二叉树的层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

 

示例:
二叉树:[3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回其层次遍历结果:

[
  [3],
  [9,20],
  [15,7]
]
通过次数186,378提交次数294,634

层序遍历一般都用队列辅助解题,其具有先进先出的特点

class Solution {
    
    
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
    
    
        vector<vector<int>> res;
        if(root==NULL)
        return res;

        queue<TreeNode*> qt;
        qt.push(root);
        while(!qt.empty()){
    
    
            vector<int> tmp;
            int len=qt.size();
            for(int i=0;i<len;i++){
    
    
                TreeNode* p=qt.front();
                qt.pop();
                tmp.push_back(p->val);
                if(p->left)  qt.push(p->left);
                if(p->right) qt.push(p->right);
            }
        res.push_back(tmp);   
        }
    return res;
        
    }
};
103. 二叉树的锯齿形层次遍历
给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

例如:
给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回锯齿形层次遍历如下:

[
  [3],
  [20,9],
  [15,7]
]
通过次数67,778提交次数123,485
class Solution {
    
    
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
    
    
        vector<vector<int>> res;
        if(root==NULL)
        return res;
       
        queue<TreeNode*> qu;
        qu.push(root);
        bool lr=true;

        while(!qu.empty()){
    
    
            int len=qu.size();
            vector<int> tmp(len,0);
            for(int i=0;i<len;i++){
    
    
                TreeNode* p=qu.front();
                qu.pop();
                lr?(tmp[i]=p->val):(tmp[len-i-1]=p->val);
                if(p->left)
                {
    
    
                    qu.push(p->left);
                }
                if(p->right)
                {
    
    
                    qu.push(p->right);
                }
            }
            res.push_back(tmp);
            lr=!lr;
        }
        return res;
        
    }
};

猜你喜欢

转载自blog.csdn.net/qq_37581730/article/details/108299529
今日推荐