порядок уровней, обход дерева - Как отслеживать уровень? - PullRequest
1 голос
/ 05 декабря 2011

Как отслеживать уровень при обходе двоичного дерева в порядке уровней или в порядке широты в порядке?

Узлы в двоичном дереве имеют только левую и правую ссылки.

Iхочу иметь возможность различать каждый ряд узлов.

Вот мой метод прохождения порядка уровня:

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

Ответы [ 3 ]

3 голосов
/ 05 декабря 2011
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 голос
/ 07 марта 2012

Можно отслеживать уровень, когда вы знаете, что количество узлов удваивается на каждом уровне. Например, на уровне 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;
}
0 голосов
/ 19 октября 2018

вот моя javascript-версия обхода порядка уровней, которая должна указать вам правильное направление

Я смотрел это видео перед тем, как написать

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
}

можно найти на моем github с тестами

...