蓝桥杯 历届试题 横向打印二叉树

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

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

比如,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

按题目上的说法分布做吧,先对二叉树进行构建,如下:

struct Node{
    int left=0, right=0;//left和right分别是左右子树的编号
    int w;//w是节点上的数
}node[N];
void push(int i, int cur)
{
    if(node[i].w<node[cur].w)
    {
        if(node[cur].left) push(i, node[cur].left);
        else node[cur].left=i;
    }
    else {
        if(node[cur].right) push(i, node[cur].right);
        else node[cur].right=i;
    }
}

还是挺好弄的,没在这里下绊子(所以他就在输出上搞事了是吗)
先看一下输出,大部分都是 ‘.’ ,然后就分为数字和 ‘-’ 以及 **‘|’**这三类,而且父节点后一定跟着 ‘-|’,然后 ‘|’ 会一直延伸到其子节点所在行,子节点前一定有 ‘|-’ ,这样分析下来这个图应该清晰了吧,为了好去把这些字符加入,用char Map[110][110]来记录这个图,然后加一些变量 int line, Leng;//line是这个点应该在第几行,Leng是这个点上数的长度来好将特殊字符放入图中

void writele(int cnt)//计算数字长度
{
    if(node[cnt].w<10) node[cnt].Leng=1;
    else if(node[cnt].w<100) node[cnt].Leng=2;
    else if(node[cnt].w<1000) node[cnt].Leng=3;
    else if(node[cnt].w<10000) node[cnt].Leng=4;
    else node[cnt].Leng=5;
}
int lc=0;
char Map[3*N][3*N];
void dfsline(int pos)//用dfs计算数字所在行
{
    if(node[pos].right) dfsline(node[pos].right);
    node[pos].line=lc++;
    if(node[pos].left) dfsline(node[pos].left);
}
void dfs(int cur, int pos)//标记特殊字符
{
    int t=node[cur].w, p2=node[cur].Leng;
    for(int i=pos+p2-1; i>=pos; i--){ Map[node[cur].line][i]=t%10+'0', t/=10;}
    if(node[cur].left||node[cur].right)
    {
        Map[node[cur].line][pos+p2]='-', Map[node[cur].line][pos+p2+1]='|';
        if(node[cur].right)
        {
            int l2=node[node[cur].right].line;
            for(int i=node[cur].line-1; i>=l2; i--)
                Map[i][p2+pos+1]='|';
            Map[l2][p2+pos+2]='-';
            dfs(node[cur].right, pos+p2+3);
        }
        if(node[cur].left)
        {
            int l2=node[node[cur].left].line;
            for(int i=node[cur].line+1; i<=l2; i++)
                Map[i][p2+pos+1]='|';
            Map[l2][p2+pos+2]='-';
            dfs(node[cur].left, pos+p2+3);
        }
    }
}

然后再把 ‘.’ 放入图中,可以发现只有数字之前要填充 ‘.’ ,所以用下面的代码填充 ‘.’

for(int i=0; i<cnt; i++)//cnt是总共有多少个数的计数
        for(int j=0; Map[i][j]<'0'||Map[i][j]>'9'; j++) if(Map[i][j]==0) Map[i][j]='.';

于是整理后的代码就像下面这样了,然后就能ac这道题了

#include <iostream>
using namespace std;
const int N=110;
struct Node{
    int left=0, right=0;
    int w,line, Leng;
}node[N];
void push(int i, int cur)
{
    if(node[i].w<node[cur].w)
    {
        if(node[cur].left) push(i, node[cur].left);
        else node[cur].left=i;
    }
    else {
        if(node[cur].right) push(i, node[cur].right);
        else node[cur].right=i;
    }
}
void writele(int cnt)
{
    if(node[cnt].w<10) node[cnt].Leng=1;
    else if(node[cnt].w<100) node[cnt].Leng=2;
    else if(node[cnt].w<1000) node[cnt].Leng=3;
    else if(node[cnt].w<10000) node[cnt].Leng=4;
    else node[cnt].Leng=5;
}
int cnt;
int lc=0;
char Map[3*N][3*N];

