Java 使用特定格式的级别顺序打印二叉树

Posted

技术标签:

【中文标题】Java 使用特定格式的级别顺序打印二叉树【英文标题】:Java Printing a Binary Tree using Level-Order in a Specific Format 【发布时间】:2011-01-15 12:55:24 【问题描述】:

好的,我已经阅读了所有其他相关问题,但找不到对 java 有帮助的问题。我从解读其他语言的内容中得到了大致的想法;但我还没有弄清楚。

问题:我想对排序进行级别排序(我使用递归)并将其打印成树的一般形状。

所以说我有这个:

    1 
   / \
  2   3
 /   / \
4   5   6

我的代码打印出这样的级别顺序:

1 2 3 4 5 6

我想这样打印出来:

1
2 3
4 5 6

现在,在你就我的工作发表道德演讲之前......我已经完成了我的 AP Comp Sci 项目,当我的老师提到广度优先搜索的事情时,我对此感到好奇。

我不知道它是否会有所帮助,但这是我目前的代码:

/**
  * Calls the levelOrder helper method and prints out in levelOrder.
  */
 public void levelOrder()
 
  q = new QueueList();
  treeHeight = height();
  levelOrder(myRoot, q, myLevel);
 

 /**
  * Helper method that uses recursion to print out the tree in 
  * levelOrder
  */
 private void levelOrder(TreeNode root, QueueList q, int curLev)
 
  System.out.print(curLev);
  if(root == null)
  
   return;
  

  if(q.isEmpty())
  
   System.out.println(root.getValue());
  
  else
  
   System.out.print((String)q.dequeue()+", ");
  

  if(root.getLeft() != null)
  
   q.enqueue(root.getLeft().getValue());
   System.out.println();
  
  if(root.getRight() != null)
  
   q.enqueue(root.getRight().getValue());
   System.out.println();
   curLev++;
  

  levelOrder(root.getLeft(),q, curLev);
  levelOrder(root.getRight(),q, curLev);
 

据我所知,我需要使用树的总高度,并使用级别计数器...唯一的问题是当我的 levelOrder 使用递归返回通过树时,我的级别计数器一直在计数。

对不起,如果这太多了,但一些提示会很好。 :)

【问题讨论】:

【参考方案1】:

我会这样做:

levelOrder(List<TreeNode> n) 
    List<TreeNode> next = new List<TreeNode>();
    foreach(TreeNode t : n) 
        print(t);
        next.Add(t.left);
        next.Add(t.right);
    
    println();
    levelOrder(next);

(本来是真正的代码 - 中途感到无聊,所以它是伪代码)

【讨论】:

Add 附加到列表的末尾。 foreach 从头开始​​。这样我们就可以按顺序得到项目了。 是什么阻止您尝试并亲自查看? 没什么,我尝试了一个列表,并在我们说话时正在修复错误:P 不,没有什么可以阻止算法在任意深度下工作。如果它不适合你,我会怀疑你的实现不正确。 递归没有退出案例!【参考方案2】:

答案很接近......我能看到的唯一问题是,如果树在特定位置没有节点,您可以将该指针设置为空。当您尝试将空指针放入列表时会发生什么?

这是我为最近的一项任务所做的事情。它完美无缺。您可以从任何根目录开始使用它。

  //Prints the tree in level order
  public void printTree()
    printTree(root);
  

 public void printTree(TreeNode tmpRoot)

    //If the first node isn't null....continue on
    if(tmpRoot != null)

        Queue<TreeNode> currentLevel = new LinkedList<TreeNode>(); //Queue that holds the nodes on the current level
        Queue<TreeNode> nextLevel = new LinkedList<TreeNode>();     //Queue the stores the nodes for the next level

        int treeHeight = height(tmpRoot);     //Stores the height of the current tree
        int levelTotal = 0;  //keeps track of the total levels printed so we don't  pass the height and print a billion "null"s

        //put the root on the currnt level's queue
        currentLevel.add(tmpRoot);

        //while there is still another level to print and we haven't gone past the tree's height
        while(!currentLevel.isEmpty()&& (levelTotal< treeHeight))

            //Print the next node on the level, add its childen to the next level's queue, and dequeue the node...do this until the current level has been printed
            while(!currentLevel.isEmpty())

                //Print the current value
                System.out.print(currentLevel.peek().getValue()+" ");

                //If there is a left pointer, put the node on the nextLevel's stack. If there is no ponter, add a node with a null value to the next level's stack
                tmpRoot = currentLevel.peek().getLeft();
                if(tmpRoot != null)
                    nextLevel.add(tmpRoot);
                else
                    nextLevel.add(new TreeNode(null));

                //If there is a right pointer, put the node on the nextLevel's stack. If there is no ponter, add a node with a null value to the next level's stack
                tmpRoot = currentLevel.remove().getRight();
                if(tmpRoot != null)
                    nextLevel.add(tmpRoot);
                else
                    nextLevel.add(new TreeNode(null));

            //end while(!currentLevel.isEmpty())

            //populate the currentLevel queue with items from the next level
            while(!nextLevel.isEmpty())
                currentLevel.add(nextLevel.remove());
            

            //Print a blank line to show height
            System.out.println("");

            //flag that we are working on the next level
            levelTotal++;

        //end while(!currentLevel.isEmpty())

    //end if(tmpRoot != null)

