C 二叉树的前中后序遍历 03-树3 Tree Traversals Again (25分)

03-树3 Tree Traversals Again (25分)

An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example, suppose that when a 6-node binary tree (with the keys numbered from 1 to 6) is traversed, the stack operations are: push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop(). Then a unique binary tree (shown in Figure 1) can be generated from this sequence of operations. Your task is to give the postorder traversal sequence of this tree.

Figure 1
在这里插入图片描述
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤30) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 to N). Then 2N lines follow, each describes a stack operation in the format: “Push X” where X is the index of the node being pushed onto the stack; or “Pop” meaning to pop one node from the stack.

Output Specification:
For each test case, print the postorder traversal sequence of the corresponding tree in one line. A solution is guaranteed to exist. All the numbers must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:

6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop

Sample Output:

3 4 2 6 5 1

题意
给定二叉树各结点入栈出栈的规则,让我们求二叉树的后序遍历。
由给定顺序可知,push的顺序为二叉树的前序遍历,
pop的顺序为二叉树的中序遍历,故模拟堆栈的进程,即可将二叉树的前序与中序遍历填满;
由此题目转化成由二叉树的前序和中序遍历求二叉树的后序遍历;

解题1:由前序遍历和中序遍历构建完整的二叉树,然后再逐个输出二叉树的后序遍历;
同样用结构数组存储二叉树即可。
建树:
设置标记位flag,
连续的push则放在上一个结点的left;
pop之后的push则放在上一个结点的right;
建树之后递归输出后序遍历即可,左右根。

#include<cstdio>
#include<stack>
#include<string>
#include<iostream>
const int maxn=35;
using namespace std;
struct TNode{
	int left, right;
	}T[maxn];
int count=0, n;
void print(int root){
	if(root==-1)return ;
	if(T[root].left!=-1)print(T[root].left);
	if(T[root].right!=-1)print(T[root].right);
	count++;
	printf("%d", root);
	if(count<n/2)printf(" ");
} 
int main(){
	int  num, cnt=0, temp, root, flag=0, first;
	scanf("%d\n", &n);
	for(int i=1; i<=n; i++){//注意题目说角标是从1开始的
		T[i].left=-1;
		T[i].right=-1;
	}
	n=n*2;
	string s;
	stack<int> st;
	for(int i=0; i<n; i++){
		cin>>s;
		if(s=="Push"){
			cin>>num;
			st.push(num);
			if(i==0){
				root=num;
				first=num;
			}else{
				if(flag==0)T[root].left=num;
				else T[root].right=num;
				root=num;
				flag=0;
			}
		}else{
			root=st.top();
			st.pop();
			flag=1;
		}
	} 
	print(first);
	return 0;
} 

解题2:递归方式处理前序中序后序遍历,由前两者推后者
递归函数:
确定前中后序的起始坐标PRE,MID,POST,要处理的节点个数n,
递归三要素:
1.终止条件:n == 0时,无结点需要处理;n == 1时,将该结点放入后序遍历给出的位置
2.缩小规模:将前序遍历的第一个结点,即头节点,放置再后序遍历的最后一个位置,即POST+n-1处
3.调用自身:分别对中序遍历中头节点左右两段进行递归调用,利用树的递归特性
注意点
查找中序遍历左右个数时,要从MID下标开始查找,才是正确个数;

void solution(int PRE,int MID, int POST, int n){
	if(n==0) return; //没有结点要处理
	if(n==1) {
		Post[POST]=Pre[PRE];
		return;
	} 
	
	int L,R;
	//前序的第一个,放在后序的最后一个,
	Post[POST+n-1]=Pre[PRE];
	//放完之后,左右继续solusion
	//通过中序计算左右剩余的结点个数 
	for(int i=0;i<N;i++){
		if(Mid[MID+i]==Pre[PRE]){     //这里很关键——Mid[MID+i],表示该头的第i个 
			L=i;    //找到左边坐标,个数为l+1
			break; 
		}
	}
	R  = n-L-1;     //减掉刚才的根节点 
	solution(PRE+1,MID,POST,L);
	solution(PRE+L+1,MID+L+1,POST+L,R); 
}

完整代码:

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

int N;
int Pre[35];
int Mid[35];
int Post[35];
int temp;
				 
void solution(int PRE,int MID, int POST, int n){
	if(n==0) return; //没有结点要处理
	if(n==1) {
		Post[POST]=Pre[PRE];
		return;
	} 
	
	int L,R;
	//前序的第一个,放在后序的最后一个,
	Post[POST+n-1]=Pre[PRE];
	//放完之后,左右继续solusion
	//通过中序计算左右剩余的结点个数 
	for(int i=0;i<N;i++){
		if(Mid[MID+i]==Pre[PRE]){     //这里很关键——Mid[MID+i],表示该头的第i个 
			L=i;    //找到左边坐标,个数为l+1
			break; 
		}
	}
	R  = n-L-1;     //减掉刚才的根节点 
	solution(PRE+1,MID,POST,L);
	solution(PRE+L+1,MID+L+1,POST+L,R); 
}




int main()
{	int num;
	string cmd;
	stack <int> st;
	int m=0,n=0;
	cin>>N;
	for(int i=0;i<2*N;i++)
	{
		cin>>cmd;
		if(cmd=="Push"){
			cin>>num;
			st.push(num);
			Pre[m++]=num;
		}
		else{
			temp=st.top();
			st.pop();
			Mid[n++]=temp;
		}
	}
	//这时,已得到前序和中序遍历。
	solution(0,0,0,N);
	for(int i=0;i<N;i++){
		if(i==N-1){
			cout<<Post[i];
		}
		else cout<<Post[i]<<" ";
		 
	}
	
}
发布了77 篇原创文章 · 获赞 3 · 访问量 3032

猜你喜欢

转载自blog.csdn.net/BLUEsang/article/details/105307688