У меня было дерево (не двоичное), и в конце концов я решил его с помощью этого очень простого алгоритма. Другие решения использовали left и right , которые не были актуальны или даже реализованы в примерах.
Моя структура была: узлы с каждым родителем, содержащим список дочерних элементов, и каждый дочерний элемент, содержащий указатель на родителя. Довольно часто ...
После некоторого рефакторинга я придумал следующий пример с использованием Kotlin. Это должно быть тривиально, чтобы перейти на ваш язык по вашему выбору.
Вспомогательные функции
Во-первых, узел должен обеспечивать 2 простые функции. Это будет зависеть от реализации вашего класса Node:
leftMost - Это первый дочерний узел. Если у этого узла есть дочерние элементы, это первый дочерний элемент и т. Д. Если нет дочерних элементов, верните this .
fun leftMost(): Node {
if (children.isEmpty()) {
return this
}
var n = this
while (n.children.isNotEmpty()) {
n = n.children[0]
}
return n
}
nextSibling - следующий брат этого узла или NULL
fun nextSibling(): Node? {
if (parent == null) return null
val siblingIndex = parent.children.indexOf(this) + 1
return if (siblingIndex < parent.children.size) {
parent.children[siblingIndex]
} else {
null
}
}
Итерация
Итерация начинается с левой части корня.
Затем осмотрите следующего брата.
- Если NOT NULL, левый или младший брат одного из братьев
- Если NULL, родитель, и если родитель NULL, мы закончили.
Вот и все.
Вот итератор Котлина.
fun iterator(): Iterator<Node> {
var next: Node? = this.leftMost()
return object : Iterator<Node> {
override fun hasNext(): Boolean {
return next != null
}
override fun next(): Node {
val ret = next ?: throw NoSuchElementException()
next = ret.nextSibling()?.leftMost() ?: ret.parent
return ret
}
}
}
Здесь та же функция next (), но без сокращения Kotlin для работы со значениями NULL, для тех, которые не соответствуют синтаксису.
fun next(): Node {
val ret = next
if (ret == null) throw NoSuchElementException()
val nextSibling = ret.nextSibling()
if (nextSibling != null) {
next = nextSibling.leftMost()
}
else {
next = ret.parent
}
return ret
}