L3-010 是否完全二叉搜索树 (30分)
将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),你需要判断最后的树是否一棵完全二叉树,并且给出其层序遍历的结果。
输入格式:
输入第一行给出一个不超过20的正整数N;第二行给出N个互不相同的正整数,其间以空格分隔。
输出格式:
将输入的N个正整数顺序插入一个初始为空的二叉搜索树。在第一行中输出结果树的层序遍历结果,数字间以1个空格分隔,行的首尾不得有多余空格。第二行输出YES,如果该树是完全二叉树;否则输出NO。
输入样例1:
9
38 45 42 24 58 30 67 12 51
输出样例1:
38 45 24 58 42 30 12 67 51
YES
输入样例2:
8
38 24 12 45 58 67 42 51
输出样例2:
38 45 24 58 42 12 67 51
NO
判断是否完全二叉树有两种方法:
一是用数组存,下标乘2和下标乘2加1分别是他的两个子树,这样做的好处是简单,最后判断完全二叉树的时候只用判断前n个数都付上了值就ok了,但是有缺点就是如果给的节点数太大数组根本存不下,题目上是 n < = 20 n <= 20 n<=20,若 n < = 30 n <= 30 n<=30这种方法就写不了了,因为会有一种情况使下标达到 2 30 2^{30} 230,数组使存不下的,更何况n是一千一万的大小了。
第二种是用指针存,也就是真正的建树,这样的数据结构能存1e5的数据量。但是判断完全二叉树的时候就麻烦了一些。
放上以前写的代码以作对比,
//#include<bits/stdc++.h>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;
#define ri register int
#define ms(x, n) memset(x, n, sizeof(x))
#define wht() \
int t; \
cin >> t; \
while (t--)
#define For(i, a, b) for (ri i = a; i <= b; i++)
#define nowl now << 1
#define nowr now << 1 | 1
#define mi (l + r) / 2
#define ioss ios::sync_with_stdio(false)
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int maxn = 2e5 + 7;
const int maxm = 2e3 + 7;
const int mod = 1e9 + 7;
int dir[6][3] = {{0, 0, 1}, {0, 0, -1}, {0, 1, 0},
{0, -1, 0}, {1, 0, 0}, {-1, 0, 0}};
int n, v, m, l, d, s, t, o, e;
int ans = 0, tot = 0;
int a[maxn], b[maxn];
bool flag, vis[maxm];
char str[maxn];
string ss[maxn];
class node {
public:
int v;
int len;
int time;
node(int v, int len, int time) : v(v), len(len), time(time) {}
// bool operator < (const node &b) const{
// return cost < b.cost;
// }
};
vector<node> ve[maxm];
vector<int> fa[maxm];
int mx = 1;
void build(int now, int x) {
if (b[now] == 0) {
b[now] = x;
mx = max(now, mx);
return;
}
if (x > b[now]) {
build(nowl, x);
} else {
build(nowr, x);
}
return;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("D://hp//Desktop//Temporarily//test.txt", "r", stdin);
#endif
ioss;
int x, y, z;
string s1, s2;
cin >> n;
if (n == 0) {
cout << "YES";
return 0;
}
For(i, 1, n) { cin >> a[i]; }
b[1] = a[1];
For(i, 2, n) { build(1, a[i]); }
For(i, 1, mx) {
if (!b[i]) continue;
cout << b[i];
if (i == mx) {
cout << '\n';
} else {
cout << " ";
}
}
if (mx == n) {
cout << "YES";
} else {
cout << "NO";
}
}
#include <bits/stdc++.h>
#include <limits.h>
#include <math.h>
#include <memory.h>
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define ms(x, n) memset(x, n, sizeof(x))
#define wht() \
int _; \
for (scanf("%d", &_); _; _--)
#define For(i, a, b) for (int i = a; i <= (b); ++i)
#define Rof(i, a, b) for (int i = a; i >= (b); --i)
#define ioss ios::sync_with_stdio(false)
#define all(a) a.begin(), a.end()
#define ll long long
// #define input(x) scanf("%lld", &x);
// #define print(x) printf("%lld", x);
// #define println(x) printf("%lld\n", x);
typedef vector<int> vi;
typedef pair<int, int> pii;
const int maxn = 2e6 + 7;
const int maxm = 5e3 + 7;
const int MOD = 1e9 + 7;
const int mod = 998244353;
int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline int input() {
int x = 0, f = 0;
char ch = 0;
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
return f ? -x : x;
}
const int N = 1e5 + 5;
int n, m, k;
int a[N], b[N], f[N];
vi g[N];
struct node {
int val;
node *le, *ri;
};
void build(node *&r, int val) {
if (!r) {
r = new node, r->val = val, r->le = r->ri = nullptr;
return;
}
if (val < r->val) build(r->ri, val);
if (val > r->val) build(r->le, val);
}
void work() {
n = input();
if (n == 0) {
puts("YES");
return;
}
node *root = nullptr;
For(i, 1, n) {
int x = input();
build(root, x);
}
queue<node *> q;
q.push(root);
int fir = 0;
vi ve;
int flag = 0;
int leaf = 0; //标记出现没右子树的节点
while (q.size()) {
int tot = q.size();
For(i, 1, tot) {
node *cur = q.front();
q.pop();
if (fir) putchar(' ');
fir = 1;
printf("%d", cur->val);
// 如果该节点没左子树但有右子树,则不完全
// 或者在出现过没有右子树的节点之后该节点有任意一子树都不完全
if ((leaf && (cur->le || cur->ri)) || (!cur->le && cur->ri)) {
flag = 1;
}
if (cur->le) q.push(cur->le);
if (cur->ri)
q.push(cur->ri);
else
leaf = 1;
}
ve.push_back(tot);
}
// for (auto i : ve) {
// cout << i << "\n";
// }
ll ans = 1;
For(i, 0, (int)ve.size() - 2) {
// cout << ve[i] << " " << ans << "\n";
if (ve[i] != ans) {
flag = 1;
break;
}
ans <<= 1;
}
puts(flag ? "\nNO" : "\nYES");
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif
work();
}