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
刚开始没搞懂这题这么回事,给出一个序列,还要判断是不是一个搜索树的先序遍历。
后来想明白了,要是先序遍历序列,按照顺序插入搜索树就可以构成一颗搜索树,然后再输出前序和所给对比。
镜像搜索树有个特点:
1.镜像后序序列的倒序与正常先序序列相同
2.正常后序序列的倒序与镜像先序序列相同
AC代码:
#include<stdio.h>
typedef struct node {
int data;
struct node *lchild, *rchild;
}Node, *Tree;
void insert(Tree &root,int x) {
if (root == NULL) {
root = new Node;
root->lchild = root->rchild = NULL;
root->data = x;
} else if (x < root->data) {
insert(root->lchild, x);
} else {
insert(root->rchild, x);
}
}
Tree create(int n,int buf[]) {
Tree root = NULL;
for (int i = 1; i <= n; i++) {
scanf("%d", &buf[i]);
insert(root, buf[i]);
}
return root;
}
void preorder(Tree root,int pre[],int &i) {
if (root == NULL)return;
pre[i++] = root->data;
preorder(root->lchild, pre, i);
preorder(root->rchild, pre, i);
}
void posorder(Tree root, int pos[], int &i) {
if (root == NULL)return;
posorder(root->lchild, pos, i);
posorder(root->rchild, pos, i);
pos[i++] = root->data;
}
bool issma(int a[], int b[], int n,bool rvs) {
for (int i = 1; i <= n; i++) {
if (rvs) {
int j = n - i + 1;
if (a[i] != b[j])return false;
} else {
if (a[i] != b[i])return false;
}
}
return true;
}
void show(int order[], int n, bool rvs) {
bool first = true;
for (int i = 1; i <= n; i++) {
if (first)
first = false;
else
printf(" ");
if (rvs) {
int j = n + 1 - i;
printf("%d", order[j]);
} else {
printf("%d", order[i]);
}
}
}
int main() {
int n;
scanf("%d", &n);
int buf[1001], pre[1001], pos[1001];
Tree root;
root = create(n, buf);
int i = 1, j = 1;
preorder(root, pre, i);//先序遍历
posorder(root, pos, j);//后序遍历
//通过观察有以下规律:规律1.镜像后序遍历的倒序与正常先序相同;规律2.正常后序的倒序与镜像先序相同
if (issma(buf, pre, n,false)) {//先序遍历与所给序列一致
printf("YES\n");
show(pos, n, false);
} else if(issma(buf, pos, n, true)){//若是镜像二叉树,则所给序列是该序列对应二叉树后序遍历的倒序(规律2)
printf("YES\n");
show(pre, n, true);//镜像的后序就为正常先序的倒序(规律1)
} else {
printf("NO\n");
}
}
这代码量算比较少得了,没想到一次就AC了。