//end method printTree

public int height()
    return height(getRoot());


public int height(TreeNode tmpRoot)

    if (tmpRoot == null)
        return 0;
    int leftHeight = height(tmpRoot.getLeft());
    int rightHeight = height(tmpRoot.getRight());

    if(leftHeight >= rightHeight)
        return leftHeight + 1;
    else
        return rightHeight + 1;
 

【讨论】:

【参考方案3】:

我真的很喜欢 Anon 代码的简洁性;它的优雅。但是,有时优雅的代码并不总能转化为直观容易掌握的代码。因此,这是我尝试展示一种需要 Log(n) 更多空间的类似方法,但对于那些最熟悉深度优先搜索(沿着树的长度)的人来说应该更自然地阅读

下面的代码 sn-p 设置属于列表中特定级别的节点,并将该列表安排在包含树的所有级别的列表中。因此,您将在下面看到 List&lt;List&lt;BinaryNode&lt;T&gt;&gt;&gt;。其余的应该是不言自明的。

public static final <T extends Comparable<T>> void printTreeInLevelOrder(
        BinaryTree<T> tree) 
    BinaryNode<T> root = tree.getRoot();
    List<List<BinaryNode<T>>> levels = new ArrayList<List<BinaryNode<T>>>();
    addNodesToLevels(root, levels, 0);
    for(List<BinaryNode<T>> level: levels)
        for(BinaryNode<T> node: level)
            System.out.print(node+ " ");
        
        System.out.println();
    


private static final <T extends Comparable<T>> void addNodesToLevels(
        BinaryNode<T> node, List<List<BinaryNode<T>>> levels, int level) 
    if(null == node)
        return;
    

    List<BinaryNode<T>> levelNodes;
    if(levels.size() == level)
        levelNodes = new ArrayList<BinaryNode<T>>();
        levels.add(level, levelNodes);
    
    else
        levelNodes = levels.get(level);
    

    levelNodes.add(node);
    addNodesToLevels(node.getLeftChild(), levels, level+1);
    addNodesToLevels(node.getRightChild(), levels, level+1);

【讨论】:

【参考方案4】:

只是想在真正的 java 代码中分享 Anon 的建议并修复几个 KEY 问题(比如递归没有结束条件,因此它永远不会停止添加到堆栈中,并且不检查接收到的数组中的 null你是一个空指针异常)。

正如 Eric Hauser 所建议的,也不例外,因为它不是在修改它循环通过的集合,而是在修改一个新集合。

这里是:

public void levelOrder(List<TreeNode> n) 
    List<TreeNode> next = new ArrayList<TreeNode>();
    for (TreeNode t : n) 
        if (t != null) 
            System.out.print(t.getValue());
            next.add(t.getLeftChild());
            next.add(t.getRightChild());
        
    
    System.out.println();
    if(next.size() > 0)levelOrder(next);

【讨论】:

【参考方案5】:
public void printAllLevels(BNode node, int h)
    int i;
    for(i=1;i<=h;i++)
        printLevel(node,i);
        System.out.println();
    


public void printLevel(BNode node, int level)
    if (node==null)
        return;
    if (level==1)
        System.out.print(node.value + " ");
        else if (level>1)
            printLevel(node.left, level-1);
            printLevel(node.right, level-1);
        


