题意分析:
(1)给出一数列,判断这个数列是否是一个二叉查找树的先序遍历序列或镜像二叉查找树的先序遍历序列,所谓镜像二叉查找树就是二叉查找树所有节点的左右子树交换后的二叉树
(2)二叉查找树有一个特性就是根节点左边所有子树节点的值小于根节点的值,右子树所有节点的值大于或等于根节点的值,同时左右子树也是一颗二叉查找树
(3)由(2)的递归的性质:于是判断这个序列是否是BST或者镜像BST先序遍历序列也是递归实现的:若是BST,首先根节点i肯定是第一个数,假设之后从i+1到j的连续项是小于num[i]的,按照定义,这是左子树,从第j+1项起,后面所有项是右子树,若存在小于num[i]的项,则这一定不是BST的先序遍历序列。然后递归判断下去。
(4)接下来就是要根据有规律的先序序列来构造后序序列,策略依然是递归构造。这里有两种思路:一种是根据这种BST性质和先序序列去构造二叉树,然后再后序遍历这颗二叉树。但是很遗憾,这样做会导致段错误,是因为数据量过大时建树会造成溢出,代码如下:
void buildTree(TreeNode *&root,int num[],int start,int end,bool flag)
{
root=(TreeNode*)malloc(sizeof(TreeNode));
if(start==end)
{
root->value=num[start];
root->lchild=NULL;
root->rchild=NULL;
return;
}
if(start>end)root=NULL;
int lr,rl;
if(flag)
{
for(lr=start+1;lr<=end&&num[lr]<num[start];lr++);
for(rl=lr;rl<=end;rl++)
{
if(num[rl]<num[start])return;
}
}
else
{
for(lr=start+1;lr<=end&&num[lr]>=num[start];lr++);
for(rl=lr;rl<=end;rl++)
{
if(num[rl]>=num[start])return;
}
}
root->value=num[start];
buildTree(root->lchild,num,start+1,lr-1,flag);
buildTree(root->rchild,num,lr,end,flag);
}
另外一种思路就是直接使用递归打印:因为左右子树的边界很容易确定,因此先访问左子树,再访问右子树,再访问根节点。
(5)最后需要注意的是:要区分是BST还是镜像BST,很简单,直接判断num[0]和num[1]的大小,然后设置flag来标识这是按什么顺序来作为参数传入,这样就避免相同代码的冗余
可能坑点:
(1)不要建树,否则会因为存储过大导致段错误
(2)要区分BST和镜像BST
#include <iostream>
#include <stdlib.h>
using namespace std;
int num[1001];
bool checkBST(int num[],int start,int end,bool flag)
{
if(start>=end)return true;
int lr,rl;
if(flag)
{
for(lr=start+1;lr<=end&&num[lr]<num[start];lr++);
for(rl=lr;rl<=end;rl++)
{
if(num[rl]<num[start])return false;
}
}
else
{
for(lr=start+1;lr<=end&&num[lr]>=num[start];lr++);
for(rl=lr;rl<=end;rl++)
{
if(num[rl]>=num[start])return false;
}
}
if(checkBST(num,start+1,lr-1,flag)&&checkBST(num,lr,end,flag))
{
return true;
}
}
int first=1;
void postOrder(int num[],int start,int end,bool flag)
{
if(start>end)return;
int lr,rl;
if(flag)
{
for(lr=start+1;lr<=end&&num[lr]<num[start];lr++);
for(rl=lr;rl<=end;rl++)
{
if(num[rl]<num[start])return;
}
}
else
{
for(lr=start+1;lr<=end&&num[lr]>=num[start];lr++);
for(rl=lr;rl<=end;rl++)
{
if(num[rl]>=num[start])return;
}
}
postOrder(num,start+1,lr-1,flag);
postOrder(num,lr,end,flag);
if(first)first=0;
else cout<<" ";
cout<<num[start];
}
int main()
{
int N,i=0;
cin>>N;
while(i<N)cin>>num[i++];
bool flag=(num[1]<num[0]?1:0);
if(checkBST(num,0,N-1,flag))
{
cout<<"YES"<<endl;
postOrder(num,0,N-1,flag);
}
else cout<<"NO"<<endl;
return 0;
}