Двоичная куча — различия между версиями
Строка 5: | Строка 5: | ||
'''Двоичная куча''' или '''пирамида''' — такое двоичное дерево, для которого выполнены три условия: | '''Двоичная куча''' или '''пирамида''' — такое двоичное дерево, для которого выполнены три условия: | ||
− | * Значение (ключ) в любой вершине не | + | * Значение (ключ) в любой вершине не больше, чем значения её потомков. |
* Каждый лист имеет глубину (расстояние до корня) либо <tex>d</tex> либо <tex>d-1</tex>. Иными словами, если назвать слоем совокупность вершин, находящихся на определённой глубине, то все слои, кроме, быть может, последнего, заполнены полностью. | * Каждый лист имеет глубину (расстояние до корня) либо <tex>d</tex> либо <tex>d-1</tex>. Иными словами, если назвать слоем совокупность вершин, находящихся на определённой глубине, то все слои, кроме, быть может, последнего, заполнены полностью. | ||
Строка 19: | Строка 19: | ||
===Восстановление свойств кучи=== | ===Восстановление свойств кучи=== | ||
− | Если в куче изменяется один из элементов, то она может перестать удовлетворять свойству упорядоченности. Для восстановления этого свойства | + | Если в куче изменяется один из элементов, то она может перестать удовлетворять свойству упорядоченности. Для восстановления этого свойства служат процедуры '''Shift_Down'''(просеивание вниз) и '''Shift_Up'''(просеивание вверх). Если значение измененного элемента увеличивается, то свойства кучи восстанавливаются функцией '''Shift_Down(i)'''. |
− | + | Работа процедуры : если <tex>i</tex>-й элемент больше, чем его сыновья, всё поддерево уже является кучей, и делать ничего не надо. В противном случае меняем местами <tex>i</tex>-й элемент с наибольшим из его сыновей, после чего выполняем '''Shift_Down''' для этого сына. | |
Процедура выполняется за время <tex>O(logN)</tex>. | Процедура выполняется за время <tex>O(logN)</tex>. | ||
Строка 37: | Строка 37: | ||
min = i | min = i | ||
If (min <> i) | If (min <> i) | ||
− | + | Поменять A[i] и A[largest] | |
Shift_Down(A, min) | Shift_Down(A, min) | ||
+ | </code> | ||
+ | Если значение измененного элемента уменьшается, то свойства кучи восстанавливаются функцией'''Shift_Up(i)'''. | ||
+ | |||
+ | Работа процедуры : если элемент больше своего отца, условие 1 соблюдено для всего дерева, и больше ничего делать не нужно. Иначе, мы меняем местами его с отцом. После чего выполняем '''Shift_Up''' для этого отца. Иными словами, слишком большой элемент всплывает наверх. | ||
+ | Процедура выполняется за время <tex>O(logN)</tex>. | ||
+ | |||
+ | <code> | ||
+ | Shift_Up(i) | ||
+ | If (A[i] < A[i / 2]) | ||
+ | Поменять A[i] и A[i / 2] | ||
+ | Shift_Up(i / 2) | ||
</code> | </code> | ||
Строка 54: | Строка 65: | ||
A[1] = A[A.heap_size] | A[1] = A[A.heap_size] | ||
A.heap_size = A.heap_size - 1 | A.heap_size = A.heap_size - 1 | ||
− | Shift_Down( | + | Shift_Down(1) |
return min | return min | ||
</code> | </code> | ||
Строка 60: | Строка 71: | ||
===Добавление нового элемента=== | ===Добавление нового элемента=== | ||
− | + | Выполняет добавление элемента в кучу за время <tex>O(logN)</tex>. | |
+ | Добавление произвольного элемента в конец кучи, и восстановление свойства упорядоченности с помощью | ||
+ | |||
+ | <code> | ||
+ | Insert(key) | ||
+ | A.heap_size = A.heap_size + 1 | ||
+ | A[A.heap_size] = key; | ||
+ | Shift_Up(A.heap_size) | ||
+ | </code> | ||
== Источники == | == Источники == | ||
* [http://ru.wikipedia.org/wiki/Min-heap Двоичная куча] | * [http://ru.wikipedia.org/wiki/Min-heap Двоичная куча] |
Версия 09:29, 15 марта 2011
Определение: |
Двоичная куча или пирамида — такое двоичное дерево, для которого выполнены три условия:
|
Удобная структура данных для сортирующего дерева — массив
, у которого первый элемент, — элемент в корне, а потомками элемента являются и . Высота кучи определяется как высота двоичного дерева. То есть она равна количеству рёбер в самом длинном простом пути, соединяющем корень кучи с одним из её листьев. Высота кучи есть , где — количество узлов дерева.Содержание
Базовые процедуры
Восстановление свойств кучи
Если в куче изменяется один из элементов, то она может перестать удовлетворять свойству упорядоченности. Для восстановления этого свойства служат процедуры Shift_Down(просеивание вниз) и Shift_Up(просеивание вверх). Если значение измененного элемента увеличивается, то свойства кучи восстанавливаются функцией Shift_Down(i). Работа процедуры : если
-й элемент больше, чем его сыновья, всё поддерево уже является кучей, и делать ничего не надо. В противном случае меняем местами -й элемент с наибольшим из его сыновей, после чего выполняем Shift_Down для этого сына. Процедура выполняется за время .
Shift_Down(i)
left = 2 * i // левый сын right = 2 * i + 1 // правый сын // heap_size - количество элементов в куче If (left ≤ A.heap_size) and (A[left] < A[i]) min = left else min = i If (right ≤ A.heap_size) and (A[right] < A[i]) min = right else min = i If (min <> i) Поменять A[i] и A[largest] Shift_Down(A, min)
Если значение измененного элемента уменьшается, то свойства кучи восстанавливаются функциейShift_Up(i).
Работа процедуры : если элемент больше своего отца, условие 1 соблюдено для всего дерева, и больше ничего делать не нужно. Иначе, мы меняем местами его с отцом. После чего выполняем Shift_Up для этого отца. Иными словами, слишком большой элемент всплывает наверх. Процедура выполняется за время
.
Shift_Up(i)
If (A[i] < A[i / 2]) Поменять A[i] и A[i / 2] Shift_Up(i / 2)
Извлечение минимального элемента
Выполняет извлечение минимального элемента из кучи за время
. Извлечение выполняется в четыре этапа:- Значение корневого элемента (он и является минимальным) сохраняется для последующего возврата.
- Последний элемент копируется в корень, после чего удаляется из кучи.
- Вызывается Shift_Down для корня.
- Сохранённый элемент возвращается.
extract_min()
min = A[1] A[1] = A[A.heap_size] A.heap_size = A.heap_size - 1 Shift_Down(1) return min
Добавление нового элемента
Выполняет добавление элемента в кучу за время
. Добавление произвольного элемента в конец кучи, и восстановление свойства упорядоченности с помощью
Insert(key)
A.heap_size = A.heap_size + 1 A[A.heap_size] = key; Shift_Up(A.heap_size)