Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску
Пример полной двоичной max-heap
Пример полной двоичной минимальной кучи

Двоичная куча является кучной структурой данных , которая принимает форму двоичного дерева . Двоичные кучи - это распространенный способ реализации очередей с приоритетом . [1] : 162–163 Двоичная куча была введена Дж. Уильямсом Вильямсом в 1964 году как структура данных для heapsort . [2]

Двоичная куча определяется как двоичное дерево с двумя дополнительными ограничениями: [3]

  • Свойство формы: двоичная куча - это полное двоичное дерево ; то есть все уровни дерева, кроме, возможно, последнего (самого глубокого), полностью заполнены, и, если последний уровень дерева не завершен, узлы этого уровня заполняются слева направо.
  • Свойство кучи: ключ, хранящийся в каждом узле, либо больше, либо равен (≥), либо меньше или равен (≤) ключам в дочерних узлах, в соответствии с некоторым общим порядком .

Кучи, в которых родительский ключ больше или равен (≥) дочерним ключам, называются максимальными кучами ; те, где он меньше или равен (≤), называются минимальными кучами . Известны эффективные ( логарифмические по времени ) алгоритмы для двух операций, необходимых для реализации очереди приоритетов в двоичной куче: вставка элемента и удаление наименьшего или наибольшего элемента из минимальной или максимальной кучи, соответственно. Двоичные кучи также часто используются в алгоритме сортировки heapsort , который является алгоритмом на месте, потому что двоичные кучи могут быть реализованы как неявная структура данных , сохраняя ключи в массиве и используя их относительные положения в этом массиве для представления дочерних и родительских отношений .

Операции с кучей [ править ]

Операции вставки и удаления сначала изменяют кучу, чтобы она соответствовала свойству формы, путем добавления или удаления из конца кучи. Затем свойство кучи восстанавливается путем обхода кучи вверх или вниз. Обе операции занимают время O (log n ).

Вставить [ изменить ]

Чтобы добавить элемент в кучу, мы можем выполнить такой алгоритм:

  1. Добавьте элемент на нижний уровень кучи в крайнее левое открытое пространство.
  2. Сравните добавленный элемент с его родителем; если они в правильном порядке, остановитесь.
  3. Если нет, поменяйте местами элемент с его родителем и вернитесь к предыдущему шагу.

Шаги 2 и 3, которые восстанавливают свойство кучи путем сравнения и, возможно, замены узла с его родительским узлом, называются операцией увеличения кучи (также известной как всплытие , фильтрация , просеивание , просачивание , всплытие). вверх , навалом или каскадом ).

Количество требуемых операций зависит только от количества уровней, на которые должен подняться новый элемент, чтобы удовлетворить свойству кучи. Таким образом, операция вставки имеет временную сложность в наихудшем случае O (log n ). Для случайной кучи и для повторяющихся вставок операция вставки имеет среднюю сложность O (1). [4] [5]

В качестве примера вставки двоичной кучи, скажем, у нас есть максимальная куча

Кучу добавить step1.svg

и мы хотим добавить число 15 в кучу. Сначала мы помещаем 15 в позицию, отмеченную X. Однако свойство кучи нарушено, поскольку 15> 8 , поэтому нам нужно поменять местами 15 и 8. Итак, у нас есть куча, которая после первого обмена выглядит следующим образом:

Кучу добавить step2.svg

Однако свойство кучи по-прежнему нарушается с 15> 11 , поэтому нам нужно снова поменять местами:

что является допустимой максимальной кучей. Нет необходимости проверять левый дочерний элемент после этого последнего шага: вначале максимальная куча была допустимой, то есть корень уже был больше, чем его левый дочерний элемент, поэтому замена корня на еще большее значение сохранит свойство, которое каждый узел больше, чем его дочерние элементы ( 11> 5 ; если 15> 11 и 11> 5 , то 15> 5 из-за транзитивного отношения ).

Извлечь [ править ]

