PAT (Advanced Level) Practice 1020 Tree Traversals 中序加后序等于二叉树,层序遍历

一、概述

给出一棵二叉树的中序和后序遍历,求其层序遍历。

408时DS部分很喜欢出的题,现在要用代码实现。

原理很简单。

首先用一个函数重建二叉树,然后层序遍历即可。

第一次做还是有几个小坑的。

二、分析

首先是重建二叉树。代码如下:

Node* create(int inhead, int inend, int posthead, int postend)
{
	if (posthead>postend)//递归出口 
		return NULL;
	Node* root = new Node;//新建根节点 
	root->data = postorder[postend];//根节点数据域赋值 
									//printf("%d",root->data); 
	int i = inhead;
	for (i = inhead; i <= inend; i++)
		if (inorder[i] == root->data)
			break;//找到根节点在中序的位置 
	int leftNumber = i - inhead;
	//root->lchild=create(inhead,i-1,posthead,i-1);//根节点左右子树 
	//在后序遍历中,找到左子树的元素时,不能用[posthead,i-1],要用[posthead,posthead+leftNumber-1] 
	root->lchild = create(inhead, i - 1, posthead, posthead + leftNumber - 1);
	//root->rchild=create(i+1,inend,i,postend-1);
	//右子树也一样,总结起来就是除了中序序列,找子树元素时要用左子树个数来定位 
	root->rchild = create(i + 1, inend, posthead + leftNumber, postend - 1);
	//千万不要忘了return
	return root;
}

二叉树是由递归定义的,因此重建二叉树要使用递归函数。

函数的返回值是节点指针,这是一定要注意的。如果没有返回值,那么根节点指针就是0x00,这是易犯的错误。

四个参数分别是目前要重建的二叉(子)树的中序遍历节点下标,后序遍历节点下标。

首先判断递归出口,以除中序以外的序列的左下标大于右下标为出口。

其次申请内存,建新节点,用new关键字,为节点赋值。

再然后根据后序遍历的下标定位根节点在中序遍历的下标。

最后递归调用函数。

一定要注意函数参数。

然后是层序遍历。如下:

void levelorder(Node* root)
{
	queue<Node*> q;
	q.push(root);
	while (!q.empty())
	{
		Node* newnode = q.front();
		q.pop();
		N--;
		printf("%d", newnode->data);
		if (N > 0)
			printf(" ");
		if (newnode->lchild != NULL)
			q.push(newnode->lchild);
		if (newnode->rchild != NULL)
			q.push(newnode->rchild);
	}
}

是由BFS改进而来的,比BFS简单些。使用队列实现。注意队列的元素是节点指针而不是节点。

三、总结

二叉树的遍历、重建也是很重要的知识点,要熟练掌握。

PS:代码如下:

#include<stdio.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct Node
{
	int data;
	Node* lchild;
	Node* rchild;
};
int inorder[30] = { 0 };//中序序列 
int postorder[30] = { 0 };//后序序列 
int N;
Node* create(int inhead, int inend, int posthead, int postend)
{
	if (posthead>postend)//递归出口 
		return NULL;
	Node* root = new Node;//新建根节点 
	root->data = postorder[postend];//根节点数据域赋值 
									//printf("%d",root->data); 
	int i = inhead;
	for (i = inhead; i <= inend; i++)
		if (inorder[i] == root->data)
			break;//找到根节点在中序的位置 
	int leftNumber = i - inhead;
	//root->lchild=create(inhead,i-1,posthead,i-1);//根节点左右子树 
	//在后序遍历中,找到左子树的元素时,不能用[posthead,i-1],要用[posthead,posthead+leftNumber-1] 
	root->lchild = create(inhead, i - 1, posthead, posthead + leftNumber - 1);
	//root->rchild=create(i+1,inend,i,postend-1);
	//右子树也一样,总结起来就是除了中序序列,找子树元素时要用左子树个数来定位 
	root->rchild = create(i + 1, inend, posthead + leftNumber, postend - 1);
	//千万不要忘了return
	return root;
}
void levelorder(Node* root)
{
	queue<Node*> q;
	q.push(root);
	while (!q.empty())
	{
		Node* newnode = q.front();
		q.pop();
		N--;
		printf("%d", newnode->data);
		if (N > 0)
			printf(" ");
		if (newnode->lchild != NULL)
			q.push(newnode->lchild);
		if (newnode->rchild != NULL)
			q.push(newnode->rchild);
	}
}
int main()
{
	scanf("%d", &N);
	int i;
	for (i = 0; i<N; i++)
		scanf("%d", &postorder[i]);
	for (i = 0; i<N; i++)
		scanf("%d", &inorder[i]);
	Node* root = create(0, N - 1, 0, N - 1);
	levelorder(root);
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值