英文:
Pretty Print Binary Tree
问题
I understand the issues you're facing with your code for pretty printing the binary search tree. To add the "|" character to connect nodes vertically, you can modify your printTree
method as follows:
private void printTree(Node node, int space, boolean isRight) {
if (node == null) return;
space += node.getSize() + 1;
printTree(node.left, space, false);
if (node == root) {
space = space - root.getSize() - 1;
}
if (node == root.left) {
space = root.getSize();
}
if (node == root.right) {
space = root.getSize();
}
mainSB.append(" ".repeat(Math.max(0, space)));
if (node.right == null && node.left == null) {
if (node == root)
mainSB.append(node.data).append("\n");
else
mainSB.append(isRight ? "└──" : "┌──").append(node.data).append("\n");
} else {
if (node == root)
mainSB.append(node.data).append("┤\n");
else
mainSB.append(isRight ? "└──" : "┌──").append(node.data).append("┤\n");
}
printTree(node.right, space, true);
}
This change should help you add the "|" character to connect nodes that are far apart vertically and improve the horizontal spacing as well. Please give it a try with the provided code modifications.
英文:
I am working on the following code challenge:
> PrintableTree
is a simple Binary Search Tree with no balancing.
It may contain int values that are added via the add
method.
The main challenge is to pretty print the tree via the prettyPrint
method. This means that the whole tree should be converted to a String representing its inner structure from the smaller values to the greater ones. Also, you must use box-drawing characters to show node connections.
>
> ### Example:
>
> Elements: 123 11 200 1 100 150 2000
>
> Pretty printed tree:
>
>
> ┌1
> ┌11┤
> │ └100
> 123┤
> │ ┌150
> └200┤
> └2000
>
>
> Another example (of not so balanced tree):
>
> Elements: 931 39 196 385 388 207 185 955 957 542 904 498 394
>
> Pretty printed tree:
>
>
> ┌39┐
> │ │ ┌185
> │ └196┤
> │ │ ┌207
> │ └385┤
> │ └388┐
> │ │ ┌394
> │ │ ┌498┘
> │ └542┤
> │ └904
> 931┤
> └955┐
> └957
>
>
> Your class should implement this interface
>
>
> public interface PrintableTree {
>
> void add(int i);
> String prettyPrint();
>
> static PrintableTree getInstance() {
> return new PrettyPrintableTree();
> }
> }
>
I wrote this implementation:
public class PrettyPrintableTree implements PrintableTree {
private static class Node {
private final int data;
private Node left = null;
private Node right = null;
public Node(int data) {
this.data = data;
}
public int getSize() {
return Integer.toString(data).length();
}
}
private Node root = null;
private StringBuilder mainSB = new StringBuilder();
@Override
public void add(int i) {
root = add(root, i);
}
private Node add(Node node, int value) {
if (node == null) {
return new Node(value);
} else if (value < node.data) {
node.left = add(node.left, value);
} else {
node.right = add(node.right, value);
}
return node;
}
private void printSimple(Node node) {
if (node != null) {
printSimple(node.left);
System.out.println(node.data);
printSimple(node.right);
}
}
@Override
public String prettyPrint() {
printTree(root,0, false);
System.out.println(mainSB);
return mainSB.toString();
}
private void printTree(Node node, int space, boolean isRight)
{
if (node == null) return;
space += node.getSize() + 1;
printTree(node.left, space, false);
if (node == root) {
space = space - root.getSize() - 1;
}
if (node == root.left) {
space = root.getSize();
}
if (node == root.right) {
space = root.getSize();
}
mainSB.append(" ".repeat(Math.max(0, space)));
if (node.right == null && node.left == null) {
if (node == root)
mainSB.append(node.data).append("\n");
else
mainSB.append(isRight ? "└" : "┌").append(node.data).append("\n");
}
else if (node.right != null && node.left != null) {
if (node == root)
mainSB.append(node.data).append("┤").append("\n");
else
mainSB.append(isRight ? "└" : "┌").append(node.data).append("┤").append("\n");
}
else if (node.right == null) {
if (node == root)
mainSB.append(node.data).append("┘").append("\n");
else
mainSB.append(isRight ? "└" : "┌").append(node.data).append("┘").append("\n");
}
else {
if (node == root)
mainSB.append(node.data).append("┐").append("\n");
else
mainSB.append(isRight ? "└" : "┌").append(node.data).append("┐").append("\n");
}
printTree(node.right, space, true);
}
}
But I have some problems:
I can't figure out how to add the "|" character so to connect nodes that are far apart in their vertical distance. There are some problems with the horizontal spacing as well.
You can see these problems in the following outputs produced by the above code:
Elements: 123 11 200 1 100 150 2000
┌1
┌11┤
└100
123┤
┌150
└200┤
└2000
elements: 931 39 196 385 388 207 185 955 957 542 904 498 394
┌39┐
┌185
└196┤
┌207
└385┤
└388┐
┌394
┌498┘
└542┤
└904
931┤
└955┐
└957
答案1
得分: 0
以下是您要翻译的内容:
You could use a second StringBuilder to maintain what should appear on one line only, so you can keep track of vertical lines that should be drawn higher up (more left) in the tree.
Then extend the main StringBuilder with copies from that.
NB: I wouldn't use an instance variable for maintaining that StringBuilder. It seems better practice to use a local variable for that, passing it on as an argument.
Here are the functions you could define:
public void prettyPrint() {
System.out.println(prettyString());
}
public String prettyString() {
StringBuilder treeSB = new StringBuilder();
prettyString(root, new StringBuilder("\n"), treeSB);
return treeSB.substring(1); // Omit the initial '\n'
}
private void prettyString(Node node, StringBuilder lineSB, StringBuilder treeSB) {
if (node == null) return;
int dataSize = node.getSize();
int depth = lineSB.length();
int i = "\n │".indexOf(lineSB.charAt(depth - 1));
int j = (node.left != null ? 2 : 0) + (node.right != null ? 1 : 0);
lineSB.append(" ".repeat(dataSize + 1));
prettyString(node.left, lineSB, treeSB);
lineSB.set length(depth - 1);
treeSB.append(lineSB);
treeSB.append("\n┌└".charAt(i));
treeSB.append(node.data);
treeSB.append(" ┐┘┤".charAt(j));
lineSB.append("│ ".charAt(i));
lineSB.append(" ".repeat(dataSize));
lineSB.append(" │ │".charAt(j));
prettyString(node.right, lineSB, treeSB);
}
英文:
You could use a second StringBuilder to maintain what should appear on one line only, so you can keep track of vertical lines that should be drawn higher up (more left) in the tree.
Then extend the main StringBuilder with copies from that.
NB: I wouldn't use an instance variable for maintaining that StringBuilder. It seems better practice to use a local variable for that, passing it on as argument.
Here are the functions you could define:
public void prettyPrint() {
System.out.println(prettyString());
}
public String prettyString() {
StringBuilder treeSB = new StringBuilder();
prettyString(root, new StringBuilder("\n"), treeSB);
return treeSB.substring(1); // Omit initial '\n'
}
private void prettyString(Node node, StringBuilder lineSB, StringBuilder treeSB)
{
if (node == null) return;
int dataSize = node.getSize(); // Integer.toString(node.data).length();
int depth = lineSB.length();
int i = "\n │".indexOf(lineSB.charAt(depth - 1));
int j = (node.left != null ? 2 : 0) + (node.right != null ? 1 : 0);
lineSB.append(" ".repeat(dataSize + 1));
prettyString(node.left, lineSB, treeSB);
lineSB.setLength(depth - 1);
treeSB.append(lineSB);
treeSB.append("\n┌└".charAt(i));
treeSB.append(node.data);
treeSB.append(" ┐┘┤".charAt(j));
lineSB.append("\n│ ".charAt(i));
lineSB.append(" ".repeat(dataSize));
lineSB.append(" │ │".charAt(j));
prettyString(node.right, lineSB, treeSB);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论