Процедура удаления корня из кучи (эффективное извлечение максимального элемента в максимальной куче или минимального элемента в минимальной куче) при сохранении свойства кучи выглядит следующим образом:

  1. Замените корень кучи последним элементом на последнем уровне.
  2. Сравните новый корень с его дочерними элементами; если они в правильном порядке, остановитесь.
  3. Если нет, поменяйте местами элемент с одним из его дочерних элементов и вернитесь к предыдущему шагу. (Поменяйте местами его меньший дочерний элемент в минимальной куче и его более крупный дочерний элемент в максимальной куче.)

Шаги 2 и 3, которые восстанавливают свойство кучи путем сравнения и , возможно , замен узла с одним из своих детей, называются вниз кучи (также известные как пузырь-вниз , просачивается вниз , сито-вниз , раковина вниз , струйки down , heapify-down , cascade-down , extract-min или extract-max , или просто heapify ).

Итак, если у нас такая же максимальная куча, что и раньше

Снимаем 11 и заменяем на 4.

Теперь свойство кучи нарушено, поскольку 8 больше 4. В этом случае замены двух элементов, 4 и 8, достаточно для восстановления свойства кучи, и нам больше не нужно менять местами элементы:

Перемещающийся вниз узел заменяется более крупным из своих дочерних узлов в максимальной куче (в минимальной куче он будет заменен на меньший дочерний узел ), пока он не удовлетворит свойство кучи в своей новой позиции. Эта функциональность достигается функцией Max-Heapify, как определено ниже в псевдокоде для кучи A с поддержкой массива длиной length ( A ). Обратите внимание, что A индексируется, начиная с 1.

// Выполняем операцию down-heap или heapify-down для max-heap// A : массив, представляющий кучу, индексированный, начиная с 1// i : индекс, с которого нужно начинать копирование вниз Max-Heapify ( A , i ): left ← 2 × i  right ← 2 × i + 1 наибольшееi  если  leftlength ( A ) и  A [ left ]> A [ наибольшее ], то : наибольшееleft, 
если rightlength ( A ) и A [ right ]> A [ наибольшее ], то : наибольшеесправа если наибольшийi, то : поменяйте местами A [ i ] и A [ наибольший ] Max-Heapify ( A , наибольший )

Для приведенного выше алгоритма для правильной повторной кучи массива никакие узлы, кроме узла с индексом i и двух его прямых дочерних узлов, не могут нарушить свойство кучи. Операция «down-heap» (без предшествующей замены) также может использоваться для изменения значения корня, даже если элемент не удаляется.

В худшем случае новый корень должен быть заменен его дочерним элементом на каждом уровне, пока он не достигнет нижнего уровня кучи, что означает, что операция удаления имеет временную сложность относительно высоты дерева или O (log n ).

Вставить, затем извлечь [ редактировать ]

Вставка элемента с последующим извлечением из кучи может выполняться более эффективно, чем простой вызов функций вставки и извлечения, определенных выше, которые будут включать как операции увеличения, так и уменьшения объема. Вместо этого мы можем выполнить просто операцию уменьшения объема, как показано ниже:

  1. Сравните, больше ли элемент, который мы нажимаем, или верхняя часть кучи (при условии максимальной кучи)
  2. Если корень кучи больше:
    1. Замените корень новым элементом
    2. Down-heapify, начиная с корня
  3. В противном случае верните товар, который мы толкаем

Python предоставляет такую функцию для вставки затем экстракция называется «heappushpop», который перефразировать ниже. [6] [7] Предполагается , что массив кучи , чтобы иметь свой первый элемент с индексом 1.

// Помещаем новый элемент в (максимальную) кучу, а затем извлекаем корень полученной кучи. // куча : массив, представляющий кучу, с индексом 1// item : элемент для вставки// Возвращает большее из двух между элементом и корнем кучи .Push-Pop ( ворох : List <T>, пункт : T) -> T: если  куча не пуста и куча [1]> Пункт  затем : // <если мин кучи подкачка  куча [1] и пункт _downheap ( куча Отправной из индекса 1) вернуть  товар

Аналогичную функцию можно определить для извлечения, а затем вставки, которая в Python называется "heapreplace":

// Извлекаем корень кучи и помещаем новый элемент // куча : массив, представляющий кучу, с индексом 1// item : элемент для вставки// Возвращает текущий корень кучи Replace ( heap : List <T>, item : T) -> T: swap  heap [1] и item _downheap ( куча, начиная с индекса 1) возвращает  элемент

