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) { Listqueue = 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.