中序遍历
一直遍历左子树到空,然后转移到右子树
void inorder(TreeNode *root,vector<int> &path){
stack<TreeNode*> s;
TreeNode* p=root;
while(p||!s.empty()){ //节点不为空时,或者栈不为空的情况下继续执行循环体
//一直遍历左子树直到底
while(p!=NULL){
s.push(p);
p=p->left;
}
//p为空,说明已经到了左子树的最下面,这时需要出栈
if(!s.empty()){
p=s.top();
path.push_back(p->val);
s.pop();
//进入右子树,开始新一轮的左子树遍历(递归的自我实现)
p=p->right;
}
}
}
先序遍历
先序遍历和中序遍历差不多,也是需要借助根节点访问右子树,只不过和中序遍历的区别在于在根节点被压栈时就输出它的值,而不是在出栈的时候再访问
void preOrder(TreeNode* root,vector<int> &path){
if(root==NULL) return;
stack<TreeNode*> s;
TreeNode* p=root;
while(!s.empty()||p!=NULL){
while(p){
path.push_back(p->val);
s.push(p);
p=p->left;
}
if(!s.empty()){
TreeNode* temp=s.top();
s.pop();
p=temp->right;
}
}
}
后序遍历
需要判断上次访问的是位于左子树还是右子树。若位于左子树,则要跳过根节点,先进入右子树,再访问根节点;若是位于右子树,则直接访问根节点。
需要保存当前访问节点和上次访问节点
后序遍历访问的一直都是从栈中弹出的元素
- 使用栈来实现,并设置两个指针,分别指向当前访问的节点和上次访问的节点
- 初始化时将当前访问的节点指向最左下的节点,上次访问的节点为NULL
- 取栈顶元素为当前访问节点,如果此节点没有右孩子或者是右孩子为上次访问节点,那么输出此节点信息,并将此节点赋值给上次访问节点,继续从栈中取元素
- 如果右孩子不是上面说的那种情况的话,将当前访问节点(也就是原来的栈顶元素)再次压入栈中,然后访问右子树,将右子树的左节点左节点持续压入栈中,继续循环第3步
void postOrder(TreeNode* root,vector<int> &path){
if(root==NULL) return;
stack<TreeNode*> s;
//当前访问节点,上次访问节点
TreeNode *pCur,*pLastVisit;
pCur=root;
pListVisit=NULL;
//从左子树的最下边开始访问
while(pCur){
s.push(pCur);
pCur=pCur->left;
}
while(!s.empty()){
//走到这里时,已经遍历到二叉树的最低端
pCur=s.top();
s.pop();
//如果没有右子树或者右子树已经被访问,那么访问这个根节点
if(pCur->right==NULL||pCur->right==pLastVisit){
path.push_back(pCur->val);
//修改为最近被访问的节点
//只有输出结果的时候才会修改上次访问节点
pLastVisit=pCur;
}
else{
//将根节点再次入栈
s.push(pCur);
//访问右子树,进入右子树
pCur=pCur->right;
while(pCur){
s.push(pCur);
pCur=pCur->left;
}
}
}
}
层序遍历
层序遍历用非递归的方法更容易实现些,使用队列保存节点,然后逐层遍历即可
用递归实现的方法并不常用,首先要知道树的深度,逐层输出(这里的递归的作用似乎就只是到达了对应的层)
void level(TreeNode* root,int i,vector<int>& path){
if(root==NULL||i==0) return;
if(i==1){
path.push_back(root->val);
}
level(root->left,i-1,path);
level(root->right,i-1,path);
}
int getDepth(TreeNode *root,int depth){
if(root==NULL)
return depth;
else{
int l=getDepth(root->left,depth+1);
int r=getDepth(root->right,depth+1);
return max(l,r);
}
}
void levelOrder(TreeNode* root,vector<int>& path){
if(root==NULL) return;
int dep=getDepth(root);
for(int i=1;i<=dep;i++){
level(root,i,path);
}
}
测试代码
int main(){
TreeNode* one=new TreeNode();
one->val=1;
TreeNode* two=new TreeNode();
two->val=2;
TreeNode* three=new TreeNode();
three->val=3;
TreeNode* four=new TreeNode();
four->val=4;
one->right=two;
one->left=three;
three->left=four;
vector<int> path;
// levelOrder(one,path);
// inorder(one,path);
// preOrder(one,path);
postOrder(one,path);
for(int i=0;i<path.size();i++){
cout<<path[i]<<" ";
}
return 0;
}