Искать [ редактировать ]

На поиск произвольного элемента уходит O (n) времени.

Удалить [ редактировать ]

Удалить произвольный элемент можно следующим образом:

  1. Найдите индекс элемента, который мы хотим удалить
  2. Поменяйте местами этот элемент с последним элементом
  3. Down-heapify или up-heapify для восстановления свойства кучи. В max-heap (min-heap) up-heapify требуется только тогда, когда новый ключ элемента больше (меньше), чем предыдущий, потому что может быть нарушено только свойство heap родительского элемента. Предполагая, что свойство heap было действительным между элементом и его дочерними элементами до замены элемента, оно не может быть нарушено более крупным (меньшим) значением ключа. Когда новый ключ меньше (больше), чем предыдущий, тогда требуется только down-heapify, потому что свойство heap может быть нарушено только в дочерних элементах.

Клавиша уменьшения или увеличения [ править ]

Операция с ключом уменьшения заменяет значение узла заданным значением с более низким значением, а операция с ключом увеличения делает то же самое, но с более высоким значением. Это включает в себя поиск узла с заданным значением, изменение значения, а затем добавление или увеличение кучи для восстановления свойства кучи.

Клавишу уменьшения можно сделать следующим образом:

  1. Найдите индекс элемента, который мы хотим изменить
  2. Уменьшить значение узла
  3. Down-heapify (при условии максимальной кучи) для восстановления свойства кучи

Увеличить ключ можно следующим образом:

  1. Найдите индекс элемента, который мы хотим изменить
  2. Увеличьте значение узла
  3. Up-heapify (при условии максимальной кучи) для восстановления свойства кучи

Создание кучи [ править ]

Создание кучи из массива из n входных элементов можно выполнить, начав с пустой кучи, а затем последовательно вставив каждый элемент. Этот подход, получивший название метода Вильямса по имени изобретателя двоичных куч, легко увидеть, что он выполняется за время O ( n log n ) : он выполняет n вставок по цене O (log n ) каждая. [а]

Однако метод Вильямса не оптимален. Более быстрый метод (из-за Флойда [8] ) начинается с произвольного размещения элементов в двоичном дереве, соблюдая свойство формы (дерево может быть представлено массивом, см. Ниже). Затем, начиная с самого нижнего уровня и двигаясь вверх, просеивайте корень каждого поддерева вниз, как в алгоритме удаления, пока свойство кучи не будет восстановлено. Более конкретно, если все поддеревья, начинающиеся на некоторой высоте , уже были «нагромождены» (самый нижний уровень, соответствующий ), деревья на высоте могут быть скопированы, отправив их корень вниз по пути максимальных значений дочерних элементов при построении максимальной кучи, или минимальные дочерние элементы при построении минимальной кучи. Этот процесс занимаетопераций (свопов) на узел. В этом методе большая часть нагромождения происходит на нижних уровнях. Так как высота кучи равна , количество узлов на высоте равно . Следовательно, стоимость накопления всех поддеревьев составляет:

При этом используется тот факт, что данный бесконечный ряд сходится .

Известно, что точное значение вышеприведенного (наихудшее количество сравнений во время построения кучи) равно:

, [9] [b]

где ев 2 ( п ) является суммой всех цифр двоичного представления о н и е 2 ( п ) является показателем 2 в простые множители из п .

Средний случай сложнее для анализа, но можно показать, что он асимптотически приближается к 1.8814  n - 2 log 2 n + O (1) сравнений. [10] [11]

Встроенный Макс-кучного функция , которая следует, преобразует массив A , который хранит полное бинарное дерево с п узлами макс кучи, многократно используя Max-Heapify (вниз-heapify для макс кучи) в восходящем порядке . Элементы массива, проиндексированные с помощью floor ( n / 2) + 1 , floor ( n / 2) + 2 , ..., n, являются листьями для дерева (при условии, что индексы начинаются с 1) - таким образом, каждый является одноэлементным куча, и не нужно складывать в кучу. Build-Max-Heap запускает Max-Heapify на каждом из оставшихся узлов дерева.

Build-Max-Heap ( A ): для каждого индекса i  от  этажа ( длина ( A ) / 2) до 1 do:  Max-Heapify ( A , i )

