历届试题 横向打印二叉树

@ 蓝桥杯 练习系统 历届试题 PREV-11

资源限制

时间限制:1.0s 内存限制:256.0MB


问题描述

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

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

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

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


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


输入格式

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

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


输出格式

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


测试样例1

in: 
10 5 20

out:
...|-20
10-|
...|-5

测试样例2

in: 
5 10 20 8 4 7

out:
.......|-20
..|-10-|
..|....|-8-|
..|........|-7
5-|
..|-4

AC code:

import java.io.IOException;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.io.StreamTokenizer;
import java.io.InputStreamReader;

public class Main {

    static Node root;
    static PrintWriter out;
    static String regex = "[^.|]";

    public static void main(String[] args) throws IOException {
        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        in.nextToken();
        root = new Node((int)in.nval, false);
        while (in.nextToken() != -1)
            insert((int)in.nval, root);
        String rootStr = root.value + "-|";
        show(root.right, rootStr, true);
        out.println(rootStr);
        show(root.left, rootStr, false);
        out.close();
    }

    static void show(Node n, String f, boolean ftag) {
        if (n == null) return;
        String now = f.replaceAll(regex, ".") + "-" + n.value + noLeaf(n);
        if (n.tag == ftag) now = pruning(now);
        show(n.right, now, n.tag);
        out.println(now);
        show(n.left, now, n.tag);
    }

    static void insert(int value, Node n) {
        if (value < n.value) {
            if (n.left == null) n.left = new Node(value, true);
            else insert(value, n.left);
        } else {
            if (n.right == null) n.right = new Node(value, false);
            else insert(value, n.right);
        }
    }

    static String noLeaf(Node n) { return n.left == n.right? "":"-|"; }

    static String pruning(String s) {
        StringBuilder str = new StringBuilder(s);
        int index = str.lastIndexOf("|.");
        if (index < 0) return s;
        return str.replace(index, index + 2, "..").toString();
    }

    static class Node {
        int value;
        boolean tag;
        Node left, right;

        Node(int value, boolean tag) {
            this.value = value;
            this.tag = tag;
        }
    }
}

没有像多数程序一样,记录树枝范围再生产树枝

而是在创建节点时记录该节点是左子树还是右子树

如果同向则裁剪掉上一条树枝,否则继承所有树枝


AGO

没仔细看测试用例
一开始我以为拿到节点的深度再做中梗遍历即可
所以写了个优化版的流程,觉得代码质量害行,想先左树改下 compareTo 两参数的位置就行

import java.io.IOException;
import java.io.BufferedReader;
import java.io.StreamTokenizer;
import java.io.InputStreamReader;

import java.util.Arrays;

public class Main {

    public static void main(String[] args) throws IOException {
        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        int v, n, len = -1, dmax[] = new int[100];
        Node[] tree = new Node[100];
        tree[0] = new Node(0);
        tree[0].deep = 1;
        while (in.nextToken() != -1) {
            tree[++len] = new Node(v = (int)in.nval);
            n = 0;
            while (true) {
                if (v < tree[n].value) {
                    if (tree[n].left == 0) {
                        tree[n].left = len;
                        break;
                    } else n = tree[n].left;
                } else {
                    if (tree[n].right == 0) {
                        tree[n].right = len;
                        break;
                    } else n = tree[n].right;
                }
            }
            if (v > dmax[tree[len].deep = tree[n].deep + 1]) dmax[tree[len].deep] = v;
        }
        Arrays.sort(tree, 0, len + 1);
    }

    static class Node implements Comparable<Node> {

        int value, deep, left, right;

        Node(int value) {
            this.value = value;
        }

        public int compareTo(Node n) {
            return n.value - this.value;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值