绘制二叉树

#

1、小写字母“o”表示结点,对于一个父亲结点,分别用“/”、“\”连接左、右子树。
2、定义[i,j]为位于第i行,第j列的某个字符。若[i,j]为“/”,那么[i-1,j+1]与[i+1,j-1]只可能是“o”或者“/”。若[i,j]为“\”,那么[i-1,j-1]与[i+1,j+1]只可能是“o”或者“\”。同样,若[i,j]为第1-m层的某个节点(即“o”),那么[i+1,j-1]为“/”,[i+1,j+1]为“\”。

3、对于第m层节点也就是叶子结点,若两个属于同一个父亲,那么它们之间由3个空格隔开,若两个结点相邻但不属于同一个父亲,那么它们之间由1个空格隔开。第m层左数第1个节点之前没有空格。

最后需要在一颗绘制好的满二叉树上删除n个结点(包括它的左右子树,以及与父亲的连接),原有的字符用空格替换(ASCII 32)。

#include<iostream>
#include<cmath>
using namespace std;
const int maxn=1<<10|1;
int tree[maxn];
int del_count=0;
int m,n,total,w,h,last;
char p[1<<11][1<<11];

int get_id(int x,int y){
    return pow(2,x-1)-1+y;
}

void del(int id){
    if (id>total) return;
    tree[id]=0;
    del(id*2);
    del(id*2+1);
} //删节点

void draw(int id,int& x,int& y){
    if (id>last){
        int tmp=id-last;
        x=h;
        y=6*((tmp-1)/2)+(tmp%2!=0?1:5);
        if (tree[id]) p[x][y]='o';
        else del_count++;
        return;
    }
    int lx,ly,rx,ry;
    draw(id<<1,lx,ly);
    draw(id<<1|1,rx,ry);
    y=(ly+ry)/2;
    x=lx-(ry-ly)/2;
    if (tree[id]){
        p[x][y]='o';
        for (int i=1;i<(ry-ly)/2;i++){
            if (tree[id*2])p[x+i][y-i]='/';
            if (tree[id*2+1]) p[x+i][y+i]='\\';
    }
}
    else {
    del_count++;
}
}//绘制 

int main(){
    cin>>m>>n;
    total=pow(2,m)-1;
    int n0=pow(2,m-1);
    w=n0/2*5+n0/2-1;
    h=w/2+1;
    last=pow(2,m-1)-1;
    for (int i=1;i<=(1<<m);i++){
        tree[i]=1;
    }   
    for (int i=1;i<=n;i++){
        int x,y;
        cin>>x>>y;
        int id=get_id(x,y); 
        del(id);    
    }
    int x,y;
    draw(1,x,y);
    cout<<total-del_count<<"\n";
    for (int i=1;i<=h;i++){
        for (int j=1;j<=w;j++){
            if (p[i][j]=='o'||p[i][j]=='/'||p[i][j]=='\\'){
                cout<<p[i][j]; 
            }
            else cout<<" ";
        }
        cout<<"\n";
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章