对于二叉搜索树,我们规定任一结点的左子树仅包含严格小于该结点的键值,而其右子树包含大于或等于该结点的键值。如果我们交换每个节点的左子树和右子树,得到的树叫做镜像二叉搜索树。
现在我们给出一个整数键值序列,请编写程序判断该序列是否为某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,如果是,则输出对应二叉树的后序遍历序列。
输入格式:
输入的第一行包含一个正整数N(≤1000),第二行包含N个整数,为给出的整数键值序列,数字间以空格分隔。
输出格式:
输出的第一行首先给出判断结果,如果输入的序列是某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,则输出YES,否侧输出NO。如果判断结果是YES,下一行输出对应二叉树的后序遍历序列。数字间以空格分隔,但行尾不能有多余的空格。
题目思路:
代码稍微长了一点,但是思路还是比较清晰的
#include<iostream>
using namespace std;
typedef struct tree {
int data;
tree* left;
tree* right;
} *BinTree;
BinTree BST(int *pre, int len);
BinTree MirBST(int *pre, int len);
void LRD(BinTree T);
int flag1 = 0;
int flag2 = 0;
int ar[1000], k = 0;
int main()
{
int preorder[1000];
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> preorder[i];
BinTree T1 = BST(preorder, n);
BinTree T2 = MirBST(preorder, n);
if (T1 && flag1 == 0)
{
cout << "YES\n";
LRD(T1);
for (int i = 0; i < n; i++)
{
if (i)cout << " ";
cout << ar[i];
}
}
else if (T2 && flag2 == 0)
{
cout << "YES\n";
LRD(T2);
for (int i = 0; i < n; i++)
{
if (i) cout << " ";
cout << ar[i];
}
}
else
{
cout << "NO\n";
}
return 0;
}
BinTree BST(int *pre, int len)
{
if (len == 0)return NULL;
BinTree T = new tree;
T->data = *pre;
int m;
for ( m = 1; m < len; m++)
if (pre[m] >= T->data) //二叉搜索树右侧大于等于T->data,将m调整到T右子树第一个位置
break;
int n;
for (n = m; n < len; n++)
if (pre[n] < T->data) //如果T的右子树中有节点的值小于T的data
{
flag1 = 1; //该二叉树不是二叉搜索树
return NULL;
}
T->left = BST(pre + 1, m - 1);
T->right = BST(pre + m, len - m);
return T;
}
BinTree MirBST(int *pre, int len)
{
if (len == 0)return NULL;
BinTree T = new tree;
T->data = *pre;
int m;
for (m = 0; m < len; m++) //镜像二叉搜索树右侧严格小于T->data,找到第一个右子树的位置
if (pre[m] < T->data)
break;
int n;
for (n = m; n < len; n++)
if (pre[n] >= T->data) //如果镜像二叉树的右子树有一个大于等于T->data的节点
{
flag2 = 1; //该镜像二叉树不是镜像搜索二叉树
return NULL;
}
T->left = MirBST(pre + 1, m - 1);
T->right = MirBST(pre + m, len - m);
return T;
}
void LRD(BinTree T)
{
if (T)
{
LRD(T->left);
LRD(T->right);
ar[k++] = T->data;
}
}