简体   繁体   English

级别顺序,树遍历 - 如何跟踪级别?

[英]level-order, tree traversal - How to keep track of the level?

How to keep track of the level while traversing a binary tree in level order or breadth-first order?如何在以级别顺序或广度优先顺序遍历二叉树时跟踪级别?

The nodes in the binary tree have left and right references only.二叉树中的节点只有左右引用。

I want to be able to distinguish between each row of nodes.我希望能够区分每行节点。

Here is my method for level-order traversal:这是我的层序遍历方法:

private static Queue<Node> traverseLevelOrder(final Node node)
{
    final Queue<Node> temporaryQueue = new LinkedList<Node>(); // Temporary queue is used for traversal.
    final Queue<Node> permanentQueue = new LinkedList<Node>(); // Permanent queue is used for node storage.

    // Add the root node, as current, to the queue.
    Node current = node;
    temporaryQueue.add(current);
    permanentQueue.add(current);

    while (!temporaryQueue.isEmpty())
    {
        current = temporaryQueue.remove();
        System.out.println(String.valueOf(current));

        // Check current's children.
        if (current != null)
        {
            final Node left = current.getLeft();
            final Node right = current.getRight();

            current = left;
            if (current != null)
            {
                temporaryQueue.add(current);
                permanentQueue.add(current);
            }

            current = right;
            if (current != null)
            {
                temporaryQueue.add(current);
                permanentQueue.add(current);
            }
        }
    }

    return permanentQueue;
}
public void bfs(Node root) {
    Queue<Node> q = new LinkedList<Node>();
    Node dummy = new Node(null);

    q.add(root);
    q.add(dummy);

    while(!q.isEmpty()) {
        Node curr = q.poll();

        if(curr != null) {
            System.out.print(curr.data + " ");

            if(curr.left != null)
                q.insert(curr.left);
            if(curr.right !== null)
                q.insert(curr.right);
        } else {
            System.out.println();
            if(!q.isEmpty())
                q.insert(dummy);
        }
    }
}

This code does not show the in-between null nodes.此代码不显示中间null节点。

Here's a code I wrote to find the left view of a binary tree without recursion.这是我编写的代码,用于在没有递归的情况下找到二叉树的左视图。 Here I am keeping track of the number of nodes considering a null as a node in the tree istself.在这里,我正在跟踪将空值视为树本身中的节点的节点数。 The number of null nodes for a null node in a paricular level will double up in the next level.节点用于在paricular级节点的数量将在一个新的水平翻倍。 The currNulls and nextNulls are keeping track of the nulls at the current and next level currNullsnextNulls跟踪当前和下一级别的空值

void leftView(Node root){
        if(root==null) return;
        boolean newL=true;
        int level=0,count=0,nextNulls=0,currNulls=0;
        Queue<Node> q=new LinkedList<>();
        q.add(root);
        while(!q.isEmpty()){
           Node node=q.remove();
           if(newL){
               System.out.print(node.data+" ");
               newL=false;
           }
           count++;
           if(node.left!=null){
               q.add(node.left);
           }
           else{
               nextNulls++;
           }
           if(node.right!=null){
               q.add(node.right);
           }
           else{
               nextNulls++;
           }
           if(1<<level == count+currNulls){
               level++;
               newL=true;
               count=0;

            //   System.out.println("Curr -"+currNulls+"\tNext - "+nextNulls);

               currNulls=nextNulls;
               nextNulls=2*nextNulls;
           }
        }
    }

It is possible to keep track of the level when you know that the number of nodes doubles each level.当您知道每个级别的节点数量加倍时,就可以跟踪级别。 For example, in level 0, there is only 1 node;例如,在级别 0 中,只有 1 个节点; in level 1, there are 2 nodes;在级别 1 中,有 2 个节点; in level 2, there are 4 nodes;在第 2 级,有 4 个节点; in level 3, there are 8 nodes; 3级有8个节点; in level 4, there are 16 nodes;在第 4 级,有 16 个节点; etc.等等。

The code for grouping each level of nodes into an array using level-order traversal in Java may look like this:在 Java 中使用层序遍历将每一层节点分组到一个数组中的代码可能如下所示:

