Поисковые структуры данных — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Новая статья)
Строка 1: Строка 1:
'''Поисковая структура данных''' {{---}} любая структура данных реализующая эффективный поиск конкретных элементов множества, например, конкретной записи в базе данных.
+
'''Приоритетная очередь''' (англ. ''priority queue'') {{---}} это абстрактная структура данных на подобии стека или очереди, где у каждого элемента есть приоритет. Элемент с более высоким приоритетом находится перед элементом с более низким приоритетом. Если у элементов одинаковые приоритеты, они распологаются в зависимости от своей позиции в очереди. Обычно приоритетные очереди реализуются с помощью куч (англ. ''heap'').
  
Простейший, наиболее общий, но менее эффективный поисковой структурой является простая неупорядоченный последовательная всех элементов. Расположив элементы в такой список, неизбежно возникнет ряд операций, которые потребуют линейного времени, в худшем случае, а также в средней случае. Используемые в реальной жизни поисковые структуры данных позволяют совершать операции более быстро, однако они ограничены запросами некоторого конкретного вида. Кроме того, поскольку стоимость построение таких структур пропорциональна <tex>n</tex>, их построение окупится, даже если поступает лишь несколько запросов.
+
==Операции==
  
=== Тип ===
+
* find-min (find-max) - поиск элемента с наибольшим приоритетом
 +
* insert (push) - вставка нового элемента
 +
* extract-min (extract-max) - извлечь элемент с наибольшим приоритетом
 +
* delete-min (delete-max) - удалить элемент с наибольшим приоритетом
 +
* merge - объединение двух приоритетных очередей
  
'''Статические поисковые структуры данных''' (англ. ''Online search structures'') предназначены для ответа на запросы на фиксированной базе данных.
+
==Реализации==
 +
===Наивная===
 +
В качестве наивной реализации мы можем взять обычный список и при добавлении нового элемента класть его в конец, а при запросе элемента с максимальным приоритетом проходить по всему списку. Тогда операция insert будет выполняться за <tex>O(1)</tex>, а extract-max (extract-min) за <tex>O(n)</tex>.
  
'''Динамические поисковые структуры''' (англ. ''Offline search structures'') также позволяют вставки, удаления или модификации элементов между последовательными запросами. В динамическом случае, необходимо также учитывать стоимость изменения структуры данных. Любую динамическую структуру данных можно сделать статической, если запретить вставку и удаление. Также если множество ключей известно, то можно его заранее упорядочить так, чтобы избежать худших случаев в поисках в структурах данных.
+
===Обычная===
 +
Для лучшей производительности приоритетные очереди реализуют с помощью куч, что позволяет выполнять операции вставки и удаления за <tex>O(\log n)</tex>. Использование специальных куч, таких как Фибоначчиева куча и спаренная куча, позволяет еще больше улучшить асимптотику некоторый операций.
  
=== Время работы ===
+
==Виды приорететных очередей==
 
 
Эту классификацию обычно считают самой важной. Оценивают худшее время алгоритма, среднее и лучшее для каждой операции. Лучшее время {{---}} минимальное время работы алгоритма на каком-либо наборе. Худшее время {{---}} наибольшее время.
 
 
 
=== Используемая память ===
 
 
 
Параметр структуры данных, показывающий, сколько памяти ей требуется. Обычно затраты составляют <tex>O(n)</tex>.
 
 
 
=== Сравнение структур данных ===
 
 
 
Сравним эффективность поисковых структур данных для реализации интерфейса [[Упорядоченное множество|упорядоченного множества]]. Время работы методов <tex>Predecessor</tex> и <tex>Successor</tex> совпадает с временем работы <tex>Search</tex>.
 
 
 
<tex>n</tex> {{---}} количество хранимых чисел, каждое из которых представляется с помощью <tex>w</tex> битов.
 
  
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! rowspan="2" |
+
! rowspan="2" | Название
! colspan="2" | Insert
+
! colspan="4" | Операции
! colspan="2" | Delete
 
