PAT甲级1020答案(使用C语言)

PAT甲级1020答案(使用C语言)

题目描述

Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, you are supposed to output the level order traversal sequence of the corresponding binary tree.

**

Input Specification:

**
Each input file contains one test case. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the level order traversal sequence of the corresponding binary tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:

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

Sample Output:

4 1 6 3 5 7 2

对题目简单的总结:

1.输入二叉树的结点个数, 输入二叉树的后序序列和二叉树的中序序列
2.根据输入的两个序列建立二叉树

main函数

int main(){
	
	scanf("%d", &n);//输入结点个数n
	
	for(int i = 0; i < n; i++){
		scanf("%d", &post[i]);
	}//输入后序序列
	for(int j = 0; j < n; j++){
		scanf("%d", &in[j]);
	}//输入中序序列
	
	node* root = CreateTree(0, n-1, 0, n-1);//调用二叉树建立函数
	levelorder(root);//输出层次序列
	return 0;
}

搞清楚整个题目的大概逻辑之后就是对里面的函数进行设计
1.CreateTree()的设计
思路:根据后序和中序确定二叉树实际上可以看成一个递归的过程

  • 根据后序序列确定根节点(初始时为后序序列的最后一个数);
  • 根据根节点找出中序序列中该节点的位置,此时中序序列被根节点分为左右两颗子树
  • 再分别对这两棵子树进行上述操作,直到后序序列中最左边节点的下标大于最右边节点的下标

    这里引用《算法笔记》一书中在这个问题上的图解
    代码如下:
//这里先给出node的结构体
struct node{
	int data;
	node* lchild;
	node* rchild;
};

node* CreateTree(int pol, int por, int inl, int inr){
	
	if(por < pol){
		return NULL;
	} //跳出递归的边界
	int rootdata = post[por]; //在后序序列中找到根节点
	node* root = (node*)malloc(sizeof(node)); //为新节点分配内存空间
	root -> data = rootdata; //为新节点附上数据值
	int i; //i用来寻找根节点在中序序列中的下标
	for( i = inl ; i <= inr; i++){
		if(in[i] == rootdata){
			break;
		}
	}
	
	int numleft = i - inl; //左子树节点的个数
	//这两行递归要注意参数的变化,像lchild的第二个参数,不能直接用numleft-1,
	root -> lchild = CreateTree(pol, pol + numleft - 1, inl, i - 1);
	root -> rchild = CreateTree(pol + numleft, por - 1, i + 1, inr);
	return root;
}

2.levelorder()的设计
这个函数是层次遍历,使用队列进行设计,这里不做赘述

void levelorder(node* root){
	queue<node*> q; //定义一个队列q
	q.push(root);//将root节点入队
	while(!q.empty()){
		node* now = q.front(); //将now指针指向队头;
		q.pop(); //将队头节点出队
		printf("%d", now -> data); 
		num++ ;
		if(num < n) printf(" "); //这里两行代码是为了符合题目对输出格式的要求
		//如果root节点的左右孩子非空,则将他们依次入队
		if(now -> lchild != NULL) q.push(now->lchild); 
		if(now -> rchild != NULL) q.push(now->rchild);
	}
}

整体代码:

#include <stdio.h>
#include <cstdlib>
#include<queue>
#include<algorithm>
# define maxv 1000   
using namespace std;
int post[maxv], in[maxv];
int n;

struct node{
	int data;
	node* lchild;
	node* rchild;
};

node* CreateTree(int pol, int por, int inl, int inr){
	
	if(por < pol){
		return NULL;
	} //跳出递归的边界
	int rootdata = post[por]; //在后序序列中找到根节点
	node* root = (node*)malloc(sizeof(node)); //为新节点分配内存空间
	root -> data = rootdata; //为新节点附上数据值
	int i; //i用来寻找根节点在中序序列中的下标
	for( i = inl ; i <= inr; i++){
		if(in[i] == rootdata){
			break;
		}
	}
	
	int numleft = i - inl; //左子树节点的个数
	//这两行递归要注意参数的变化,像lchild的第二个参数,不能直接用numleft-1,
	root -> lchild = CreateTree(pol, pol + numleft - 1, inl, i - 1);
	root -> rchild = CreateTree(pol + numleft, por - 1, i + 1, inr);
	return root;
}
int num = 0;
void levelorder(node* root){
	queue<node*> q; //定义一个队列q
	q.push(root);//将root节点入队
	while(!q.empty()){
		node* now = q.front(); //将now指针指向队头;
		q.pop(); //将队头节点出队
		printf("%d", now -> data); 
		num++ ;
		if(num < n) printf(" "); //这里两行代码是为了符合题目对输出格式的要求
		//如果root节点的左右孩子非空,则将他们依次入队
		if(now -> lchild != NULL) q.push(now->lchild); 
		if(now -> rchild != NULL) q.push(now->rchild);
	}
}

int main(){
	
	scanf("%d", &n);//输入结点个数n
	
	for(int i = 0; i < n; i++){
		scanf("%d", &post[i]);
	}//输入后序序列
	for(int j = 0; j < n; j++){
		scanf("%d", &in[j]);
	}//输入中序序列
	
	node* root = CreateTree(0, n-1, 0, n-1);//调用二叉树建立函数
	levelorder(root);//输出层次序列
	return 0;
}

注意这里题目要求的输出格式:题目要求每个节点的数据中间要有空格作为间隔,这里隐含的意思是最后一个节点不能带空格,否则OJ会判断出现输出格式错误

最后上一下AC的图
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值