3 搜索树判断 (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:
//若是二叉树的先序遍历,则可以完全恢复原二叉搜索树
#include <iostream>
#include <malloc.h>
using namespace std;
struct Node
{
int data;
struct Node *lchild;
struct Node *rchild;
};
bool flag = true; //控制最后不打印空格
bool flag1 = true; //是否为二叉搜索树的标志
bool flag2 = true; //是否为二叉镜像搜索树的标志
//检查是否为二叉搜索树,若是则生成相应的二叉树
Node *IsBinSearchTree(int num[], int n)
{
if (!n)
return nullptr;
int i; //保存右子树第一个数的下标
Node *temp = (Node *)malloc(sizeof(struct Node));
temp->data = num[0];
for (i = 1; i < n; i++)
{ //寻找右子树
if (num[0] <= num[i])
break;
}
for (int j = i; j < n; j++)
{
if (num[0] > num[j])
{
flag1 = false;
return nullptr;
}
}
temp->lchild = IsBinSearchTree(num + 1, i - 1); //生成左子树
temp->rchild = IsBinSearchTree(num + i, n - i); //生成右子树
return temp;
}
Node *IsBinMirror(int num[], int n)
{
if (!n)
return nullptr;
int i; //保存右子树第一个数的下标
Node *temp = (Node *)malloc(sizeof(struct Node));
temp->data = num[0];
for (i = 1; i < n; i++)
{ //寻找右子树
if (num[0] > num[i])
break;
}
for (int j = i; j < n; j++)
{
if (num[0] <= num[j])
{
flag2 = false;
return nullptr;
}
}
temp->lchild = IsBinMirror(num + 1, i - 1);
temp->rchild = IsBinMirror(num + i, n - i);
return temp;
}
//后序打印输出树
void printTree(Node *tree)
{
if (tree)
{ //存在空指针,当出现空指针时不打印
printTree(tree->lchild);
printTree(tree->rchild);
if (flag)
flag = false;
else
cout << ' ';
cout << tree->data;
}
}
int main()
{
int n;
cin >> n;
int num[1005];
for (int i = 0; i < n; i++)
cin >> num[i];
Node *tree1, *tree2;
tree1 = IsBinSearchTree(num, n);
tree2 = IsBinMirror(num, n);
if (flag1 && tree1)
{
cout << "YES\n";
printTree(tree1);
cout << endl;
}
else if (flag2 && tree2)
{
cout << "YES\n";
printTree(tree2);
cout << endl;
}
else
cout << "NO\n";
return 0;
}
代码2:
/*
分析:假设它是二叉搜索树,一开始isMirror为FALSE,根据二叉搜索树的性质将已知的前序转换为后序,转换过程中,如果发现最后输出的后序数组长度不为n,那就设isMirror为true,然后清空后序数组,重新再转换一次(根据镜面二叉搜索树的性质),如果依旧转换后数组大小不等于n,就输出NO否则输出YES
*/
#include <cstdio>
#include <vector>
using namespace std;
bool isMirror;
vector<int> pre;
vector<int> post;
void getpost(int root, int tail)
{
if (root > tail)
return;
int i = root + 1, j = tail;
if (!isMirror)
{
while (i <= tail && pre[root] > pre[i])
i++;
while (j > root && pre[root] <= pre[j])
j--;
}
else
{
while (i <= tail && pre[root] <= pre[i])
i++;
while (j > root && pre[root] > pre[j])
j--;
}
if (i - j != 1)
return;
getpost(root + 1, j);
getpost(i, tail);
post.push_back(pre[root]);
}
int main()
{
int n;
scanf("%d", &n);
pre.resize(n);
for (int i = 0; i < n; i++)
scanf("%d", &pre[i]);
getpost(0, n - 1);
if (post.size() != n)
{
isMirror = true;
post.clear();
getpost(0, n - 1);
}
if (post.size() == n)
{
printf("YES\n%d", post[0]);
for (int i = 1; i < n; i++)
printf(" %d", post[i]);
}
else
{
printf("NO");
}
return 0;
}