题目
L2-004 这是二叉搜索树吗? (25 分)
L2-006 树的遍历 (25 分)
L2-011 玩转二叉树 (25 分)
L2-035 完全二叉树的层序遍历 (25 分)
L3-010 是否完全二叉搜索树 (30 分)
代码
L2-004 这是二叉搜索树吗? (25 分)
#include<bits/stdc++.h>
using namespace std;
const int N = 1100;
int n, a[N];
vector <int> v;
void dfs (int l, int r, int mir) {
if (l > r) return ;
int rt = a[l];
int p = l+1, q = l+1;
if (!mir) {
while (p <= r && a[p] < rt) p ++, q ++;
while (q <= r && a[q] >= rt) q ++;
} else {
while (p <= r && a[p] >= rt) p ++, q ++;
while (q <= r && a[q] < rt) q ++;
}
dfs (l+1, p-1, mir);
dfs (p, q-1, mir);
v.push_back (rt);
}
void print () {
puts ("YES");
cout << v[0];
for (int i = 1;i < v.size();i ++)
cout << ' ' << v[i];
}
int main()
{
int n;
cin >> n;
for (int i = 1;i <= n;i ++) cin >> a[i];
dfs (1, n, 0);
if (v.size () == n) {
print ();
return 0;
}
v.clear ();
dfs (1, n, 1);
if (v.size() == n) print ();
else puts ("NO");
return 0;
}
L2-006 树的遍历 (25 分)
题解
#include<bits/stdc++.h>
using namespace std;
vector <int> v;
int a[50], b[50], n, left_val[50], right_val[50];
int dfs (int l1, int r1, int l2, int r2) {
if (l1 > r1 || l2 > r2) return 0;
int root = a[r1], p = l2;
while (p <= r2) {
if (b[p] == root) break;
p ++;
}
int left_sum = p - l2;
left_val[root] = dfs (l1, l1+left_sum-1, l2, p-1);
right_val[root] = dfs (l1+left_sum, r1-1, p+1, r2);
return root;
}
void bfs (int x) {
queue <int> q;
q.push (x);
while (q.size ()) {
int t = q.front ();
q.pop ();
v.push_back (t);
if (left_val[t]) q.push (left_val[t]);
if (right_val[t]) q.push (right_val[t]);
}
}
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++) cin >> a[i];
for (int i = 1;i <= n;i ++) cin >> b[i];
dfs (1, n, 1, n);
bfs (a[n]);
cout << v[0];
for (int i = 1;i < v.size();i ++)
cout << ' ' << v[i];
return 0;
}
L2-011 玩转二叉树 (25 分)
#include<bits/stdc++.h>
using namespace std;
const int N = 50;
int n, a[N], b[N];
int right_subtree_root[N<<1], left_subtree_root[N<<1];
int dfs (int l1, int r1, int l2, int r2) {
if (l1 > r1 || l2 > r2) return 0;
int rt = b[l2];
int p = l1;
while (p <= r1 && a[p] != rt) p ++;
right_subtree_root[rt] = dfs (l1, p-1, l2+1, l2+p-l1);
left_subtree_root[rt] = dfs (p+1, r1, l2+p-l1+1, r2);
return rt;
}
void bfs (int x) {
vector <int> v;
queue <int> q;
q.push (x);
while (q.size()) {
int t = q.front ();
v.push_back (t);
q.pop ();
if (left_subtree_root[t]) q.push (left_subtree_root[t]);
if (right_subtree_root[t]) q.push (right_subtree_root[t]);
}
cout << v[0] ;
for (int i = 1;i < v.size();i ++) cout << ' ' << v[i];
}
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++) cin >> a[i];
for (int i = 1;i <= n;i ++) cin >> b[i];
dfs (1, n, 1, n);
bfs (b[1]);
return 0;
}
L2-035 完全二叉树的层序遍历 (25 分)
充分利用了完全二叉树索引的性质,第i 个节点的左孩子保存在a[2*i] 中,右孩子保存在a[2*i+1] 中,所以我们可以根据后续遍历递归输入。
这个方法太棒了!
#include<bits/stdc++.h>
using namespace std;
const int N = 100;
int n, tree[N];
void build (int x) {
if (x > n) return ;
build (x << 1);
build (x << 1 | 1);
cin >> tree[x];
}
int main()
{
cin >> n;
build (1);
cout << tree[1];
for (int i = 2;i <= n;i ++)
cout << ' ' << tree[i];
return 0;
}
我写的:(繁琐)
只要思想就是递归确定左子树和右子树元素个数,左子树元素个数就是左子树完美时的元素个数-左子树缺少的元素个数,缺少的元素个数主要看根节点的右子树,也就是该左子树的兄弟子树,如果整个树缺少元素的个数大于右子树完美时最后一层的元素个数,说明左子树也缺少元素了,缺少的元素个数就是二者的差值。
#include<bits/stdc++.h>
using namespace std;
const int N = 100;
vector <int> v;
queue <int> q;
int n, a[N];
int left_subtree_root[N<<1], right_subtree_root[N<<1];
int dfs (int l, int r) {
if (l > r) return 0;
int num = r-l+1;
int dp = int (log2(num));
int lack = (1 << (dp+1)) - 1 - num;
int last_layer_num = (1<<dp);
int left_subtree_num = (1<<dp) - 1 - max (0, lack - last_layer_num/2);
left_subtree_root[r] = dfs (l, l + left_subtree_num - 1);
right_subtree_root[r] = dfs (l + left_subtree_num, r-1);
return r;
}
void layer_order (int x) {
q.push (x);
while (q.size()) {
int t = q.front ();
q.pop ();
v.push_back (a[t]);
if (left_subtree_root[t]) q.push(left_subtree_root[t]);
if (right_subtree_root[t]) q.push(right_subtree_root[t]);
}
cout << v[0];
for (int i = 1;i < v.size();i ++)
cout << ' ' << v[i];
}
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++) cin >> a[i];
dfs (1, n);
layer_order (n);
return 0;
}
L3-010 是否完全二叉搜索树 (30 分)
搜索二叉树插入元素的过程:
- 树空,则插入到根节点位置;
- 树非空,与根节点比较,如果大于根节点的值则递归进入右子树,否则进入左子树。
#include<bits/stdc++.h>
using namespace std;
const int N = 100;
int n, x, cnt;
int tr[N];
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++) {
cin >> x;
int p = 1;
while (tr[p] != 0) {
if (x > tr[p]) p = (p << 1);
else p = (p << 1 | 1);
}
tr[p] = x;
}
for (int i = 1; ;i ++) {
if (tr[i]) {
cnt ++;
if (cnt == 1) cout << tr[i];
else cout << ' ' << tr[i];
}
if (cnt == n) {
cout << endl;
if (i == n) puts ("YES");
else puts ("NO");
return 0;
}
}
return 0;
}
|