7-28 搜索树判断 (25 分) 数据结构与算法题目集(中文)

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

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

输入格式:

输入的第一行包含一个正整数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

判断给出的前序遍历是否正确的,由于可能是镜像的前序遍历,首先判断左子树结点和根的大小关系,如果是小于根那就可能是正常树,否则可能是镜像,用flag标记,然后判断是否正确,即左子树右子树和根的大小关系始终保持一致,这里用疑惑来判断条件的一致性。正确的话需要根据给出的树进行后序遍历,由于对于给出的前序遍历我们能够分清他的根左子树和右子树,所以直接进行后续遍历。
代码:
#include <stdio.h>
#include <string.h>
int n,pre[1000],flag,li[1000];
int check(int l,int r) {
    if(l >= r) return 1;
    int ll = l + 1,rr = r;
    while(ll <= r && (pre[ll] < pre[l]) ^ flag) ll ++;
    while(rr > l && (pre[rr] >= pre[l]) ^ flag) rr --;
    if(ll - rr != 1) return 0;
    li[l] = rr;
    return check(l + 1,rr) && check(ll,r);
}
void post(int l,int r) {
    if(l > r) return;
    if(li[l] != -1) {
        post(l + 1,li[l]);
        post(li[l] + 1,r);
    }
    if(l) printf("%d ",pre[l]);
    else printf("%d",pre[l]);
}
int main() {
    scanf("%d",&n);
    memset(li,-1,sizeof(li));
    for(int i = 0;i < n;i ++) {
        scanf("%d",&pre[i]);
    }
    if(n > 1 && pre[0] <= pre[1]) flag = 1;
    if(!check(0,n - 1)) printf("NO\n");
    else {
        printf("YES\n");
        post(0,n - 1);
    }
}

猜你喜欢

转载自www.cnblogs.com/8023spz/p/11909186.html