! colspan="2" | Search
 
! colspan="2" | Память
 
 
! rowspan="2" | Описание
 
! rowspan="2" | Описание
 
|-
 
|-
! style="background: #ddffdd;" | Среднее
+
| align="center" width="5%" | find-min
! style="background: #ffdddd;" | Худшее
+
| align="center" | insert
! style="background: #ddffdd;" | Среднее
+
| align="center" width="5%" | delete-min
! style="background: #ffdddd;" | Худшее
+
| align="center" | merge
! style="background: #ddffdd;" | Среднее
 
! style="background: #ffdddd;" | Худшее
 
! style="background: #ddffdd;" | Среднее
 
! style="background: #ffdddd;" | Худшее
 
|-
 
!
 
! colspan="9" align="center" |  Динамические структуры данных
 
|-
 
| Неотсортированный массив
 
| align="center" style="background: #ddffdd;" | <tex>O(1)</tex>
 
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
 
| align="center" style="background: #ddffdd;" | <tex>O(1)</tex>
 
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
 
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
 
| align="center" | Наивная реализация, использующая [[Динамический массив|динамический массив]]. Добавление происходит в конец массива, а для поиска элемента просто проходим по всему массиву.
 
|-
 
| Отсортированный массив
 
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
 
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
 
| align="center" | То же самое, но теперь массив отсортирован. Поиск ускоряется за счёт возможности применить [[Целочисленный двоичный поиск|двоичный поиск]]. Вставка замедляется из-за необходимости поддерживать инвариант отсортированности.
 
|-
 
| Неотсортированный [[Список|список]]
 
| colspan="2" align="center" style="background: #ddffdd;" | <tex>O(1)</tex>
 
| colspan="2" align="center" style="background: #ddffdd;" | <tex>O(1)</tex>
 
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
 
| align="center" rowspan="2" | Аналогично массиву, но храним данные в [[Список|списке]]. Можно хранить дополнительную информацию о вершинах, что позволит ускорить время работы операции delete.
 
 
|-
 
|-
| Отсортированный [[Список|список]]
+
| [[2-3 куча]]
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
| align="center" rowspan="11" | <tex>O(1)</tex>
| colspan="2" align="center" style="background: #ddffdd;" | <tex>O(1)</tex>
+
| align="center" | <tex>O(1)</tex>
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
+
| align="center" | <tex>O(1)</tex>
 +
| Структура похожа на Фибоначчиеву кучу и использует в своей реализации 2-3 дерево.
 
|-
 
|-
| [[Дерево поиска, наивная реализация]]
+
| [[Биномиальная куча]]
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(1)</tex>
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(1)</tex>
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
| [[Биномиальная куча]] (англ. ''binomial heap'') {{---}} структура данных, реализующая приоритетную очередь, которая представляет собой набор биномиальных деревьев с двумя свойствами:
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
* ключ каждой вершины не меньше ключа ее родителя
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
* все биномиальные деревья имеют разный размер
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
 
| align="center" | Бинарное дерево поиска  обладает следующим свойством:  если <tex>x</tex> {{---}} узел бинарного дерева с ключом <tex>k</tex>, то все узлы в левом поддереве должны иметь ключи, меньшие <tex>k</tex>,  а в правом поддереве большие <tex>k</tex>.
 
 
|-
 
