绘制二叉树
题目描述
二叉树是一种基本的数据结构,它要么为空,要么由根结点,左子树和右子树组成,同时左子树和右子树也分别是二叉树。
当一颗二叉树高度为 m − 1 m-1 m−1 时,共有 m m m 层。若一棵二叉树除第 m m m 层外,其他各层的结点数都达到最大,且叶子结点都在第 m m m 层时,则其为一棵满二叉树。
现在,需要你用程序来绘制一棵二叉树,它由一棵满二叉树去掉若干结点而成。对于一棵满二叉树,我们需要按照以下要求绘制:
-
结点用小写字母
o
表示,对于一个父亲结点,用/
连接左子树,用\
连接右子树。 -
定义 [ i , j ] [i,j] [i,j] 为位于第 i i i 行第 j j j 列的某个字符。若 [ i , j ] [i,j] [i,j] 为
/
,那么 [ i − 1 , j + 1 ] [i-1,j+1] [i−1,j+1] 与 [ i + 1 , j − 1 ] [i+1,j-1] [i+1,j−1] 要么为o
,要么为/
。若 [ i , j ] [i,j] [i,j] 为\
,那么 [ i − 1 , j − 1 ] [i-1,j-1] [i−1,j−1] 与 [ i + 1 , j + 1 ] [i+1,j+1] [i+1,j+1] 要么为o
,要么为\
。同样,若 [ i , j ] [i,j] [i,j] 为第 1 ∼ m − 1 1\sim m-1 1∼m−1 层的某个结点o
,那么 [ i + 1 , j − 1 ] [i+1,j-1] [i+1,j−1] 为/
, [ i + 1 , j + 1 ] [i+1,j+1] [i+1,j+1] 为\
。 -
对于第 m m m 层结点也就是叶子结点点,若两个属于同一个父亲,那么它们之间由 3 3 3 个空格隔开;若两个结点相邻但不属于同一个父亲,那么它们之间由 1 1 1 个空格隔开。第 m m m 层左数第 1 1 1 个结点之前没有空格。
最后需要在一棵绘制好的满二叉树上删除 n n n 个结点(包括这个结点的左右子树,以及与父亲的连接),原有的字符用空格替换(空格为 ASCII 32
,若输出 ASCII 0
会被算作错误答案)。
输入格式
第 1 1 1 行包含 2 2 2 个正整数 m m m 和 n n n,为需要绘制的二叉树层数和需要删除的结点数。
接下来 n n n 行,每行两个正整数,表示删除第 i i i 层的第 j j j 个结点。
输出格式
按照题目要求绘制的二叉树。
样例 #1
样例输入 #1
2 0
样例输出 #1
o
/ \
o o
样例 #2
样例输入 #2
4 0
样例输出 #2
o
/ \
/ \
/ \
/ \
/ \
o o
/ \ / \
/ \ / \
o o o o
/ \ / \ / \ / \
o o o o o o o o
样例 #3
样例输入 #3
4 3
3 2
4 1
3 4
样例输出 #3
o
/ \
/ \
/ \
/ \
/ \
o o
/ /
/ /
o o
\ / \
o o o
提示
30 % 30\% 30% 的数据满足: n = 0 n=0 n=0;
50 % 50\% 50% 的数据满足: 2 ≤ m ≤ 5 2\le m\le 5 2≤m≤5;
100 % 100\% 100% 的数据满足: 2 ≤ m ≤ 10 , 0 ≤ n ≤ 10 , 1 < i ≤ M , j ≤ 2 i − 1 2\le m\le10,0\le n\le 10,1<i\le M,j\le 2^{i-1} 2≤m≤10,0≤n≤10,1<i≤M,j≤2i−1。
问题链接: P1185 绘制二叉树
问题分析: 二叉树问题,不解释。
参考链接: (略)
题记: (略)
AC的C++语言程序如下:
/* P1185 绘制二叉树 */
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
const int M = 10, M2 = 1 << (M - 1);
bool del[M + 1][M2 + 1];
char g[800][2000];
int m, n, h, w;
void draw(int x, int y, int depth, int i, int j)
{
g[x][y] = 'o';
if(i == m) return;
int il = i + 1, jl = j * 2 - 1;
int ir = i + 1, jr = j * 2;
for (int i = 1; i < depth; i++) {
if (!del[il][jl]) g[x + i][y - i] = '/';
if (!del[ir][jr]) g[x + i][y + i] = '\\';
}
if (!del[il][jl]) draw(x + depth, y - depth, (depth + 1) / 2, il, jl);
if (!del[ir][jr]) draw(x + depth, y + depth, (depth + 1) / 2, ir, jr);
}
void show()
{
for (int i = 1; i <= h; i++) {
for (int j = 1; j <= w; j++)
cout << g[i][j];
cout << endl;
}
}
int main()
{
memset(g, ' ', sizeof g);
cin >> m >> n;
while (n--) {
int i, j;
cin >> i >> j;
del[i][j] = true;
}
h = 3 * pow(2, m - 2);
w = 5 * pow(2, m - 2) + pow(2, m - 2) - 1;
draw(1, w / 2 + 1, (h + 1) / 2, 1, 1);
show();
return 0;
}