版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/AK_97_CT/article/details/87118524
前序遍历
思路:遇到一个节点,就访问该节点,然后进栈,然后遍历左子树,遍历完成后,弹出栈顶节点并出栈,并访问右子树。
class Solution {
public:
/*
伪代码:
1.栈初始化(空栈);
2.循环直到root为空且栈为空
2.1 当root不空时循环
2.1.1 访问root;
2.1.2 将root的值保存到栈中;
2.1.3 遍历root的左子树。
2.2 如果栈不空,则
2.2.1 将栈顶元素弹出至root;
2.2.2 遍历root的右子树。
*/
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
if(!root) return res;
stack<TreeNode*> sta;
while(root!=nullptr||!sta.empty())
{
if(root!=nullptr)
{
sta.push(root);
res.push_back(root->val);
root=root->left;
}
else
{
auto t=sta.top();
sta.pop();
root=t->right;
}
}
return res;
}
};
中序遍历
思路:和前序遍历类似。不同的仅仅只是访问的顺序移到出栈时。
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
if(!root) return res;
stack<TreeNode*> sta;
while(root!=nullptr||!sta.empty())
{
if(root!=nullptr)
{
sta.push(root);
root=root->left;
}
else
{
auto t=sta.top();
sta.pop();
res.push_back(t->val);
root=t->right;
}
}
return res;
}
};
后序遍历
思路:对于每个节点,都压入两遍,在循环体中,每次弹出一个节点赋给p,如果p仍然等于栈的头结点,说明p的孩子们还没有被操作过,应该把它的孩子们加入栈中,否则,访问p。也就是说,第一次弹出,将p的孩子压入栈中,第二次弹出,访问p。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> vec;
if(!root) return vec;
stack<TreeNode*> sta;
TreeNode* P=root;
sta.push(P);
sta.push(P);
while(!sta.empty())
{
P=sta.top();
sta.pop();
if(!sta.empty()&&P==sta.top())
{
if(P->right){ sta.push(P->right); sta.push(P->right); }
if(P->left){ sta.push(P->left); sta.push(P->left); }
}
else
vec.push_back(P->val);
}
return vec;
}
};