public int height(BNode node) 
    if (node == null) 
        return 0;
     else 
        return 1 + Math.max(height(node.left),
                height(node.right));
    

首先,我不喜欢把这个解决方案归功于自己。这是对某人功能的修改,我对其进行了定制以提供解决方案。

我在这里使用了 3 个函数。

    首先我计算树的高度。 然后我有一个函数来打印树的特定级别。 使用树的高度和打印树的级别的函数,我遍历树并使用我的第三个函数迭代并打印树的所有级别。

我希望这会有所帮助。

编辑:此解决方案用于按级别顺序遍历打印所有节点的时间复杂度不会是 O(n)。原因是,每次你下一层,你都会一次又一次地访问相同的节点。

如果您正在寻找 O(n) 解决方案,我认为使用队列会是更好的选择。

【讨论】:

【参考方案6】:

这是代码,在一次采访中问过我这个问题...

public void printTree(TreeNode tmpRoot) 

        Queue<TreeNode> currentLevel = new LinkedList<TreeNode>();
        Queue<TreeNode> nextLevel = new LinkedList<TreeNode>();

        currentLevel.add(tmpRoot);

        while (!currentLevel.isEmpty()) 
            Iterator<TreeNode> iter = currentLevel.iterator();
            while (iter.hasNext()) 
                TreeNode currentNode = iter.next();
                if (currentNode.left != null) 
                    nextLevel.add(currentNode.left);
                
                if (currentNode.right != null) 
                    nextLevel.add(currentNode.right);
                
                System.out.print(currentNode.value + " ");
            
            System.out.println();
            currentLevel = nextLevel;
            nextLevel = new LinkedList<TreeNode>();

        

    

【讨论】:

【参考方案7】:

以下实现使用 2 个队列。在此处使用 ListBlokcingQueue,但任何队列都可以。

import java.util.concurrent.*;

public class Test5 

    public class Tree 
        private String value;
        private Tree left;
        private Tree right;

        public Tree(String value) 
            this.value = value;
        

        public void setLeft(Tree t) 
            this.left = t;
        

        public void setRight(Tree t) 
            this.right = t;
        

        public Tree getLeft() 
            return this.left;
        

        public Tree getRight() 
            return this.right;
        

        public String getValue() 
            return this.value;
        
    

    Tree tree = null;

    public void setTree(Tree t) 
        this.tree = t;
    

    public void printTree() 
        LinkedBlockingQueue<Tree> q = new LinkedBlockingQueue<Tree>();
        q.add(this.tree);
        while (true) 
            LinkedBlockingQueue<Tree> subQueue = new LinkedBlockingQueue<Tree>();
            while (!q.isEmpty()) 
                Tree aTree = q.remove();
                System.out.print(aTree.getValue() + ", ");
                if (aTree.getLeft() != null) 
                    subQueue.add(aTree.getLeft());
                
                if (aTree.getRight() != null) 
                    subQueue.add(aTree.getRight());
                
            
            System.out.println("");
            if (subQueue.isEmpty()) 
                return;
             else 
                q = subQueue;
            
        
    

    public void testPrint() 
        Tree a = new Tree("A");
        a.setLeft(new Tree("B"));
        a.setRight(new Tree("C"));
        a.getLeft().setLeft(new Tree("D"));
        a.getLeft().setRight(new Tree("E"));
        a.getRight().setLeft(new Tree("F"));
        a.getRight().setRight(new Tree("G"));
        setTree(a);
        printTree();
    

    public static void main(String args[]) 
        Test5 test5 = new Test5();
        test5.testPrint();
    

【讨论】:

【参考方案8】:

我认为我们可以通过使用一个队列本身来实现这一点。这是一个仅使用一个队列的 java 实现。基于 BFS...

public void BFSPrint()

    Queue<Node> q = new LinkedList<Node>();
    q.offer(root);
    BFSPrint(q);


private void BFSPrint(Queue<Node> q)

    if(q.isEmpty())
        return;
    int qLen = q.size(),i=0;
     /*limiting it to q size when it is passed, 
       this will make it print in next lines. if we use iterator instead, 
       we will again have same output as question, because iterator 
       will end only q empties*/
    while(i<qLen) 
        
        Node current = q.remove();
        System.out.print(current.data+" ");
        if(current.left!=null)
            q.offer(current.left);
        if(current.right!=null)
            q.offer(current.right);
        i++;
    
    System.out.println();
    BFSPrint(q);


