繁体   English   中英

在 Java 中以树结构打印值?

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

我正在尝试编写此代码以在下面的树结构中打印给定的用户输入

      x
  x       x
x            x

但它不会那样输出。 我得到的输出为

x
x
x

这是我编写的获取和打印函数:

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

这种方法会遇到麻烦,因为对println()任何调用都会阻止在一行上打印更多节点。 仅当给定树级别上的所有节点都已打印时,使用级别顺序遍历/BFS将使您能够调用println()以移动到下一行。

更大的困难在于跟踪关卡中每个节点的水平位置。 正确执行此操作涉及考虑节点数据的深度、长度和任何空子节点。 如果可以,请考虑打印深度从左到右增加的树,类似于 unix 命令tree ,而不是自上而下,这简化了算法。

这是自顶向下打印的概念验证。 间距公式来自这篇关于这个主题的优秀文章 我使用的策略是使用队列运行 BFS,在每个级别的列表中存储节点(和空占位符)。 一旦到达一个级别的末尾,间距将根据级别上的节点数确定,即 2 n-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;
    }
}

输出:

       1
   2       3
 4       5   6
7 8     9     a

尝试一下!

您在按照您想要的方式打印时遇到问题。 In order 将打印左、当前和右。 它们位于树中的不同级别。 一旦你打印下一层,你就不能打印上面的当前层,因为它已经被打印了。

也不要忘记 println 将打印该字符串并在之后给出一个新行。

为了有一个漂亮的设计,你可能需要做一些漂亮的工程来完美地对齐它们,就像这样:

您需要一个队列来访问节点。

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

我知道这是伪代码,但您应该能够实现它。

这是我见过的最好的解决方案: https : //stackoverflow.com/a/42449385/9319615

这是我利用它的代码片段。 这个类将按原样运行。

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

}

输出示例

暂无
暂无

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

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