L2-004 这是二叉搜索树吗? (25 分)

一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,

  • 其左子树中所有结点的键值小于该结点的键值;
  • 其右子树中所有结点的键值大于等于该结点的键值;
  • 其左右子树都是二叉搜索树。

所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。

给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。

输入格式:

输入的第一行给出正整数 N(≤1000)。随后一行给出 N 个整数键值,其间以空格分隔。

输出格式:

如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出 YES ,然后在下一行输出该树后序遍历的结果。数字间有 1 个空格,一行的首尾不得有多余空格。若答案是否,则输出 NO

输入样例 1:

7
8 6 5 7 10 8 11

输出样例 1:

YES
5 7 6 8 11 10 8

输入样例 2:

7
8 10 11 8 6 7 5

输出样例 2:

YES
11 8 10 7 5 6 8

输入样例 3:

7
8 6 8 5 10 9 11

输出样例 3:

NO

做法: 

按给定的先序序列建立二叉搜索树,然后对建立的二叉搜索树和镜像的二叉树先序遍历,将遍历后的序列与给定的序列比对,若有一个序列比对成功就返回YES。

本题关键是要清楚若给定的先序序列合法,则按给定的先序序列建立的二叉搜索树的先序序列与给定序列相等

代码:

#include <iostream>

using namespace std;

typedef struct tNode * tree;

const int N = 1010;

struct tNode{
    int val;
    tree left, right;
    tNode(int val){this->val = val, left = right = NULL;}
};

int n, a[N], b[N], cnt;

void insert(tree t, int val){
    if(val < t->val){
        if(t->left) insert(t->left, val);
        else t->left = new tNode(val);
    }
    else{
        if(t->right) insert(t->right, val);
        else t->right = new tNode(val);
    }
}

void toMirror(tree t){//镜像
    if(!t) return ;
    tree temp = t->left;
    t->left = t->right;
    t->right = temp;
    toMirror(t->left);
    toMirror(t->right);
}

void pre(tree t){//先序
    if(!t) return;
    b[cnt ++] = t->val;
    pre(t->left);
    pre(t->right);
}

void post(tree t){//后序
    if(!t) return;
    post(t->left);
    post(t->right);
    b[cnt ++] = t->val;
}

int main(){
    cin >> n;
    for(int i = 0; i < n; i ++) cin >> a[i];
    tree root = new tNode(a[0]);
    for(int i = 1; i < n; i ++) insert(root, a[i]);

    pre(root);
    bool flag = true;
    for(int i = 0; i < n; i ++) if(a[i] != b[i]) flag = false;

    if(!flag){
        toMirror(root);
        cnt = 0;
        pre(root);
        flag = true;
        for(int i = 0; i < n; i ++) if(a[i] != b[i]) flag = false;
    }

    if(flag) {
        cout << "YES" << endl;
        cnt = 0;
        post(root);
        for(int i = 0; i < n; i ++){
            if(i != 0) cout << " ";
            cout << b[i];
        }
    }
    else cout << "NO" << endl;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值