Двоичная куча — различия между версиями
(→Определение) |
(→Восстановление свойств кучи) |
||
Строка 31: | Строка 31: | ||
sift_down(i) | sift_down(i) | ||
// heap_size - количество элементов в куче | // heap_size - количество элементов в куче | ||
− | if (2 * i <= A.heap_size) | + | if (2 * i + 1 <= A.heap_size) |
− | left = A[2 * i] // левый сын | + | left = A[2 * i + 1] // левый сын |
else | else | ||
left = inf | left = inf | ||
− | if (2 * i + | + | if (2 * i + 2 <= A.heap_size) |
− | right = A[2 * i + | + | right = A[2 * i + 2] // правый сын |
else | else | ||
right = inf | right = inf | ||
if (left == right == inf) return | if (left == right == inf) return | ||
if (right <= left && right < A[i]) | if (right <= left && right < A[i]) | ||
+ | swap(A[2 * i + 2], A[i]) | ||
+ | sift_down(2 * i + 2) | ||
+ | if (left < A[i]) | ||
swap(A[2 * i + 1], A[i]) | swap(A[2 * i + 1], A[i]) | ||
− | sift_down(2 * i + 1 | + | sift_down(2 * i + 1) |
− | |||
− | |||
− | |||
</code> | </code> | ||
Если значение измененного элемента уменьшается, то свойства кучи восстанавливаются функцией sift_up(i). | Если значение измененного элемента уменьшается, то свойства кучи восстанавливаются функцией sift_up(i). |
Версия 11:51, 11 июня 2012
Содержание
Определение
Определение: |
Двоичная куча или пирамида — такое двоичное подвешенное дерево, для которого выполнены следующие три условия:
|
Удобнее всего двоичную кучу хранить в виде массива
, у которого нулевой элемент, — элемент в корне, а потомками элемента являются и . Высота кучи определяется как высота двоичного дерева. То есть она равна количеству рёбер в самом длинном простом пути, соединяющем корень кучи с одним из её листьев. Высота кучи есть , где — количество узлов дерева.Чаще всего используют кучи для минимума (когда предок не больше детей) и для максимума (когда предок не меньше детей).
Двоичные кучи используют, например, для того, чтобы извлекать минимум из набора чисел за
. Двоичные кучи — частный случай приоритетных очередей. Приоритетная очередь — это структура данных, которая позволяет хранить пары (значение и ключ) и поддерживает операции добавления пары, поиска пары с минимальным ключом и ее извлечение.Базовые процедуры
Восстановление свойств кучи
Если в куче изменяется один из элементов, то она может перестать удовлетворять свойству упорядоченности. Для восстановления этого свойства служат процедуры sift_down (просеивание вниз) и sift_up (просеивание вверх). Если значение измененного элемента увеличивается, то свойства кучи восстанавливаются функцией sift_down(i). Работа процедуры: если
-й элемент меньше, чем его сыновья, всё поддерево уже является кучей, и делать ничего не надо. В противном случае меняем местами -й элемент с наименьшим из его сыновей, после чего выполняем sift_down() для этого сына. Процедура выполняется за время .
sift_down(i) // heap_size - количество элементов в куче if (2 * i + 1 <= A.heap_size) left = A[2 * i + 1] // левый сын else left = inf if (2 * i + 2 <= A.heap_size) right = A[2 * i + 2] // правый сын else right = inf if (left == right == inf) return if (right <= left && right < A[i]) swap(A[2 * i + 2], A[i]) sift_down(2 * i + 2) if (left < A[i]) swap(A[2 * i + 1], A[i]) sift_down(2 * i + 1)
Если значение измененного элемента уменьшается, то свойства кучи восстанавливаются функцией sift_up(i).
Работа процедуры: если элемент больше своего отца, условие 1 соблюдено для всего дерева, и больше ничего делать не нужно. Иначе, мы меняем местами его с отцом. После чего выполняем sift_up для этого отца. Иными словами, слишком большой элемент всплывает наверх. Процедура выполняется за время
.
sift_up(i) if (i == 1) return if (A[i] < A[i / 2]) swap(A[i], A[i / 2]); sift_up(i / 2)
Извлечение минимального элемента
Выполняет извлечение минимального элемента из кучи за время
. Извлечение выполняется в четыре этапа:- Значение корневого элемента (он и является минимальным) сохраняется для последующего возврата.
- Последний элемент копируется в корень, после чего удаляется из кучи.
- Вызывается sift_down(i) для корня.
- Сохранённый элемент возвращается.
extract_min() min = A[1] A[1] = A[A.heap_size] A.heap_size = A.heap_size - 1 sift_down(1) return min
Добавление нового элемента
Выполняет добавление элемента в кучу за время
. Добавление произвольного элемента в конец кучи, и восстановление свойства упорядоченности с помощью процедуры sift_up.
insert(key) A.heap_size = A.heap_size + 1 A[A.heap_size] = key sift_up(A.heap_size)