【讨论】:

【参考方案9】:

这是最简单的解决方案

public void byLevel(Node root)
     Queue<Node> level  = new LinkedList<>();
     level.add(root);
     while(!level.isEmpty())
         Node node = level.poll();
         System.out.print(node.item + " ");
         if(node.leftChild!= null)
         level.add(node.leftChild);
         if(node.rightChild!= null)
         level.add(node.rightChild);
     

https://github.com/camluca/Samples/blob/master/Tree.java 在我的 github 中,您可以在类 Tree 中找到其他有用的功能,例如:

显示树

****......................................................****
                            42
            25                              65                              
    12              37              43              87              
9      13      30      --      --      --      --      99      
****......................................................****
Inorder traversal
9 12 13 25 30 37 42 43 65 87 99  
Preorder traversal
42 25 12 9 13 37 30 65 43 87 99  
Postorder traversal
9 13 12 30 37 25 43 99 87 65 42  
By Level
42 25 65 12 37 43 87 9 13 30 99  

【讨论】:

你没有在你的解决方案的任何地方打印新行 需要层次打印而不是树遍历。 你如何得到这个输出。不可能有解决方案【参考方案10】:

***解决方案仅将每个节点的子节点打印在一起。根据描述,这是错误的。

我们需要的是同一级别的所有节点在同一行中。

1) 应用 BFS

2) 将节点的高度存储到将保存级别的地图 - 节点列表。

3) 遍历地图并打印出结果。

参见下面的 Java 代码:

public void printByLevel(Node root)
    Queue<Node> q = new LinkedBlockingQueue<Node>();
    root.visited = true;
    root.height=1;
    q.add(root);
    //Node height - list of nodes with same level
    Map<Integer, List<Node>> buckets = new HashMap<Integer, List<Node>>();
    addToBuckets(buckets, root);
    while (!q.isEmpty())
        Node r = q.poll();

        if (r.adjacent!=null)
        for (Node n : r.adjacent)
            if (!n.visited)
                n.height = r.height+1; //adjust new height
                addToBuckets(buckets, n);
                n.visited = true;
                q.add(n);
            
        
    

    //iterate over buckets and print each list
    printMap(buckets);



//helper method that adds to Buckets list
private void addToBuckets(Map<Integer, List<Node>> buckets, Node n)
        List<Node> currlist = buckets.get(n.height);
    if (currlist==null)
    
        List<Node> list = new ArrayList<Node>();
        list.add(n);
        buckets.put(n.height, list);
    
    else
        currlist.add(n);
    



//prints the Map
private void printMap(Map<Integer, List<Node>> buckets)
    for (Entry<Integer, List<Node>> e : buckets.entrySet())
        for (Node n : e.getValue())
            System.out.print(n.value + " ");
        
    System.out.println();

【讨论】:

【参考方案11】:
public class PrintATreeLevelByLevel 
public static class Node
    int data;
    public Node left;
    public Node right;

    public Node(int data)
        this.data = data;
        this.left = null;
        this.right = null;

    


public void printATreeLevelByLevel(Node n)
    Queue<Node> queue =  new LinkedList<Node>();
    queue.add(n);
    int node = 1; //because at root
    int child = 0; //initialize it with 0 
    while(queue.size() != 0)
        Node n1 = queue.remove();
        node--;
        System.err.print(n1.data +" ");

        if(n1.left !=null)
            queue.add(n1.left);
            child ++;
        
        if(n1.right != null)
            queue.add(n1.right);
            child ++;
        
        if( node == 0)
            System.err.println();
            node = child ;
            child = 0;
        

    




public static void main(String[]args)
    PrintATreeLevelByLevel obj = new PrintATreeLevelByLevel();
    Node node1 = new Node(1);
    Node node2 = new Node(2);
    Node node3 = new Node(3);
    Node node4 = new Node(4);
    Node node5 = new Node(5);
    Node node6 = new Node(6);
    Node node7 = new Node(7);
    Node node8 = new Node(8);

    node4.left = node2;
    node4.right = node6;
    node2.left = node1;
