L3-016 二叉搜索树的结构 (30 分)
目录
【分析】
一开始建树做,想把它转换成完全二叉树,但是N=100的话,肯定数组是存不下的,所以导致最后一个测试点过不了段错误,只有27分..
数组开大点就可以了...数据比较水
代码1(段错误 数组开小了..开大一点能过)
#include<bits/stdc++.h>
using namespace std;
typedef struct node{
struct node *lchild,*rchild;
int val;
}node,*tree;
const int maxn=1e6+10;
int lv[maxn];
map<int,int>dep;
int n,cnt,cur,max_deep;
void insert(tree &T,int x,int deep)
{
if(T==NULL)
{
T=new node();
T->val=x;
dep[x]=deep;
max_deep=max(max_deep,deep);
T->lchild=T->rchild=NULL;
return;
}
if(x<T->val)insert(T->lchild,x,deep+1);
else if(x>T->val)insert(T->rchild,x,deep+1);
}
void getLevel(tree &T)
{
if(T==NULL)return;
queue<tree>q;
q.push(T);
while(!q.empty())
{
tree t=q.front();
q.pop();
lv[cur++]=t->val;
if(t->lchild!=NULL)q.push(t->lchild);
else {t->lchild=new node();t->lchild->val=-1;q.push(t->lchild);}
if(t->rchild!=NULL)q.push(t->rchild);
else {t->rchild=new node();t->rchild->val=-1;q.push(t->rchild);}
if(cur>pow(2,max_deep+1))break;
}
}
int main()
{
tree T=NULL;
scanf("%d",&n);
for(int i=0;i<n;++i)
{
int x;scanf("%d",&x);
insert(T,x,0);
}
//cout<<"max_deep="<<max_deep<<endl;
memset(lv,-1,sizeof(lv));
getLevel(T);
int q;scanf("%d",&q);
getchar();
while(q--)
{
string s;getline(cin,s);
int x,y,f=0;
if(s.find("root")!=string::npos)
{
sscanf(s.c_str(),"%d is the root",&x);
if(dep.count(x) && x==lv[0])puts("Yes");
else puts("No");
}
if(s.find("siblings")!=string::npos)
{
sscanf(s.c_str(),"%d and %d are siblings",&x,&y);
if(dep.count(x) && dep.count(y))
{
for(int i=0;i<cur;++i)
if((lv[i]==x && lv[i+1]==y)||(lv[i]==y && lv[i+1]==x))
{
puts("Yes");f=1;
break;
}
}
if(!f) puts("No");
}
if(s.find("parent")!=string::npos)
{
sscanf(s.c_str(),"%d is the parent of %d",&x,&y);
if(dep.count(x) && dep.count(y))
{
for(int i=0;i<cur;++i)
if(lv[i]==x && (lv[i*2+1]==y || lv[2*i+2]==y))
{
f=1;puts("Yes");
break;
}
}
if(!f) puts("No");
}
if(s.find("left")!=string::npos)
{
sscanf(s.c_str(),"%d is the left child of %d",&x,&y);
if(dep.count(x) && dep.count(y))
{
for(int i=0;i<cur;++i)
if(lv[i]==y && lv[i*2+1]==x)
{
f=1;puts("Yes");
break;
}
}
if(!f) puts("No");
}
if(s.find("right")!=string::npos)
{
sscanf(s.c_str(),"%d is the right child of %d",&x,&y);
if(dep.count(x) && dep.count(y))
{
for(int i=0;i<cur;++i)
if(lv[i]==y && lv[i*2+2]==x )
{
f=1;puts("Yes");
break;
}
}
if(!f) puts("No");
}
if(s.find("same")!=string::npos)
{
sscanf(s.c_str(),"%d and %d are on the same level",&x,&y);
if(dep.count(x) && dep.count(y))
{
if(dep[x]==dep[y])puts("Yes");
else puts("No");
}
else puts("No");
}
}
return 0;
}
然后看了下小伙伴滴代码,直接深搜的,但是注意一下如果根节点的父亲是根节点的话,是No的,然后是30分...但是我觉得这个和建树一样啊数组a也会存不下的啊...为啥这个可以过呢??【然后我输入100个点从100到1降序输入,果然他是出不来结果的..】
因为数据水啊!!!
代码二:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int a[maxn];
map<int,int>mp;
int n;
void insert(int x,int pos)
{
// cout<<"pos="<<pos<<endl;
if(a[pos]==-1)
{
a[pos]=x;
mp[x]=pos;
return;
}
if(x<a[pos])insert(x,pos*2+1);
else insert(x,pos*2+2);
}
int main()
{
scanf("%d",&n);
memset(a,-1,sizeof(a));
for(int i=0;i<n;++i)
{
int x;scanf("%d",&x);
insert(x,0);
}
int q;scanf("%d",&q);
getchar();
while(q--)
{
string s;getline(cin,s);
int x,y,f=0;
if(s.find("root")!=string::npos)
{
sscanf(s.c_str(),"%d is the root",&x);
if(mp.count(x) && x==a[0])puts("Yes");
else puts("No");
}
if(s.find("siblings")!=string::npos)
{
sscanf(s.c_str(),"%d and %d are siblings",&x,&y);
if(mp.count(x) && mp.count(y) && mp[x] && mp[y] && (mp[x]-1)/2==(mp[y]-1)/2)puts("Yes");
else puts("No");
}
if(s.find("parent")!=string::npos)
{
sscanf(s.c_str(),"%d is the parent of %d",&x,&y);
// cout<<mp[y]-1<<endl;
if(mp.count(x) && mp.count(y) && mp[y] && mp[x]==(int)(mp[y]-1)/2)puts("Yes");
else puts("No");
}
if(s.find("left")!=string::npos)
{
sscanf(s.c_str(),"%d is the left child of %d",&x,&y);
if(mp.count(x) && mp.count(y) && mp[y]*2+1==mp[x] && x<y)puts("Yes");
else puts("No");
}
if(s.find("right")!=string::npos)
{
sscanf(s.c_str(),"%d is the right child of %d",&x,&y);
if(mp.count(x) && mp.count(y) && mp[y]*2+2==mp[x] && x>y)puts("Yes");
else puts("No");
}
if(s.find("same")!=string::npos)
{
sscanf(s.c_str(),"%d and %d are on the same level",&x,&y);
if(mp.count(x) && mp.count(y) && (int)(log2(mp[x]+1))==(int)(log2(mp[y]+1)))puts("Yes");
else puts("No");
}
}
return 0;
}
还是百度了下大佬的代码...
不用定义结构体,直接用数组来做;l[i] & r[i]分别代表节点i的左右节点的下标;
deep数组存每个节点对应的index的深度;
mp存每个值的对应的下标
因为上面的数组的值对应的都是下标,所以要用map存一下;
这个就算100个降序读入数据,也是不会爆的... 但是这种思路我不太会想得到吧....
代码3(AC)
#include<bits/stdc++.h>
using namespace std;
const int maxn=110;
int a[maxn],l[maxn],r[maxn];
int pre[maxn],deep[maxn];
map<int,int>mp;
int n,q;
int root;
void insert(int &Root,int fa,int dep,int id)
{
// cout<<l[Root]<<","<<r[Root]<<endl;
if(Root==-1)
{
Root=id;//这里就是给l,r数组赋值;如果是-1那么会走这个if语句,然后赋值返回
pre[id]=fa;
deep[id]=dep;
return;
}
if(a[id]<a[Root])insert(l[Root],Root,dep+1,id);
else insert(r[Root],Root,dep+1,id);
}
int main()
{
scanf("%d",&n);
memset(l,-1,sizeof(l));
memset(r,-1,sizeof(r));
root=-1;
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
insert(root,-1,1,i);
mp[a[i]]=i;
}
scanf("%d",&q);getchar();
while(q--)
{
string s;getline(cin,s);
int x,y,f=0;
if(s.find("root")!=string::npos)
{
sscanf(s.c_str(),"%d is the root",&x);
if(mp.find(x)!=mp.end() && a[root]==x)f=1;
}
else if(s.find("siblings")!=string::npos)
{
sscanf(s.c_str(),"%d and %d are siblings",&x,&y);
if(mp.find(x)!=mp.end() && mp.find(y)!=mp.end() && pre[mp[x]]==pre[mp[y]])f=1;
}
else if(s.find("parent")!=string::npos)
{
sscanf(s.c_str(),"%d is the parent of %d",&x,&y);
if(mp.find(x)!=mp.end() && mp.find(y)!=mp.end() && pre[mp[y]]==mp[x])f=1;
}
else if(s.find("left")!=string::npos)
{
sscanf(s.c_str(),"%d is the left child of %d",&x,&y);
if(mp.find(x)!=mp.end() && mp.find(y)!=mp.end() && pre[mp[x]]==mp[y] && x<y)f=1;
}
else if(s.find("right")!=string::npos)
{
sscanf(s.c_str(),"%d is the right child of %d",&x,&y);
if(mp.find(x)!=mp.end() && mp.find(y)!=mp.end() && pre[mp[x]]==mp[y] && x>y)f=1;
}else if(s.find("same")!=string::npos)
{
sscanf(s.c_str(),"%d and %d are on the same level",&x,&y);
if(mp.find(x)!=mp.end() && mp.find(y)!=mp.end() && deep[mp[x]]==deep[mp[y]])f=1;
}
if(f)puts("Yes");
else puts("No");
}
}