历届试题 横向打印二叉树

问题描述

二叉树可以用于排序。其原理很简单:对于一个排序二叉树添加新节点时,先与根节点比较,若小则交给左子树继续处理,否则交给右子树。

当遇到空子树时,则把该节点放入那个位置。

比如,10 8 5 7 12 4 的输入顺序,应该建成二叉树如下图所示,其中.表示空白。

...|-12
10-|
...|-8-|
.......|...|-7
.......|-5-|
...........|-4

本题目要求:根据已知的数字,建立排序二叉树,并在标准输出中横向打印该二叉树。

输入格式

输入数据为一行空格分开的N个整数。 N<100,每个数字不超过10000。

输入数据中没有重复的数字。

输出格式

输出该排序二叉树的横向表示。为了便于评卷程序比对空格的数目,请把空格用句点代替:

样例输入1
10 5 20
样例输出1
...|-20
10-|
...|-5
样例输入2
5 10 20 8 4 7
样例输出2
.......|-20
..|-10-|
..|....|-8-|
..|........|-7
5-|
..|-4



#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#define bug(x) printf("%d****\n",x)
using namespace std;
typedef long long ll;
map<int,int> pos;

struct node{
    int val,fa;
    node* l,*r;
    node(int _fa=-1,int _val=-1){
        fa=_fa,val=_val,l=r=NULL;
    }
};

const int maxn=410;
char mp[maxn][maxn];
int arr[maxn];
queue<node*> q1,q2;
void insert_tr(node*& tr,int val,int fa){
    if(tr==NULL){
        tr=new node(fa,val);
        return;
    }
    if(val>tr->val)
        insert_tr(tr->l,val,tr->val);
    else
        insert_tr(tr->r,val,tr->val);
}

int cnt;
int num[10];

void print(){
	for(int i=0;i<=3;i++){
		for(int j=0;j<=5;j++){
			printf("%c",mp[i][j]);
		}
		printf("\n");
	}
}

void put_char(int val,int& p){
    int cnt=0,tmp=val;//卧槽,你别把数给改了啊 
    while(tmp){
        num[cnt++]=tmp%10;
        tmp/=10;
    }
    for(int i=cnt-1,j=0;i>=0;i--,j++){
        mp[pos[val]][p+j]=num[i]+'0';
    } 
    p+=(cnt-1);
}
 
int put_val(int pf,int val,int dep,int rt){
    int  p=maxn-1;
    while(mp[pf][p]!='|')
        p--;
    if(pos[val]<pf){
        for(int i=pos[val];i<=pf;i++){
            mp[i][p]='|';
            for(int j=0;j<p;j++){
        		if(mp[i][j]==0)mp[i][j]='.';
    		}
        }
    }
    else{
        for(int i=pf+1;i<=pos[val];i++){
        	 mp[i][p]='|';
        	 for(int j=0;j<p;j++){
        		if(mp[i][j]==0)mp[i][j]='.';
    		}
    	}
    }
    p++;
    if(val!=rt){
    	mp[pos[val]][p]='-';
    	p++;	
    }
    put_char(val,p);
    return p;
}

int check(char ch){
	if(ch>='0'&&ch<='9')	return 1;
	return 0;
}

void put_xian(int val){
    int p=maxn-1;
    while(!check(mp[pos[val]][p]))
        p--;
    p++;
    mp[pos[val]][p]='-';
    p++;
    mp[pos[val]][p]='|';
}
/*
头一次写这样的模拟题,尽管写的时间比较长,写了有2个小时,但是一发过,还是蛮爽的
还是汝佳大神的建议中肯,先写简单的,把他们抽象成函数,这样的话,就会比较好写,
不会写的很乱 
*/

int main(){
    for(int i=0;i<maxn;i++){
        for(int j=0;j<maxn;j++)
                mp[i][j]=0;
    }
    cnt=1;
    int val,pre=-1;
    node* tr=new node(val);
    while(scanf("%d",&val)==1){
        if(cnt==1){
            tr->val=val;
            tr->fa=val;
        }
        else
            insert_tr(tr,val,pre);
        pre=val;
        arr[cnt++]=val;
    }
    sort(arr+1,arr+cnt);
    for(int i=1;i<cnt;i++){
        pos[arr[i]]=i;
	}
    mp[pos[tr->val]][0]='|';
    q1.push(tr);
    int dep=1,max_dep=1;
    while(!q1.empty()||!q2.empty()){
        if(dep&1){
            while(!q1.empty()){
                node* now=q1.front();
                q1.pop();
                int val=now->val;
                int tmp=put_val(pos[now->fa],val,dep,tr->val);
                if(now->l)  q2.push(now->l);
                if(now->r)  q2.push(now->r);
                if(now->l||now->r) put_xian(val);
                max_dep=max(max_dep,tmp);
            }
        }
        else{
            while(!q2.empty()){
                node* now=q2.front();
                q2.pop();
                int val=now->val;
                int tmp=put_val(pos[now->fa],val,dep,tr->val);
                if(now->l)  q1.push(now->l);
                if(now->r)  q1.push(now->r);
                if(now->l||now->r) put_xian(val);
                max_dep=max(max_dep,tmp);
            }
        }
        dep++;
    }
    for(int i=cnt-1;i>=1;i--){
        for(int j=1;j<=max_dep;j++)
                printf("%c",mp[i][j]);
        printf("\n");
    }
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值