方法:设置一个stack和vector,stack用于模拟递归,而vector用于记录数据。
1、无论是前、中、后序都是从根一直向最左的节点递进。因此模拟依然如此。(同时用stack记录每一个根节点,0,1,3,8)
2、遍历右子树,对根节点出栈,向右跳转,根->right。这样也就结束模拟实现了。
语言无法形容该过程,我们先看代码再加深理解。
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root)
{
stack<TreeNode*> st;//记录根节点
vector<int> ret;
TreeNode* cur=root;
while(cur||!st.empty())
{
while(cur)//遍历每个根节点的左树
{
ret.push_back(cur->val);//记录数据
st.push(cur);//每个遍历过的节点入栈
cur=cur->left;
}
TreeNode* top=st.top();//记录栈顶节点
st.pop();//出栈
cur=top->right;//跳转到每个根的右树
}
return ret;
}
};
代码对上图树的记录前序过程:
第一次循环从根节点5出发,进入while(cur)后一直往左迭代5->3->1->0->nullptr,从stack中弹出0,cur=0->right==nullptr,第二次循环cur是空,进入不了while(cur),直接cur=1->right==2。
第三次循环,cur不为空,stack记录了它的节点,vector记录了它的数值,cur=cur->left=nullptr。
跳出循环,cur=2->right==nullptr,第4次循环,直接跳过while(cur),cur=3->right==4。
第5次循环,第6次循环亦是如此不过多介绍(不然会导致文章又臭又长)
中序:
和前序一模一样不多解释
lass Solution {
public:
vector<int> inorderTraversal(TreeNode* root)
{
vector<int> ret;
stack<TreeNode*> st;
TreeNode* cur=root;
while(cur||!st.empty())
{
while(cur)
{
st.push(cur);
cur=cur->left;
}
TreeNode* top=st.top();
ret.push_back(top->val);//改为在左树底部记录数据
st.pop();
cur=top->right;
}
return ret;
}
};
后序:
拥有着与前两者相同的模板,但又有些不一样是思想方式。因为在刚才的模板中,走完左节点后一定会结果根节点,才能从根节点过度到右节点。无法改变,那就忽略。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root)
{
vector<int> ret;
stack<TreeNode*> st;
TreeNode* cur=root;
TreeNode* lastNode=nullptr;//用于记录是否已经遍历过该节点
while(cur||!st.empty())
{
while(cur)
{
st.push(cur);
cur=cur->left;
}
//记录栈顶数据,用于向右跳转或者删除数据
TreeNode* top=st.top();
if(top->right==nullptr||lastNode==top->right)
{
//右节点不存在或者已经遍历过右节点时
//记录该叶子节点(根节点)
ret.push_back(top->val);
lastNode=top;//记录走过的节点
st.pop();//弹出栈
}
else
{
cur=top->right;
}
}
return ret;
}
};
代码对上图树的记录后序过程:
第一次循环从根节点5出发,进入while(cur)后一直往左迭代cur=5->3->1->0->nullptr,top=0,
0->right==nullptr,lastNode=0;且0被弹出栈,第二次循环cur依然为nullptr,则不进入while(cur)
top=1,top->right==2,cur=top->right==2,第三次循环cur=cur->left==nullptr,记录2,弹出栈。
后面的循环亦是如此