一、技术总结
- 这里有几个点需要注意,一个是完全二叉树的特点。(结点的编号从1开始)假设当前结点的编号为X,其左结点的编号一定是2X,而右结点的编号为2X+1。同时,结点的最大编号数等于结点的数量。
- 假设是完全二叉树后,要判断某个结点是否为叶子结点的标志是,该结点的编号X的左子结点编号2X大于结点的总个数n;判断结点是是否为空节点的标志为,该结点的编号X大于结点的总个数n。
- 下面来看到该题,题目给出二叉树,要我们判断是否为完全二叉树。我们选择深度搜索dfs,我们设置一个变量maxn,用于记录结点的最大编号。解读一下dfs函数,root是当前结点的编号,如果当前结点的编号大于之前最大maxn,即保存下来,同时使用ans记录该结点的下标,用于后续输出。代表这最后一个结点的下标,前提是如果是安全二叉树。
- 然后就是stoi函数,用于把字符串转化为十进制的数字。详情看这篇博客:https://www.cnblogs.com/tsruixi/p/12944470.html
- 在一个就是have数组,用来存储,用于判断根结点的位置。如果是根结点,那么在该have数组中下标内容为0,其余不是根结点的内容是1。
- 最后判断,如果maxn记录的最大下标等于结点总数,那么为完全二叉树。否则不是,输出root即根结点下标。
二、参考代码
#include<bits/stdc++.h>
using namespace std;
struct node{
int l, r;
}a[100];
int maxn = -1, ans;
void dfs(int root, int index){
if(index > maxn){
maxn = index;
ans = root;
}
if(a[root].l != -1) dfs(a[root].l, 2 * index);
if(a[root].r != -1) dfs(a[root].r, 2 * index + 1);
}
int main(){
int n, root = 0;
int have[100] = {0};
scanf("%d", &n);
for(int i = 0; i < n; i++){
string str1, str2;
cin >> str1 >> str2;
if(str1 == "-"){
a[i].l = -1;
}else{
a[i].l = stoi(str1);
have[stoi(str1)] = 1;
}
if(str2 == "-"){
a[i].r = -1;
}else{
a[i].r = stoi(str2);
have[stoi(str2)] = 1;
}
}
while(have[root] != 0) root++;
dfs(root, 1);
if(maxn == n){
printf("YES %d", ans);
}else{
printf("NO %d", root);
}
return 0;
}