MOOC 03-树3 Tree Traversals Again

MOOC 03-树3 Tree Traversals Again,第1张

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序列是中序遍历序列;已知先序序列和中序序列,可知后序遍历序列;具体求解的算法上还是很考察逻辑能力的;说实话,是真想不到能这样递归求解

        具体算法解析:根据给出的Push和Pop序列 可得出先序和中序序列,各自放在数组里;先序的第一个是根,在后序中对应的值存放在数组的最后,再在中序数组中找出根所在的位置,将数组分为左和右,长度可以算出,然后递归的求解左和右的根;

 

#include 
#include 
#define STR_LEN 5
#define MAXSIZE 30

int Stack[MAXSIZE]; //堆栈
int Top; 

int Pre[MAXSIZE],In[MAXSIZE],Post[MAXSIZE]; //存放先序、中序、后序遍历的数组

void Push( int Stack[],int M ); //入栈

int Pop( int Stack[] );    //出栈

void solve( int PreL,int InL,int PostL,int n );  //核心算法

int main()
{
	//根据给出的Push和Pop顺序得出 先序序列和中序序列,存放在数组中
	int N,M,i;
	scanf("%d",&N);
	
	int iPre,iIn;
	iPre = iIn = 0;
	
	char str[STR_LEN];
	
	for(i=0;i<2*N;i++){
		
		scanf("%s",str);
		
		if(strcmp(str,"Push") == 0){
			
			scanf("%d",&M);
			Pre[iPre] = M;
			iPre++;
			
			Push( Stack,M );
		}else{
			
			In[iIn] = Pop( Stack );
			iIn++;
		}
	}
//	for(i=0;i

 经过这么一折腾,应该是已知中序和其他两个遍历序列中的一种,求可以得出另一种的遍历序列,这是通用的方法;其中递归求解的思维,应当好练习;诸君共勉。

在这之前,其实我自己已经写出了AC代码,但是可能不具有通用性,可以拿出来跟大家一起学习探讨;

我的思路是:中序、先序、后序的入栈顺序是一样的,只是后序在出栈中还需判断是否有右子树,有的话就重新压入栈;那么就在每个结点中增加一个域,表示第几次入栈;当遇到Pop时,只Pop出来入栈次数为2的结点,然后将栈顶的结点入栈次数标为2;

具体看代码:

#include 
#include 
#include 
#include 
#define STR_LEN 5

typedef struct _TreeNode{ //树结点
	int Data;
	int Tag;  //入栈次数 
}TreeNode;

typedef struct _Stack{ 堆栈
	TreeNode* Array;
	int Top;
	int Len;
}Stack;

Stack* CreateStack( );

void PostTraversal( Stack* S );

bool IsEmpty( Stack* S );

void Push( Stack* S,int M );

void Pop( Stack* S,bool* pfirst );

void FreeStack( Stack* S );

int main()
{
	Stack* S = CreateStack( );
	
	PostTraversal( S );
	
	FreeStack( S );
	
	return 0;
}

//创建空栈,这里没用全局变量,而是练习另一种方式,根据实际需要来malloc堆栈大小
Stack* CreateStack( )
{
	Stack* S = (Stack*)malloc(sizeof(Stack));
	
	scanf("%d",&(S->Len));
	
	S->Array = malloc(S->Len*sizeof(TreeNode));
	
	S->Top = -1; 
	
	return S;
}

//核心算法
void PostTraversal( Stack* S )
{
	int M,N = 2*(S->Len);
	bool first = true;//first是为了满足题目要求的输出格式的标记
	char string[STR_LEN ];
	
	while(N--){
		
		scanf("%s",string);
		
		if(strcmp(string,"Push") == 0){ //入栈
			
			scanf("%d",&M);
			Push( S,M );
		}else{
			
			//出栈时,判别入栈次数,只出入栈2次的结点
			while(!IsEmpty( S ) && S->Array[S->Top].Tag == 2){
				
				Pop( S,&first );//第一个出栈的 打印不带空格,后面的都带空格,满足题目输出要求
			}
			
			//第一次遇到Pop,不出栈,做第二次入栈标记
			if(!IsEmpty( S )){
				
				S->Array[S->Top].Tag = 2;
			}
		}
	}
	
	while(!IsEmpty( S )){
		
		Pop( S,&first );
	}
}

bool IsEmpty( Stack* S )
{
	return S->Top == -1 ? true : false;	
}

void Push( Stack* S,int M )
{
	S->Top++;
	S->Array[S->Top].Data = M;
	S->Array[S->Top].Tag = 1;
}

void Pop( Stack* S,bool* pfirst )
{
	if(*pfirst){
		
		printf("%d",S->Array[S->Top].Data);
		*pfirst = false;
	}else{
		
		printf(" %d",S->Array[S->Top].Data);
	}
	
	S->Top--;
}

void FreeStack( Stack* S )
{
	free(S->Array);
	free(S);
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/798512.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)