简体   繁体   English

在 Java 中以树结构打印值?

[英]Printing values in a tree structure in Java?

I am trying to write this code to print the given user inputs in a tree structure that follows我正在尝试编写此代码以在下面的树结构中打印给定的用户输入

      x
  x       x
x            x

but it does not output that way.但它不会那样输出。 I am getting the output as我得到的输出为

x
x
x

This is the function I have written that gets and prints:这是我编写的获取和打印函数:

private void inOrder(Node n)
{
    if(n == null) // recursion ends when node is null
    return;
{
    inOrder(n.left);
    System.out.println(n.data);
    inOrder(n.right);
}
}

public void printInorder()
{
    inOrder(root);
}

This approach runs into trouble because any calls to println() preclude printing further nodes on a line.这种方法会遇到麻烦,因为对println()任何调用都会阻止在一行上打印更多节点。 Using a level order traversal/BFS will enable you to call println() to move to the next line only when all nodes on a given tree level have already been printed.仅当给定树级别上的所有节点都已打印时,使用级别顺序遍历/BFS将使您能够调用println()以移动到下一行。

The bigger difficulty lies in keeping track of the horizontal placement of each node in a level.更大的困难在于跟踪关卡中每个节点的水平位置。 Doing this properly involves considering the depth, length of the node data and any empty children.正确执行此操作涉及考虑节点数据的深度、长度和任何空子节点。 If you can, consider printing your tree with depth increasing from left to right, similar to the unix command tree , rather than top-down, which simplifies the algorithm.如果可以,请考虑打印深度从左到右增加的树,类似于 unix 命令tree ,而不是自上而下,这简化了算法。

Here's a proof-of-concept for a top-down print.这是自顶向下打印的概念验证。 Spacing formulas are from this excellent post on this very topic.间距公式来自这篇关于这个主题的优秀文章 The strategy I used is to run a BFS using a queue, storing nodes (and null placeholders) in a list per level.我使用的策略是使用队列运行 BFS,在每个级别的列表中存储节点(和空占位符)。 Once the end of a level is reached, spacing is determined based on the number of nodes on a level, which is 2 n-1 , and printed.一旦到达一个级别的末尾,间距将根据级别上的节点数确定,即 2 n-1 ,并打印。 A simplifying assumption is that node data width is 1.一个简化的假设是节点数据宽度为 1。

import java.util.*;
import static java.lang.System.out;

public class Main {
    static void printLevelOrder(Node root) {
        LinkedList<QItem> queue = new LinkedList<>();
        ArrayList<Node> level = new ArrayList<>();
        int depth = height(root);
        queue.add(new QItem(root, depth));

        for (;;) {
            QItem curr = queue.poll();

            if (curr.depth < depth) {
                depth = curr.depth;

                for (int i = (int)Math.pow(2, depth) - 1; i > 0; i--) { 
                    out.print(" ");
                }

                for (Node n : level) {
                    out.print(n == null ? " " : n.val);

                    for (int i = (int)Math.pow(2, depth + 1); i > 1; i--) {
                        out.print(" ");
                    }
                }

                out.println();
                level.clear();

                if (curr.depth <= 0) {
                    break;
                }
            }

            level.add(curr.node);

            if (curr.node == null) {
                queue.add(new QItem(null, depth - 1));
                queue.add(new QItem(null, depth - 1));
            }
            else {
                queue.add(new QItem(curr.node.left, depth - 1));
                queue.add(new QItem(curr.node.right, depth - 1));
            }
        }
    }

    static int height(Node root) {
        return root == null ? 0 : 1 + Math.max(
            height(root.left), height(root.right)
        );
    }

    public static void main(String[] args) {
        printLevelOrder(
            new Node<Integer>(
                1, 
                new Node<Integer>(
                    2, 
                    new Node<Integer>(
                        4, 
                        new Node<Integer>(7, null, null), 
                        new Node<Integer>(8, null, null)
                    ),
                    null
                ),
                new Node<Integer>(
                    3, 
                    new Node<Integer>(
                        5, 
                        new Node<Integer>(9, null, null),
                        null
                    ),
                    new Node<Integer>(
                        6,
                        null,
                        new Node<Character>('a', null, null)    
                    )
                )
            )
        );
    }
}

class Node<T> {
    Node left;
    Node right;
    T val;

    public Node(T val, Node left, Node right) {
        this.left = left;
        this.right = right;
        this.val = val;
    }
}

class QItem {
    Node node;
    int depth;

    public QItem(Node node, int depth) {
        this.node = node;
        this.depth = depth;
    }
}

Output:输出:

       1
   2       3
 4       5   6
7 8     9     a

Try it!尝试一下!

You have a problem to print the way you want.您在按照您想要的方式打印时遇到问题。 An In order will print left, current and right. In order 将打印左、当前和右。 These are in different levels in the tree.它们位于树中的不同级别。 As soon you print a down level you can't print the current one above because it was already printed.一旦你打印下一层,你就不能打印上面的当前层,因为它已经被打印了。

Also don't forget the println will print that string and give a new line after.也不要忘记 println 将打印该字符串并在之后给出一个新行。

To have a fancy design, you probably need to do some fancy engineering to align them perfectly, something like this:为了有一个漂亮的设计,你可能需要做一些漂亮的工程来完美地对齐它们,就像这样:

You need a Queue for the nodes to visit.您需要一个队列来访问节点。

printNode(Node root, queueWithNodesAndStartAndEnd, start, end)
   print me at the middle of start and end
   put my left child in the queue with start = myStart and end = middle of my start and my end
   put my right child in the queue with start = middle of my start and my end and end  = my end
   pop (get and remove) first element from queue
   if not empty print popped node with start and end provided

I know this is pseudo-code but you should be able to implement it.我知道这是伪代码,但您应该能够实现它。

This is the nicest solution I've seen: https://stackoverflow.com/a/42449385/9319615这是我见过的最好的解决方案: https : //stackoverflow.com/a/42449385/9319615

Here is my code snippet leveraging it.这是我利用它的代码片段。 This class will run as is.这个类将按原样运行。

class Node {
    final int value;
    Node left;
    Node right;

    Node(int value) {
        this.value = value;
        right = null;
        left = null;
    }

    public void print() {
        print("", this, false);
    }

    private void print(String prefix, Node n, boolean isLeft) {
        if (n != null) {
            System.out.println(prefix + (isLeft ? "|-- " : "\\-- ") + n.value);
            print(prefix + (isLeft ? "|   " : "    "), n.left, true);
            print(prefix + (isLeft ? "|   " : "    "), n.right, false);
        }
    }


}

class BinaryTree {
    Node root;

    private Node addRecursive(Node current, int value) {
        if (current == null) {
            return new Node(value);
        }

        if (value < current.value) {
            current.left = addRecursive(current.left, value);
        } else if (value > current.value) {
            current.right = addRecursive(current.right, value);
        } else {
            // value already exists
            return current;
        }

        return current;
    }

    public void add(int value) {
        root = addRecursive(root, value);
    }

    public void traverseInOrder(Node node) {
        if (node != null) {
            traverseInOrder(node.left);
            System.out.print(" " + node.value);
            traverseInOrder(node.right);
        }
    }


}

public class Main {

    public static void main(String[] args) {

        BinaryTree bt = new BinaryTree();
        bt.add(6);
        bt.add(4);
        bt.add(8);
        bt.add(3);
        bt.add(5);
        bt.add(7);
        bt.add(9);

        System.out.println("Print in order->");
        bt.traverseInOrder(bt.root);

        System.out.println("\n\nPrint Tree Structure");
        bt.root.print();
    }

}

Output example输出示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM