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

分析
因为前序遍历是根左右,所以在插入某个孩子节点时,它的父节点肯定已经被插入了,又由于搜索树的限制关系(小的左边,大的右边),所以可以确定一棵唯一的二叉搜索树,然后对其进行两种不同的前序遍历,再分别与题目所给的序列比较即可。
代码

//                              _ooOoo_
//                             o8888888o
//                             88" . "88
//                             (| -_- |)
//                              O\ = /O
//                           ____/`---'\____
//                        .   ' \| |// `.
//                         / \||| : |||// \
//                        / _||||| -:- |||||- \
//                         | | \\ - /// | |
//                       | \_| ''\---/'' | |
//                        \ .-\__ `-` ___/-. /
//                    ___`. .' /--.--\ `. . __
//                  ."" '< `.___\_<|>_/___.' >'"".
//                 | | : `- \`.;`\ _ /`;.`/ - ` : | |
//                    \ \ `-. \_ __\ /__ _/ .-` / /
//           ======`-.____`-.___\_____/___.-`____.-'======
//                              `=---='
//
//           .............................................
//                   佛祖保佑     一发AC     永无BUG
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 1e3 + 10;
const int inf = 0x3f3f3f3f;
const double PI = acos(-1.0);
typedef pair<int, int> PII;
struct node {
    node *l, *r;
    int data;
};
//s1为正常前序遍历,s2为左右儿子颠倒的前序遍历,s为输入序列
int s1[maxn], s2[maxn], s[maxn], n, cnt;
vector<int> ans;
node *build(node *root, int x) {
    if (root == NULL) {
        //到达最底部,创建新节点,并赋值
        root = new node;
        root->l = root->r = NULL;
        root->data = x;
    } else if (x < root->data) {
        //x小于当前节点,说明x在root的左半边,向左递归
        root->l = build(root->l, x);
    } else {
        root->r = build(root->r, x);
    }
    return root;
}
//正常前序遍历
void qian1(node *root) {
    if (root == NULL) return;
    s1[cnt++] = root->data;
    qian1(root->l);
    qian1(root->r);
}
//左右颠倒的前序
void qian2(node *root) {
    if (root == NULL) return;
    s2[cnt++] = root->data;
    qian2(root->r);
    qian2(root->l);
}
//正常后序
void hou1(node *root) {
    if (root == NULL) return;
    hou1(root->l);
    hou1(root->r);
    ans.push_back(root->data);
}
//左右颠倒的后序
void hou2(node *root) {
    if (root == NULL) return;
    hou2(root->r);
    hou2(root->l);
    ans.push_back(root->data);
}
//比较两个序列是否完全相同
bool judge(int *a) {
    for (int i = 0; i < n; i++) {
        if (a[i] != s[i]) return 0;
    }
    return 1;
}
int main(int argc, char const *argv[]) {
    cin >> n;
    for (int i = 0; i < n; i++) cin >> s[i];
    node *root = NULL;
    for (int i = 0; i < n; i++) {
        root = build(root, s[i]);
    }
    qian1(root);
    cnt = 0;
    qian2(root);
    if (judge(s1)) {//说明所给序列是二叉搜索树的前序遍历
        hou1(root);
        puts("YES");
        for (int i = 0; i < n; i++)
            printf("%d%c", ans[i], i == n - 1 ? '\n' : ' ');
    } else if (judge(s2)) {//是镜像的前序遍历
        puts("YES");
        hou2(root);
        for (int i = 0; i < n; i++)
            printf("%d%c", ans[i], i == n - 1 ? '\n' : ' ');
    } else {//不是二叉搜索树输出-1
        puts("NO");
    }
    return 0;
}
暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