【数据结构·考研】后序遍历二叉树

后序遍历二叉树

递归的后序遍历二叉树还是和之前一样,调整一下输出语句就可以。非递归有两种方式,一种是规规矩矩的类似中序的迭代,另一种是通过倒序输出镜像前序的序列来得到后序序列。

依旧是那棵老树:

/*------------
树的形状:
      a
    b   c
  d  e f 
--------------*/

递归:

//递归
void PostOrder(Tree& t){
	if(t == NULL) return;
	PostOrder(t->left);
	PostOrder(t->right);
	cout<<t->val<<" ";   
} 

非递归:

//非递归
/*中序非递归的代码稍加修改*/
void PostOrderTraversal(Tree& t){
	/*与中序遍历的差别在于从左孩子走到根节点后不是急着输出
	根节点,而是再进入右结点,之后再返回,这样根节点会被访问到两次,
	设置指向上一个被访问结点的标志pre,限制它只能访问一次右孩子。*/
	stack<TreeNode*> s; 
	TreeNode* cur = t; 
	TreeNode* pre = NULL;
	//左-中-右 
	while(cur != NULL || !s.empty()){
		while(cur != NULL){
			s.push(cur);
			cur=cur->left;
		}
		cur = s.top();//此时查看的是最左边的叶子结点 
		if(cur->right == NULL || cur->right == pre){
			//如果该结点的右孩子为空或者被访问过,该访问根节点
			cout<<cur->val<<" ";
			s.pop();//根节点被访问过,应该出栈 
			pre = cur;//更新被访问过的结点 
			cur = NULL;//已经被访问过,避免上方while循环再次进栈 
		} 
		//右孩子非空,且未被访问过 
		else cur = cur->right;//去右子树重新执行上述过程 
	}
}

代码如下:

#include<iostream>
#include<queue>
#include<stack>
using namespace std;

typedef struct node{
	char val;
	struct node* left;
	struct node* right;
}TreeNode,*Tree;

//递归
void PostOrder(Tree& t){
	if(t == NULL) return;
	PostOrder(t->left);
	PostOrder(t->right);
	cout<<t->val<<" ";   
} 

//非递归
/*中序非递归的代码稍加修改*/
void PostOrderTraversal(Tree& t){
	/*与中序遍历的差别在于从左孩子走到根节点后不是急着输出
	根节点,而是再进入右结点,之后再返回,这样根节点会被访问到两次,
	设置指向上一个被访问结点的标志pre,限制它只能访问一次右孩子。*/
	stack<TreeNode*> s; 
	TreeNode* cur = t; 
	TreeNode* pre = NULL;
	//左-中-右 
	while(cur != NULL || !s.empty()){
		while(cur != NULL){
			s.push(cur);
			cur=cur->left;
		}
		cur = s.top();//此时查看的是最左边的叶子结点 
		if(cur->right == NULL || cur->right == pre){
			//如果该结点的右孩子为空或者被访问过,该访问根节点
			cout<<cur->val<<" ";
			s.pop();//根节点被访问过,应该出栈 
			pre = cur;//更新被访问过的结点 
			cur = NULL;//已经被访问过,避免上方while循环再次进栈 
		} 
		//右孩子非空,且未被访问过 
		else cur = cur->right;//去右子树重新执行上述过程 
	}
}

//非递归 
/*前序非递归的代码稍加修改*/ 
void postOrderTraversal(Tree& t){
	/*前序遍历顺序:中->左->右, 
	前序遍历左右颠倒:中->右->左,变成了前序遍历的镜像, 
	整个顺序再颠倒:右->左->中,得到了后序遍历的序列。 */
	if(t == NULL) return; 
	stack<TreeNode*> s;
	stack<char> res; //用一个栈来倒序输出结果 
	s.push(t); //根结点入栈 
	while(!s.empty()){ 
		TreeNode* p = s.top(); 
		res.push(p->val);
		s.pop();
		//对前序的入栈顺序做了调整,使它以镜像前序的方式遍历 
		if(p->left != NULL) 
			s.push(p->left);
		if(p->right != NULL)
			s.push(p->right);
	}
	//倒序输出 
	while(!res.empty()){
		cout<<res.top()<<" ";
		res.pop();
	}
}


void CreateTree(Tree& t){
	char x;
	cin>>x;
	if(x == '#') t = NULL; 
	else{
		t = new TreeNode; 
		t->val = x;  
		CreateTree(t->left); 
		CreateTree(t->right); 
	}
} 

void levelOrder(Tree& t) {
    if(t == NULL) return;
    queue<TreeNode*> q;
    q.push(t);
    while(!q.empty()){
        int n = q.size();
        for(int i = 0;i<n;i++){
            TreeNode* s = q.front();
            cout<<s->val<<" ";
            q.pop();
            if(s->left) q.push(s->left);
            if(s->right) q.push(s->right);
        }
        cout<<endl;
    } 
}

int main(){
	Tree t;
	CreateTree(t);
	/*
	   a b d # # e # # c f # # #
	*/
	levelOrder(t); 
	cout<<endl<<"递归:"<<endl;
	PostOrder(t);
	cout<<endl<<"非递归1:"<<endl;
	PostOrderTraversal(t);
	cout<<endl<<"非递归2:"<<endl;	
	postOrderTraversal(t);	
}

运行结果:

猜你喜欢

转载自blog.csdn.net/cjw838982809/article/details/108236208