PAT (Advanced Level) Practice 1043 Is It a Binary Search Tree 二叉排序树建立、树的遍历

本文详细介绍了如何构建二叉排序树,并进行先序、镜像先序及后序遍历。通过具体代码示例,讲解了遍历算法的实现细节,包括插入节点、遍历比较以及输出结果的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

根据输入建一棵二叉排序树,对其进行先序遍历和镜像先序遍历。然后后序遍历并输出。

这题通过率很高,但我觉得很麻烦——通过率很高大概是因为能把样例过了就全过了的缘故。

二、分析

首先要建一棵二叉排序树,如下:

scanf("%d",&N);
int i;
root->lchild=NULL;
root->rchild=NULL;
int b;
scanf("%d",&b);
root->data=b;
start.push_back(b);
for(i=0;i<N-1;i++)
{
	int a;
	scanf("%d",&a);
	start.push_back(a);
	insert(root,a);
}

insert函数如下:

void insert(node* root,int a)
{
	if(root->data>a)
		if(root->lchild!=NULL)
			insert(root->lchild,a);
		else
			{
				node* leaf=new node;
				leaf->data=a;
				leaf->lchild=NULL;
				leaf->rchild=NULL;
				root->lchild=leaf;
				return;
			}
	else
		if(root->rchild!=NULL)
			insert(root->rchild,a);
		else
			{
				node* leaf=new node;
				leaf->data=a;
				leaf->lchild=NULL;
				leaf->rchild=NULL;
				root->rchild=leaf;
				return;
			}
}

二叉排序树有按序插入的性质,小于插左边大于插右边。什么时候插呢?root=NULL的时候插就可以了。在插之前要先建一个node并声明空间,然后初始化,不要忘了指针置为NULL,然后接上去即可。

另外要注意一点,很多insert函数的参数都是node*&root,而我的是node* root。例如下面的insert:

void insert(node* &root,int x)
{
    if(root==NULL)
    {
        root=newNode(x);
        return;
    }
    if(条件一)
    {
        insert(root->lchild,x);
    }
    else
    {
        insert(root->lchild,x);
    }
}

注意观察二者的区别,下面的插入函数是直接在root上开了一个node大小的空间,而我是首先声明一个根节点,创建好后在根节点上操作,再声明一个node空间,接到根节点上。本质上我并没有修改根节点自己。因此我不需要用取地址操作。

当然,无论是出于简洁的角度还是不需准备的角度,人家都比我写得好。

然后是前序遍历以及镜像前序遍历。

前序遍历是十分好写的,如下

void preorder(node* root)
{
	if(root->data!=NULL)
	pre.push_back(root->data);
	if(root->lchild!=NULL)
	preorder(root->lchild);
	if(root->rchild!=NULL)
	preorder(root->rchild);
}

因为懒得数了,所以直接用vector来push一下很简单。镜像前序遍历的区别就是:镜像遍历是先右后左的,明白了这点就不用再去建一棵镜像树了,又麻烦又容易晕。如下:

void preordermirror(node* root)
{
	if(root->data!=NULL)
	mirror.push_back(root->data);
	if(root->rchild!=NULL)
	preordermirror(root->rchild);
	if(root->lchild!=NULL)
	preordermirror(root->lchild);
}

也是用vector来实现。写多了以后就越来越喜欢全局变量。

遍历之后就要判断初始序列是和哪个相等了。

注意!两个向量a和b中所有元素都相等,判断这个可以直接用a==b,即

if(start==pre)
{
	equal_pre=1;
}
if(start==mirror)
{
	equal_mirror=1;
}

而不用像我这样麻烦的

for(it_pre=pre.begin(),it_start=start.begin();it_pre!=pre.end(),it_start!=start.end();it_pre++,it_start++)
		if(*it_pre!=*it_start)
		{
			equal_pre=0;
			break;
		}
for(it_mirror=mirror.begin(),it_start=start.begin();it_mirror!=mirror.end(),it_start!=start.end();it_mirror++,it_start++)
		if(*it_mirror!=*it_start)
		{
			equal_mirror=0;
			break;
		}