|-
| [[Рандомизированное бинарное дерево поиска]]
+
| [[Куча Бродала-Окасаки]]
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(1)</tex>
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(1)</tex>
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
| [[Куча Бродала-Окасаки]] (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании биномиальной кучи без каскадных ссылок, добавлении минимального элемента и на идеи Data-structural bootstrapping.
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
 
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
 
| align="center" | Вариант [[Дерево поиска, наивная реализация|двоисного дерево поиска]] с добавлением инвариата "случайности", что уменьнашает ожидаемую высоту дерева.
 
 
|-
 
|-
|[[АВЛ-дерево]]
+
| [[Двоичная куча]]
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(m \log(n+m))</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
+
| [[Двоичная куча]] (англ. ''binary heap'') {{---}} такое двоичное дерево, для которого выполнены три условия:
| align="center" | Сбалансированное [[Дерево поиска, наивная реализация|двоичное дерево поиска]], в котором поддерживается следующее свойство: для каждой его вершины высота её двух поддеревьев различается не более чем на <tex>1</tex>.
+
*Значение в любой вершине не меньше, чем значения её потомков.
 +
*Глубина листьев (расстояние до корня) отличается не более чем на 1 слой.
 +
*Последний слой заполняется слева направо.
 
|-
 
|-
|[[2-3 дерево]]
+
| [[Двуродительская куча]]
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(\sqrt{n})</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(\sqrt{n})</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| |
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
+
| [[Двуродительская куча]] (англ. ''bi-parental heap'' или ''beap'') {{---}} такая куча, где у каждого элемента обычно есть два ребенка (если это не последний уровень) и два родителя (если это не первый уровень). Структура позволяет производить сублиненый поиск.
| align="center" | Структура данных, представляющая собой сбалансированное дерево поиска, такое что из каждого узла может выходить две или три ветви и глубина всех листьев одинакова. Является частным случаем [[B-дерево#B.2B-.D0.B4.D0.B5.D1.80.D0.B5.D0.B2.D0.BE|B+ дерева]].
 
 
|-
 
|-
|[[B-дерево]]
+
| [[d-арная куча| <tex>d</tex>-арная куча]]
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(\log n / \log d)</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(d\log n / \log d)</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(m \log(n+m) / \log d)</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
+
| [[d-арная куча| <tex>d</tex>-арная куча]] (англ. ''<tex>d</tex>-ary heap'') {{---}} [[двоичная куча]], в которой у каждого элемента <tex>d</tex> детей вместо <tex>2</tex>.
| align="center" | Cильноветвящееся сбалансированное дерево поиска, позволяющее проводить поиск, добавление и удаление элементов за <tex>O(\log n)</tex>. B-дерево с <tex>n</tex> узлами имеет высоту <tex>O(\log n)</tex>. Количество детей узлов может быть от нескольких до тысяч (обычно степень ветвления B-дерева определяется характеристиками устройства (дисков), на котором производится работа с деревом). В-деревья также могут использоваться для реализации многих операций над динамическими множествами за время <tex>O(\log n)</tex>
 
 
|-
 
|-
|[[Красно-черное дерево]]
+
| [[Левосторонняя куча]]
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
+
| [[Левосторонняя куча]] (англ. ''leftist heap'') {{---}} двоичное левосторонее дерево (не обязательно сбалансированное), но с соблюдением порядка кучи.
| align="center" | Сбалансированное [[Дерево поиска, наивная реализация|двоичное дерево поиска]], в котором баланс осуществляется на основе "цвета" узла дерева, который принимает только два значения: "красный" (англ. ''red'') и "чёрный" (англ. ''black'').  При этом все листья дерева являются фиктивными и не содержат данных, но относятся к дереву и являются чёрными.
 
 
|-
 
|-
| [[Декартово дерево]]
+
| [[Спаренная куча]]
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(1)</tex>
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(1)</tex>
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
| [[Спаренная куча]] (англ. ''pairing heap'') {{---}} куча с относительно простой реализацией и хорошей производительностью, может быть рассмотрена как упрощенная [[Фибоначчиева куча]].
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
 
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
 
| align="center" | Бинарное дерево, в узлах которого хранится пары <tex> (x,y) </tex>, где <tex>x</tex> {{---}} это ключ, а <tex>y</tex> {{---}} это приоритет. Также оно является [[Дерево поиска, наивная реализация|двоичным деревом поиска]] по <tex>x</tex> и [[Двоичная куча|пирамидой]] по <tex>y</tex>. Предполагая, что все <tex>x</tex> и все <tex>y</tex> являются различными, получаем, что если некоторый элемент дерева содержит <tex>(x_0,y_0)</tex>, то у всех элементов в левом поддереве <tex>x < x_0</tex>, у всех элементов в правом поддереве <tex> x > x_0</tex>, а также и в левом, и в правом поддереве имеем: <tex> y < y_0</tex>.
 
 
|-
 
|-
|[[Splay-дерево]]
+
| [[Толстая куча]]
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(1)</tex>
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
| [[Толстая куча]] {{---}} это почти кучеобразный нагруженный лес.
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
 
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
 
| align="center" | [[Дерево поиска, наивная реализация|Двоичное дерево поиска]]. Оно позволяет находить быстрее те данные, которые использовались недавно, за счёт '''перемещения к корню''' (англ. ''Move to root''). Относится к разряду сливаемых деревьев. Сплей-дерево было придумано Робертом Тарьяном и Даниелем Слейтером в 1983 году.
 
 
|-
 
|-
|[[Дерево ван Эмде Боаса]]
+
| [[Тонкая куча]]
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log w)</tex>
+
| align="center" | <tex>O(1)</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log w)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log w)</tex>
+
| align="center" | <tex>O(1)</tex>
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(2^w)</tex>
+
| [[Тонкая куча]] (англ. ''thin heap'') {{---}} это структура данных, реализующая приоритетную очередь с теми же асимптотическими оценками, что и [[фибоначчиева куча]], но имеющая большую практическую ценность из-за меньших констант.
| align="center" | Cтруктура данных, представляющая собой [[Дерево поиска, наивная реализация|дерево поиска]], позволяющее хранить целые неотрицательные числа в интервале <tex>[0;2^w)</tex> и осуществлять над ними все соответствующие дереву поиска операции. Проще говоря, данная структура позволяет хранить <tex>w</tex>-битные числа.
 
