二叉树的遍历(前序、中序、后序、层次)

61 篇文章 2 订阅
22 篇文章 1 订阅


定义树的结构体

 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) {}
 };

1 前序

1.1 递归

 void preorder(vector<int> &res, TreeNode* root){
        if(root == NULL)  return;    //遇到空节点则返回
       
        res.push_back(root->val);  //先遍历根节点
        preorder(res, root->left);  //再去左子树
        preorder(res, root->right);//最后去右子树
    }

调用

  vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
     
        preorder(res, root);    //递归前序遍历
        return res;
    }

复杂度分析:

时间复杂度:O(n),其中nnn为二叉树的节点数,遍历二叉树所有节点
空间复杂度:O(n),最坏情况下二叉树化为链表,递归栈深度为n

1.2 借助栈,非递归

vector<int> preorderTraversal(TreeNode* root) {
       vector<int> res;
       if(root == NULL)
           return res;
           
        //辅助栈
        stack<TreeNode*> s;
        //根节点先进栈
        s.push(root); //push,pop 对应stack;;;;push_back对应vector
        while(!s.empty()){   //s.empty(),当栈空时,返回true。
            //每次栈顶就是访问元素
            TreeNode* node = s.top(); //访问栈顶
            s.pop();//出栈操作只是删除栈顶元素,并不返回该元素。
            res.push_back(node->val);
            
            //每次先弹出栈顶元素。然后遍历左右子树,因为是借助栈,所以入栈顺序是右左,出栈左右
            //如果右边还有右子树进栈
            if(node->right)
                s.push(node->right);
            //如果左边还有右子树进栈
            if(node->left)
                s.push(node->left);
        }
        return res;
    }

复杂度分析:

时间复杂度:O(n)O(n)O(n),其中nnn为二叉树的节点数,遍历二叉树所有节点
空间复杂度:O(n)O(n)O(n),最坏情况下二叉树化为链表,递归栈深度为nnn

2 中序遍历

void inorder(vector<int> &res, TreeNode* root){
        if(root == NULL)  return;      //遇到空节点则返回
     
        inorder(res, root->left);   //先遍历左子树
        res.push_back(root->val);  //再遍历根节点
        inorder(res, root->right); //最后遍历右子树
    }
 vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
    
        inorder(res, root);    //递归中序遍历
        return res;
    }

复杂度分析:

时间复杂度:O(n),其中nnn为二叉树的节点数,遍历二叉树所有节点
空间复杂度:O(n),最坏情况下二叉树化为链表,递归栈深度为n

2.2 借助栈,非递归

vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        //辅助栈
        stack<TreeNode*> s;
        //当树节点不为空或栈中有节点时
        while(root != NULL || !s.empty()){
            //每次找到最左节点
            while(root != NULL){
                s.push(root);
                root = root->left;
            }
            //访问该节点
            TreeNode* node = s.top();
            s.pop();
            res.push_back(node->val);
            //进入右节点
            root = node->right;
        }
        return res;
    }

复杂度分析:

时间复杂度:O(n),其中nnn为二叉树的节点数,遍历二叉树所有节点
空间复杂度:O(n),辅助栈空间最大为链表所有节点数

3 后序遍历

3.1 递归

 void inorder(vector<int> &res, TreeNode* root){
        if(root == NULL)  return;      //遇到空节点则返回
     
        inorder(res, root->left);   //先遍历左子树
        inorder(res, root->right); //最后遍历右子树
        res.push_back(root->val);  //再遍历根节点
    }
vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
    
        inorder(res, root);    //递归中序遍历
        return res;
    }

复杂度分析:

时间复杂度:O(n),其中n为二叉树的节点数,遍历二叉树所有节点
空间复杂度:O(n),最坏情况下二叉树化为链表,递归栈深度为n

3.2 借助栈,非递归

 vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        //辅助栈
        stack<TreeNode*> s;
        TreeNode* pre = NULL;
        while(root != NULL || !s.empty()){
            //每次先找到最左边的节点
            while(root != NULL){
                s.push(root);
                root = root->left;
            }
            //弹出栈顶
            TreeNode* node = s.top();
            s.pop();
            //如果该元素的右边没有或是已经访问过
            if(node->right == NULL || node->right == pre){
                //访问中间的节点
                res.push_back(node->val);
                //且记录为访问过了
                pre = node;
            }else{
                //该节点入栈
                s.push(node);
                //先访问右边
                root = node->right;
            }
        }
        return res;
    }

复杂度分析:

时间复杂度:O(n),其中nnn为二叉树的节点数,遍历二叉树所有节点
空间复杂度:O(n),辅助栈空间最大为链表所有节点数

4 层次遍历

 void LevelOrder(vector<vector<int>>& res,TreeNode* root){
        if(root == NULL) return ;

        vector<int> row;
        queue<TreeNode*> q;
        TreeNode* cur;

        q.push(root);
        while(!q.empty()){   
            int n = q.size();

            for(int i = 0; i < n; i++){
                cur = q.front();
                q.pop();
                row.push_back(cur->val);

               if(cur->left) q.push(cur->left);
               if(cur->right) q.push(cur->right);
            }
        res.push_back(row);
        row.clear();//row定义在循环外面,每次存入res后,要清空;;;若定义在循环内部,则不用清空,因每次次循环都会重新定义一次
        }
    }
vector<vector<int>> levelOrder(TreeNode* root) {
         vector<vector<int>> res;
         LevelOrder(res,root);
         return res;
       
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

R-G-B

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值