历届试题 横向打印二叉树  (排序二叉树)

  历届试题 横向打印二叉树  

时间限制: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 花费时间和空间 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是实现二叉树按凹入表形式横向打印的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` 函数用于创建二叉树,这里使用了一个示例二叉树进行测试,你可以根据需要修改。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值