这个很方便。

之后选择对应的输出即可,后序遍历和镜像后序遍历也类似,就不赘述了。

三、总结

本题应用了建树、树的遍历、排序树的性质等知识点,不难,但需要熟练。

PS:代码如下

#include<stdio.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
struct node
{
	int data;
	node* lchild;
	node* rchild;
};
node* root=new node;
vector<int> pre;
vector<int> mirror;
vector<int> start;
int postnum=0;
int N;
void insert(node* root,int a)
{
	if(root->data>a)
		if(root->lchild!=NULL)
			insert(root->lchild,a);
		else
			{
				node* leaf=new node;
				leaf->data=a;
				leaf->lchild=NULL;
				leaf->rchild=NULL;
				root->lchild=leaf;
				return;
			}
	else
		if(root->rchild!=NULL)
			insert(root->rchild,a);
		else
			{
				node* leaf=new node;
				leaf->data=a;
				leaf->lchild=NULL;
				leaf->rchild=NULL;
				root->rchild=leaf;
				return;
			}
}
void preorder(node* root)
{
	if(root->data!=NULL)
	pre.push_back(root->data);
	if(root->lchild!=NULL)
	preorder(root->lchild);
	if(root->rchild!=NULL)
	preorder(root->rchild);
}
void postorder(node* root)
{
	if(root->lchild!=NULL)
	postorder(root->lchild);
	if(root->rchild!=NULL)
	postorder(root->rchild);
	if(root->data!=NULL)
	{
		printf("%d",root->data);
		postnum++;
		if(postnum<N)
		printf(" ");
	}
}
void postordermirror(node* root)
{
	if(root->rchild!=NULL)
	postordermirror(root->rchild);
	if(root->lchild!=NULL)
	postordermirror(root->lchild);
	if(root->data!=NULL)
	{
		printf("%d",root->data);
		postnum++;
		if(postnum<N)
		printf(" ");
	}
}
void preordermirror(node* root)
{
	if(root->data!=NULL)
	mirror.push_back(root->data);
	if(root->rchild!=NULL)
	preordermirror(root->rchild);
	if(root->lchild!=NULL)
	preordermirror(root->lchild);
}
int main()
{
	scanf("%d",&N);
	int i;
	root->lchild=NULL;
	root->rchild=NULL;
	int b;
	scanf("%d",&b);
	root->data=b;
	start.push_back(b);
	for(i=0;i<N-1;i++)
	{
		int a;
		scanf("%d",&a);
		start.push_back(a);
		insert(root,a);
	}
	preorder(root);
	preordermirror(root);
	vector<int>::iterator it_pre;
	vector<int>::iterator it_mirror;
	vector<int>::iterator it_start;
	int equal_pre=1;
	int equal_mirror=1;
	////////////////////////////////////////
	/*printf("pre:\n");
	for(it_pre=pre.begin();it_pre!=pre.end();it_pre++)
		printf("%d ",*it_pre);
	printf("\nmirror:\n");
	for(it_mirror=mirror.begin();it_mirror!=mirror.end();it_mirror++)
		printf("%d ",*it_mirror);
	printf("\nstart:\n");
	for(it_start=start.begin();it_start!=start.end();it_start++)
		printf("%d ",*it_start);*/
	////////////////////////////////////////
	for(it_pre=pre.begin(),it_start=start.begin();it_pre!=pre.end(),it_start!=start.end();it_pre++,it_start++)
		if(*it_pre!=*it_start)
		{
			equal_pre=0;
			break;
		}
	for(it_mirror=mirror.begin(),it_start=start.begin();it_mirror!=mirror.end(),it_start!=start.end();it_mirror++,it_start++)
		if(*it_mirror!=*it_start)
		{
			equal_mirror=0;
			break;
		}
	if(equal_pre==1)
	{
		printf("YES\n");
		postorder(root);
	}
	else if(equal_mirror==1)
	{
		printf("YES\n");
		postordermirror(root);
	}
	else
		printf("NO");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值