//  node2.right = node3;
    node6.left = node5;
    node6.right = node7;
    node1.left = node8;
    obj.printATreeLevelByLevel(node4);

【讨论】:

【参考方案12】:

不使用任何隐含假设在每个节点中的级别信息的最简单方法。只需在每个级别后附加一个“空”节点。检查此空节点以了解何时打印新行:

public class BST
     private Node<T> head;
     BST()
     public void setHead(Node<T> val)head = val;

     public static void printBinaryTreebyLevels(Node<T> head)
         if(head == null) return;
         Queue<Node<T>> q = new LinkedList<>();//assuming you have type inference (JDK 7)
         q.add(head);
         q.add(null);
         while(q.size() > 0)
              Node n = q.poll();
              if(n == null)
                   System.out.println();
                   q.add(null);
                   n = q.poll();
              
              System.out.print(n.value+" ");
              if(n.left != null) q.add(n.left);
              if(n.right != null) q.add(n.right);
         
     
     public static void main(String[] args)
           BST b = new BST();
           c = buildListedList().getHead();//assume we have access to this for the sake of the example
           b.setHead(c);
           printBinaryTreeByLevels();
           return;
     

class Node<T extends Number>
     public Node left, right;
     public T value;
     Node(T val)value = val;

【讨论】:

【参考方案13】:

试试这个,使用 2 个队列来跟踪关卡。

public static void printByLevel(Node root)
    LinkedList<Node> curLevel = new LinkedList<Node>();
    LinkedList<Node> nextLevel = curLevel;

    StringBuilder sb = new StringBuilder();
    curLevel.add(root);
    sb.append(root.data + "\n");

    while(nextLevel.size() > 0)
        nextLevel = new LinkedList<Node>();
        for (int i = 0; i < curLevel.size(); i++)
            Node cur = curLevel.get(i);
            if (cur.left != null) 
                nextLevel.add(cur.left);
                sb.append(cur.left.data + " ");
            
            if (cur.right != null) 
                nextLevel.add(cur.right);
                sb.append(cur.right.data + " ");
            
        
        if (nextLevel.size() > 0) 
            sb.append("\n");
            curLevel = nextLevel;

         
    
    System.out.println(sb.toString());

【讨论】:

【参考方案14】:

这对我有用。调用 printLevel 时传递一个带有 rootnode 的数组列表。

void printLevel(ArrayList<Node> n)
    ArrayList<Node> next = new ArrayList<Node>();       
    for (Node t: n) 
        System.out.print(t.value+" "); 
        if (t.left!= null)
            next.add(t.left);
        if (t.right!=null)
            next.add(t.right);
    
    System.out.println();
    if (next.size()!=0)
        printLevel(next);

【讨论】:

【参考方案15】:

以下方法逐级返回包含所有节点的ArrayList的ArrayList:-

 public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) 

    ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>(); 
    if(root == null) return result;
    Queue q1 = new LinkedList();
    Queue q2 = new LinkedList();

    ArrayList<Integer> list = new ArrayList<Integer>();
    q1.add(root);

    while(!q1.isEmpty() || !q2.isEmpty())

        while(!q1.isEmpty())
            TreeNode temp = (TreeNode)q1.poll();
            list.add(temp.val);
            if(temp.left != null) q2.add(temp.left);
            if(temp.right != null) q2.add(temp.right);
        
        if(list.size() > 0)result.add(new ArrayList<Integer>(list));
        list.clear();
        while(!q2.isEmpty())
            TreeNode temp = (TreeNode)q2.poll();
            list.add(temp.val);
            if(temp.left != null) q1.add(temp.left);
            if(temp.right != null) q1.add(temp.right);
        
        if(list.size() > 0)result.add(new ArrayList<Integer>(list));
        list.clear();
    
    return result;

【讨论】:

【参考方案16】:

使用单个队列按级别顺序打印二叉树:

public void printBFSWithQueue() 
    java.util.LinkedList<Node> ll = new LinkedList<>();
    ll.addLast(root);
    ll.addLast(null);
    Node in = null;
    StringBuilder sb = new StringBuilder();
    while(!ll.isEmpty()) 
        if(ll.peekFirst() == null) 
            if(ll.size() == 1) 
                break;
            
            ll.removeFirst();
            System.out.println(sb);
            sb = new StringBuilder();
            ll.addLast(null);
            continue;
        
        in = ll.pollFirst();
        sb.append(in.v).append(" ");
        if(in.left != null) 
            ll.addLast(in.left);
        
        if(in.right != null) 
            ll.addLast(in.right);
        
    

