Если вам действительно нужна куча, вы можете использовать немного другую структуру данных, называемую левым деревом - это дерево, которое всегда не сбалансировано определенным образом, что позволяет вам выполнять операции O(log(N))
кучи.Вы можете увидеть описание этого в этом посте блога о левых деревьях .
Одна из стратегий сбалансировать ваше дерево, которая проста для понимания, - это то, что называется деревом AVL.Дерево AVL - это двоичное дерево, в котором разница в высоте между двумя дочерними элементами любого узла не может быть больше единицы.Это дерево почти сбалансировано тем, что его высота может быть не более 2log(N)
в любое время.Способ достижения этого здесь:
Сохранить высоту дерева в узлах:
defstruct value: nil, right: nil, left: nil, height: 1
Обновить высоту дерева после вставкии затем сбалансировать его:
def insert(newValue = %MaxHeap{value: rootValue}, nextValue) do
if nextValue <= rootValue do
%MaxHeap{newValue | left: insert(newValue.left, nextValue)}
else
%MaxHeap{newValue | right: insert(newValue.right, nextValue)}
end
|> set_height()
|> balance()
end
Есть функция height
, которая обрабатывает пустые деревья:
def height(nil), do: 0
def height(tree), do: tree.height
Иметь set_height
функция, которая устанавливает высоту родительского элемента на основе высоты дочерних элементов:
defp set_height(tree) do
%{tree | height: max(height(tree.left), height(tree.right)) + 1}
end
В функции balance
применяется поворот влево или вправо, если поддеревья изменяются болеечем 1 по высоте:
defp balance(tree) do
cond do
height(tree.left) > height(tree.right) + 1 -> rotate_right(tree)
height(tree.right) > height(tree.left) + 1 -> rotate_left(tree)
true -> tree
end
end
Имеют функцию rotate_left
(и аналогичную функцию rotate_right
):
defp rotate_right(tree) do
%{tree.left | right: set_height(%{tree | left: tree.left.right})}
|> set_height()
end
defp rotate_left(tree) do
%{tree.right | left: set_height(%{tree | right: tree.right.left})}
|> set_height()
end
Важно отметить, что эти повороты сохраняют инвариант двоичного дерева.
Подробнее об этом подходе вы можете прочитать в этой статье geeksforgeeks о деревьях AVL .