前序遍历-根左右:
循环到左子树空,else转右子树,当一个结点已经访问右子树时,该结点出栈
#include<iostream>
#include<string>
#include<stack>
#include<sstream>
#include<vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans;
stack<TreeNode*> treestack;
TreeNode* tem = root;
while(!treestack.empty()||tem){//栈空防止指针指空
if(tem){
ans.push_back(tem->val);//前序在这里进行内容的读取
treestack.push(tem);//在这里入栈,减少判断次数
tem = tem->left;
}//左子树到底了
else{
tem = treestack.top();
treestack.pop();//左空就算结束,要弹出
tem = tem->right;
}
}
return ans;
}
};
int main(){
TreeNode* root = new TreeNode(6);
root->left = new TreeNode(2);
root->left->left = new TreeNode(1);
root->left->right = new TreeNode(4);
root->left->right->left = new TreeNode(3);
root->left->right->right = new TreeNode(5);
root->right = new TreeNode(7);
root->right->right = new TreeNode(8);
root->right->right->left = new TreeNode(9);
Solution s;
vector<int> v = s.preorderTraversal(root);
for(int i=0;i<v.size();i++){
cout<<v[i]<<endl;
}
return 0;
}
中序遍历-左根右:
原理同前序,因为总是访问右子树时出栈,意味着出栈结点左子树空,即我们要访问的结点
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans;
stack<TreeNode*> treestack;
TreeNode* tem = root;
while(!treestack.empty()||tem){//栈空防止指针指空
if(tem){
treestack.push(tem);//在这里入栈,减少判断次数
tem = tem->left;
}//左子树到底了
else{
tem = treestack.top();
treestack.pop();//左空就算结束,要弹出
ans.push_back(tem->val);//中序在这里进行内容的读取
tem = tem->right;
}
}
return ans;
}
};
后序遍历-左右根:
后序非递归遍历一般有两种思路
①变左右根为根右左再取反
即先类似前序遍历得到根右左的结果,然后再对结果取反,思路是简单可行的,但是不方便对树进行其他操作,只能看遍历结果
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans,fin;
stack<TreeNode*> treestack;
TreeNode* tem = root;
while(!treestack.empty()||tem){//栈空防止指针指空
if(tem){
ans.push_back(tem->val);
treestack.push(tem);//在这里入栈,减少判断次数
tem = tem->right;
}//左子树到底了
else{
tem = treestack.top();
treestack.pop();//左空就算结束,要弹出
tem = tem->left;
}
}
for(int i=ans.size()-1;i>=0;i--){
fin.push_back(ans[i]);
}
return fin;
}
};
②当前结点没有孩子或孩子都被访问时访问此结点
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
TreeNode* tem;//注意这里不需要初始化
stack<TreeNode*> treestack;
treestack.push(root);//根要先入栈,这一点与前面不同
vector<int> ans;
TreeNode* pre = NULL;
while(!treestack.empty()){//判断条件只需要栈不空
tem = treestack.top();
if((tem->left==NULL&&tem->right==NULL)||(pre!=NULL&&(pre==tem->left||pre==tem->right))){
//子树空或子树都已经被访问过
ans.push_back(tem->val);
treestack.pop();
pre = tem;
}
else{
if(tem->right!=NULL)treestack.push(tem->right);//先右子树入栈
if(tem->left!=NULL)treestack.push(tem->left);//再左子树入栈,实际上也是根右左,只不过栈是后进先出
}
}
return ans;
}
};