如何直观形象地树状打印一棵二叉树?
2019-05-16 本文已影响1人
SunshineBrother
网上绝大部分的二叉树打印效果都十分潦草,也不够直观形象,最近自己用JS写了个图形化小工具
BinaryTreeGraph
,也用Java写了个打印器BinaryTreePrinter
,还有个Objective-C版本BinaryTreePrinterOC
具体代码实现请看github
1、BinaryTreeGraph(JS版)
- 在线演示:BinaryTreeGraph





2、BinaryTreePrinter(Java版)
2.1、简介
-
树状打印一棵二叉树
-
比如输入一棵二叉搜索树
- [381, 12, 410, 9, 40, 394, 540, 35, 190, 476, 760, 146, 445, 600, 800]
-
就会输出

- 或者输出

2.2、核心API
public final class BinaryTrees {
// 打印一棵二叉树
public static void print(BinaryTreeInfo tree);
public static void print(BinaryTreeInfo tree, PrintStyle style);
// 打印一棵二叉树(打印完自动换行)
public static void println(BinaryTreeInfo tree);
public static void println(BinaryTreeInfo tree, PrintStyle style);
// 获得一棵二叉树的打印字符串
public static String printString(BinaryTreeInfo tree);
public static String printString(BinaryTreeInfo tree, PrintStyle style);
// 可选的打印样式
public enum PrintStyle {
LEVEL_ORDER,
INORDER
}
}
2.3、示例
** 2.3.1、实现BinaryTreeInfo**
- 根节点是谁?
- 如何查找左节点?
- 如何查找右节点?
- 如何打印单个节点?
/**
* BinarySearchTree是你自己编写的二叉树类
*/
public class BinarySearchTree<E> implements BinaryTreeInfo {
/**这里省略了大量代码,只贴出了脉络代码**/
private Node<E> root;
private static class Node<E> {
E element;
Node<E> left;
Node<E> right;
}
/********** BinaryTreeInfo **********/
@Override
public Object root() {
// 根节点是谁?
return root;
}
@Override
public Object left(Object node) {
// 如何查找左节点?
return ((Node<E>)node).left;
}
@Override
public Object right(Object node) {
// 如何查找右节点?
return ((Node<E>)node).right;
}
@Override
public Object string(Object node) {
// 如何打印单个节点?
return ((Node<E>)node).element;
}
/********** BinaryTreeInfo **********/
}
2.3.2、打印
// 随机生成的一棵二叉搜索树(random generation)
BinarySearchTree<Integer> bst = ...;
// PrintStyle.LEVEL_ORDER(层序打印)
BinaryTrees.println(bst);
// PrintStyle.INORDER(中序打印)
BinaryTrees.println(bst, PrintStyle.INORDER);


2.3.3、生成字符串写入文件
Files.writeToFile("F:/test/bst.txt", BinaryTrees.printString(bst));
2.3.4、不需要定义二叉树类
BinaryTrees.println(new BinaryTreeInfo() {
@Override
public Object root() {
return 8;
}
@Override
public Object left(Object node) {
if (node.equals(8)) return 3;
if (node.equals(3)) return 1;
if (node.equals(6)) return 4;
if (node.equals(14)) return 13;
return null;
}
@Override
public Object right(Object node) {
if (node.equals(8)) return 10;
if (node.equals(10)) return 14;
if (node.equals(3)) return 6;
if (node.equals(6)) return 7;
return null;
}
@Override
public Object string(Object node) {
return node;
}
});
BinaryTrees.println(new BinaryTreeInfo() {
@Override
public Object root() {
return "Life";
}
@Override
public Object left(Object node) {
if (node.equals("Life")) return "Animal";
if (node.equals("Person")) return "Man";
if (node.equals("Animal")) return "Cat";
if (node.equals("Dog")) return "Teddy";
return null;
}
@Override
public Object right(Object node) {
if (node.equals("Life")) return "Person";
if (node.equals("Person")) return "Woman";
if (node.equals("Animal")) return "Dog";
if (node.equals("Dog")) return "SingleDog";
return null;
}
@Override
public Object string(Object node) {
return node;
}
});


2.3.5、二叉堆
public class BinaryHeap<E> implements BinaryTreeInfo {
private int size;
private E[] elements;
@Override
public Object root() {
return 0;
}
@Override
public Object left(Object node) {
int leftIndex = ((int)node << 1) + 1;
if (leftIndex >= size) return null;
return leftIndex;
}
@Override
public Object right(Object node) {
int rightIndex = ((int)node << 1) + 2;
if (rightIndex >= size) return null;
return rightIndex;
}
@Override
public Object string(Object node) {
return elements[(int) node];
}
}
BinaryHeap<Integer> heap = new BinaryHeap<>();
for (int i = 0; i < 10; i++) {
heap.add((int)(Math.random() * 100));
}
BinaryTrees.println(heap);

3、BinaryTreePrinterOC
实现MJBinaryTreeInfo协议
@interface MJBSTNode : NSObject {
@public
id _element;
MJBSTNode *_left;
MJBSTNode *_right;
}
@end
@interface MJBinarySearchTree : NSObject <MJBinaryTreeInfo>
@end
@interface MJBinarySearchTree() {
MJBSTNode *_root;
}
@end
@implementation MJBinarySearchTree
#pragma mark - MJBinaryTreeInfo
- (id)left:(MJBSTNode *)node {
return node->_left;
}
- (id)right:(MJBSTNode *)node {
return node->_right;
}
- (id)string:(MJBSTNode *)node {
return node->_element;
}
- (id)root {
return _root;
}
@end
打印
[MJBinaryTrees println:bst];
[MJBinaryTrees println:bst style:MJPrintStyleLevelOrder];
[MJBinaryTrees println:bst style:MJPrintStyleInorder];
NSString *str = [MJBinaryTrees printString:bst];
NSString *file = @"/Users/mj/Desktop/1.txt";
[str writeToFile:file atomically:YES encoding:NSUTF8StringEncoding error:nil];
文章转载自: 如何直观形象地树状打印一棵二叉树?