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

时间:2011-12-05 14:03:55

标签: java tree binary-tree tree-traversal 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;
}

4 个答案:

答案 0 :(得分:2)

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

此代码不会显示中间null个节点。

答案 1 :(得分:1)

当您知道每个级别的节点数量加倍时,可以跟踪级别。 例如,在级别0中,只有1个节点;在1级,有2个节点;在2级,有4个节点;在3级,有8个节点;在4级,有16个节点;等

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

它检查当前级别的节点数。当节点填满当前级别时,它会启动一个新级别。

例如,二叉树可能如下所示:

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

以下是示例的输出:

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.
]

以下是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;
}

答案 2 :(得分:1)

这是我编写的代码,用于查找没有递归的二叉树的左视图。在这里,我一直在考虑将空值视为树本身的节点的节点数量。特定级别的节点的节点数将在下一级别增加一倍。 currNulls nextNulls 会在当前级别和下一级别跟踪空值

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

答案 3 :(得分:0)

这是我的关卡遍历的javascript版本,应该为您指明正确的方向

我在写这篇文章之前看过this video

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
}
通过测试也可以在my github上找到