Pretty Print Binary Tree

huangapple go评论60阅读模式
英文:

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);
}

huangapple
  • 本文由 发表于 2023年3月9日 23:43:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/75686912.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定