二叉树遍历大总结

Posted 老猫想编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树遍历大总结相关的知识,希望对你有一定的参考价值。

相关题目

  • No. 144 二叉树的前序遍历

  • No. 94   二叉树的中序遍历

  • No. 145 二叉树的后序遍历

  • No. 102 二叉树的层序遍历

解法总结

关于二叉树遍历的概念不再赘述,直接开始怼题目。

先对前序遍历、中序遍历和后序遍历做总结,层序遍历拎出来单独说。

关于二叉树的定义如下:

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

递归解法

前序遍历

void preOrderRecur(TreeNode* root,vector<int>&res)
{
  if(root==nullptr) return;
  res.push_back(root->val);
  preOrderRecur(root->left,res);
  preOrderRecur(root->right,res);
}

中序遍历

void inOrderRecur(TreeNode* root,vector<int>&res)
{
  if(root==nullptr) return;
  inOrderRecur(root->left,res);
  res.push_back(root->val);
  inOrderRecur(root->right,res);
}

后序遍历

void postOrderRecur(TreeNode* root,vector<int>&res)
{
  if(root==nullptr) return;
  postOrderRecur(root->left,res);
  postOrderRecur(root->right,res);
  res.push_back(root->val);
}

迭代解法

迭代解法的核心就是用一个栈去模拟递归过程中的系统栈,可以加深我们对递归具体过程的理解。

前序遍历

前序遍历就是中结点随进随出,右结点先于左结点压入栈。然后栈中会记录应该回溯的路径信息,每次弹出栈的顶结点。

void preOrderIteration(TreeNode* root,vector<int>&res)
{
  if(root==nullptr) return ;
  stack<TreeNode*>st;
  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);
  }
}

中序遍历

中序遍历由于中间结点先不输出,所以得有一个指针来帮助访问结点,栈同样保存了回溯时的位置信息。

void inOrderIteration(TreeNode* root,vector<int>&res)
{
  if(root==nullptr) return ;
  stack<TreeNode*>st;
  TreeNode* cur=root;
  while(cur!=nullptr||!st.empty())
  {
      if(cur!=nullptr)
      {
          st.push(cur);
          cur=cur->left;   //左
      }
      else{
          cur=st.top();
          st.pop();
          res.push_back(cur->val);//中
          cur=cur->right;//右
      }
  }  
}

后序遍历

后序遍历可以由先序遍历稍微改动得到。后序遍历的顺序是左右中,先序遍历的顺序是中左右,可以先调换左右顺序,得到中右左,然后颠倒结果数组即可得到答案。

void postOrderIteration(TreeNode* root,vector<int>&res)
{
  if(root==nullptr) return ;
  stack<TreeNode*>st;
  st.push(root);
  while(!st.empty())
  {
      TreeNode* node=st.top();
      st.pop();
      if(node->left) st.push(node->left);
      if(node->right) st.push(node->right);
  }  
  reverse(res.begin(),res.end());
}

层序遍历

BFS常规解法

方法不再详述。给出两种不同输出格式的代码

void levelOrder(TreeNode* root,vector<vector<int>>&res)
{
  if(root==nullptr) return ;
  queue<TreeNode*>q;
  q.push(root);
  while(!q.empty())
  {
      int size=q.size();
      vector<int>level;
      for(int i=0;i<size;i++)
      {
          TreeNode* cur=q.front();
          q.pop();
          if(!cur) continue;
          level.push_back(cur->val);
          q.push(cur->left);
          q.push(cur->right);
      }
      if(level.size()>0) res.push_back(level);
  }
}
void levelOrder_single(TreeNode* root,vector<int>&res)
{
  if(root==nullptr) return ;
  queue<TreeNode*>q;
  q.push(root);
  while(!q.empty())
  {
      int size=q.size();
      for(int i=0;i<size;i++)
      {
          TreeNode* cur=q.front();
          q.pop();
          if(!cur) continue;
          res.push_back(cur->val);
          q.push(cur->left);
          q.push(cur->right);
      }
  }
}

DFS递归解法

DFS递归解法就是使用level变量来记录二叉树的层数,只有相同的层,才将对应结点的值加入相应的vector中。

void levelOrder_DFS(TreeNode* root,vector<vector<int>>&res,int level)
{
  if(root==nullptr) return ;
  if(level>=res.size()) res.push_back(vector<int>());
  res[level].push_back(root->val);
  levelOrder_DFS(root->left,res,level+1);
  levelOrder_DFS(root->right,res,level+1);
}

vector<vector<int>> levelOrder(TreeNode* root)
{
  vector<vector<int>>res;
  levelOrder_DFS(root,res,0);
  return res;
}






以上是关于二叉树遍历大总结的主要内容,如果未能解决你的问题,请参考以下文章

树 -- 二叉树遍历方法思路大总结(10种方法)

LeetCode与《代码随想录》二叉树篇:做题笔记与总结-JavaScript版

最全二叉树的遍历方式总结

最全二叉树的遍历方式总结

算法总结你真的掌握了二叉树的遍历嘛

总结了一些算法二叉树操作的干货 (附Python代码)