Особенностью этой структуры является то, что все операции выполняются за <tex>O(\log w)</tex>, что асимптотически лучше, чем <tex>O(\log n)</tex> в большинстве других деревьев поиска, где <tex>n</tex> {{---}} количество элементов в дереве.
 
 
|-
 
|-
| [[Список с пропусками]]
+
| [[Фибоначчиева куча]]
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(1)</tex>
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
| align="center" | <tex>O(\log n)</tex>
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
+
| align="center" | <tex>O(1)</tex>
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
+
| Куча, построенная на основе Фибоначчиева дерева. [[Фибоначчиево дерево]] (англ. ''Fibonacci tree'') {{---}} биномиальное дерево, где у каждой вершины удалено не более одного ребенка.
| align="center" style="background: #ffffdd;" | <tex>O(\log n)</tex>
 
| align="center" style="background: #ffdddd;" | <tex>O(n)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
 
| align="center" | Вероятностная структура данных, основанная на нескольких отсортированных односвязных списках.
 
Отсортированный связный список является простейшей структурой с временем поиска <tex>\Theta(n)</tex>. Добавление дополнительных уровней, обеспечивающих быстрый доступ через несколько элементов, помогает улучшить асимптотику до <tex>\Theta(\log(n))</tex>
 
 
|-
 
|-
|[[Fusion tree]]
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log_{w} n)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log_{w} n)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log_{w} n)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
 
| align="center" | Дерево поиска, позволяющее хранить <tex>n</tex> <tex>w</tex>-битных чисел, используя <tex>O(n)</tex> памяти, и выполнять операции поиска за время <tex>O(\log_{w} n)</tex>. Эта структура данных была впервые предложена в 1990 году М. Фредманом (M. Fredman) и Д. Уиллардом (D. Willard).
 
|-
 
| [[Сверхбыстрый цифровой бор|Цифровой бор]]
 
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(w)</tex>
 
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(w)</tex>
 
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(w)</tex>
 
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(n \cdot w)</tex>
 