void dfsline(int pos)
{
    if(node[pos].right) dfsline(node[pos].right);
    node[pos].line=lc++;
    if(node[pos].left) dfsline(node[pos].left);
}
void dfs(int cur, int pos)
{
    int t=node[cur].w, p2=node[cur].Leng;
    for(int i=pos+p2-1; i>=pos; i--){ Map[node[cur].line][i]=t%10+'0', t/=10;}
    if(node[cur].left||node[cur].right)
    {
        Map[node[cur].line][pos+p2]='-', Map[node[cur].line][pos+p2+1]='|';
        if(node[cur].right)
        {
            int l2=node[node[cur].right].line;
            for(int i=node[cur].line-1; i>=l2; i--)
                Map[i][p2+pos+1]='|';
            Map[l2][p2+pos+2]='-';
            dfs(node[cur].right, pos+p2+3);
        }
        if(node[cur].left)
        {
            int l2=node[node[cur].left].line;
            for(int i=node[cur].line+1; i<=l2; i++)
                Map[i][p2+pos+1]='|';
            Map[l2][p2+pos+2]='-';
            dfs(node[cur].left, pos+p2+3);
        }
    }
}
int main()
{
    int a;
    scanf("%d", &a);
    node[cnt].w=a;
    writele(cnt++);
    while(scanf("%d", &a)!=EOF)
    {
        node[cnt].w=a;
        push(cnt, 0);
        writele(cnt++);
    }
    dfsline(0);
    dfs(0, 0);
    for(int i=0; i<cnt; i++)
        for(int j=0; Map[i][j]<'0'||Map[i][j]>'9'; j++) if(Map[i][j]==0) Map[i][j]='.';
    for(int i=0; i<cnt; i++) 
    {
        int j=0;
        while(Map[i][j]!=0)
            cout <<Map[i][j++];
        cout <<endl;
    }
    return 0;
}

本来差不多是一个月一篇,这个月竟然有两篇,我真勤快呢(滑稽)

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是实现二叉树按凹入表形式横向打印的C语言代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_DEPTH 100 typedef struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; } TreeNode; // 计算树的深度 int calcDepth(TreeNode *root) { if (root == NULL) { return 0; } int leftDepth = calcDepth(root->left); int rightDepth = calcDepth(root->right); return (leftDepth > rightDepth ? leftDepth : rightDepth) + 1; } // 按凹入表形式打印二叉树 void printTree(TreeNode *root) { if (root == NULL) { return; } int depth = calcDepth(root); int maxWidth = (1 << depth) - 1; char **res = (char **)malloc(sizeof(char *) * depth); for (int i = 0; i < depth; i++) { res[i] = (char *)malloc(sizeof(char) * (maxWidth + 1)); memset(res[i], ' ', maxWidth); res[i][maxWidth] = '\0'; } // 递归填充凹入表 void fillTable(TreeNode *node, int depth, int pos, int offset) { if (node == NULL) { return; } int idx = pos + offset; res[depth][idx] = node->val + '0'; fillTable(node->left, depth + 1, pos, offset / 2); fillTable(node->right, depth + 1, idx + 1, offset / 2); } fillTable(root, 0, 0, maxWidth / 2); // 打印凹入表 for (int i = 0; i < depth; i++) { printf("%s\n", res[i]); free(res[i]); } free(res); } // 创建二叉树 TreeNode *createTree(int *arr, int size, int pos) { if (pos >= size || arr[pos] == 0) { return NULL; } TreeNode *root = (TreeNode *)malloc(sizeof(TreeNode)); root->val = arr[pos]; root->left = createTree(arr, size, pos * 2 + 1); root->right = createTree(arr, size, pos * 2 + 2); return root; } int main() { int arr[] = {1, 2, 3, 0, 5, 6, 7}; // 示例二叉树 int size = sizeof(arr) / sizeof(arr[0]); TreeNode *root = createTree(arr, size, 0); printTree(root); // 按凹入表形式打印二叉树 return 0; } ``` 其中,`calcDepth` 函数计算树的深度,`printTree` 函数按凹入表形式打印二叉树,`fillTable` 函数递归填充凹入表。`createTree` 函数用于创建二叉树,这里使用了一个示例二叉树进行测试,你可以据需要修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值