94. 二叉树的中序遍历
-
递归版本很简单,这里就不过多介绍,接下来使用非递归版本,就是使用栈,并且是前、中、后序遍历,统一一套逻辑的非递归的二叉树遍历。
-
中序遍历:遍历顺序是,左中右,不能使用递归,那我们就要自己使用栈来保存「现场」。当来到一个节点时,第一次来到,不能够输出,要先将左子树的内容全部得到后,再输出该节点。
-
所以我们第一次来到一个节点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; } };
-
-
前序遍历
-
中左右,因为遇到一个节点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; } };
-
后序遍历
-
左右中,第一次遇到节点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; } };
-
三种非递归,代码整体逻辑一摸一样,就是压入栈的时候,顺序不一致
标签:
leetcode刷题
, 数据结构与算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理