【讨论】:

【参考方案17】:
void printTreePerLevel(Node root)
    
        Queue<Node> q= new LinkedList<Node>();
        q.add(root);
        int currentlevel=1;
        int nextlevel=0;
        List<Integer> values= new ArrayList<Integer>();
        while(!q.isEmpty())
        
            Node node = q.remove();
            currentlevel--;
            values.add(node.value);
            if(node.left != null)
            
                q.add(node.left);
                nextlevel++;
            
            if(node.right != null)
            
                q.add(node.right);
                nextlevel++;
            
            if(currentlevel==0)
            
                for(Integer i:values)
                
                    System.out.print(i + ",");
                
                System.out.println();
                values.clear();
                currentlevel=nextlevel;
                nextlevel=0;
            


        

    

【讨论】:

【参考方案18】:

哇。这么多答案。对于它的价值,我的解决方案是这样的:

我们知道级别顺序遍历的常规方法:对于每个节点,首先访问该节点,然后将其子节点放入 FIFO 队列中。我们需要做的是跟踪每个级别,以便该级别的所有节点都打印在一行中,而无需换行。

所以我很自然地认为它是维护一个队列。主队列包含每个级别的内部队列。每个内部队列按 FIFO 顺序包含一层中的所有节点。当我们将一个内部队列出队时,我们遍历它,将它的所有子队列添加到一个新队列中,并将这个队列添加到主队列中。

public static void printByLevel(Node root) 

    Queue<Node> firstQ = new LinkedList<>();
    firstQ.add(root);

    Queue<Queue<Node>> mainQ = new LinkedList<>();
    mainQ.add(firstQ);

    while (!mainQ.isEmpty()) 
        Queue<Node> levelQ = mainQ.remove();
        Queue<Node> nextLevelQ = new LinkedList<>();
        for (Node x : levelQ) 
            System.out.print(x.key + " ");
            if (x.left != null)    nextLevelQ.add(x.left);
            if (x.right != null)   nextLevelQ.add(x.right);
        
        if (!nextLevelQ.isEmpty()) mainQ.add(nextLevelQ);
        System.out.println();
    

【讨论】:

【参考方案19】:
public void printAtLevel(int i)
    printAtLevel(root,i);

private void printAtLevel(BTNode<T> n,int i)
    if(n != null)
        sop(n.data);
     else 
        printAtLevel(n.left,i-1);
        printAtLevel(n.right,i-1);
    

private void printAtLevel(BTNode<T> n,int i)
    if(n != null)
        sop(n.data);
        printAtLevel(n.left,i-1);
        printAtLevel(n.right,i-1);
    

【讨论】:

【参考方案20】:

A - 解决方案

我在这里写了直接解决方案。想要详细答案、demo代码和解释,可以跳过查看答案的其余标题;

public static <T> void printLevelOrder(TreeNode<T> root) 
    System.out.println("Tree;");
    System.out.println("*****");

    // null check
    if(root == null) 
        System.out.printf(" Empty\n");
        return;
    

    MyQueue<TreeNode<T>> queue = new MyQueue<>();
    queue.enqueue(root);

    while(!queue.isEmpty()) 
        handleLevel(queue);
    


// process each level
private static <T> void handleLevel(MyQueue<TreeNode<T>> queue) 
    int size = queue.size();

    for(int i = 0; i < size; i++) 
        TreeNode<T> temp = queue.dequeue();
        System.out.printf("%s ", temp.data);
        queue.enqueue(temp.left);
        queue.enqueue(temp.right);
    

    System.out.printf("\n");

B - 解释

为了按级别顺序打印树,您应该使用简单的队列实现来处理每个级别。在我的演示中,我编写了一个非常简约的简单队列类,称为 MyQueue

公共方法printLevelOrderTreeNode&lt;T&gt; 对象实例root 作为代表树根的参数。私有方法handleLevelMyQueue 实例作为参数。

在每个级别上,handleLevel 方法使队列出队的次数与队列的大小一样多。级别限制是受控的,因为此过程仅在队列大小完全等于该级别元素的情况下执行,然后将换行符放入输出。

