java横向打印二叉树_横向打印二叉树

问题描述

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

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

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

其实就是按照 右子树 根 左子树的顺序遍历,每个输出占一行,写一个递归遍历的函数,traversal(BST *node,int h),h是空白的位数,当然空白中可能也有'|',对于结点node先遍历

它的右子树即最先输出的,node和他的右子树之间是竖线连接的,即他们之间这些行每行相同位置都是’|‘取代'.',一共多少行(node右子树的左子树结点总数),后面左子树的情况类似。不过这里右子树的情况需要加个判断,因为遍历是从node右子树的右子树开始。num记录行数,tar记录这个判断条件也就是node的右结点Data,只有比这个值小才满足。

代码:

#include #include#include#include#include#include

using namespacestd;structBST {intData,l,r;

BST*Left = NULL,*Right =NULL;

BST(intd) {

Data=d;

l= 0,r = 0;///记录左子树结点个数以及右子树的 后面遍历用到

}

}*head;int num[2000];int tar[2000];

BST* Insert(BST *h,intd) {if(h ==NULL) {

h= newBST(d);

}else if(d < h ->Data) {

h-> Left = Insert(h ->Left,d);

h-> l ++;

}else{

h-> Right = Insert(h ->Right,d);

h-> r ++;

}returnh;

}int nc(intd) {int c = 0;while(d) {

c++;

d/= 10;

}returnc;

}void traversal(BST *node,int h) {///中序遍历 右 中 左

if(node == NULL) return;int ht = nc(node -> Data);///h是上层空白的个数,ht记录这一层的数字占的空间那么下一层需要输出的空白就是h + ht

if(h) ht += 2;///不是根 数字前要输出 |- 所以这是两个位

if(node -> Left || node -> Right) ht ++;///有子树需要输出 -| 竖线重合不算在内

if(node ->Right) {

num[h+ ht] += node -> Right -> l;///右子树的左子树的结点个数 表示 后面在输出右子树的左子树的时候h + ht位置不输出'.'而是输出'|'

tar[h + ht] = node -> Right -> Data;///因为这中间情况会先遍历右子树的右子树 为了避免提前输出'|'所以设置当Data小于tar时才输出

traversal(node -> Right,h +ht);

}for(int i = 0;i < h;i ++) {if(num[i] && (tar[i] == 10001 || node -> Data

putchar('|');

num[i]--;

}else putchar('.');

}if(h) printf("|-");

printf("%d",node ->Data);if(node -> Left || node -> Right) printf("-|");

putchar('\n');if(node ->Left) {

num[h+ ht] += node -> Left ->r;

tar[h+ ht] = 10001;///跟前面不同

traversal(node -> Left,h +ht);

}

}intmain() {intd;while(~scanf("%d",&d)) {

head=Insert(head,d);

}

traversal(head,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、付费专栏及课程。

余额充值