L2-004 这是二叉搜索树吗? (25 分)
题目
一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,
- 其左子树中所有结点的键值小于该结点的键值;
- 其右子树中所有结点的键值大于等于该结点的键值;
- 其左右子树都是二叉搜索树。
所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。
给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。
输入格式:
输入的第一行给出正整数 N(≤1000)。随后一行给出 N 个整数键值,其间以空格分隔。
输出格式:
如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出 YES
,然后在下一行输出该树后序遍历的结果。数字间有 1 个空格,一行的首尾不得有多余空格。若答案是否,则输出 NO
。
输入样例 1:
7
8 6 5 7 10 8 11
输出样例 1:
YES
5 7 6 8 11 10 8
输入样例 2:
7
8 10 11 8 6 7 5
输出样例 2:
YES
11 8 10 7 5 6 8
输入样例 3:
7
8 6 8 5 10 9 11
输出样例 3:
NO
思路
因为给定的是前序遍历的序列,所以可以直接根据给定序列构造二叉树(根节点肯定是没问题的,不会出现因为根节点选择不同而导致树不同)。构造完成再前序遍历一遍看是不是和原数组一样,若一样则YES,若不一样再去判断其镜像树的前序遍历是否和原数组一样,若一样则YES,若都不一样输出NO。前序遍历、后序遍历的构造方法在这里不详述(学过数据结构应该都明白)。
代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e4 + 19;
const ll mod = 1e9 + 7;
queue<int> que;
int a[N];
struct node //二叉树基本构造
{
node* lson = nullptr;
node* rson = nullptr;
int data;
node() {}
node(int d)
{
data = d;
}
}*head;
void push_down(int data) //插入节点
{
if(head == nullptr)
{
head = new node(data);
return ;
}
node* ptr = head;
node* pre = nullptr;
while(ptr)
{
pre = ptr;
if(ptr->data > data)
{
ptr = ptr->lson;
}
else
{
ptr = ptr->rson;
}
}
ptr = new node(data);
if(pre->data > data)
{
pre->lson = ptr;
}
else
{
pre->rson = ptr;
}
}
void rev(node* ptr) //镜像翻转
{
if(ptr == nullptr)
return;
//翻转左右子树
rev(ptr->lson);
rev(ptr->rson);
//反转自身
node* tmp = ptr->lson;
ptr->lson = ptr->rson;
ptr->rson = tmp;
}
void preShow(node* ptr) //前序遍历并存入队列
{
if(ptr == nullptr)
return ;
que.push(ptr->data);
preShow(ptr->lson);
preShow(ptr->rson);
}
void postShow(node* ptr) //后序遍历并存入队列
{
if(ptr == nullptr)
return ;
postShow(ptr->lson);
postShow(ptr->rson);
que.push(ptr->data);
}
bool isSame() //判断队列是否与数组元素一致并清空队列
{
bool flag = 1;
for(int i = 0; !que.empty(); i++)
{
if(que.front() != a[i])
{
flag = 0; //不break是因为要清空队列
}
que.pop();
}
return flag;
}
int main()
{
int n;
cin >> n;
for(int i = 0; i < n; i++)
{
cin >> a[i];
push_down(a[i]);
}
//判断前序遍历是否与给定相同
preShow(head);
if(isSame())
{
cout << "YES" << endl;
postShow(head);
while(!que.empty())
{
cout << que.front();
que.pop();
if(que.size())
cout << ' ';
}
cout << endl;
return 0;
}
//镜像反转再判断一遍
rev(head);
preShow(head);
if(isSame())
{
cout << "YES" << endl;
postShow(head);
while(!que.empty())
{
cout << que.front();
que.pop();
if(que.size())
cout << ' ';
}
cout << endl;
return 0;
}
//都不行就NO
cout << "NO" << endl;
return 0;
}