二叉搜索树
题意:给你要判断的个数n,告诉你初始序列,根据这个序列可以构造出一棵二叉搜索树。然后给你n个序列,每个序列格式跟第一个序列一样,请判断这两个序列是否能组成同一棵二叉搜索树。
这个题和The order of a Tree类似,不同的是,本题要求输入为字符串,并且要判断多组数据。同样思路,如果两个序列为同一棵二叉搜索树,那么他们的先序遍历是一样的,因为先序遍历是字典序最小且为相同的树。
举个🌰:如:4 6 5 2 7 1 3
先序:4 2 1 3 6 5 7(同树,字典序最小)
中序:1 2 3 4 5 6 7(不同树)
后序:1 3 2 5 7 6 4(不同树)
层次:4 2 6 1 3 5 7(同树,字典序不最小)
这里发现层次遍历也是可以的,他们都表示同一棵树,这里采取先序遍历。
#include<bits/stdc++.h>
using namespace std;
const int N=20;
int k,m;
char pre[N],PRE[N];
string s;
struct node
{
char value;//结点的值
node *l,*r;//左右结点
};
node * root;
void add(node* &root,int t)//插入
{
//t表示插入的价值
if(root==NULL)
{
root=new node;//新建结点
root->value=t;
root->l=root->r=NULL;
}
else
{
if(t>root->value)
add(root->r,t);
else add(root->l,t);
}
}
void preorder(node * root)//求先序序列
{
if(root!=NULL)
{
pre[k++]=root->value+'0';//输出
preorder(root->l);
preorder(root->r);
}
}
void Preorder(node * root)//求先序序列
{
if(root!=NULL)
{
PRE[m++]=root->value+'0';//输出
Preorder(root->l);
Preorder(root->r);
}
}
void remove_tree(node * root)
{
if(root==NULL)
return;
remove_tree(root->l);
remove_tree(root->r);
delete root;
}
int main()
{
int n;
while(scanf("%d",&n)==1&&n)
{ k=0;//很重要
root=NULL;
cin>>s;
int x=s.length();
for(int i=0; i<x; i++)
{
add(root,s[i]-'0');
}
preorder(root);
pre[k]='\0';//注意,很重要
while(n--)
{ m=0;//很重要
root=NULL;
cin>>s;
int h=s.length();
for(int i=0; i<h; i++)
{
add(root,s[i]-'0');
}
Preorder(root);
PRE[m]='\0';//注意,很重要
if(strcmp(pre,PRE)==0)
cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
return 0;
}
错题总结:
•数组N保留着之前的习惯,开太大了,没注意题目要求,有点浪费。
•一开始总是rumtime error,改了十几遍才发现是因为忘记给k和m赋值为0,导致数组越界。
•然后开始答案错误,明明根测试样例一样一样的,又改了好几遍,然后加了个pre[k]='\0'
和PRE[m]='\0'
就神奇的过了。个人觉得原因是如果样例很多,前一组样例比较长,后一组比较短,就会造成字符数组前面变化后面不变仍是上一组数据,导致答案错误,正确做法是在用完的数组后面一位赋’\0’。