您的位置:首页 > 其它

L2-004. 这是二叉搜索树吗?

2016-07-10 22:23 344 查看
题目链接是:

https://www.patest.cn/contests/gplt/L2-004

题解:

根节点的值是位于左右子树之间的,即大于左子树的所有值,但是小于等于右子树的所有值。

而先序遍历的序列,第一个值就是其根的值,我们可以利用这些性质来递归判断一棵树是否为二叉搜索树。

首先,遍历这个序列,找到第一个大于等于根节点值的节点,如果从这个节点开始之后的所有节点的值都是大于等于根节点的,那么这

棵树就是二叉搜索树。而二叉搜索树的“镜像”也可以利用这种思想进行判断。

如果是一棵二叉搜索树或者是其镜像,我们就可以开始建树,建树之后可以递归的输出其后序遍历序列。

代码及注释:

#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

const int maxn = 1000+10;

struct Node
{
int value;
Node *lson, *rson;
Node():lson(NULL),rson(NULL){}
}*root;

int n;
int s[maxn];
vector<int> ans; //按序记录后序遍历的元素,因为在后序遍历输出时不能控制最后的空格

//判断 kind为true判断原树,为false判断镜像
bool test(bool kind, int L, int R)
{
if(L >= R)
return true;
int i;
for(i = L+1; i <= R; i++)
{
if(kind)
{
if(s[L] <= s[i])
break;      //到 i-1 为止为左子树
}
else
{
if(s[L] > s[i])
break;
}
}
bool flag = true;
for(int j = i; j <= R; j++)
{
if(kind)
{
if(s[j] < s[L])
flag = false;  //若右子树有小于根结点值的直接返回 false
}
else
{
if(s[j] >= s[L])
flag = false;
}

}
if(flag)
return test(kind, L+1, i-1) && test(kind, i, R); //一直递归分治下去

else
return false;
}

Node* create(bool kind, int L, int R)
{
if(L > R)
return NULL;
int i;
for(i = L+1; i <= R; i++)
{
if(kind)
{
if(s[L] <= s[i])
break;   //到i-1为止为左子树
}
else
{
if(s[L] > s[i])
break;
}
}
Node *p = new Node();
p->value = s[L];
p->lson = create(kind, L+1, i-1); //递归建立左子树
p->rson = create(kind, i, R);  //递归建立右子树

return p;
}

void postOrderTraverse(Node *p)
{
if(p)
{
postOrderTraverse(p->lson);
postOrderTraverse(p->rson);
ans.push_back(p->value);
}
}

void Print()
{
postOrderTraverse(root);
int len = ans.size();
for(int i = 0; i < len-1; i++)
printf("%d ", ans[i]);
printf("%d\n", ans[len-1]);
}
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%d", &s[i]);

int flag = 0;
if(test(true, 0, n-1))
{
flag = 1;
root = create(true, 0, n-1);
}
else if(test(false, 0, n-1))
{
flag = 2;
root = create(false, 0, n-1);
}
if(flag != 0)
{
puts("YES");
Print();
}
else
puts("NO");

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