| align="center" | [[Бор]], в котором в качестве строк используются двоичные записи чисел, включая ведущие нули. Таким образом он имеет глубину <tex>w</tex>.
 
|-
 
| [[Сверхбыстрый цифровой бор|Быстрый цифровой бор]]
 
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(w)</tex>
 
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(w)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log w)</tex>
 
| colspan="2" align="center" style="background: #ffdddd;" | <tex>O(n \cdot w)</tex>
 
| align="center" | Улучшеная версия структуры цифрового бора.
 
|-
 
| [[Сверхбыстрый цифровой бор]]
 
| align="center" style="background: #ffffdd;" | <tex>O(\log w)</tex>
 
| align="center" style="background: #ffdddd;" | <tex>O(w)</tex>
 
| align="center" style="background: #ffffdd;" | <tex>O(\log w)</tex>
 
| align="center" style="background: #ffdddd;" | <tex>O(w)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(\log w)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
 
| align="center" | Улучшеная версия структуры быстрого цифрового бора.
 
|-
 
!
 
! colspan="9" align="center" | Статические структуры данных
 
|-
 
|[[Tango-дерево]]
 
| colspan="2" align="center" style="background: #e5e5e5;" | -
 
| colspan="2" align="center" style="background: #e5e5e5;" | -
 
| colspan="2" align="center" style="background: #ddffdd;" | <tex>O(\log \log n)</tex>
 
| colspan="2" align="center" style="background: #ffffdd;" | <tex>O(n)</tex>
 
| align="center" | [[Дерево поиска, наивная реализация|Двоичное дерево поиска]], которое изобрели Эрик Д. Демейн, Дион Хармон, Джон Яконо и Михаи Патраску в 2004 году. Не поддерживает операции вставки и удаления, но перестраивается по ходу поисковых запросов, чтобы отвечать на них как можно оптимальней. Это лучшая известная реализация на данный момент.
 
 
|}
 
|}
  
==См. также==
+
==Применение==
 +
* Алгоритм Дейкстры
 +
* Алгоритм Прима
 +
* Дискретно-событийное моделирование (англ. ''discrete-event simulation, DES'')
 +
* Код Хаффмана
 +
* Поиск по первому наилучшему совпадению
 +
* Управление полосой пропускания
 +
 
 +
==Реализации в языках программирования==
 +
* Стандартная библиотека шаблонов (англ. ''STL'') в C++ предоставляет методы управления кучей make_heap, push_heap и pop_heap (обычно реализуются бинарные кучи), которые оперируют с итераторами произвольного случайного доступа. Методы используют итераторы как ссылки на массивы и выполняют преобразование массив-куча.
 +
* Библиотека Boost для C++ включает в себя библиотеку для работу с кучами. В отличии от STL, поддерживает операции decrease-key и increase-key, а также имеет поддержку дополнительных видов куч, таких как [[Фибоначчиева куча]], [[Биномиальная куча]] и [[Спаренная куча]].
 +
* В Java 2 (начиная с версии 1.5) предоставляется реализация бинарной кучи в классе java.util.PriorityQueue<E>, который не поддерживает операции decrease-key и increase-key.
 +
* Python имеет модуль heapq, который реализует очереди с приоритетами с помощью бинарной кучи.
 +
* PHP имеет поддержку кучи на максимум (SplMaxHeap) и кучи на минимум (SplMinHeap), как часть Standard PHP Library начиная с версии 5.3.
 +
* В Perl имеются реализации бинарной, биномиальной и фибоначчиевой куч во всеобъемлющей сети архивов.
 +
* Go имеет пакет heap, в котором реализованы алгоритмы для работы с кучами.
 +
 
  
*[[:Сортировка|Сортировка]]
 
*[[:Поиск_подстроки_в_строке|Поиск подстроки в строке]]
 
*[[:Приоритетные_кучи|Приоритетные кучи]]
 
  
 
== Источники информации ==
 
== Источники информации ==
 
