问题:二叉树的前序遍历
解题思路
前序遍历按照根、左、右的顺序访问节点,非递归实现要使用到栈,我们先访问本节点,然后将本节点入栈,用于下次遍历此节点的右子树,然后继续访问本节点的左孩子,重复,直到本节点的左孩子为NULL,此时就可以退栈,直到栈顶节点的右孩子不为空,下一个要访问的节点就是栈顶元素的右孩子,将栈顶元素弹出。如果找不到则遍历结束
C++代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*>s;
vector<int>pre;
while(root){
while(root){
pre.push_back(root->val);//访问本节点
s.push(root);//将本节点入栈,用于下次访问其右子树
root = root->left;//访问左孩子
}
//退栈直到栈顶节点有右孩子
while(!s.empty() && !s.top()->right) s.pop();
if(s.empty()) break;//如果栈空就退出
root = s.top()->right;
s.pop();
}
return pre;
}
};
问题:二叉树的中序遍历
解题思路
中序遍历的顺序是左、根、右,中序遍历的非递归实现和前序遍历差不多,只是在中序遍历中我们先不要访问本节点,直接入栈,继续访问本节点的左孩子,当回退时再访问本节点。
C++代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int>inorder;
stack<TreeNode*>s;
while(root){
while(root){
//先将本节点入栈,等它的左子树被访问完了再访问它
s.push(root);
root = root->left;//继续访问它的左孩子
}
while(!s.empty()){//如果栈不空
//栈顶元素的左子树都被访问了,接下来访问栈顶元素
TreeNode *tmp = s.top();
s.pop();//退栈
inorder.push_back(tmp->val);
//如果栈顶元素有右子树,则遍历它的右子树
if(tmp->right){
root = tmp->right;
break;
}
}
}
return inorder;
}
};
问题:二叉树的后序遍历
解题思路
二叉树后序遍历的非递归实现和前两种遍历的实现不同,由于访问的顺序是左、右、根,只有当本节点的左子树和右子树被访问后才能访问本节点,我们用映射map记录每个节点入栈的次数,出栈时,当节点的入栈次数为1,说明本节点的左子树被访问完了,但是其右子树还没有被访问,此时不能访问本节点,让本节点再次入栈,访问本节点的右子树,出栈时,当节点的入栈次数为2,说明本节点的左右子树都被访问完了,可以访问本节点。
C++代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
map<TreeNode*,int>dict;//记录每个节点入栈的次数
stack<TreeNode*>s;
vector<int>post;
while(root){
while(root){
s.push(root);//先不访问,直接入栈
dict[root]++;//节点root入栈的次数加一
root = root->left;//继续访问左子树
}
while(!s.empty()){
TreeNode *tmp = s.top();
s.pop();
//如果本节点入栈过两次则访问
if(dict[tmp] == 2)
post.push_back(tmp->val);
else{//本节点的右子树还没有被访问
s.push(tmp);//再次入栈
dict[tmp]++;//入栈次数加一
root = tmp->right;//访问本节点的右子树
}
if(root) break;
}
}
return post;
}
};