C - TreeNode 类

public class TreeNode<T> 

    T data;
    TreeNode<T> left;
    TreeNode<T> right;

    public TreeNode(T data) 
        this.data = data;;
    


D - MyQueue 类:一个简单的队列实现

public class MyQueue<T> 

    private static class Node<T> 

        T data;
        Node next;

        public Node(T data) 
            this(data, null);
        

        public Node(T data, Node<T> next) 
            this.data = data;
            this.next = next;
        

    

    private Node head;
    private Node tail;
    private int size;

    public MyQueue() 
        head = null;
        tail = null;
    

    public int size() 
        return size;
    

    public void enqueue(T data) 
        if(data == null)
            return;

        if(head == null)
            head = tail = new Node(data);
        else 
            tail.next = new Node(data);
            tail = tail.next;
        

        size++;
    

    public T dequeue() 

        if(tail != null) 
            T temp = (T) head.data;
            head = head.next;

            size--;

            return temp;
        

        return null;
    

    public boolean isEmpty() 
        return size == 0;
    

    public void printQueue() 
        System.out.println("Queue: ");
        if(head == null)
            return;
        else 
            Node<T> temp = head;
            while(temp != null) 
                System.out.printf("%s ", temp.data);
                temp = temp.next;
            
        
        System.out.printf("%n");
    

E - DEMO : 按级别顺序打印树

public class LevelOrderPrintDemo 

    public static void main(String[] args) 
        // root level
        TreeNode<Integer> root = new TreeNode<>(1);

        // level 1
        root.left           = new TreeNode<>(2);
        root.right          = new TreeNode<>(3);

        // level 2
        root.left.left      = new TreeNode<>(4);

        root.right.left     = new TreeNode<>(5);
        root.right.right    = new TreeNode<>(6);

        /*
         *      1      root
         *     / \
         *    2   3    level-1
         *   /   / \
         *  4   5   6  level-2
         */

        printLevelOrder(root);
    

    public static <T> void printLevelOrder(TreeNode<T> root) 
        System.out.println("Tree;");
        System.out.println("*****");

        // null check
        if(root == null) 
            System.out.printf(" Empty\n");
            return;
        

        MyQueue<TreeNode<T>> queue = new MyQueue<>();
        queue.enqueue(root);

        while(!queue.isEmpty()) 
            handleLevel(queue);
        
    

    // process each level
    private static <T> void handleLevel(MyQueue<TreeNode<T>> queue) 
        int size = queue.size();

        for(int i = 0; i < size; i++) 
            TreeNode<T> temp = queue.dequeue();
            System.out.printf("%s ", temp.data);
            queue.enqueue(temp.left);
            queue.enqueue(temp.right);
        

        System.out.printf("\n");
    


F - 样本输入

    1      // root
   / \
  2   3    // level-1
 /   / \
4   5   6  // level-2

G - 样本输出

Tree;
*****
1 
2 3 
4 5 6 

【讨论】:

【参考方案21】:

Python 实现

# Function to  print level order traversal of tree
def printLevelOrder(root):
    h = height(root)
    for i in range(1, h+1):
        printGivenLevel(root, i)


# Print nodes at a given level
def printGivenLevel(root , level):
    if root is None:
        return
    if level == 1:
        print "%d" %(root.data),
    elif level > 1 :
        printGivenLevel(root.left , level-1)
        printGivenLevel(root.right , level-1)


""" Compute the height of a tree--the number of nodes
    along the longest path from the root node down to
    the farthest leaf node
"""
def height(node):
    if node is None:
        return 0
    else :
        # Compute the height of each subtree 
        lheight = height(node.left)
        rheight = height(node.right)

        #Use the larger one
        if lheight > rheight :
            return lheight+1
        else:
            return rheight+1

【讨论】:

【参考方案22】:
        Queue<Node> queue = new LinkedList<>();
        queue.add(root);

        Node leftMost = null;
        while (!queue.isEmpty()) 
            Node node = queue.poll();

            if (leftMost == node) 
                System.out.println();
                leftMost = null;
            

            System.out.print(node.getData() + " ");

            Node left = node.getLeft();
            if (left != null) 
                queue.add(left);
                if (leftMost == null) 
                    leftMost = left;
                
            

            Node right = node.getRight();
            if (right != null) 
                queue.add(right);

                if (leftMost == null) 
                    leftMost = right;
                
            
        