+
* [http://en.wikipedia.org/wiki/Heap_(data_structure)| Wikidedia {{---}} Heap (data structure)]
* [[wikipedia:en:Search_data_structure|Wikidedia {{---}} Search data structure]]
+
* [http://en.wikipedia.org/wiki/2%E2%80%933_heap| Wikidedia {{---}} 2-3 heap]
* [http://habrahabr.ru/post/188010/ Habrahabr {{---}} Знай сложности алгоритмов ]
+
* [http://en.wikipedia.org/wiki/Beap| Wikidedia {{---}} Beap]
 +
* [http://en.wikipedia.org/wiki/Binary_heap| Wikidedia {{---}} Binary heap]
 +
* [http://en.wikipedia.org/wiki/Binomial_heap| Wikidedia {{---}} Binomial heap]
 +
* [http://en.wikipedia.org/wiki/Brodal_queue| Wikidedia {{---}} Brodal queue]
 +
* [http://en.wikipedia.org/wiki/D-ary_heap| Wikidedia {{---}} <tex>d</tex>-ary heap]
 +
* [http://en.wikipedia.org/wiki/Fibonacci_heap| Wikidedia {{---}} Fibonacci heap]
  
 
[[Категория: Дискретная математика и алгоритмы]]
 
[[Категория: Дискретная математика и алгоритмы]]
[[Категория: Деревья поиска]]
+
[[Категория: Приоритетные очереди]]
 
[[Категория: Структуры данных]]
 
[[Категория: Структуры данных]]

Версия 21:36, 6 июня 2015

Приоритетная очередь (англ. priority queue) — это абстрактная структура данных на подобии стека или очереди, где у каждого элемента есть приоритет. Элемент с более высоким приоритетом находится перед элементом с более низким приоритетом. Если у элементов одинаковые приоритеты, они распологаются в зависимости от своей позиции в очереди. Обычно приоритетные очереди реализуются с помощью куч (англ. heap).

Операции

  • find-min (find-max) - поиск элемента с наибольшим приоритетом
  • insert (push) - вставка нового элемента
  • extract-min (extract-max) - извлечь элемент с наибольшим приоритетом
  • delete-min (delete-max) - удалить элемент с наибольшим приоритетом
  • merge - объединение двух приоритетных очередей

Реализации

Наивная

В качестве наивной реализации мы можем взять обычный список и при добавлении нового элемента класть его в конец, а при запросе элемента с максимальным приоритетом проходить по всему списку. Тогда операция insert будет выполняться за [math]O(1)[/math], а extract-max (extract-min) за [math]O(n)[/math].

Обычная

Для лучшей производительности приоритетные очереди реализуют с помощью куч, что позволяет выполнять операции вставки и удаления за [math]O(\log n)[/math]. Использование специальных куч, таких как Фибоначчиева куча и спаренная куча, позволяет еще больше улучшить асимптотику некоторый операций.

Виды приорететных очередей

Название Операции Описание
find-min insert delete-min merge
2-3 куча [math]O(1)[/math] [math]O(1)[/math] [math]O(\log n)[/math] [math]O(1)[/math] Структура похожа на Фибоначчиеву кучу и использует в своей реализации 2-3 дерево.
Биномиальная куча [math]O(1)[/math] [math]O(\log n)[/math] [math]O(1)[/math] Биномиальная куча (англ. binomial heap) — структура данных, реализующая приоритетную очередь, которая представляет собой набор биномиальных деревьев с двумя свойствами:
  • ключ каждой вершины не меньше ключа ее родителя
  • все биномиальные деревья имеют разный размер
Куча Бродала-Окасаки [math]O(1)[/math] [math]O(\log n)[/math] [math]O(1)[/math] Куча Бродала-Окасаки (англ. Brodal's and Okasaki's Priority Queue) — основана на использовании биномиальной кучи без каскадных ссылок, добавлении минимального элемента и на идеи Data-structural bootstrapping.
Двоичная куча [math]O(\log n)[/math] [math]O(\log n)[/math] [math]O(m \log(n+m))[/math] Двоичная куча (англ. binary heap) — такое двоичное дерево, для которого выполнены три условия:
  • Значение в любой вершине не меньше, чем значения её потомков.
  • Глубина листьев (расстояние до корня) отличается не более чем на 1 слой.
  • Последний слой заполняется слева направо.
Двуродительская куча [math]O(\sqrt{n})[/math] [math]O(\sqrt{n})[/math] Двуродительская куча (англ. bi-parental heap или beap) — такая куча, где у каждого элемента обычно есть два ребенка (если это не последний уровень) и два родителя (если это не первый уровень). Структура позволяет производить сублиненый поиск.
[math]d[/math]-арная куча [math]O(\log n / \log d)[/math] [math]O(d\log n / \log d)[/math] [math]O(m \log(n+m) / \log d)[/math] [math]d[/math]-арная куча (англ. [math]d[/math]-ary heap) — двоичная куча, в которой у каждого элемента [math]d[/math] детей вместо [math]2[/math].
Левосторонняя куча [math]O(\log n)[/math] [math]O(\log n)[/math] [math]O(\log n)[/math] Левосторонняя куча (англ. leftist heap) — двоичное левосторонее дерево (не обязательно сбалансированное), но с соблюдением порядка кучи.
Спаренная куча [math]O(1)[/math] [math]O(\log n)[/math] [math]O(1)[/math] Спаренная куча (англ. pairing heap) — куча с относительно простой реализацией и хорошей производительностью, может быть рассмотрена как упрощенная Фибоначчиева куча.
Толстая куча [math]O(1)[/math] [math]O(\log n)[/math] [math]O(\log n)[/math] Толстая куча — это почти кучеобразный нагруженный лес.
Тонкая куча [math]O(1)[/math] [math]O(\log n)[/math] [math]O(1)[/math] Тонкая куча (англ. thin heap) — это структура данных, реализующая приоритетную очередь с теми же асимптотическими оценками, что и фибоначчиева куча, но имеющая большую практическую ценность из-за меньших констант.
Фибоначчиева куча [math]O(1)[/math] [math]O(\log n)[/math] [math]O(1)[/math] Куча, построенная на основе Фибоначчиева дерева. Фибоначчиево дерево (англ. Fibonacci tree) — биномиальное дерево, где у каждой вершины удалено не более одного ребенка.

Применение

  • Алгоритм Дейкстры
  • Алгоритм Прима
  • Дискретно-событийное моделирование (англ. discrete-event simulation, DES)
  • Код Хаффмана
  • Поиск по первому наилучшему совпадению
  • Управление полосой пропускания

Реализации в языках программирования

  • Стандартная библиотека шаблонов (англ. STL) в C++ предоставляет методы управления кучей make_heap, push_heap и pop_heap (обычно реализуются бинарные кучи), которые оперируют с итераторами произвольного случайного доступа. Методы используют итераторы как ссылки на массивы и выполняют преобразование массив-куча.
  • Библиотека Boost для C++ включает в себя библиотеку для работу с кучами. В отличии от STL, поддерживает операции decrease-key и increase-key, а также имеет поддержку дополнительных видов куч, таких как Фибоначчиева куча, Биномиальная куча и Спаренная куча.
  • В Java 2 (начиная с версии 1.5) предоставляется реализация бинарной кучи в классе java.util.PriorityQueue<E>, который не поддерживает операции decrease-key и increase-key.
  • Python имеет модуль heapq, который реализует очереди с приоритетами с помощью бинарной кучи.
  • PHP имеет поддержку кучи на максимум (SplMaxHeap) и кучи на минимум (SplMinHeap), как часть Standard PHP Library начиная с версии 5.3.
  • В Perl имеются реализации бинарной, биномиальной и фибоначчиевой куч во всеобъемлющей сети архивов.
  • Go имеет пакет heap, в котором реализованы алгоритмы для работы с кучами.


Источники информации