94. 二叉树的中序遍历

  1. 题目链接

  2. 递归版本很简单,这里就不过多介绍,接下来使用非递归版本,就是使用栈,并且是前、中、后序遍历,统一一套逻辑的非递归的二叉树遍历。

  3. 中序遍历:遍历顺序是,左中右,不能使用递归,那我们就要自己使用栈来保存「现场」。当来到一个节点时,第一次来到,不能够输出,要先将左子树的内容全部得到后,再输出该节点。

    • 所以我们第一次来到一个节点A时,我们要将其压入栈,然后第二次遇到节点A时,就可以输出其内容了。但是,我们压入栈的时候,我们怎么知道是第几次来到该节点?

    • 我们使用特殊的节点,nullptr,来标识,也就是我们第一次压入栈后,再压入nullptr,当我们获得一个nullptr时,我们就知道,下一个节点,是第二次来到了。

    • 第一次遇到一个节点A时,我们要怎么操作?注意我们的顺序是左中右,但是要记住,这是栈,所以压入的顺序应该是「右->中->左」,压入「右」和「左」时,正常压入即可,压入「中」时,要先压入「中」,再压入一个nullptr,标识「中」是第二次来到。

    • 第二次遇到节点A时,可以直接弹出了,因为左子树内容肯定已经处理完毕了,右子树也在第一次遇到节点A的时候,已经处理了。

    • 代码

      class Solution {
      public:
      vector<int> inorderTraversal(TreeNode* root) {
      vector<int> ans;
      if (root == nullptr) {
      return ans;
      }
      stack<TreeNode*> st;
      st.push(root); // 第一个节点 不用压入nullptr 因为还不算第一次处理
      while(!st.empty()) {
      TreeNode *cur = st.top();
      st.pop();
      if (cur == nullptr) { // 栈顶的 就是第二次遇到了 第二次遇到 不需要再入栈了 收集答案即可
      cur = st.top();
      st.pop();
      ans.push_back(cur->val);
      } else { // 第一次遇到 中序 左中右 压入顺序就是右中左
      // 右
      if (cur->right != nullptr) {
      st.push(cur->right);
      }
      // 中 注意这里不要弄反了
      st.push(cur);
      st.push(nullptr);
      // 左
      if(cur->left != nullptr) {
      st.push(cur->left);
      }
      }
      }
      return ans;
      }
      };
  4. 前序遍历

    • 题目链接

    • 中左右,因为遇到一个节点A,直接得到结果,所以不需要再次入栈了,也就不需要用nullptr来标识了。

    • 代码

      class Solution {
      public:
      vector<int> preorderTraversal(TreeNode* root) {
      vector<int> ans;
      if (root == nullptr) {
      return ans;
      }
      stack<TreeNode*> st;
      st.push(root); // 第一个节点 不用压入nullptr 因为还不算第一次处理
      while(!st.empty()) {
      TreeNode *cur = st.top();
      st.pop();
      ans.push_back(cur->val);
      // 前序,所以是中左右,压入栈就是反过来 右左中,又因为中已经得到结果了所以不用压入栈了
      // 右
      if (cur->right != nullptr) {
      st.push(cur->right);
      }
      // 左
      if(cur->left != nullptr) {
      st.push(cur->left);
      }
      }
      return ans;
      }
      };
  5. 后序遍历

    • 题目链接

    • 左右中,第一次遇到节点A,不能够得到结果,还需要压入栈,所以和中序的套路一样的,用nullptr来标识

    • 代码

      class Solution {
      public:
      vector<int> postorderTraversal(TreeNode* root) {
      vector<int> ans;
      if (root == nullptr) {
      return ans;
      }
      stack<TreeNode*> st;
      st.push(root); // 第一个节点 不用压入nullptr 因为还不算第一次处理
      while(!st.empty()) {
      TreeNode *cur = st.top();
      st.pop();
      if (cur == nullptr) { // 栈顶的 就是第二次遇到了 第二次遇到 不需要再入栈了 收集答案即可
      cur = st.top();
      st.pop();
      ans.push_back(cur->val);
      } else { // 第一次遇到 后序 左右中 压入顺序就是中右左
      // 中 注意这里不要弄反了
      st.push(cur);
      st.push(nullptr);
      // 右
      if (cur->right != nullptr) {
      st.push(cur->right);
      }
      // 左
      if(cur->left != nullptr) {
      st.push(cur->left);
      }
      }
      }
      return ans;
      }
      };
  6. 三种非递归,代码整体逻辑一摸一样,就是压入栈的时候,顺序不一致

posted @   ouyangxx  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示