【讨论】:

【参考方案23】:

要解决这类需要同层或同层遍历方法的问题,可以立即使用Breath First Search或简称BFS。要实现 BFS,可以使用队列。在Queue中,每一项都是按插入顺序来的,比如一个节点有两个孩子,我们可以把它的孩子一个接一个地插入队列,这样就可以按顺序插入了。当从队列返回轮询时,我们遍历子节点,就像我们进入同一级别的树一样。 Hense 我将使用有序遍历方法的简单实现。 我建立了我的树并传递了指向根的根。 inorderTraversal 获取 root 并执行一个 while 循环,首先查看一个节点,然后获取子节点并将它们重新插入队列。请注意,节点会一一插入队列中,如您所见,一旦获取子节点,您将其附加到 StringBuilder 以构造最终输出。

levelOrderTraversal 方法中,我想按级别顺序打印树。所以我需要执行上述方法,但我不会从队列中轮询并将其子项插入回队列。因为我打算在循环中插入“下一行字符”,并且如果我将子项插入队列,这个循环将继续为每个节点插入一个新行,而我只需要检查一个级别。这就是为什么我使用 for 循环来检查我的队列中有多少项目。 我根本不从队列中轮询任何东西,因为我只想知道是否存在任何级别。

这种方法分离有助于我继续使用 BFS 数据,并且在需要时,我可以根据应用程序的要求按顺序或级别顺序打印它们。

public class LevelOrderTraversal 

public static void main(String[] args) throws InterruptedException 
    BinaryTreeNode node1 = new BinaryTreeNode(100);
    BinaryTreeNode node2 = new BinaryTreeNode(50);
    BinaryTreeNode node3 = new BinaryTreeNode(200);
    node1.left = node2;
    node1.right = node3;
    BinaryTreeNode node4 = new BinaryTreeNode(25);
    BinaryTreeNode node5 = new BinaryTreeNode(75);
    node2.left = node4;
    node2.right = node5;
    BinaryTreeNode node6 = new BinaryTreeNode(350);
    node3.right = node6;
    String levelOrderTraversal = levelOrderTraversal(node1);
    System.out.println(levelOrderTraversal);
    String inorderTraversal = inorderTraversal(node1);
    System.out.println(inorderTraversal);


private static String inorderTraversal(BinaryTreeNode root) 
    Queue<BinaryTreeNode> queue = new LinkedList<>();
    StringBuilder sb = new StringBuilder();
    queue.offer(root);
    BinaryTreeNode node;
    while ((node = queue.poll()) != null) 
        sb.append(node.data).append(",");
        if (node.left != null) 
            queue.offer(node.left);
        
        if (node.right != null) 
            queue.offer(node.right);
        
    
    return sb.toString();


public static String levelOrderTraversal(BinaryTreeNode root) 
    Queue<BinaryTreeNode> queue = new LinkedList<>();
    queue.offer(root);
    StringBuilder stringBuilder = new StringBuilder();
    while (!queue.isEmpty()) 
        handleLevelPrinting(stringBuilder, queue);
    
    return stringBuilder.toString();


private static void handleLevelPrinting(StringBuilder sb, Queue<BinaryTreeNode> queue) 
    for (int i = 0; i < queue.size(); i++) 
        BinaryTreeNode node = queue.poll();
        if (node != null) 
            sb.append(node.data).append("\t");
            queue.offer(node.left);
            queue.offer(node.right);
        
    
    sb.append("\n");


private static class BinaryTreeNode 
    int data;
    BinaryTreeNode right;
    BinaryTreeNode left;

    public BinaryTreeNode(int data) 
        this.data = data;
    



【讨论】:

虽然此代码可能会解决问题,including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。

以上是关于Java 使用特定格式的级别顺序打印二叉树的主要内容,如果未能解决你的问题,请参考以下文章

《剑指Offer——三种顺序打印二叉树》代码

数据结构之二叉树二叉树的创建遍历等操作

数据结构树相关代码(数据结构笔试复测Leecode牛客)

树二叉树存储结构二叉数遍历& 数据结构基本概念和术语

树二叉树存储结构二叉数遍历& 数据结构基本概念和术语

Java中二叉树存储结构实现