算法思路:因为在后序遍历的时候只有当前节点的左子树和右子树均访问完后,才能访问当前节点。
所以这里就涉及到入栈出栈的问题了。
之前写中序的时候,只要指针非空就可以入栈,然后更新为左孩子,指针变空就访问栈顶元素,然后更新为右孩子并出栈
但是现在指针非空入栈,指针变空的时候不能直接访问栈顶元素了,因为栈顶元素的右子树(或者右孩子)还没访问呢
我的想法是每次节点指针出栈入栈的时候把相应的一个bool变量也在另一个bool栈中进行相同的出栈入栈操作
这些bool变量标识的是相应节点能否被访问,起始情况下均为false
然后第一次遇到之后把相应的bool值改为true,这样下一次就可以访问节点了
也就是这部分代码
temp = nodeStack.top();
nodeStack.pop();
if(flagStack.top() == false){//第一次出现在栈顶
flagStack.pop();
flagStack.push(true);
nodeStack.push(temp);
curr = temp->right;
}
二叉树后序遍历非递归正确代码如下:
/**
* 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) {
vector<int> array;
if(!root) return array;
TreeNode* curr = root;
TreeNode* temp = NULL;
stack<TreeNode*> nodeStack;
stack<bool> flagStack; //辅助说明当前栈顶可以访问还是继续等待右子树的后序遍历
while(curr != NULL || !nodeStack.empty()){
while(curr){//当前节点不为空
nodeStack.push(curr);
flagStack.push(false);
curr = curr->left;
}
if(!nodeStack.empty()){
temp = nodeStack.top();
nodeStack.pop();
if(flagStack.top() == false){//第一次出现在栈顶
flagStack.pop();
flagStack.push(true);
nodeStack.push(temp);
curr = temp->right;
}
else{
array.push_back(temp->val);
flagStack.pop();
curr = NULL;
}
}
}
return array;
}
};
之前写中序非递归遍历的时候比较简单,请看代码:
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> returnArray;
stack<struct TreeNode*> nodeStack;//栈的元素是指针,而不是相应结构体
struct TreeNode* p = root;
while(p != NULL || !nodeStack.empty()){
if(p){
nodeStack.push(p);
p = p->left;
}
else if(!nodeStack.empty()){
//此时nodeStack.top()就是一个没有左子节点的节点,所以直接入数组,遍历顺序是:左中右
returnArray.push_back(nodeStack.top()->val);
p = nodeStack.top()->right;
nodeStack.pop();
}
}
return returnArray;
}
};
第一次的错误代码(超时)
/**
* 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) {
vector<int> array;
if(!root) return array;
TreeNode* p = root;
stack<TreeNode*> nodeStack;
stack<bool> flagStack; //辅助说明当前栈顶可以访问还是继续等待右子树的后序遍历
while(p != NULL || !nodeStack.empty()){
if(p){//当前节点不为空
nodeStack.push(p);
flagStack.push(false);
p = p->left;
}
else if(!nodeStack.empty()){
//当前节点为叶子节点
if(flagStack.top()){
array.push_back(nodeStack.top()->val);
flagStack.pop();
nodeStack.pop();
p = nodeStack.top();
}
else{
p = nodeStack.top()->right;
flagStack.pop();
flagStack.push(true);
}
}
}
return array;
}
};
第二次错误代码(解答错误 )
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> array;
if(!root) return array;
TreeNode* curr = root;
TreeNode* temp = NULL;
stack<TreeNode*> nodeStack;
stack<bool> flagStack; //辅助说明当前栈顶可以访问还是继续等待右子树的后序遍历
while(curr != NULL || !nodeStack.empty()){
while(curr){//当前节点不为空
nodeStack.push(curr);
flagStack.push(false);
curr = curr->left;
}
if(!nodeStack.empty()){
//先开始执行的时候是因为curr为NULL才会进到这个while循环中
// array.push_back(nodeStack.top()->val);
// curr = nodeStack.top()->right;
temp = nodeStack.top();
nodeStack.pop();
if(flagStack.top() == false){//第一次出现在栈顶
flagStack.pop();
flagStack.push(true);
nodeStack.push(temp);
curr = temp->right;
}
else{
array.push_back(temp->val);
curr = NULL;
}
}
}
return array;
}
};