Приоритетные очереди — различия между версиями
Eadm (обсуждение | вклад) м |
|||
| Строка 1: | Строка 1: | ||
| − | '''Приоритетная очередь''' (англ. ''priority queue'') {{---}} это абстрактная структура данных на подобии стека или очереди, где у каждого элемента есть приоритет. Элемент с более высоким приоритетом находится перед элементом с более низким приоритетом. Если у элементов одинаковые приоритеты, они распологаются в зависимости от своей позиции в очереди. Обычно приоритетные очереди реализуются с помощью куч (англ. ''heap''). | + | '''Приоритетная очередь''' (англ. ''priority queue'') {{---}} это абстрактная структура данных на подобии стека или очереди, где у каждого элемента есть приоритет. Элемент с более высоким приоритетом находится перед элементом с более низким приоритетом. Если у элементов одинаковые приоритеты, они распологаются в зависимости от своей позиции в очереди. Обычно приоритетные очереди реализуются с помощью '''куч''' (англ. ''heap''). |
| + | |||
==Операции== | ==Операции== | ||
| − | * | + | |
| − | * insert | + | * <tex>\mathrm{findMin}</tex> или <tex>\mathrm{findMax}</tex> {{---}} поиск элемента с наибольшим приоритетом |
| − | * | + | * <tex>\mathrm{insert}</tex> или <tex>\mathrm{push}</tex> {{---}} вставка нового элемента |
| − | * | + | * <tex>\mathrm{extractMin}</tex> или <tex>\mathrm{extractMax}</tex> {{---}} извлечь элемент с наибольшим приоритетом |
| − | * merge - объединение двух приоритетных очередей | + | * <tex>\mathrm{deleteMin}</tex> или <tex>\mathrm{deleteMax}</tex> {{---}} удалить элемент с наибольшим приоритетом |
| + | * <tex>\mathrm{increaseKey}</tex> или <tex>\mathrm{decreaseKey}</tex> {{---}} обновить значение элемента | ||
| + | * <tex>\mathrm{merge}</tex> {{---}} объединение двух приоритетных очередей | ||
| + | |||
==Реализации== | ==Реализации== | ||
===Наивная=== | ===Наивная=== | ||
| − | В качестве наивной реализации мы можем взять обычный список и при добавлении нового элемента класть его в конец, а при запросе элемента с максимальным приоритетом проходить по всему списку. Тогда операция insert будет выполняться за <tex>O(1)</tex>, а | + | В качестве наивной реализации мы можем взять обычный список и при добавлении нового элемента класть его в конец, а при запросе элемента с максимальным приоритетом проходить по всему списку. Тогда операция <tex>\mathrm{insert}</tex> будет выполняться за <tex>O(1)</tex>, а <tex>\mathrm{extractMin}</tex> или <tex>\mathrm{extractMax}</tex> за <tex>O(n)</tex>. |
| + | |||
===Обычная=== | ===Обычная=== | ||
Для лучшей производительности приоритетные очереди реализуют с помощью куч, что позволяет выполнять операции вставки и удаления за <tex>O(\log n)</tex>. Использование специальных куч, таких как Фибоначчиева куча и спаренная куча, позволяет еще больше улучшить асимптотику некоторый операций. | Для лучшей производительности приоритетные очереди реализуют с помощью куч, что позволяет выполнять операции вставки и удаления за <tex>O(\log n)</tex>. Использование специальных куч, таких как Фибоначчиева куча и спаренная куча, позволяет еще больше улучшить асимптотику некоторый операций. | ||
| + | |||
==Виды приорететных очередей== | ==Виды приорететных очередей== | ||
| + | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
| Строка 18: | Строка 25: | ||
! rowspan="2" | Описание | ! rowspan="2" | Описание | ||
|- | |- | ||
| − | |||
| align="center" | insert | | align="center" | insert | ||
| − | | align="center" width="5%" | | + | | align="center" width="5%" | extractMin |
| + | | align="center" width="5%" | decreaseKey | ||
| align="center" | merge | | align="center" | merge | ||
|- | |- | ||
| [[2-3 куча]] | | [[2-3 куча]] | ||
| − | |||
| align="center" | <tex>O(1)</tex> | | align="center" | <tex>O(1)</tex> | ||
| align="center" | <tex>O(\log n)</tex> | | align="center" | <tex>O(\log n)</tex> | ||
| + | | align="center" | <tex>O(1)</tex> | ||
| align="center" | <tex>O(1)</tex> | | align="center" | <tex>O(1)</tex> | ||
| Структура похожа на Фибоначчиеву кучу и использует в своей реализации 2-3 дерево. | | Структура похожа на Фибоначчиеву кучу и использует в своей реализации 2-3 дерево. | ||
| + | |- | ||
| + | | [[Тонкая куча]] | ||
| + | | align="center" | <tex>O(1)</tex> | ||
| + | | align="center" | <tex>O(\log n)</tex> | ||
| + | | align="center" | <tex>O(1)</tex> | ||
| + | | align="center" | <tex>O(1)</tex> | ||
| + | | [[Тонкая куча]] (англ. ''thin heap'') {{---}} это структура данных, реализующая приоритетную очередь с теми же асимптотическими оценками, что и [[фибоначчиева куча]], но имеющая большую практическую ценность из-за меньших констант. | ||
| + | |- | ||
| + | | [[Фибоначчиева куча]] | ||
| + | | align="center" | <tex>O(1)</tex> | ||
| + | | align="center" | <tex>O(\log n)</tex> | ||
| + | | align="center" | <tex>O(1)</tex> | ||
| + | | align="center" | <tex>O(1)</tex> | ||
| + | | Куча, построенная на основе Фибоначчиева дерева. [[Фибоначчиево дерево]] (англ. ''Fibonacci tree'') {{---}} биномиальное дерево, где у каждой вершины удалено не более одного ребенка. | ||
| + | |- | ||
| + | | [[Куча Бродала-Окасаки]] | ||
| + | | align="center" | <tex>O(1)</tex> | ||
| + | | align="center" | <tex>O(\log n)</tex> | ||
| + | | align="center" | <tex>O(1)</tex> | ||
| + | | align="center" | <tex>O(1)</tex> | ||
| + | | [[Куча Бродала-Окасаки]] (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании биномиальной кучи без каскадных ссылок, добавлении минимального элемента и на идеи Data-structural bootstrapping. | ||
|- | |- | ||
| [[Биномиальная куча]] | | [[Биномиальная куча]] | ||
| align="center" | <tex>O(1)</tex> | | align="center" | <tex>O(1)</tex> | ||
| + | | align="center" | <tex>O(\log n)</tex> | ||
| align="center" | <tex>O(\log n)</tex> | | align="center" | <tex>O(\log n)</tex> | ||
| align="center" | <tex>O(1)</tex> | | align="center" | <tex>O(1)</tex> | ||
| Строка 38: | Строка 67: | ||
* все биномиальные деревья имеют разный размер | * все биномиальные деревья имеют разный размер | ||
|- | |- | ||
| − | | [[ | + | | [[Спаренная куча]] |
| + | | align="center" | <tex>O(1)</tex> | ||
| + | | align="center" | <tex>O(\log n)</tex> | ||
| + | | align="center" | <tex>O(\log n)</tex> | ||
| + | | align="center" | <tex>O(1)</tex> | ||
| + | | [[Спаренная куча]] (англ. ''pairing heap'') {{---}} куча с относительно простой реализацией и хорошей производительностью, может быть рассмотрена как упрощенная [[Фибоначчиева куча]]. | ||
| + | |- | ||
| + | | [[Толстая куча]] | ||
| align="center" | <tex>O(1)</tex> | | align="center" | <tex>O(1)</tex> | ||
| align="center" | <tex>O(\log n)</tex> | | align="center" | <tex>O(\log n)</tex> | ||
| align="center" | <tex>O(1)</tex> | | align="center" | <tex>O(1)</tex> | ||
| − | | [[ | + | | align="center" | <tex>O(\log n)</tex> |
| + | | [[Толстая куча]] {{---}} это почти кучеобразный нагруженный лес. | ||
|- | |- | ||
| [[Двоичная куча]] | | [[Двоичная куча]] | ||
| + | | align="center" | <tex>O(\log n)</tex> | ||
| align="center" | <tex>O(\log n)</tex> | | align="center" | <tex>O(\log n)</tex> | ||
| align="center" | <tex>O(\log n)</tex> | | align="center" | <tex>O(\log n)</tex> | ||
| Строка 52: | Строка 90: | ||
*Глубина листьев (расстояние до корня) отличается не более чем на 1 слой. | *Глубина листьев (расстояние до корня) отличается не более чем на 1 слой. | ||
*Последний слой заполняется слева направо. | *Последний слой заполняется слева направо. | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
|- | |- | ||
| [[Левосторонняя куча]] | | [[Левосторонняя куча]] | ||
| + | | align="center" | <tex>O(\log n)</tex> | ||
| align="center" | <tex>O(\log n)</tex> | | align="center" | <tex>O(\log n)</tex> | ||
| align="center" | <tex>O(\log n)</tex> | | align="center" | <tex>O(\log n)</tex> | ||
| Строка 71: | Строка 98: | ||
| [[Левосторонняя куча]] (англ. ''leftist heap'') {{---}} двоичное левосторонее дерево (не обязательно сбалансированное), но с соблюдением порядка кучи. | | [[Левосторонняя куча]] (англ. ''leftist heap'') {{---}} двоичное левосторонее дерево (не обязательно сбалансированное), но с соблюдением порядка кучи. | ||
|- | |- | ||
| − | | [[ | + | | [[d-арная куча| <tex>d</tex>-арная куча]] |
| − | | align="center" | <tex>O( | + | | align="center" | <tex>O(\log_{d} n)</tex> |
| − | | align="center" | <tex>O(\ | + | | align="center" | <tex>O(d\log_{d} n)</tex> |
| − | | align="center" | <tex>O( | + | | align="center" | <tex>O(\log_{d} n)</tex> |
| − | | [[ | + | | align="center" | <tex>O(m \log_{d}(n+m))</tex> |
| + | | [[d-арная куча| <tex>d</tex>-арная куча]] (англ. ''<tex>d</tex>-ary heap'') {{---}} [[двоичная куча]], в которой у каждого элемента <tex>d</tex> детей вместо <tex>2</tex>. | ||
|- | |- | ||
| − | | [[ | + | | [[Двуродительская куча]] |
| − | | align="center" | <tex>O( | + | | align="center" | <tex>O(\sqrt{n})</tex> |
| − | | align="center" | <tex>O(\ | + | | align="center" | <tex>O(\sqrt{n})</tex> |
| − | | | + | | | |
| − | | [[ | + | | | |
| + | | [[Двуродительская куча]] (англ. ''bi-parental heap'' или ''beap'') {{---}} такая куча, где у каждого элемента обычно есть два ребенка (если это не последний уровень) и два родителя (если это не первый уровень). Структура позволяет производить сублиненый поиск. | ||
|- | |- | ||
| − | | | + | | Наивная реализация |
| align="center" | <tex>O(1)</tex> | | align="center" | <tex>O(1)</tex> | ||
| − | | align="center" | <tex>O( | + | | align="center" | <tex>O(n)</tex> |
| + | | align="center" | <tex>O(n)</tex> | ||
| align="center" | <tex>O(1)</tex> | | align="center" | <tex>O(1)</tex> | ||
| − | | | + | | Наивная реализация с использованием списка. |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
|- | |- | ||
|} | |} | ||
| + | |||
==Применение== | ==Применение== | ||
| − | + | Приоритетные очереди используются в следующих алгоритмах: [[алгоритм Дейкстры]], [[алгоритм Прима]], дискретно-событийное моделирование (англ. ''discrete-event simulation, DES''), [[алгоритм Хаффмана]], поиск по первому наилучшему совпадению, управление полосой пропускания. | |
| − | + | ||
| − | |||
| − | |||
| − | |||
| − | |||
==Реализации в языках программирования== | ==Реализации в языках программирования== | ||
| − | * Стандартная библиотека шаблонов (англ. ''STL'') в C++ предоставляет методы управления кучей make_heap, push_heap и pop_heap (обычно реализуются бинарные кучи), которые оперируют с итераторами произвольного случайного доступа. Методы используют итераторы как ссылки на массивы и выполняют преобразование массив-куча. | + | * [http://en.cppreference.com/w/cpp/container Стандартная библиотека шаблонов] (англ. ''STL'') в C++ предоставляет методы управления кучей make_heap, push_heap и pop_heap (обычно реализуются бинарные кучи), которые оперируют с итераторами произвольного случайного доступа. Методы используют итераторы как ссылки на массивы и выполняют преобразование массив-куча. |
| − | * Библиотека Boost для C++ включает в себя библиотеку для работу с кучами. В отличии от STL, поддерживает операции decrease-key и increase-key, а также имеет поддержку дополнительных видов куч, таких как [[ | + | * Библиотека [http://www.boost.org/ Boost] для C++ включает в себя библиотеку для работу с кучами. В отличии от [http://en.cppreference.com/w/cpp/container STL], поддерживает операции decrease-key и increase-key, а также имеет поддержку дополнительных видов куч, таких как [[фибоначчиева куча]], [[биномиальная куча]] и [[спаренная куча]]. |
| − | * В Java 2 (начиная с версии 1.5) предоставляется реализация бинарной кучи в классе java.util.PriorityQueue<E>, который не поддерживает операции decrease-key и increase-key. | + | * В Java 2 (начиная с версии 1.5) предоставляется реализация бинарной кучи в классе [http://docs.oracle.com/javase/6/docs/api/java/util/PriorityQueue.html java.util.PriorityQueue<E>], который не поддерживает операции decrease-key и increase-key. |
| − | * Python имеет модуль heapq, который реализует очереди с приоритетами с помощью бинарной кучи. | + | * Python имеет модуль [http://docs.python.org/2/library/heapq.html heapq], который реализует очереди с приоритетами с помощью бинарной кучи. |
| − | * PHP имеет поддержку кучи на максимум | + | * PHP имеет поддержку кучи на максимум [http://php.net/manual/ru/class.splmaxheap.php SplMaxHeap] и кучи на минимум [http://php.net/manual/ru/class.splminheap.php SplMinHeap], как часть Standard PHP Library начиная с версии 5.3. |
| − | * В Perl имеются реализации бинарной, биномиальной и фибоначчиевой куч во всеобъемлющей сети архивов. | + | * В Perl имеются [http://metacpan.org/pod/Heap реализации] бинарной, биномиальной и фибоначчиевой куч во всеобъемлющей сети архивов. |
| − | * Go имеет пакет heap, в котором реализованы алгоритмы для работы с кучами. | + | * Go имеет пакет [http://golang.org/pkg/container/heap/ heap], в котором реализованы алгоритмы для работы с кучами. |
| + | |||
| + | |||
| + | |||
== Источники информации == | == Источники информации == | ||
| − | * [http://en.wikipedia.org/wiki/Heap_(data_structure) | + | * [http://en.wikipedia.org/wiki/Heap_(data_structure) Wikidedia {{---}} Heap (data structure)] |
| − | * [http://en.wikipedia.org/wiki/2%E2%80%933_heap | + | * [http://en.wikipedia.org/wiki/2%E2%80%933_heap Wikidedia {{---}} 2-3 heap] |
| − | * [http://en.wikipedia.org/wiki/Beap | + | * [http://en.wikipedia.org/wiki/Beap Wikidedia {{---}} Beap] |
| − | * [http://en.wikipedia.org/wiki/Binary_heap | + | * [http://en.wikipedia.org/wiki/Binary_heap Wikidedia {{---}} Binary heap] |
| − | * [http://en.wikipedia.org/wiki/Binomial_heap | + | * [http://en.wikipedia.org/wiki/Binomial_heap Wikidedia {{---}} Binomial heap] |
| − | * [http://en.wikipedia.org/wiki/Brodal_queue | + | * [http://en.wikipedia.org/wiki/Brodal_queue Wikidedia {{---}} Brodal queue] |
| − | * [http://en.wikipedia.org/wiki/D-ary_heap | + | * [http://en.wikipedia.org/wiki/D-ary_heap Wikidedia {{---}} <tex>d</tex>-ary heap] |
| − | * [http://en.wikipedia.org/wiki/Fibonacci_heap | + | * [http://en.wikipedia.org/wiki/Fibonacci_heap Wikidedia {{---}} Fibonacci heap] |
[[Категория: Дискретная математика и алгоритмы]] | [[Категория: Дискретная математика и алгоритмы]] | ||
[[Категория: Приоритетные очереди]] | [[Категория: Приоритетные очереди]] | ||
[[Категория: Структуры данных]] | [[Категория: Структуры данных]] | ||
Версия 15:41, 7 июня 2015
Приоритетная очередь (англ. priority queue) — это абстрактная структура данных на подобии стека или очереди, где у каждого элемента есть приоритет. Элемент с более высоким приоритетом находится перед элементом с более низким приоритетом. Если у элементов одинаковые приоритеты, они распологаются в зависимости от своей позиции в очереди. Обычно приоритетные очереди реализуются с помощью куч (англ. heap).
Содержание
Операции
- или — поиск элемента с наибольшим приоритетом
- или — вставка нового элемента
- или — извлечь элемент с наибольшим приоритетом
- или — удалить элемент с наибольшим приоритетом
- или — обновить значение элемента
- — объединение двух приоритетных очередей
Реализации
Наивная
В качестве наивной реализации мы можем взять обычный список и при добавлении нового элемента класть его в конец, а при запросе элемента с максимальным приоритетом проходить по всему списку. Тогда операция будет выполняться за , а или за .
Обычная
Для лучшей производительности приоритетные очереди реализуют с помощью куч, что позволяет выполнять операции вставки и удаления за . Использование специальных куч, таких как Фибоначчиева куча и спаренная куча, позволяет еще больше улучшить асимптотику некоторый операций.
Виды приорететных очередей
| Название | Операции | Описание | |||
|---|---|---|---|---|---|
| insert | extractMin | decreaseKey | merge | ||
| 2-3 куча | Структура похожа на Фибоначчиеву кучу и использует в своей реализации 2-3 дерево. | ||||
| Тонкая куча | Тонкая куча (англ. thin heap) — это структура данных, реализующая приоритетную очередь с теми же асимптотическими оценками, что и фибоначчиева куча, но имеющая большую практическую ценность из-за меньших констант. | ||||
| Фибоначчиева куча | Куча, построенная на основе Фибоначчиева дерева. Фибоначчиево дерево (англ. Fibonacci tree) — биномиальное дерево, где у каждой вершины удалено не более одного ребенка. | ||||
| Куча Бродала-Окасаки | Куча Бродала-Окасаки (англ. Brodal's and Okasaki's Priority Queue) — основана на использовании биномиальной кучи без каскадных ссылок, добавлении минимального элемента и на идеи Data-structural bootstrapping. | ||||
| Биномиальная куча | Биномиальная куча (англ. binomial heap) — структура данных, реализующая приоритетную очередь, которая представляет собой набор биномиальных деревьев с двумя свойствами:
| ||||
| Спаренная куча | Спаренная куча (англ. pairing heap) — куча с относительно простой реализацией и хорошей производительностью, может быть рассмотрена как упрощенная Фибоначчиева куча. | ||||
| Толстая куча | Толстая куча — это почти кучеобразный нагруженный лес. | ||||
| Двоичная куча | Двоичная куча (англ. binary heap) — такое двоичное дерево, для которого выполнены три условия:
| ||||
| Левосторонняя куча | Левосторонняя куча (англ. leftist heap) — двоичное левосторонее дерево (не обязательно сбалансированное), но с соблюдением порядка кучи. | ||||
| -арная куча | -арная куча (англ. -ary heap) — двоичная куча, в которой у каждого элемента детей вместо . | ||||
| Двуродительская куча | Двуродительская куча (англ. bi-parental heap или beap) — такая куча, где у каждого элемента обычно есть два ребенка (если это не последний уровень) и два родителя (если это не первый уровень). Структура позволяет производить сублиненый поиск. | ||||
| Наивная реализация | Наивная реализация с использованием списка. | ||||
Применение
Приоритетные очереди используются в следующих алгоритмах: алгоритм Дейкстры, алгоритм Прима, дискретно-событийное моделирование (англ. 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, в котором реализованы алгоритмы для работы с кучами.