搜索树判断

该博客主要介绍了如何判断给定的整数序列是否为二叉搜索树或镜像二叉搜索树的前序遍历,并在确认后输出对应的后序遍历序列。作者分享了三种不同的解题思路,包括直接建树比对、数组建树判断和递归盘点。在经过一系列尝试和错误后,作者最终给出了正确解决方案,并提供了自我测试的数据集。

题目描述:

对于二叉搜索树,我们规定任一结点的左子树仅包含严格小于该结点的键值,而其右子树包含大于或等于该结点的键值。如果我们交换每个节点的左子树和右子树,得到的树叫做镜像二叉搜索树。
现在我们给出一个整数键值序列,请编写程序判断该序列是否为某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,如果是,则输出对应二叉树的后序遍历序列。
输入的第一行包含一个正整数N(≤1000),第二行包含N个整数,为给出的整数键值序列,数字间以空格分隔。
输出的第一行首先给出判断结果,如果输入的序列是某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,则输出YES,否侧输出NO。如果判断结果是YES,下一行输出对应二叉树的后序遍历序列。数字间以空格分隔,但行尾不能有多余的空格。

具体代码

#include <stdio.h>
#include <stdlib.h>
#define N 1003
typedef struct node * tree;//定义指向结点的指针
struct node
{
    tree left,right;
    int data;
};
int index;//用于输出的数组的游标
tree creat(tree root,int data)
{
    if(root)
    {
        if(root->data > data)//题目数据要求为严格小于
            root->left = creat(root->left,data);
        else
            root->right = creat(root->right,data);
    }
    else
    {
        root = (tree)malloc(sizeof(struct node));
        root->data = data;
        root->left = root->right= NULL;
    }
    return root;
}
//后序遍历 将东西放到输出数组中去
void postOrder(tree root,int output[])
{
    if(root)
    {
        postOrder(root->left,output);
        postOrder(root->right,output);
        output[index++] = root->data;
    }
}
//先序遍历将数据放入输出数组
void preOrder(tree root,int output[])
{
    if(root)
    {
        output[index++] = root->data;
        preOrder(root->left,output);
        preOrder(root->right,output);
    }
}
//交换树的左右孩子
void swap(tree root)
{
    if(root)
    {
        tree temp = root->left;
        root->left = root->right;
        root->right = temp;
        swap(root->left);
        swap(root->right);
    }
}
int main ()
{
    int n;//结点总数n
    int i,data,j;//两个循环变量与读取数据的变量
    int f,flag,mirror_flag;//判断是何种情况的标志变量
    tree root = NULL;//建树的根
    int output[N],input[N];//输入输出数组
//赋值
    f = flag = mirror_flag = 1;
    index = 0;
    //读取数据
    scanf("%d",&n);
    for(i = 0; i < n; i++)
    {
        scanf("%d",&data);
        input[i] = data;//放入输入数组便于后续比较
        root = creat(root,data);
    }
    //先判断是不是正常的二叉树
    index = 0;
    preOrder(root,output);
    for(i = 0; i < n; i++)
        if(output[i] != input[i])
            flag = 0;
            //再判断是不是镜像二叉搜索树
    index = 0;
    swap(root);
    preOrder(root,output);
    for(i = 0; i < n; i++)
        if(output[i] != input[i])
            mirror_flag = 0;
    index = 0;
    if(mirror_flag)//如果是镜像的已经交换过了 所以直接后序即可
    {
        printf("YES\n");
        postOrder(root,output);
        for(i = 0; i < index; i++)
        {
            if(f)
                f = 0;
            else
                printf(" ");
            printf("%d",output[i]);
        }
    }
    else if(flag)//正常的 需要先交换一次
    {
        printf("YES\n");
        swap(root);
        postOrder(root,output);
        for(i = 0; i < index; i++)
        {
            if(f)
                f = 0;
            else
                printf(" ");
            printf("%d",output[i]);
        }
    }
    else
        printf("NO\n");
    return 0;
}


这题最开始就想复杂了
把简单的问题想得太复杂不好
苍天啊,请给我一双明辨是非的眼睛吧
整体其实可采取的思路多种
整体程序需要做的事情不过以下几种
1.建树
2.判断树是二叉树还是镜像二叉树
3.根据输入序列判断这序列无法建树

当时就把时间耗在建树那里了
以及怎么使用二叉树这个条件
走了不少弯路,当时是打算利用顺序存储去读取,但是后来幡然醒悟,这样更加没利用上条件,还把问题搞复杂了,但是这时脑袋被限制思维了,所以就没选择死写代码,而是选择去看看别人的代码。主体看的就是两块第一块 建树 第二块 怎么判断NO。
看了一圈,大致的解题思路分三种。
第一种是直接读取数据,按正常建二叉树的方式建,通过比对建的二叉树的先序遍历的结果与输入是否一致,达到对各种情况的判定。第一种
第二种是读取数据后,将这些数据放入数组,然后递归的建树,边建树边判断,最后再按一定顺序输出。第二种
第三种是按正常程序建,然后递归的盘点左右子树。第三种,这篇文章写得特别详细 这题写到各种程度都可以看看

后来就针对一种思路明确的,模块之间联系不大的代码进行了较大的改善得到了我现在代码的雏形
然后就把输出板块写好
最后就是去判断是镜像还是不是镜像这个玩意
这个被一种特殊情况坑了 由于我只判断与根节点的大小 没有管其他元素之间的 才导致了这些错误
pta虽然说给出了你的提示 但是没有给测试数据 而且那个提示我总感觉读起来不通顺 特别怪
先给出我自己用于自己代码测试的机组数据
7
8 6 5 7 10 8 11
YES
5 7 6 8 11 10 8
7
8 10 11 8 6 7 5
YES
11 8 10 7 5 6 8
7
8 6 5 7 10 11 8
NO
7
8 6 8 5 10 9 11
NO
*/
2022/1/16 又一次写到了这个题目。本想直接把之前的代码提交。发现之前的代码写的是个错的,连我自己给出的测试点都没过。只好再次进行更改。目前的代码是正确的。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值