您的位置:首页 > 其它

PAT (Advanced Level) 1043. Is It a Binary Search Tree (25) 判断序列是否为BST的先序遍历,递归

2015-07-25 14:27 591 查看
A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:

The left subtree of a node contains only nodes with keys less than the node's key.

The right subtree of a node contains only nodes with keys greater than or equal to the node's key.

Both the left and right subtrees must also be binary search trees.

If we swap the left and right subtrees of every node, then the resulting tree is called the Mirror Image of a BST.

Now given a sequence of integer keys, you are supposed to tell if it is the preorder traversal sequence of a BST or the mirror image of a BST.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (<=1000). Then N integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, first print in a line "YES" if the sequence is the preorder traversal sequence of a BST or the mirror image of a BST, or "NO" if not. Then if the answer is "YES", print in the next line the postorder traversal sequence of that tree. All
the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.
Sample Input 1:
7
8 6 5 7 10 8 11

Sample Output 1:
YES
5 7 6 8 11 10 8

Sample Input 2:
7
8 10 11 8 6 7 5

Sample Output 2:
YES
11 8 10 7 5 6 8

Sample Input 3:
7
8 6 8 5 10 9 11

Sample Output 3:
NO

没必要建树,使用递归写即可,看能否按给定元素顺序用完所有元素建立起BST或BST的镜像。按照根、右、左的顺序处理,这样逆序输出结果就是左、右、根的后序遍历。

以序列本身为BST先根遍历为例,如下面的函数f1,用vector<int> &result存储结果。序列第一个元素为根,然后是都比根小的左子树的元素,最后是都比根大的右子树的元素,若能把所有元素用完,返回true。递归时先将根节点元素压入结果数组,对右子树进行递归,再对左子树递归,途中若发现一个子树返回false,说明不能把元素用完,直接输出NO,结束程序。若所有递归函数返回true,说明用完了所有元素,逆序输出result即为左、右、根的后序遍历。

检测序列为BST镜像的先序遍历,如下面的函数f2,代码与f1几乎一样,只有左右子树元素在与根结点比较大小时与f1相反。

/*2015.7.25cyq*/
#include <iostream>
#include <vector>
using namespace std;

vector<int> data;

//检测序列是不是BST,当不能把begin到end之间的所有元素用完,返回false
//按照根、右、左的顺序进行处理,这样只要把结果逆序输出就是后序遍历
bool f1(const vector<int> &a,int begin,int end,vector<int> &result){
if(begin>end)//说明该子树不存在,直接返回
return true;
result.push_back(a[begin]);
if(begin==end)
return true;
int mid=begin+1;
while(mid<=end&&a[begin]>a[mid])//a[mid]为第一个不比a[begin]小的
mid++;
if(mid==end+1){//无右子树,直接检测左子树能不能用完元素
if(!f1(a,begin+1,end,result))
return false;
}else{//a[mid]及之后都应该大于等于a[begin]
int right=mid;
while(right<=end&&a[begin]<=a[right])
right++;
if(right<=end)//检查出右子树存在比a[begin]小的
return false;
else{
if(!f1(a,mid,end,result))//先处理右子树
return false;
if(!f1(a,begin+1,mid-1,result))
return false;
return true;
}
}

}
//检测镜像是不是BST,代码跟f1类似,只有与a[begin]比较大小的时候相反,同样按照根、右、左进行处理
bool f2(const vector<int> &a,int begin,int end,vector<int> &result){
if(begin>end)
return true;
result.push_back(a[begin]);
if(begin==end)
return true;
int mid=begin+1;
while(mid<=end&&a[begin]<=a[mid])
mid++;
if(mid==end+1){//无右子树
if(!f2(a,begin+1,end,result))
return false;
}else{//a[mid]及之后都应该小于a[begin]
int right=mid;
while(right<=end&&a[begin]>a[right])
right++;
if(right<=end)//检查出右子树存在比a[begin]大的
return false;
else{
if(!f2(a,mid,end,result))//先处理右子树
return false;
if(!f2(a,begin+1,mid-1,result))
return false;
return true;
}
}

}
int main(){
int N;
cin>>N;
int x;
for(int i=0;i<N;i++){
cin>>x;
data.push_back(x);
}
if(N==1){
cout<<"YES"<<endl;
cout<<data[0]<<endl;
return 0;
}

vector<int> result;
if(data[0]>data[1]){
if(f1(data,0,N-1,result)){//序列是BST,逆序输出result
cout<<"YES"<<endl;
cout<<result[N-1];
for(int i=N-2;i>=0;i--)
cout<<" "<<result[i];
}else
cout<<"NO";
}else{
if(f2(data,0,N-1,result)){//镜像是BST,逆序输出result
cout<<"YES"<<endl;
cout<<result[N-1];
for(int i=N-2;i>=0;i--)
cout<<" "<<result[i];
}else
cout<<"NO";
}
return 0;
}


[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: