浙大PAT (Advanced Level) Practise 1043 Is It a Binary Search Tree (25)

本文详细介绍了如何通过先序遍历序列判断一棵二叉树是否为二叉查找树及其镜像版本,并通过递归方式获取其后续遍历序列。

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

#include <cstdio>
#include <vector>
using namespace std;

/*根据题意,二叉查找数的左子树节点的所有数值都小于根节点,右子树数值都大于或等于根节点数值。
又输入的一行数字为二叉查找树的先序遍历,因此,对于某一数组num,设其后续遍历为postOrder,可以采
用如下步骤可递归确定该树是否为二叉查找树(同时获取其后续遍历):
1.输入数组的第一个数是根节点(先序遍历的性质);
2.从数组从后往前找到第一个小于根节点数值的数的下标k;k左边(含k)为左子树,右边为右子树。
将根节点数值放入postOrder末尾;
3.递归判断左子树、右子树,同时获取他们的后序遍历序列。
类似的,可以判断镜像二叉查找树,并获取其后序遍历序列。*/
bool isBST(const vector<int> &num, int l, int r, vector<int> &postOrder)//判断二叉查找树
{
	if(l == r){//数组只有一个数字
		postOrder.insert(postOrder.begin(),num[l]);
		return true;
	}
	if(l == r-1){//数组只有两个数字
		postOrder.insert(postOrder.begin(),num[l]);
		postOrder.insert(postOrder.begin(),num[r]);
		return true;
	}
	int k = r;
	while(num[l] <= num[k] && k > l) --k;
	if(k == l){
		postOrder.insert(postOrder.begin(),num[l]);
		return isBST(num, l+1, r, postOrder);
	}
	else if(k == r){
		for(int i = l + 1; i < r + 1; ++i){
			if(num[l] <= num[i]) return false;//左子树中有大于等于根节点的数值
		}
		postOrder.insert(postOrder.begin(),num[l]);
		return isBST(num, l+1, r, postOrder);
	}
	else{
		for(int i = l + 1; i < k + 1; ++i){
			if(num[l] <= num[i]) return false;//左子树中有大于等于根节点的数值
		}
		postOrder.insert(postOrder.begin(),num[l]);
		return isBST(num, k+1, r, postOrder) && isBST(num, l+1, k, postOrder);//递归判断左右子树
	}
}

bool isMIBST(const vector<int> &num, int l, int r, vector<int> &postOrder)//判断镜像二叉查找树
{
	if(l == r){
		postOrder.insert(postOrder.begin(),num[l]);
		return true;
	}
	if(l == r-1){
		postOrder.insert(postOrder.begin(),num[l]);
		postOrder.insert(postOrder.begin(),num[r]);
		return true;
	}
	int k = r;
	while(num[l] > num[k] && k > l) --k;
	if(k == l){
		postOrder.insert(postOrder.begin(),num[l]);
		return isMIBST(num, l+1, r, postOrder);
	}
	else if(k == r){
		for(int i = l + 1; i < r + 1; ++i){
			if(num[l] > num[i]) return false;
		}
		postOrder.insert(postOrder.begin(),num[l]);
		return isMIBST(num, l+1, r, postOrder);
	}
	else{
		for(int i = l + 1; i < k + 1; ++i){
			if(num[l] > num[i]) return false;
		}
		postOrder.insert(postOrder.begin(),num[l]);
		return isMIBST(num, k+1, r, postOrder) && isMIBST(num, l+1, k, postOrder);
	}
}

int main()
{
	//freopen("in.txt","r",stdin);
	int n;
	scanf("%d",&n);
	int tmp;
	vector<int> num;
	vector<int> postOrder;//用来存储后续遍历序列
	while(n > 0){
		scanf("%d", &tmp);
		num.push_back(tmp);
		--n;
	}
	bool res = isBST(num, 0, num.size()-1, postOrder);
	if(res){
		printf("YES\n");
		for(int i = 0; i < postOrder.size(); ++i){
			if(i != 0) printf(" ");
			printf("%d", postOrder[i]);
		}
	}
	else{
		postOrder.clear();
		res = isMIBST(num, 0, num.size()-1, postOrder);
		if(res){
			printf("YES\n");
			for(int i = 0; i < postOrder.size(); ++i){
				if(i != 0) printf(" ");
				printf("%d", postOrder[i]);
			}
		}
		else{
			printf("NO");
		}
	}
	return 0; 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懒行者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值