历届试题 横向打印二叉树
时间限制:1.0s 内存限制:256.0MB
问题描述
二叉树可以用于排序。其原理很简单:对于一个排序二叉树添加新节点时,先与根节点比较,若小则交给左子树继续处理,否则交给右子树。
当遇到空子树时,则把该节点放入那个位置。
比如,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
一 先对树进行排序,再一次按规律放入字符串数组
- 1 我的乱序代码:真的是一步一步调试过来的,跑满分真不容易
- 2 分析:
通过反复计算左右两边所剩结点数来确定数组存放的结构
注意左右两种情况要分开,因为左边的节点的 “|” 要从下往上,右边节点的 “|” 要上往下,所以我在调试的时候对递归函数增加了flag来标记为左子树还是右子树。并在执行的过程对两种情况作出不同处理即可。
/**
*@author 杨雨婷
*@date 2019年5月9日
*/
package 横向打印二叉树;
import java.util.Scanner;
public class Main2 {
static int n;
static String a[];
static node root;
static String mp[];
public static void main(String[] args) {
Scanner sca = new Scanner(System.in);
String st = sca.nextLine();
a = st.split(" ");
n = a.length;
root = new node(Integer.parseInt(a[0]));
root.left = null;
root.right = null;
//生成树
creatTree(root ,1);
//打印树
printTree(root, 0);
}
/**
* 打印树
* @param root2 根节点
* @param nt 树的深度
*/
private static void printTree(node root2, int nt) {
int le = findLen(root2.right);
int ri = n - 1 - le;
mp = new String[le + ri + 1];
int high = le + ri + 1;
//初始化第一列
for(int k = 0; k < high; k ++) {
String t = String.valueOf(root.data);
int len = t.length();
mp[k] = new String();
if(k == le) {
mp[le] += t;
mp[le] += "-";
}
else {
for(int i = 0; i < len; i ++)
mp[k] += ".";
mp[k] += ".";
}
}
//开始打印其他列
if(le > 0)printOtherLis(root2.right, 0 , le - 1, 0);
if(le > 0 || ri > 0)mp[le] += "|";
if(ri > 0)printOtherLis(root2.left, le + 1, high, 1);
/*printOtherLis(root2.right, 0 , le - 1, 0);//右
mp[le] += "|";
printOtherLis(root2.left, le + 1, high, 1);//左
*/
for(int i = 0; i < high; i ++) {
System.out.println(mp[i]);
}
}
/**
* 开始打印其他列
* @param root2 根节点
* @param le 起始行
* @param ri 终止行
* @param flag 标记为左子树还是右子树
*/
private static void printOtherLis(node root2, int le, int ri, int flag) {
int l = findLen(root2.right);
int r = findLen(root2.left);
int high = l + r + 1;
//初始化第一列和第二列
for(int k = le; k < le + high; k ++) {
if(flag == 0) {//右子树
if(k >= le + l) {
mp[k] += "|";
}
else {
mp[k] += ".";
}
}
else {
if(k < le + high - r) {
mp[k] += "|";
}
else {
mp[k] += ".";
}
}
if(k == le + l) {
mp[k] += "-";
}
else {
mp[k] += ".";
}
}
//其他列
for(int k = le; k < le + high; k ++) {
String t = String.valueOf(root2.data);
int len = t.length();
if(k == le + l) {
mp[k] += t;
}
else {
for(int i = 0; i < len; i ++)
mp[k] += ".";
mp[k] += ".";
}
}
if(l > 0)printOtherLis(root2.right, le , le + l - 1,0);
if(l > 0 || r > 0)mp[le + l] += "-|";
if(r > 0)printOtherLis(root2.left, le + l + 1, high, 1);
}
/**
* 找出左右的结点数
* @param root2
* @return
*/
private static int findLen(node root2) {
return root2 == null ? 0 : findLen(root2.left) + findLen(root2.right) + 1;
}
/**
* 生成树
* @param h 移动的头结点
* @param nt 依次递归到的节点下标
*/
private static void creatTree(node h, int nt) {
//跳出递归
if(nt == n) {
return;
}
if(Integer.parseInt(a[nt]) > h.data) {//生成右树
if(h.right == null) {
node t = new node(Integer.parseInt(a[nt]));
h.right = t;
creatTree(root, nt + 1);
}
else {
creatTree(h.right, nt);
}
}
else {//生成左树
if(h.left == null) {
node t = new node(Integer.parseInt(a[nt]));
h.left = t;
creatTree(root, nt + 1);
}
else {
creatTree(h.left, nt);
}
}
}
}
/**
* 结点
* @author ASUS
*
*/
class node{
int data;
node left;
node right;
node(int data){
this.data = data;
}
}
- 3 测试结果1:
1 3 5 7 9 2 4 6 8
..............|-9-|
..............|...|-8
..........|-7-|
..........|...|-6
......|-5-|
......|...|-4
..|-3-|
..|...|-2
1-|
- 4 时间空间花费:
二 .生成数的时候带上标记,我觉得更难理解一些
- 1 代码
/**
*@author yangyvting
*@date 2019年3月19日
*/
package 横向打印二叉树;
import java.util.Scanner;
public class 答案 {
/**
* 节点
*/
static class Node{
//值
int data;
Node left;
Node right;
//输出的值
String s;
public Node(int e){
this.data=e;
}
}
public static void main(String[] args) {
int[] n=getInput();
Node root=new Node(n[0]);
root.s=root.data+"-|";
for(int i=1;i<n.length;i++){
Node node=new Node(n[i]);
if(node.data>root.data){
addRight(node, root,0);
}else{
addLeft(node,root,0);
}
}
print(root);
}
/**
* 接收输入
* @return
*/
public static int[] getInput(){
Scanner scan=new Scanner(System.in);
String s=scan.nextLine();
String[] ss=s.split(" ");
int[] nn=new int[ss.length];
for(int i=0;i<ss.length;i++){
nn[i]=Integer.parseInt(ss[i]);
}
return nn;
}
/**
* 打印
* @param node 根节点
*/
public static void print(Node node){
//始终先打印右节点,然后打印本身,最后打印左节点
if(node.right!=null){
print(node.right);
}
//如果没有子节点,就不打印后面的"-|“
if(node.left==null&&node.right==null){
System.out.println(node.s.substring(0, node.s.length()-2));
}else{
System.out.println(node.s);
}
if(node.left!=null){
print(node.left);
}
}
/**
* 添加右节点
* @param node 子节点
* @param root 父节点
* @param flag 括号层数(0 只有一层括号,1 有多层括号)
*/
public static void addRight(Node node,Node root,int flag){
if(root.right==null){
node.s=root.s.replaceAll("[0-9]|-", ".").substring(0, root.s.length()-1);
if(flag==0){
int index=node.s.lastIndexOf("|");
if(index!=-1){
node.s=node.s.substring(0,index)+"."+node.s.substring(index+1);
}
}
node.s+="|-"+node.data+"-|";
root.right=node;
}else if(node.data>root.right.data){
addRight(node, root.right,0);
}else{
addLeft(node,root.right,1);
}
}
/**
* 添加左节点
* @param node 子节点
* @param root 父节点
* @param flag 括号层数(0 只有一层括号,1 有多层括号)
*/
public static void addLeft(Node node,Node root,int flag){
if(root.left==null){
node.s=root.s.replaceAll("[0-9]|-", ".").substring(0, root.s.length()-1);
if(flag==0){
int index=node.s.lastIndexOf("|");
if(index!=-1){
node.s=node.s.substring(0,index)+"."+node.s.substring(index+1);
}
}
node.s+="|-"+node.data+"-|";
root.left=node;
}else if(node.data>root.left.data){
addRight(node, root.left,1);
}else{
addLeft(node,root.left,0);
}
}
}
- 2 测试结果
2 3213 323 31
..|-3213-|
..|......|-323-|
..|............|-31
2-|
- 3 花费时间和空间