用栈中序遍历二叉树
核心思路(算法流程):
- 对每一个点:先将它自己以及它的的左子树上的根节点入栈(因为是用链表实现的的父节点与子节点的连接,遍历只能从父节点到子节点,所以入栈后就逆序了,此时,栈顶的点就是要加入到res中的点)。
- 将每一个点都加入到栈中,执行上边的流程(root==nullptr时,加不加都一样,没加入栈也相当于加入了)。
- 将一个点的val加入到res中后,这个点就只剩下右子树上的点没有加入到res了,所以就有
root=root->right
,开始遍历这个点的右子树。 - 循环退出的条件是:
!stack.empty() || root!=nullptr
。
个人感觉,最难理解的就是当叶子结点为空时,算法执行的流程了。把root==null
(即root为空)时,也当作加入到栈stk中,可能更好理解。
代码:
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> stk;
while (root != nullptr || !stk.empty()) {
//栈中存当前结点以及当前结点每个左子树上的根节点。
while (root != nullptr) {
stk.push(root);
root = root->left;
}
root = stk.top();
stk.pop();
/*
将当前结点加入到res中,当前结点的左子树上的所有点以及当前结点都已经被加入到了res中。
*/
res.push_back(root->val);
//查找当前节点的右子节点
root = root->right;
}
return res;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/er-cha-shu-de-zhong-xu-bian-li-by-leetcode-solutio/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
二叉树的前序遍历
思路:
- 栈中存储的是结点的左子树上的根节点。
代码一:
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
if (root == nullptr) {
return res;
}
stack<TreeNode*> stk;
TreeNode* node = root;
while (!stk.empty() || node != nullptr) {
while (node != nullptr) {
res.emplace_back(node->val);
stk.emplace(node);
node = node->left;
}
node = stk.top();
stk.pop();
node = node->right;
}
return res;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/er-cha-shu-de-qian-xu-bian-li-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
代码二
(原来和官方题解写的一样。。。)
/**
* Definition for a binary tree node.
* 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) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> stk;
vector<int> res;
while(!stk.empty() || root!=nullptr){
//将当前点的左子树的根节点都加入到栈中
while(root!=nullptr){
//先根遍历,边入栈边存答案
res.push_back(root->val);
stk.push(root);
root=root->left;
}
//栈顶的点以及它左子树上所有的点都已经存到答案里了
root=stk.top();
stk.pop();
//开始遍历当前点的右子树上的点
root=root->right;
}
return res;
}
};