代码随想录算法训练营第十四天|二叉树的理论基础、递归遍历、迭代遍历和统一遍历

day14 2023/02/14

一、二叉树的递归遍历

递归算法的三个要素:

  1. 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。

  2. 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。

  3. 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

以下以前序遍历为例:

  1. 确定递归函数的参数和返回值:因为要打印出前序遍历节点的数值,所以参数里需要传入vector来放节点的数值,除了这一点就不需要再处理什么数据了也不需要有返回值,所以递归函数返回类型就是void
  2. 确定终止条件:在递归的过程中,如何算是递归结束了呢,当然是当前遍历的节点是空了,那么本层递归就要结束了,所以如果当前遍历的这个节点是空,就直接return
  3. 确定单层递归的逻辑:前序遍历是中左右的循序,所以在单层递归的逻辑,是要先取中节点的数值

 前序遍历代码:

class Solution {
public:
    void Traversal(TreeNode* cur,vector& res)
    {
        if(cur==NULL) return;
        res.push_back(cur->val);
        Traversal(cur->left,res);
        Traversal(cur->right,res);
    }
    vector preorderTraversal(TreeNode* root) {
          vector res;
          Traversal(root,res);
          return res;
    }
};

中序遍历代码:

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

后序遍历代码:

class Solution {
public:
    void Traversal(TreeNode* cur,vector& res)
    {
        if(cur==NULL) return;
        Traversal(cur->left,res);
        Traversal(cur->right,res);
        res.push_back(cur->val);
    }
    vector postorderTraversal(TreeNode* root) {
        vector res;
        Traversal(root,res);
        return res;
    }
};

二、二叉树的迭代遍历(统一迭代就不掌握了)

1)前序遍历

class Solution {
public:
    vector preorderTraversal(TreeNode* root) {
        stack st;
        vector res;
        if(root==NULL) 
          return res;
        st.push(root);
        while(!st.empty())
        {
            TreeNode* node=st.top();
            st.pop();
            res.push_back(node->val);
            if(node->right) st.push(node->right);
            if(node->left) st.push(node->left);
        }
        return res;
    }
};

2)中序遍历

  1. 处理:将元素放进result数组中
  2. 访问:遍历节点

 

class Solution {
public:
    vector inorderTraversal(TreeNode* root) {
       stack st;
       vector res;
       TreeNode* cur=root;
       while(cur!=NULL||!st.empty())
       {
           if(cur!=NULL)
           {
                st.push(cur);
                cur=cur->left;
           }
           else
           {
               cur=st.top();
               st.pop();
               res.push_back(cur->val);
               cur=cur->right;
           }
       }
       return res;
    }
};

3)后序遍历

前序到后序

后序遍历只需要前序遍历的代码稍作修改就可以了,代码如下:

 

class Solution {
public:
    vector postorderTraversal(TreeNode* root) {
        stack st;
        vector res;
        if(root==NULL) return res;
        st.push(root);
        while(!st.empty())
        {
            TreeNode* node=st.top();
            res.push_back(node->val);
            st.pop();
            if(node->left) st.push(node->left);
            if(node->right) st.push(node->right);
        }
        reverse(res.begin(),res.end());
        return res;
    }
};

你可能感兴趣的:(算法,数据结构)