Реализация кучи [ править ]

Небольшое полное двоичное дерево, хранящееся в массиве
Сравнение двоичной кучи и реализации массива.

Кучи обычно реализуются с помощью массива . Любое двоичное дерево можно сохранить в массиве, но поскольку двоичная куча всегда является полным двоичным деревом, ее можно хранить компактно. Для указателей места не требуется ; вместо этого родитель и потомки каждого узла могут быть найдены арифметическими методами по индексам массива. Эти свойства делают эту реализацию кучи простым примером неявной структуры данных или списка Ahnentafel . Детали зависят от корневой позиции, которая, в свою очередь, может зависеть от ограничений языка программирования, используемого для реализации, или предпочтений программиста. В частности, иногда корень помещается в индекс 1, чтобы упростить арифметику.

Пусть n - количество элементов в куче, а i - произвольный допустимый индекс массива, в котором хранится куча. Если корень дерева находится в индексе 0, с допустимыми индексами от 0 до n - 1, то каждый элемент a с индексом i имеет

  • дети с индексами 2 i + 1 и 2 i + 2
  • его родитель на индексном этаже (( i - 1) ∕ 2).

В качестве альтернативы, если корень дерева находится в индексе 1 с допустимыми индексами от 1 до n , то каждый элемент a с индексом i имеет

  • дети с индексами 2 i и 2 i +1
  • его родитель на индексном этаже ( i 2).

Эта реализация используется в алгоритме heapsort , где она позволяет повторно использовать пространство во входном массиве для хранения кучи (т.е. алгоритм выполняется на месте ). Реализация также полезна для использования в качестве приоритетной очереди, где использование динамического массива позволяет вставлять неограниченное количество элементов.

Затем операции upheap / downheap могут быть сформулированы в терминах массива следующим образом: предположим, что свойство heap выполняется для индексов b , b +1, ..., e . Функция sift-down расширяет свойство heap до b −1, b , b +1, ..., e . Только индекс i = b −1 может нарушить свойство кучи. Пусть j будет индексом самого большого дочернего элемента a [ i ] (для max-heap или самого маленького дочернего элемента для min-heap) в диапазоне b , ..., e . (Если такого индекса не существует, потому что 2 i >e, тогда свойство кучи сохраняется для вновь расширенного диапазона, и ничего не нужно делать.) Путем замены значений a [ i ] и a [ j ] устанавливается свойство кучи для позиции i . На этом этапе единственная проблема заключается в том, что свойство кучи может не выполняться для индекса j . Функция отсеивания вниз применяется хвостовой рекурсивно к индексу j до тех пор, пока свойство кучи не будет установлено для всех элементов.

Функция просеивания работает быстро. На каждом этапе требуется только два сравнения и один обмен. Значение индекса , где он работает двойники в каждой итерации, так что в большинстве журналов 2 е необходимы шаги.

Для больших куч и использования виртуальной памяти хранение элементов в массиве по указанной выше схеме неэффективно: (почти) каждый уровень находится на отдельной странице . B-кучи - это двоичные кучи, которые хранят поддеревья на одной странице, уменьшая количество страниц, к которым осуществляется доступ, до десяти раз. [12]

Операция слияния двух двоичных куч занимает Θ ( n ) для куч одинакового размера. Лучшее, что вы можете сделать (в случае реализации массива), просто объединить два массива кучи и построить кучу результата. [13] Куча на n элементах может быть объединена с кучей на k элементах с использованием O (log n log k ) сравнений ключей или, в случае реализации на основе указателя, за O (log n log k ) времени. [14] Алгоритм разделения кучи на n элементов на две кучи на k и nkэлементов, соответственно, на основе нового представления о кучах как упорядоченных коллекциях под куч, представленных в [15] . Алгоритм требует O (log n * log n ) сравнений. В представлении также представлен новый и концептуально простой алгоритм объединения куч. Когда слияние является общей задачей, рекомендуется другая реализация кучи, например, биномиальные кучи , которые можно объединить за O (log n ).

