平时开发时,偶尔会操作二叉树,而查看二叉树的结构,是一种比较费时的事情,我们可以把它按照本身的结构打印出来,从而方便查看。
例如
Node a = new Node(110);
Node b = new Node(105);
Node c = new Node(115);
Node d = new Node(102);
Node e = new Node(107);
Node f = new Node(112);
Node g = new Node(117);
a.left = b;
a.right = c;
b.left = d;
b.right = e;
c.left = f;
c.right = g;
当查看此树的数据结构,咱们一般会debug,一个一个节点的看,比较浪费时间。若是把它可视化的打印出来,一窥树的全貌,就能节省一些时间。
打印之后的树:
代码如下:
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
/**
* @author wzgl
* @version 1.0
* @date 2023/5/30 13:48
*/
public class PrintTree {
/**
* 打印二叉树
*
* @param info 树信息
* @param
* @return 树
*/
public static
if (info == null) {
return "";
}
T node = info.getNode();
int deep = findDepth(node, info);
if (deep > info.maxDepth) {
throw new RuntimeException("太深了, 不好打印啊");
}
int size = (1 << deep) - 1;
List
for (int i = 0; i < deep; i++) {
lists[i] = new ArrayList<>();
}
info.setLists(lists);
addPrint(info, node, size >> 1, 0, deep);
for (List
list.sort((a, b) -> Integer.compare(a.index, b.index));
}
StringBuilder all = new StringBuilder();
for (List
StringBuilder sb = new StringBuilder();
int pre = -1;
for (PrintNode printNode : list) {
int index = printNode.index;
String value = printNode.value;
int i = index - pre - 1;
for (int j = 0; j < i; j++) {
sb.append(info.getWight());
}
pre = index;
sb.append(value);
}
all.append(sb).append(info.line);
}
return all.toString();
}
/**
* 前序 遍历,获取节点,并存储到lists中(按层存储,可以层序遍历实现)
*
* @param info 树信息
* @param node 节点
* @param index 当前元素的坐标为位置
* @param item 当前深度
* @param depth 深度
* @param
*/
private static
if (node == null) {
return;
}
List
List
String s = info.valStr == null ? String.valueOf(info.val.apply(node)) : info.valStr.apply(node);
PrintNode printNode = new PrintNode(index, s);
list.add(printNode);
int w = 1 << (depth - item - 2);
addPrint(info, info.left.apply(node), index - w, item + 1, depth);
addPrint(info, info.right.apply(node), index + w, item + 1, depth);
}
/**
* 获取深度
*
* @param node 节点
* @param info 树信息
* @param
* @return 深度
*/
private static
if (node == null) {
return 0;
}
return Math.max(findDepth(info.left.apply(node), info), findDepth(info.right.apply(node), info)) + 1;
}
/**
* 打印的信息
*/
@Data
private static class PrintNode {
// 所处的坐标
private int index;
// 打印的内容
private String value;
public PrintNode() {
}
private PrintNode(int index, String value) {
this.index = index;
this.value = value;
}
}
/**
* 存储一棵树的信息
*
* @param
*/
@Data
public static class PrintNodeInfo
// 跟节点
private T node;
// 获取当前值,默认为Integer类型,若是其他的类型,则需要修改
private Function
// 获取左节点
private Function
// 获取右节点
private Function
// 层序遍历时,存储每一层的节点
private List
// 打印的值,若没有设置,则取val(自定义用)
private Function
// 占位符,若节点为null,则需要空格占位(长度可以自定义)。
private String wight = " ";
// 每一层拼接换行符,(可以自定义)
private String line = "\n\n";
// 若是树深大于此值,则抛出异常,防止打印的过大(默认8,可自定义)
private int maxDepth = 8;
public PrintNodeInfo() {
}
public PrintNodeInfo(T node, Function
this.node = node;
this.val = val;
this.left = left;
this.right = right;
}
}
}
PrintNodeInfo类是记录树的所有信息,此处使用lambda表达式实现的,便可以使所有的树形结构都可以使用。使用方式:
import lombok.Data;
/**
* @author wzgl
* @version 1.0
* @date 2023/5/30 16:05
*/
public class PrintTreeTest {
public static void main(String[] args) {
Node a = new Node(110);
Node b = new Node(105);
Node c = new Node(115);
Node d = new Node(102);
Node e = new Node(107);
Node f = new Node(112);
Node g = new Node(117);
a.left = b;
a.right = c;
b.left = d;
b.right = e;
c.left = f;
c.right = g;
PrintTree.PrintNodeInfo
System.out.println(PrintTree.printTree(info));
}
@Data
private static class Node {
private int val;
private Node left;
private Node right;
public Node(int val) {
this.val = val;
}
}
}
需要注意的是,因为都是依靠占位符来调整打印数据格式,当使用了不合理的长度的占位符的时候,可能会出现格式错乱。因为只是为了调试用,所以能大体看出树形结构即可。
自定义某些参数
PrintTree.PrintNodeInfo
// 占位符长度
info.setPlaceHolder(" ");
// 打印的内容
info.setValStr(n -> "$" + n.val + "$");
// 每一层结尾拼接
info.setLine("\n\n-->");
System.out.println(PrintTree.printTree(info));