繪製二叉樹

#

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章