先序和中序类似,不同点在于访问结点的时机。后序较难,双栈的较容易,常规思路的较难,要多回顾
vector<int> preorder(TreeNode* root){
if(!root)return {};
vector<int>v;
stack<TreeNode*>s;
s.push(root);
while(!s.empty()){
root=s.top();
v.push_back(root->val);
s.pop();//后面有压栈操作,先弹出
if(root->right)s.push(root->right);//先压右结点,栈先入后出,最后出来
if(root->left)s.push(root->left);
}
return v;
}
vector<int> preorder2(TreeNode* root){
if(!root)return {};
vector<int>v;
stack<TreeNode*>s;
while(root||!s.empty()){
if(root){
v.push_back(root->val);
s.push(root);
root=root->left;
}
else{
root=s.top();
s.pop();
root=root->right;
}
}
return v;
}
vector<int> inorder(TreeNode* root){
if(!root)return {};
vector<int>v;
stack<TreeNode*>s;
while(root||!s.empty()){
while(root){
s.push(root);
root=root->left;
}
if(!s.empty()){//这个判断是必要的吗
root=s.top();
v.push_back(root->val);
s.pop();
root=root->right;
}
}
return v;
}
vector<int> inorder2(TreeNode* root){
if(!root)return {};
vector<int>v;
stack<TreeNode*>s;
while(root||!s.empty()){
if(root){
s.push(root);
root=root->left;
}
else{
root=s.top();
v.push_back(root->val);
s.pop();
root=root->right;
}
}
return v;
}
vector<int> postorder(TreeNode* root){
if(!root)return {};
vector<int>v;
stack<TreeNode*>s1,s2;
s1.push(root);
while(!s1.empty()){//先按中右左顺序读入s2
root=s1.top();
s2.push(root);//中,进入s2
s1.pop();
if(root->left)s1.push(root->left);//左,由于是压栈,所以最后从s1读出,也就最后进入s2
if(root->right)s1.push(root->right);
}
while(!s2.empty()){//反序就是左右中了
v.push_back(s2.top()->val);
s2.pop();
}
return v;
}
vector<int> postorder2(TreeNode* root){
if(!root)return {};
vector<int>v;
stack<TreeNode*>s;
TreeNode* last=root;//记录上一次访问过的结点,注意不是指入栈的结点
while(root||!s.empty()){
if(root){//先一直读左边
s.push(root);
root=root->left;
}
else{//左边没有了看右边
root=s.top();
if(root->right&&root->right!=last){//右边没访问过,入栈
root=root->right;
}
else{//左右中,右边访问过了到中间
v.push_back(root->val);
last=root;
s.pop();
root=nullptr;//设置为空刚好读栈顶
}
}
}
return v;
}