Кроме того, двоичная куча может быть реализована с традиционной структурой данных двоичного дерева, но при добавлении элемента возникает проблема с нахождением соседнего элемента на последнем уровне в двоичной куче. Этот элемент может быть определен алгоритмически или путем добавления дополнительных данных к узлам, что называется «распараллеливанием» дерева - вместо того, чтобы просто хранить ссылки на дочерние элементы , мы также сохраняем порядковый преемник узла.

Можно изменить структуру кучи, чтобы обеспечить извлечение как самого маленького, так и самого большого элемента во времени. [16] Для этого строки чередуются между минимальной кучей и максимальной кучей. Алгоритмы примерно одинаковы, но на каждом шаге необходимо рассматривать чередующиеся строки с чередующимися сравнениями. Производительность примерно такая же, как у обычной однонаправленной кучи. Эту идею можно обобщить для кучи min-max-median. О {\ displaystyle O}

Вывод индексных уравнений [ править ]

В куче на основе массивов дочерние и родительские элементы узла могут быть расположены с помощью простой арифметики по индексу узла. В этом разделе выводятся соответствующие уравнения для куч с их корнем в индексе 0, с дополнительными примечаниями для куч с их корнем в индексе 1.

Чтобы избежать путаницы, мы определим уровень узла как его расстояние от корня, так что сам корень занимает уровень 0.

Дочерние узлы [ править ]

Для общего узла, расположенного с индексом (начиная с 0), мы сначала получим индекс его правого дочернего элемента .

Пусть узел находится на уровне , и обратите внимание, что любой уровень содержит ровно узлы. Кроме того, есть ровно узлы, содержащиеся в уровнях до уровня включительно (подумайте о двоичной арифметике; 0111 ... 111 = 1000 ... 000 - 1). Поскольку корень хранится в 0, й узел будет сохранен в индексе . Объединение этих наблюдений дает следующее выражение для индекса последнего узла в слое l .

Пусть в слое L есть узлы после узла , такие что

У каждого из этих узлов должно быть ровно 2 дочерних элемента , поэтому должны быть узлы, отделяющие правый дочерний элемент от конца его слоя ( ).

Как требуется.

Заметив, что левый дочерний элемент любого узла всегда на 1 место перед его правым дочерним элементом, мы получаем .

Если корень расположен в индексе 1 вместо 0, последний узел на каждом уровне вместо этого находится в индексе . Используйте это во всех урожаях и для куч с их корнем в 1.

Родительский узел [ править ]

Каждый узел является левым или правым дочерним элементом своего родителя, поэтому мы знаем, что верно одно из следующих утверждений.

Следовательно,

Теперь рассмотрим выражение .

Если node является левым дочерним элементом, это дает результат немедленно, однако он также дает правильный результат, если node является правым дочерним элементом. В этом случае должно быть четным, а значит, должно быть нечетным.

Следовательно, независимо от того, является ли узел левым или правым дочерним узлом, его родительский элемент можно найти по выражению:

Связанные структуры [ править ]

Поскольку порядок братьев и сестер в куче не определяется свойством heap, два дочерних узла одного узла можно свободно менять местами, если это не нарушает свойство shape (сравните с treap ). Обратите внимание, однако, что в общей куче на основе массива простая замена дочерних элементов может также потребовать перемещения дочерних узлов поддерева, чтобы сохранить свойство кучи.

Двоичная куча - это частный случай d-арной кучи, в которой d = 2.

Сводка времени работы [ править ]

Вот временные сложности [17] различных структур данных кучи. Имена функций предполагают минимальную кучу. Для значения " O ( F )" и " thetas ; ( е )" см Big O нотацию .

  1. ^ Фактически, можно показать, что эта процедура занимает Θ ( n log n ) времени в худшем случае , что означает, что n log n также является асимптотической нижней границей сложности. [1] : 167 В среднем случае (усреднение по всем перестановкам из п входов), хотя, метод занимает линейное время. [8]
  2. ^ Это не означает, что сортировка может выполняться за линейное время, поскольку создание кучи - это только первый шагалгоритма heapsort .
  3. ^ a b c d e f g h i Амортизированное время.
  4. ^ n - размер большей кучи.
  5. ^ Нижняя оценка [21] верхняя оценка [22]
  6. ^ Бродал и Окасаки позже описывают постоянный вариант с теми же границами, за исключением ключа уменьшения, который не поддерживается. Кучи с n элементами могут быть построены снизу вверх за O ( n ). [24]

