7-5 Tree Traversals Again

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操作给出一棵二叉树的中序遍历顺序,求这棵二叉树的后序遍历。

       这道题我写了两种解法,第一种需要建立树,具体如下:

       需要一个堆栈s,一个child变量(表示该当前结点是其父亲结点的左儿子还是右儿子),父亲结点变量fa
对于push x操作:
1).第一个push的肯定是根节点root。
2).根据child变量,建立fa与x的父子关系,fa = x;
3).由于是中序遍历,所以接下来的结点必定是x的左儿子(如果有的话),child = LEFT;
4).然后进行Push x操作,因为未来还要输入x的右儿子(如果有的话),此时有必要记住x结点

对于pop操作:
1).根据中序遍历性质,可知接下来的结点必定是当前堆栈顶部结点的右儿子(如果有的话),因此fa = Pop(),child = RIGHT;

 

代码实现如下:

#include<stdio.h>
#include<stdlib.h> 
#include<string.h>

#define ElementType int
#define MaxN 35
#define LEFT 0
#define RIGHT 1

typedef struct SNode *Stack;
struct SNode{
	ElementType *data;
	int top;
	int MaxSize; 
};

struct TreeNode{
	int left;
	int right;
}node[MaxN];

Stack CreateStack(int MaxSize); 
void Push(Stack PtrS,ElementType X);
ElementType Pop(Stack PtrS);
void PostOrderTraversal(int r);

int main()
{
	int N,x;
	int root = -1,fa;
	int child = LEFT;
	char str[10];
	
	Stack s = CreateStack(100);
	memset(node,-1,sizeof(node));
	scanf("%d",&N);
	for(int i=0; i<2*N; i++){
		scanf("%s",str);
		if(strcmp(str,"Push") == 0){
			scanf("%d",&x);
			if(root == -1){
				root = x;  //第一个输入的必是根结点 
			}else{
				if(child == LEFT){
					node[fa].left = x;
				}else{
					node[fa].right = x;
				}
			} 
			fa = x;
			child = LEFT;
			Push(s,x);
		}else{
			fa = Pop(s);
			child = RIGHT;
		}
	}
	PostOrderTraversal(root);
	
	return 0;
}

/*****后序遍历*****/ 
void PostOrderTraversal(int r)
{
	static int first = 1;
	
	if(r != -1){
		PostOrderTraversal(node[r].left);
		PostOrderTraversal(node[r].right);
		if( first ){
			first = 0;
			printf("%d",r);
		}else{
			printf(" %d",r);
		}
	}
}

//建立空栈 
Stack CreateStack(int MaxSize)
{
    Stack S = (Stack)malloc(sizeof(struct SNode));
    S->data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
    S->top = -1;
    S->MaxSize = MaxSize;
    
    return S;
}

//入栈
void Push(Stack S,ElementType X)
{
	if(S->top == S->MaxSize-1)
	    printf("堆栈满\n");  
	else
	    S->data[++(S->top)] = X;
 } 
//出栈
#define Error -1
ElementType Pop(Stack S)
{
	if(S->top == -1){
		printf("空栈\n");
		return Error; 
	}else{
		return (S->data[(S->top)--]);
	}
}

        第二种解决方法不需要建立树。因为题目给出的是非递归的中序遍历,那么其实在它的堆栈操作中,Push结点的顺序就是先序遍历的顺序,Pop结点的顺序就是中序遍历的顺序,那么我们就可以根据先序和中序遍历的顺序通过递归求解“左右子树”后序遍历顺序的方式求出后序遍历的顺序。

具体代码实现为:

#include<stdio.h>
#include<stdlib.h> 
#include<string.h>

#define ElementType int
#define MaxN 35

typedef struct SNode *Stack;
struct SNode{
	ElementType *data;
	int top;
	int MaxSize; 
};

int pre[MaxN],in[MaxN],post[MaxN];  //存储先序、中序、后序遍历的数组 

Stack CreateStack(int MaxSize); 
void Push(Stack PtrS,ElementType X);
ElementType Pop(Stack PtrS);
void Post_solve(int preL,int inL,int postL,int n); 

int main()
{
	int i,j=0,k=0,x,N;
	int first = 1;
	char str[10];
	
	scanf("%d",&N);
	Stack s = CreateStack(N);
	for(int i=0; i<2*N; i++){
		scanf("%s",str);
		if(strcmp(str,"Push") == 0){
			scanf("%d",&x);
			pre[j++] = x;
			Push(s,x);
		}else{
			in[k++] = Pop(s);
		}
	}
	Post_solve(0,0,0,N);
	for(i=0; i<N; i++){
		if( first ){
			first = 0;
			printf("%d",post[i]);
		}else{
			printf(" %d",post[i]);
		}
	}
	
	return 0;
}

void Post_solve(int preL,int inL,int postL,int n)   
{/*preL,inL,postL分别表示当前遍历数组的最左端*/
	int i,root;
	int Left,Right;
	
	if( n == 0 )  return;  //当递归至只有没有数时,直接返回 
	if( n == 1 ){
		post[postL] = pre[preL];  //当递归至只有一个数时,先序,中序,后序的数组里面的值是相等的 
		return;
	}
	root = pre[preL];  //当前树的根结点肯定是先序遍历的第一个结点 
	post[postL+n-1] = root;  //在后序遍历中,当前树的根结点肯定是最后访问的 
	for(i=0; i<n; i++){/*在中序遍历中找到当前树的根结点*/
		if( in[inL+i] == root )  break; 
	}
	Left = i;  //当前树的左子树所包含的结点数 
	Right = n-Left-1;  //当前树的右子树所包含的结点数
	Post_solve(preL+1,inL,postL,Left);  //递归解决左子树的后序遍历
	Post_solve(preL+Left+1,inL+Left+1,postL+Left,Right);  //递归解决右子树的后序遍历
}

//建立空栈 
Stack CreateStack(int MaxSize)
{
    Stack S = (Stack)malloc(sizeof(struct SNode));
    S->data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
    S->top = -1;
    S->MaxSize = MaxSize;
    
    return S;
}
//入栈
void Push(Stack S,ElementType X)
{
	if(S->top == S->MaxSize-1)
	    printf("堆栈满\n");  
	else
	    S->data[++(S->top)] = X;
 } 
//出栈
#define Error -1
ElementType Pop(Stack S)
{
	if(S->top == -1){
		printf("空栈\n");
		return Error; 
	}else{
		return (S->data[(S->top)--]);
	}
}

 

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值