private static Node[][] toArrayLevels(final Node node)
{
    final Queue<Node> temporaryQueue = new LinkedList<Node>(); // Temporary queue is used for level-order traversal.

    final ArrayList<Node[]> tree = new ArrayList<Node[]>(); // Levels containing their nodes.
    ArrayList<Node> nodes = new ArrayList<Node>(); // Current level containing its nodes.

    Node[][] treeArray = new Node[][]{};
    Node[] nodesArray = new Node[]{};

    Node current = node; // Level 0.
    int level = 1; // Node's children are level 1.
    temporaryQueue.add(current);

    nodes.add(current);
    tree.add(nodes.toArray(nodesArray));

    nodes = new ArrayList<Node>(2);

    while (!temporaryQueue.isEmpty())
    {
        // When the nodes completely fill the maximum spaces (2 ^ level) allowed on the current level, start the next level.
        if (nodes.size() >= Math.pow(2, level))
        {
            tree.add(nodes.toArray(nodesArray));
            nodes = new ArrayList<Node>((int) Math.pow(2, level));
            level += 1;
        }

        current = temporaryQueue.remove();

        // Check current's children.
        if (current != null)
        {
            final Node left = current.getLeft();
            final Node right = current.getRight();

            temporaryQueue.add(left);
            nodes.add(left);

            temporaryQueue.add(right);
            nodes.add(right);
        }
        else
        {
            // Null nodes fill spaces used to maintain the structural alignment of the tree.
            nodes.add(null);
            nodes.add(null);
        }
    }

    // Push remaining nodes.
    if (nodes.size() > 0)
    {
        tree.add(nodes.toArray(nodesArray));
    }

    return (tree.toArray(treeArray));
}

It checks the number of nodes on the current level.它检查当前级别上的节点数。 When the nodes have filled the current level, then it starts a new level.当节点填满当前级别时,它会开始一个新级别。

As an example, a binary tree may look like this:例如,二叉树可能如下所示:

Level 0:                                60
                         /                              \
Level 1:                50                              65
                 /              \                /              \
Level 2:        49              55              --              66
             /      \        /      \        /      \        /      \
Level 3:    --      --      --      --      --      --      --      71

Here is the output of the example:这是示例的输出:

System.out.println(Arrays.deepToString(binaryTree.toArrayLevels()));

[[{60}], [{50}, {65}], [{49}, {55}, null, {66}], [null, null, null, null, null, null, null, {71}], [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null]]

[
    [{60}], // Level 0.
    [{50}, {65}], // Level 1.
    [{49}, {55}, null, {66}], // Level 2.
    [null, null, null, null, null, null, null, {71}], // Level 3.
    [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null] // Level 4.
]

Here is the JavaScript version:这是 JavaScript 版本:

function toArrayLevels(node)
{
    var temporary = []; // Temporary is used for level-order traversal.

    var tree = []; // Levels containing their nodes.
    var nodes = []; // Current level containing its nodes.

    var current = node; // Level 0.
    var level = 1; // Node's children are level 1.

    temporary.push(current);
    tree.push([current]);

    while (temporary.length > 0)
    {
        // When the nodes completely fill the maximum spaces (2 ^ level) allowed on the current level, start the next level.
        if (nodes.length >= Math.pow(2, level))
        {
            tree.push(nodes);
            nodes = [];
            level += 1;
        }

        current = temporary.shift();

        // Check current's children.
        if (current !== null)
        {
            var left = current.left;
            var right = current.right;

            temporary.push(left);
            nodes.push(left);

            temporary.push(right);
            nodes.push(right);
        }
        else
        {
            // Null nodes fill spaces used to maintain the structural alignment of the tree.
            nodes.push(null);
            nodes.push(null);
        }
    }

    // Push remaining nodes.
    if (nodes.length > 0)
    {
        tree.push(nodes);
    }

    return tree;
}

here's my javascript version of the level order traversal, which should point you in the right direction这是我的水平顺序遍历的 javascript 版本,它应该为您指明正确的方向

I watched this video before writing this在写这篇文章之前我看了这个视频

var discovered = [];

var getLevels = function(node) {
    if (node == null) { return []}
    discovered.push(node)
    var levels = levelOrderTraverse(discovered,[])
    return levels
}

function levelOrderTraverse(discovered,elms) {
    var level = []
    for (var i = 0; i < discovered.length; i++) {
        level.push(discovered[i].val)
    }
    elms.push(level);
    var newlyDiscovered = [];
    for (var i = 0; i < discovered.length; i++) {
        if (discovered[i].left != null) {
            newlyDiscovered.push(discovered[i].left)
        }
        if (discovered[i].right != null) {
            newlyDiscovered.push(discovered[i].right)
        }
    }
    if (newlyDiscovered.length > 0) {
        levelOrderTraverse(newlyDiscovered,elms)
    }
    return elms
}

also can be found on my github with tests也可以在我的 github上找到测试

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

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