См. Также [ править ]

  • Куча
  • Heapsort

Ссылки [ править ]

  1. ^ а б Кормен, Томас Х .; Лейзерсон, Чарльз Э .; Ривест, Рональд Л .; Стейн, Клиффорд (2009) [1990]. Введение в алгоритмы (3-е изд.). MIT Press и McGraw-Hill. ISBN 0-262-03384-4.
  2. ^ Williams, JWJ (1964), "Алгоритм 232 - Пирамидальная сортировка", Связь по АКМ , 7 (6): 347-348, DOI : 10,1145 / 512274,512284
  3. ^ eEL, CSA_Dept, IISc, Бангалор, «Двоичные кучи» , структуры данных и алгоритмыCS1 maint: uses authors parameter (link)
  4. ^ Портер, Томас; Саймон, Иштван (сентябрь 1975 г.). «Случайная вставка в структуру приоритетной очереди». IEEE Transactions по разработке программного обеспечения . SE-1 (3): 292–298. DOI : 10.1109 / TSE.1975.6312854 . ISSN 1939-3520 . S2CID 18907513 .  
  5. ^ Mehlhorn, Курт; Цакалидис А. (февраль 1989 г.). «Структуры данных» : 27. Портер и Саймон [171] проанализировали среднюю стоимость вставки случайного элемента в случайную кучу с точки зрения обменов. Они доказали, что это среднее ограничено константой 1,61. Их доказательства не обобщаются на последовательности вставок, поскольку случайные вставки в случайные кучи не создают случайных куч. Проблема повторной вставки была решена Боллобасом и Саймоном [27]; они показывают, что ожидаемое количество обменов ограничено 1,7645. Наихудшая стоимость вставок и делетеминов была изучена Gonnet и Munro [84]; они дают оценки log log n + O (1) и log n + log n * + O (1) для количества сравнений соответственно. Cite journal requires |journal= (help)
  6. ^ "python / cpython / heapq.py" . GitHub . Проверено 7 августа 2020 .
  7. ^ «heapq - Алгоритм очереди кучи - документация Python 3.8.5» . docs.python.org . Проверено 7 августа 2020 . heapq.heappushpop (куча, элемент): поместите элемент в кучу, затем вытолкните и верните наименьший элемент из кучи. Комбинированное действие выполняется более эффективно, чем heappush (), за которым следует отдельный вызов heappop ().
  8. ^ a b Хейворд, Райан; МакДиармид, Колин (1991). «Анализ среднего случая построения кучи путем повторной вставки» (PDF) . J. Алгоритмы . 12 : 126–153. CiteSeerX 10.1.1.353.7888 . DOI : 10.1016 / 0196-6774 (91) 90027-v . Архивировано из оригинального (PDF) 05 февраля 2016 года . Проверено 28 января 2016 .  
  9. ^ Suchenek, Marek А. (2012), "Элементарные же Precise Наихудший анализ Heap-строительная программа Флойда" , Fundamenta Informaticae , 120 (1): 75-92, DOI : 10,3233 / FI-2012-751.
  10. ^ Doberkat, Ernst E. (май 1984). «Анализ среднего случая алгоритма Флойда для построения куч» (PDF) . Информация и контроль . 6 (2): 114–131. DOI : 10.1016 / S0019-9958 (84) 80053-4 .
  11. Pasanen, Tomi (ноябрь 1996 г.). Элементарный анализ среднего случая алгоритма Флойда для построения куч (технический отчет). Центр компьютерных наук Турку. CiteSeerX 10.1.1.15.9526 . ISBN  951-650-888-X. Технический отчет TUCS № 64. Обратите внимание , что этот документ использует оригинальную терминологию «siftup» Флойда за то , что теперь называется просеивания вниз .
  12. Камп, Поул-Хеннинг (11 июня 2010 г.). «Ты делаешь это неправильно» . Очередь ACM . Vol. 8 нет. 6.
  13. ^ Крис Л. Кузмаул. "binary heap". Архивировано 8 августа 2008 г. на Wayback Machine . Словарь алгоритмов и структур данных, Пол Э. Блэк, изд., Национальный институт стандартов и технологий США. 16 ноября 2009 г.
  14. ^ J.-R. Сак и Т. Стрототт "Алгоритм слияния куч " , Acta Informatica 22, 171-186 (1985).
  15. ^ Мешок, Йорг-Рюдигер; Стрототта, Томас (1990). «Характеристика кучи и ее применения» . Информация и вычисления . 86 : 69–86. DOI : 10.1016 / 0890-5401 (90) 90026-E .
  16. ^ Аткинсон, доктор медицины; Ж.-Р. Мешок ; Н. Санторо и Т. Стрототт (1 октября 1986 г.). «Мин-макс кучи и очереди с обобщенным приоритетом» (PDF) . Методы программирования и структуры данных. Comm. ACM, 29 (10): 996–1000.
  17. ^ a b c d Кормен, Томас Х .; Лейзерсон, Чарльз Э .; Ривест, Рональд Л. (1990). Введение в алгоритмы (1-е изд.). MIT Press и McGraw-Hill. ISBN 0-262-03141-8.
  18. ^ "Биномиальная куча | Блестящая математика и наука вики" . brilliant.org . Проверено 30 сентября 2019 .
  19. ^ Фредман, Майкл Лоуренс ; Тарджан, Роберт Э. (июль 1987 г.). «Куча Фибоначчи и их использование в улучшенных алгоритмах оптимизации сети» (PDF) . Журнал Ассоциации вычислительной техники . 34 (3): 596–615. CiteSeerX 10.1.1.309.8927 . DOI : 10.1145 / 28869.28874 .  
  20. ^ Яконо, Джон (2000), "Улучшенные верхние границы для парных куч", Proc. 7-й скандинавский семинар по теории алгоритмов (PDF) , Lecture Notes in Computer Science, 1851 , Springer-Verlag, стр. 63–77, arXiv : 1110.4428 , CiteSeerX 10.1.1.748.7812 , doi : 10.1007 / 3-540-44985-X_5 , ISBN   3-540-67690-2
  21. ^ Фредман, Майкл Лоуренс (июль 1999 г.). «Об эффективности объединения куч и связанных структур данных» (PDF) . Журнал Ассоциации вычислительной техники . 46 (4): 473–501. DOI : 10.1145 / 320211.320214 .
  22. ^ Петти, Сет (2005). К окончательному анализу парных куч (PDF) . FOCS '05 Материалы 46-го ежегодного симпозиума IEEE по основам информатики. С. 174–183. CiteSeerX 10.1.1.549.471 . DOI : 10.1109 / SFCS.2005.75 . ISBN   0-7695-2468-0.
  23. ^ Бродал, Герт С. (1996), "Эффективные приоритетные очереди наихудшего случая" (PDF) , Proc. 7-й ежегодный симпозиум ACM-SIAM по дискретным алгоритмам , стр. 52–58.
  24. ^ Гудрич, Майкл Т .; Тамассия, Роберто (2004). «7.3.6. Конструкция кучи снизу вверх». Структуры данных и алгоритмы в Java (3-е изд.). С. 338–341. ISBN 0-471-46983-1.
  25. ^ Haeupler, Бернхард; Сен, Сиддхартха; Тарджан, Роберт Э. (ноябрь 2011 г.). "Куча ранговых пар" (PDF) . SIAM J. Computing . 40 (6): 1463–1485. DOI : 10.1137 / 100785351 .
  26. ^ Бродал, Герт Стёльтинг ; Лагогианнис, Джордж; Тарьян, Роберт Э. (2012). Строгие кучи Фибоначчи (PDF) . Материалы 44-го симпозиума по теории вычислений - STOC '12. С. 1177–1184. CiteSeerX 10.1.1.233.1740 . DOI : 10.1145 / 2213977.2214082 . ISBN   978-1-4503-1245-5.
  27. ^ Такаок, Тадао (1999), Теория 2-3 куч (PDF) , стр. 12

Внешние ссылки [ править ]

  • Структуры открытых данных - Раздел 10.1 - BinaryHeap: неявное двоичное дерево , Пэт Морин
  • Реализация бинарной максимальной кучи на C от Робина Томаса
  • Реализация двоичной минимальной кучи на C от Робина Томаса