PTA 二叉搜索树的2层结点统计
二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树:若它的左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜索树。
将一系列数字按给定顺序插入一棵初始为空的二叉搜索树,你的任务是统计结果树中最下面 2 层的结点数。
输入格式:输入在第一行给出一个正整数 N (≤1000),为插入数字的个数。第二行给出 N 个 [−1000,1000] 区间内的整数。数字间以空格分隔。
输出格式:在一行中输出最下面 2 层的结点总数。
输入样例:
9
25 30 42 16 20 20 35 -5 28
输出样例:
6
一开始的分析:想着统计2层的结点树不就相当于先统计叶子结点树然后把该叶子结点去掉,再统计一次“叶子结点”,这样两次dfs后不就相当于统计到了两层的结点数了吗,但事实很快打脸。
下面附上错误算法下的半对代码:
#includeusing namespace std;int cnt;struct Tree{int val;Tree* l;Tree* r;};void build(Tree* &t,int data){if(t==NULL){t=new Tree();t->val=data;t->l=NULL;t->r=NULL;return;}if(dataval) build(t->l,data);else build(t->r,data);}void dfs(Tree* &tt){if(tt!=NULL&&tt->l==NULL&&tt->r==NULL){tt=NULL;cnt++;return;}else if(tt==NULL)return;dfs(tt->l);dfs(tt->r);}int main(){int n;cin>>n;Tree* root=NULL;while(n--){int x;cin>>x;build(root,x);}dfs(root);dfs(root);cout<<cnt; return 0;}
很显然肯定是过不了的,能对一半已经是幸运!
而错误点在于,比如:
这是在该算法下第一次dfs到第二次dfs树的情况,按这种算法,两层的结点数会变成4+2=6(黑色数字),而实际应该为5(绿色数字)!
下面为AC代码:
#includeusing namespace std;int mmax;mapcnt;//cnt[第几层] = 结点个数struct Tree{int val;Tree* l;Tree* r;};void dfs(Tree* &t,int data,int level){if(t==NULL){t=new Tree();t->val=data;t->l=t->r=NULL;cnt[level]++;mmax=max(mmax,level);return;}if(dataval) dfs(t->l,data,level+1);else dfs(t->r,data,level+1);}int main(){int n;cin>>n;Tree* root=NULL;while(n--){int x;cin>>x;dfs(root,x,1);}cout<<cnt[mmax]+cnt[mmax-1]; return 0;}