分析:
1.访问所有左路结点,并且入栈
2.取出栈顶结点的右子树,如果它不为空就模拟递归,即将其赋给cur上去(即以该节点访问所有左路结点...),否则就取下一个栈顶元素
3.直到当前结点为空(栈顶右子树),并且栈为空说明所有元素已访问过
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
//1.先逐个访问左路结点,并将其入栈
//2.再访问栈顶元素的右子树
stack<TreeNode*> s;
vector<int> v;
TreeNode* cur=root;
//只有cur为空,并且栈空,说明所有元素访问完
while(cur || !s.empty())
{
while(cur)//左路结点入栈
{
v.push_back(cur->val);
s.push(cur);
cur=cur->left;
}
//来到这左路结点已入栈
TreeNode* right=s.top()->right;//栈顶的右子树
s.pop();//弹出栈顶
cur=right;//将右子树赋给cur上去继续判断(cur是当前结点的右子树,它是可能为空的,当它为空时,继续取下一个栈顶的右子树,否则要将其赋给cur,再次
//当做关键结点,即左路结点入栈,取栈顶,访问右子树...)
}
return v;
}
};
分析:
和前序很类似,只是中序在左路结点入栈过程中不访问,而是当栈顶结点拿出来后,访问该结点,并将其右子树模拟递归处理(赋给cur)
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> s;
vector<int> v;
TreeNode* cur=root;
while(cur || !s.empty())
{
while(cur)
{
s.push(cur);
cur=cur->left;
}
//来到这,左路结点全都入栈
//访问栈顶元素
//对栈顶元素的右子树左同样操作
TreeNode* top=s.top();
s.pop();
v.push_back(top->val);
TreeNode* right=top->right;//右子树
cur=right;//模拟递归
}
return v;
}
分析:
和中序也很类似,将所有左路结点入栈后,但是取出栈顶元素这时候也不访问,而是直接模拟递归其右子树(取出栈顶元素可以直接访问的情况有2种,一种是当前栈顶结点的右子树为空,第二种是当前结点的右子树已经访问过了,这个可以用一个指针标记一下)
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> s;
vector<int> v;
TreeNode* cur=root;
TreeNode* prev=nullptr;
while(cur || !s.empty())
{
while(cur)
{
s.push(cur);
cur=cur->left;
}
//来到这,左路结点都已经入栈
TreeNode* top=s.top();//栈顶元素
TreeNode* right=top->right;//栈顶元素的右子树
if(right==nullptr || top->right==prev)//栈顶元素的右子树为空/或者上一次访问过的元素就是栈顶的右子树根结点(说明访问过回来了),直接可以访问栈顶元素
{
v.push_back(top->val);
prev=top;//记录上一次访问的结点
s.pop();
}
else//栈顶元素不空
{
cur=right;
}
}
return v;
}