P1185 绘制二叉树【二叉树】

绘制二叉树

题目描述

二叉树是一种基本的数据结构,它要么为空,要么由根结点,左子树和右子树组成,同时左子树和右子树也分别是二叉树。

当一颗二叉树高度为 m − 1 m-1 m1 时,共有 m m m 层。若一棵二叉树除第 m m m 层外,其他各层的结点数都达到最大,且叶子结点都在第 m m m 层时,则其为一棵满二叉树。

现在,需要你用程序来绘制一棵二叉树,它由一棵满二叉树去掉若干结点而成。对于一棵满二叉树,我们需要按照以下要求绘制:

  1. 结点用小写字母 o 表示,对于一个父亲结点,用 / 连接左子树,用 \ 连接右子树。

  2. 定义 [ 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] [i1,j+1] [ i + 1 , j − 1 ] [i+1,j-1] [i+1,j1] 要么为 o ,要么为 /。若 [ i , j ] [i,j] [i,j]\ ,那么 [ i − 1 , j − 1 ] [i-1,j-1] [i1,j1] [ 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 1m1 层的某个结点 o ,那么 [ i + 1 , j − 1 ] [i+1,j-1] [i+1,j1]/ [ i + 1 , j + 1 ] [i+1,j+1] [i+1,j+1]\

  3. 对于第 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 2m5

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} 2m10,0n10,1<iM,j2i1

问题链接: 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值