PAT 7-28. 搜索树判断 (二叉搜索树)

题目描述

对于二叉搜索树,我们规定任一结点的左子树仅包含严格小于该结点的键值,而其右子树包含大于或等于该结点的键值。如果我们交换每个节点的左子树和右子树,得到的树叫做镜像二叉搜索树。

现在我们给出一个整数键值序列,请编写程序判断该序列是否为某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,如果是,则输出对应二叉树的后序遍历序列。

输入格式:

输入的第一行包含一个正整数N(≤1000),第二行包含N个整数,为给出的整数键值序列,数字间以空格分隔。

输出格式:

输出的第一行首先给出判断结果,如果输入的序列是某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,则输出YES,否侧输出NO。如果判断结果是YES,下一行输出对应二叉树的后序遍历序列。数字间以空格分隔,但行尾不能有多余的空格。

输入样例1

7
8 6 5 7 10 8 11

输出样例1

YES
5 7 6 8 11 10 8

输入样例2

7
8 6 8 5 10 9 11

输出样例2

NO
分析
  1. 首先我们要根据输入的序列建立搜索树,之后对搜索树进行一次前序遍历。
  2. 对前序遍历生成的数组与原数组进行比对,不同则进行镜像变换。完全相同输出YES,然后后序遍历,输出遍历的数组。
  3. 镜像变换后进行前序遍历,如果与原数组不同,则输出NO。相同输出YES,则进行后序遍历,输出遍历的数组。
C++ 代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
int n,num[N],temp[N],idx;
struct node{
    int val;
    node* left;
    node* right;
    node(int x): val(x),left(NULL),right(NULL){} 
};
node* root;
node* insert(node* root,int u)  //插入节点建立搜索树
{
    if(!root) root=new node(u);
    else if(root->val > u) root->left=insert(root->left,u); //当前节点值小于根节点,为左子树
    else root->right=insert(root->right,u);
    return root;
}
bool f1;
void pre(node *root)    //树的前序遍历
{
    if(!root) return ;
    temp[++idx]=root->val;
    pre(root->left);
    pre(root->right);
}
void post(node *root)   //树的后序遍历
{
    if(!root) return ;
    post(root->left);
    post(root->right);      
    temp[++idx]=root->val;  
}
node* mirror(node *root)    //对树进行镜像操作
{
    if(!root) return NULL;
    root->left=mirror(root->left);   //优先对子树进行翻转
    root->right=mirror(root->right);
    auto t=root->left;
    root->left=root->right;
    root->right=t;
    return root;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>num[i];
        root=insert(root,num[i]);   //每输入一个节点值就插到搜索树当中
    }
    pre(root);  //通过前序遍历建立temp[]
    for(int i=1;i<=n;i++)   
    {
        if(num[i]!=temp[i]) f1=1;   //如果前序遍历和输入的数组不同,则要对镜像进行判断
    }
    if(!f1){
        puts("YES");
        idx=0;
        post(root); //后序遍历生成序列
        for(int i=1;i<=n;i++)
        {
            if(i>1) cout<<" ";
            cout<<temp[i];  //输出答案
        }
    }
    else{
        idx=0;
        mirror(root);   //对二叉树进行镜像处理
        pre(root);  //镜像后进行前序遍历,生成temp[]
        for(int i=1;i<=n;i++)   
        {
            if(num[i]!=temp[i]) //和输入的数组不同,说明失败
            {
               puts("NO"); 
               return 0;
            }
        }
        puts("YES");
        idx=0;
        post(root); //后序遍历生成temp[]
        for(int i=1;i<=n;i++)   //输出后序序列
        {
            if(i>1) cout<<" ";
            cout<<temp[i];
        }
    }
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jay_fearless

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

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

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

打赏作者

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

抵扣说明:

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

余额充值