蓝桥杯练习系统历届试题 横向打印二叉树

Posted 小小八

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯练习系统历届试题 横向打印二叉树相关的知识,希望对你有一定的参考价值。

问题描述

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

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

比如,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
 
思路:

首先就是题意,把图片顺时针旋转90°..
然后,建立排序二叉树没有问题,
输出...
1.中序遍历递归出每个节点所在行的字符串保存起来,过程中记录当前节点在str中的层数tier和当前节点需要扩展的|位置.
2.递归每个节点到它的左右子树所在层+|.

非常好的关于二叉树的题目.......还真是喜欢这个递归呢.........T_T

附代码:

/*
蓝桥杯横向打印二叉树
首先就是题意,把图片顺时针旋转90°..
然后,建立排序二叉树没有问题,
输出...
1.中序遍历递归出每个节点所在行的字符串保存起来,过程中记录当前节点在str中的层数tier和当前节点需要扩展的|位置.
2.递归每个节点到它的左右子树所在层+|.
*/

#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;

char str[210][30000];
int cnt = 0;
int cntStr = 0;

struct Node {
    int val; // 当前节点的值
    int lson, rson; // 左右孩子节点的编号
    int  num; // 当前节点在数组中的编号
    int tier; // 表示当前节点在str中是第tier个
    int ls; // 当前节点应该扩展的|位置

    Node() {
        num = -1;
        lson = -1;
        rson = -1;
        tier = -1;
        ls = -1;
    }
}tree[210];

void add(int rt, int val, int num) { // 参数:根节点 加入的值 加入值的序号
    if (tree[rt].val < val) { // 交给右子树
        if (tree[rt].rson == -1) {
            tree[rt].rson = num;
            tree[num].val = val;
            tree[num].num = num;
        }
        else add(tree[rt].rson, val, num);
    }
    else {
        if (tree[rt].lson == -1) {
            tree[rt].lson = num;
            tree[num].val = val;
            tree[num].num = num;
        }
        else add(tree[rt].lson, val, num);
    }
}

void midSearch(int rt) { // 中序遍历
    if (tree[rt].rson != -1) {
        midSearch(tree[rt].rson);
    }
    printf("%d\n", tree[rt].val);
    if (tree[rt].lson != -1)
    midSearch(tree[rt].lson);
}

int getlen(int num) {
    int cnt = 0;
    while(num) {
        num /= 10;
        cnt++;
    }
    return cnt;
}

void printToStr(int rt, int len) { // 每个节点所在的字符串输出到字符串str里 len表示遍历到当前数字的时候 前面已经确定的长度
    if (tree[rt].rson != -1) {
        printToStr(tree[rt].rson, len + getlen(tree[rt].val) - 1 +  (rt == 0 ? 2 : 4));
    }
    for (int i=0; i<len; ++i)
        str[cntStr][i] = ‘.‘;
    sprintf(str[cntStr]+len, "%s%d%s", rt == 0 ? "\0" : "|-", tree[rt].val, ((tree[rt].lson == -1 && tree[rt].rson == -1) ? "\n" : "-|\n"));
    tree[rt].tier = cntStr;
    if (tree[rt].lson != -1 || tree[rt].rson != -1)
    tree[rt].ls = len + (rt == 0 ? 0 : 2) + getlen(tree[rt].val) + 1;
    //cout << tree[rt].ls << "*\n";
    cntStr++;
    if (tree[rt].lson != -1) {
        printToStr(tree[rt].lson, len + getlen(tree[rt].val) - 1 + (rt == 0 ? 2 : 4));
    }
}

void format(int rt) { // 将字符串里的|加上 len表示当前节点的|位置
    if (tree[rt].rson != -1) {
        format(tree[rt].rson);
        for (int i=tree[tree[rt].rson].tier; i<=tree[rt].tier; ++i) {
            str[i][tree[rt].ls] = ‘|‘;
        }
    }
    if (tree[rt].lson != -1) {
        format(tree[rt].lson);
        for (int i=tree[rt].tier; i<=tree[tree[rt].lson].tier; ++i) {
            str[i][tree[rt].ls] = ‘|‘;
        }
    }
}

int main() {
//    freopen("1.in.cpp", "r", stdin);
    int n;
    scanf("%d", &n);
    tree[0].val = n; // 根节点为0
    tree[0].num = 0;

    while(~scanf("%d", &n)) {
        add(0, n, ++cnt); // 在二叉树上加入n
    }

    printToStr(0, 0); // 每个节点对应的字符串加入到str中
    format(0);

    for (int i=0; i<cntStr; ++i) {
        printf("%s", str[i]);
    }
    return 0;
}

  

以上是关于蓝桥杯练习系统历届试题 横向打印二叉树的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯练习系统历届试题 剪格子 dfs

蓝桥杯练习系统历届试题 带分数 dfs

(蓝桥杯)试题 算法训练 求先序排列

java蓝桥杯 试题-基础练习-数列排序

蓝桥杯历届试题 打印十字图

蓝桥杯的一阶题目在哪里