LeetCode 144- 二叉树的前序遍历
题目链接:力扣
题目描述:前序遍历
解题思路
思路一:
- 使用迭代法,用栈来模拟递归过程
- 前序遍历是中左右,所以可以申请一个栈,保存树节点,首先入根。然后当栈不为空就一直循环,当左右孩子存在,就入栈,然后访问。(为什么先入栈右孩子,因为栈的出栈顺序与入栈相反,先入右,再入左,马上出栈时就会先访问左孩子)
class Solution { public: vector<int> preorderTraversal(TreeNode* root) { vector<int> result; stack<TreeNode*> st; if(root == NULL) return result;//root为空直接返回 st.push(root); while(!st.empty()){ TreeNode *node = st.top(); st.pop(); result.push_back(node->val);//先访问中间节点 if(node->right) st.push(node->right);//右不为空入右 if(node->left) st.push(node->left);//左不为空入左 } return result; } };
思路二:
- 递归法
总结:
递归可以分三步:
- 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
- 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
- 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
LeetCode 94- 二叉树的中序遍历
题目链接:力扣
题目描述:中序遍历
解题思路
- 中序遍历和前后序代码逻辑差很多,此处需要一个栈和一个cur指针来完成操作。
- 首先要知道中序遍历是左中右顺序,得最先遍历最左边的节点。所以要使用cur一直往左走,将中途的节点全部压栈,直到左边没有了才压入数组然后弹栈;然后再看当前节点的右边孩子,有的话就压入栈中,再继续向左边走。
class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> result; stack<TreeNode*> st; if(root == NULL) return result; TreeNode *cur = root; while(!st.empty() || cur){//若栈不为空,或cur不为空说明没遍历完得继续 if(cur){//若cur不为空,则压入栈中 st.push(cur); cur = cur->left;//一直向左走 }else{//当左边为空了,就访问该节点元素,然后往右边走 cur = st.top();//cur为空时,就访问栈顶元素 st.pop(); result.push_back(cur->val);//访问当前元素 cur = cur->right;//向右走 } } return result; } };
总结:
- 迭代法有点抽象,需要弄懂遍历顺序就会好理解一些。
LeetCode 145- 二叉树的后序遍历
题目链接:力扣
题目描述:后序遍历
解题思路:
- 后序遍历顺序是左右中,而先序是中左右,变过来只需要这样
class Solution { public: vector<int> postorderTraversal(TreeNode* root) { stack<TreeNode*> st; vector<int> result; if (root == NULL) return result; st.push(root); while (!st.empty()) { TreeNode* node = st.top(); st.pop(); result.push_back(node->val); if (node->left) st.push(node->left); // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈) if (node->right) st.push(node->right); // 空节点不入栈 } reverse(result.begin(), result.end()); // 将结果反转之后就是左右中的顺序了 return result; } };
总结:和前序逻辑一样,改几句就可以