Рубрики
Без рубрики

Реверсирование двоичного дерева в Java

Краткое и практическое руководство по обращению двоичного дерева в Java.

Автор оригинала: baeldung.

1. Обзор

Обращение двоичного дерева-одна из проблем, которую нас могут попросить решить во время технического интервью .

В этом кратком руководстве мы рассмотрим несколько различных способов решения этой проблемы.

2. Двоичное дерево

Двоичное дерево – это структура данных , в которой каждый элемент имеет не более двух дочерних элементов , которые называются левым дочерним элементом и правым дочерним элементом. Верхний элемент дерева является корневым узлом, тогда как дочерние элементы являются внутренними узлами .

Однако если у узла нет дочернего элемента, он называется листом.

Сказав это, давайте создадим наш объект, представляющий узел:

public class TreeNode {

    private int value;
    private TreeNode rightChild;
    private TreeNode leftChild;

    // Getters and setters

}

Затем давайте создадим наше дерево, которое мы будем использовать в наших примерах:

    TreeNode leaf1 = new TreeNode(1);
    TreeNode leaf2 = new TreeNode(3);
    TreeNode leaf3 = new TreeNode(6);
    TreeNode leaf4 = new TreeNode(9);

    TreeNode nodeRight = new TreeNode(7, leaf3, leaf4);
    TreeNode nodeLeft = new TreeNode(2, leaf1, leaf2);

    TreeNode root = new TreeNode(4, nodeLeft, nodeRight);

В предыдущем методе мы создали следующую структуру:

Перевернув дерево слева направо, мы получим следующую структуру:

3. Реверсирование двоичного дерева

3.1. Рекурсивный метод

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

Прежде всего, мы вызовем наш метод, используя корень дерева, затем применим его к левым и правым дочерним элементам соответственно пока не достигнем листьев дерева:

public void reverseRecursive(TreeNode treeNode) {
    if(treeNode == null) {
        return;
    }

    TreeNode temp = treeNode.getLeftChild();
    treeNode.setLeftChild(treeNode.getRightChild());
    treeNode.setRightChild(temp);

    reverseRecursive(treeNode.getLeftChild());
    reverseRecursive(treeNode.getRightChild());
}

3.2. Итерационный метод

Во втором примере мы перевернем дерево, используя итерационный подход. Для этого мы будем использовать Связанный список , который мы инициализируем корнем нашего дерева .

Затем для каждого узла, который мы опрашиваем из списка, мы добавляем его дочерние элементы в этот список, прежде чем переставлять их .

Мы продолжаем добавлять и удалять из Связанного списка , пока не достигнем листьев дерева:

public void reverseIterative(TreeNode treeNode) {
    List queue = new LinkedList<>();

    if(treeNode != null) {
        queue.add(treeNode);
    }

    while(!queue.isEmpty()) {
        TreeNode node = queue.poll();
        if(node.getLeftChild() != null){
            queue.add(node.getLeftChild());
        }
        if(node.getRightChild() != null){
            queue.add(node.getRightChild());
        }

        TreeNode temp = node.getLeftChild();
        node.setLeftChild(node.getRightChild());
        node.setRightChild(temp);
    }
}

4. Заключение

В этой краткой статье мы рассмотрели два способа обращения двоичного дерева. Мы начали с использования рекурсивного метода, чтобы обратить его вспять. Затем мы закончили тем, что использовали итеративный способ достижения того же результата.

Полный исходный код этих примеров и примеров модульных тестов можно найти на Github.