1. 程式人生 > >二叉樹的中序後序排列求先序/先序中序排列求後序

二叉樹的中序後序排列求先序/先序中序排列求後序

7-8 根據後序和中序遍歷輸出先序遍歷 (25 分)

本題要求根據給定的一棵二叉樹的後序遍歷和中序遍歷結果,輸出該樹的先序遍歷結果。

輸入格式:

第一行給出正整數N(≤30),是樹中結點的個數。隨後兩行,每行給出N個整數,分別對應後序遍歷和中序遍歷結果,數字間以空格分隔。題目保證輸入正確對應一棵二叉樹。

輸出格式:

在一行中輸出Preorder:以及該樹的先序遍歷結果。數字間有1個空格,行末不得有多餘空格。

輸入樣例:

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

輸出樣例:

Preorder: 4 1 3 2 6 5 7

基本思路就是利用後序排列可以不斷找出根節點,從而在中序排列中找到該節點的位置,將中序排列拆分為左右兩個子樹成為新的中序排列,根據拆分結果可以將後序排列相同拆分為兩個新的後序排列......如此遞迴求解直到子樹為空。在這個遞迴過程中就可以不斷按順序找出各個根節點完成樹的重建! 

#include<stdio.h>
#include<stdlib.h>
typedef struct node{
	int data;
	struct node *l,*r;
}*bt;
//根據輸入的中序後序排列來重建樹
bt createTree(int *in,int *post,int n){   //指標in和post指向中後序的起始位置,n是長度
	if(n<=0)       
	  return NULL;  //遞迴出口,返回空指標
	int *p=in;      //p是從中序排列中找到根的位置
	while(p){
		if(*p==*(post+n-1))
		  break;
		p++;
	}
    int len=p-in;   //計算長度
	bt t=(bt)malloc(sizeof(struct node));    //建立這個節點並賦值,遞迴建立其左右孩子
	t->data=*p;
	t->l=createTree(in,post,len);
	t->r=createTree(p+1,post+len,n-len-1);   //原來長度為n,減去左邊子樹的一段和根節點,長度變為n-len-1
	return t;
} 

void preorder(bt t){                         //先序遍歷建立的樹得到先序排列
	if(t){
		printf(" %d",t->data);
		preorder(t->l);
		preorder(t->r);
	}
}

int main(){
	int n,in[50],post[50];
	bt t;
	scanf("%d",&n);
	for(int i = 0;i < n;i++)
		scanf("%d",&post[i]);
	for(int i = 0;i < n;i++)
		scanf("%d",&in[i]);
    t=createTree(in,post,n);
    printf("Preorder:");
    preorder(t);
    return 0;
}

同理按照此思路也可以完成已知先序中序求解後序排列,只需要對重建樹的程式碼進行更改:

bt createTree(int *in,int *pre,int n){
	if(n<=0)
	  return NULL;
	int *p=in;
	while(p){
		if(*p==*pre)
		  break;
		p++;
	}
	int len=p-in;
	bt t=(bt)malloc(sizeof(struct node));
	t->data=*p;
	t->l=createTree(in,pre+1,len);           //注意選取位置的變化
	t->r=createTree(p+1,pre+1+len,n-len-1); 
}