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.