Косая биномиальная куча
Косая биномиальная куча | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Тип | куча | ||||||||||||||||||||||||||
Изобретенный | 1996 | ||||||||||||||||||||||||||
Изобретён | Герт Столтинг Бродал и Крис Окасаки | ||||||||||||||||||||||||||
|
В информатике ( косая биномиальная куча или косая биномиальная очередь ) — это структура данных для операций приоритетной очереди . Это вариант биномиальной кучи , который в худшем случае поддерживает операции вставки с постоянным временем, а не с амортизированным временем .
Мотивация [ править ]
Так же, как биномиальные кучи основаны на двоичной системе счисления , косые двоичные кучи основаны на косой двоичной системе счисления . [1] Обычные биномиальные кучи страдают от логарифмической сложности вставки в наихудшем случае, поскольку операция переноса может быть каскадной, аналогично двоичному сложению. Косые биномиальные кучи основаны на косой двоичной системе счисления, где -я цифра (с нулевым индексом) представляет , вместо . Цифры могут быть либо 0, либо 1, за исключением самой младшей ненулевой цифры, которая может быть 2. Преимущество этой системы состоит в том, что требуется не более одной операции переноса. Например, 60 представлено как 11 200 в асимметричном двоичном формате (31 + 15 + 7 + 7), а добавление 1 дает 12 000 (31 + 15 + 15). Поскольку следующая старшая цифра гарантированно не равна 2, перенос выполняется не более одного раза. Эта аналогия применяется к операции вставки путем введения троичных (косых) связей, которые связывают три дерева вместе. Это позволяет операции вставки выполняться за постоянное время.
Структура [ править ]


Косая биномиальная куча — это лес косых биномиальных деревьев , которые определяются индуктивно:
- Косое биномиальное дерево ранга 0 является одноэлементным узлом.
- Косое биномиальное дерево рангов можно построить тремя способами:
- простая ссылка связывает два ранга деревья, что делает одно крайним левым дочерним элементом другого;
- соединяет Косая связь типа А три дерева. Два ранга деревья становятся потомками дерева ранга 0;
- связывает Косая связь типа B три дерева. Дерево ранга 0 и ранг дерево станет самым левым потомком другого ранга дерево.
При выполнении любой ссылки корнем всегда становится дерево с наименьшим ключом. Кроме того, мы налагаем инвариант, согласно которому может быть только одно дерево каждого ранга, за исключением самого низкого ранга, у которого может быть до двух.
Следующий код OCaml демонстрирует операции связывания:
type 'a heap = 'a tree list
and 'a tree = Tree of 'a * int * 'a tree list
let rank (Tree (_, r, _)) = r
let simple_link (Tree (k1, r, c1) as t1) (Tree (k2, r, c2) as t2) =
if k1 <= k2 then
Tree (k1, r + 1, t2 :: c1)
else
Tree (k2, r + 1, t1 :: c2)
let skew_link k1 (Tree (k2, r, c2) as t2) (Tree (k3, r, c3) as t3) =
if k1 <= k2 && k1 <= k3 then (* type A *)
Tree (k1, r + 1, [t2; t3])
else (* type B *)
let t1 = Tree (k1, 0, []) in
if k2 <= k3 then
Tree (k2, r + 1, t1 :: t3 :: c2)
else
Tree (k3, r + 1, t1 :: t2 :: c3)
Из этих свойств можно вывести, что корень ранга скошенное биномиальное дерево имеет до дети. Количество узлов в косом биномиальном дереве ранга также ограничено . Поскольку деревья одного и того же ранга могут иметь разное количество узлов, может существовать более одного способа распределения рангов в куче.
Эти конструкции можно рассматривать как обобщение бинарных и биномиальных деревьев. Косое биномиальное дерево, построенное с использованием только простых связей, является обычным биномиальным деревом, а использование только косых связей типа А приводит к идеально сбалансированному двоичному дереву.
Операции [ править ]
Найти-мин [ править ]
Найдите в списке корней узел, содержащий минимальный ключ. Это занимает время.
В императивной настройке можно сохранить указатель на корень, содержащий минимальный ключ, разрешая доступ в время. Этот указатель должен обновляться после каждой операции, добавляя лишь постоянные накладные расходы по временной сложности.
В функциональной настройке без произвольного доступа к узлам вместо этого можно представить кучу как одно дерево с косыми биномиальными деревьями в качестве его дочерних элементов. Корень этого дерева — минимум кучи, что позволяет доступ. Обратите внимание, что это дерево не обязательно само по себе будет косым биномиальным деревом. Остальные операции необходимо изменить для работы с этим единственным деревом. Эта концепция глобального корня используется в описанных ниже оптимизациях , хотя и немного по-другому.
Объединить [ править ]
Чтобы объединить две косые биномиальные кучи, сначала удалите все повторяющиеся деревья ранга в каждой куче, выполнив простые связи . Затем объедините кучи так же, как обычные биномиальные кучи, что похоже на двоичное сложение. Деревья с одинаковыми рангами связываются простой ссылкой , и при необходимости дерево переноса передается вверх. Поскольку ранг деревьев в каждой куче теперь уникален, рассматриваются не более трех деревьев одного ранга, что достаточно для установления граница.
let rec unique = function
| t1 :: t2 :: ts when rank t1 = rank t2 ->
unique (simple_link t1 t2 :: ts)
| ts -> ts
let rec merge_uniq h1 h2 = match h1, h2 with
| h1, [] -> h1
| [], h2 -> h2
| t1 :: ts1, t2 :: ts2 ->
if rank t1 < rank t2 then
t1 :: merge_uniq ts1 h2
else if rank t1 > rank t2 then
t2 :: merge_uniq h1 ts2
else
unique (simple_link t1 t2 :: merge_uniq ts1 ts2)
let merge h1 h2 = merge_uniq (unique h1) (unique h2)
Вставить [ править ]
Создайте косое биномиальное дерево ранга 0 (одноэлементный узел), содержащее вставляемый ключ. Затем рассматриваются два самых маленьких дерева в куче:
- Если они оба имеют ранг , затем выполните косую связь с этими двумя деревьями и одноэлементным узлом. Полученное дерево имеет ранг . Поскольку мог быть только один ранг дерево в исходной куче, инвариант сохраняется.
- Если они имеют разные ранги, просто добавьте дерево ранга 0 в начало списка корней. Поскольку ранее список корней не имел повторяющихся деревьев ранга, инвариант не нарушается, так как после него будет не более двух деревьев ранга 0.
Поскольку выполняется до одной ссылки, эта операция выполняется в худшем случае. время, улучшая биномиальную кучу, которая опирается на амортизированный анализ для своего связанный, с наихудшим случаем .
let insert k = function
| t2 :: t3 :: ts when rank t2 = rank t3 -> skew_link k t2 t3 :: ts
| ts -> Tree (k, 0, []) :: ts
Удалить-моё [ изменить ]
Найдите и отбросьте узел, содержащий минимальный ключ. Этот узел должен быть корнем дерева. может быть более двух дочерних элементов с рангом 0 Разделите его дочерние элементы на две группы: группы с рангом 0 и группы с рангом > 0. Обратите внимание, что из-за перекоса связей . Дочерние элементы, ранг которых > 0, образуют действительную косую биномиальную кучу, поскольку они уже упорядочены и не имеют дубликатов. Объединение этих детей в кучу занимает время. После этого повторно вставьте в кучу каждого дочернего элемента ранга 0 по цене каждый. Общее время, необходимое для .
Клавиша уменьшения [ править ]
Эта операция не отличается от биномиальных куч. Уменьшение ключа узла может привести к тому, что он станет меньше своего родителя. Неоднократно обменивайте его с родительским элементом до тех пор, пока не будет удовлетворено свойство минимальной кучи , затрачивая временная сложность. Для этой операции требуется указатель на узел, содержащий рассматриваемый ключ, и ее проще всего выполнить в императивной настройке.
Оптимизации [ править ]
Бродал и Окасаки показали, как можно сократить временную сложность операции слияния до , применив технику «бутстреппинга» Буксбаума и Тарьяна . [2]
Пусть тип примитивной косой биномиальной кучи, содержащей элементы типа быть . Вместо представления леса деревьев, описанного выше, мы поддерживаем одно дерево с глобальным корнем как минимум.
Пусть тип корневой косой биномиальной кучи будет
- ,
то есть пара, содержащая элемент типа и примитивная куча корневых куч.
Наконец, мы определяем тип самозагруженной кучи , заключая корневые кучи в параметр type :
что допускает пустую кучу.
Операции над этой самозагруженной кучей переопределяются соответствующим образом. В следующем коде OCaml простой символ '
обозначает операции для самозагруженных куч.
type 'a bootstrapped =
| Empty
| Root of 'a rooted
let find_min' (Root (k, h)) = k
let merge' bh1 bh2 = match bh1, bh2 with
| _, Empty -> bh1
| Empty, _ -> bh2
| Root (k1, h1), Root (k2, h2) ->
if k1 <= k2 then
Root (k1, insert bh2 h1)
else
Root (k2, insert bh1 h2)
let insert' k h = merge' (Root(k, [])) h
let delete_min' (Root (x, h)) =
let Root (y, h1) = find_min h in
let h2 = delete_min h in
Root (y, merge h1 h2)
Новая операция слияния использует только операции вставки в примитивные кучи. Таким образом, он выполняется в время. Этот метод можно применить к любой приоритетной очереди с вставкой постоянного времени и логарифмическим слиянием.
Сводка времени работы [ править ]
Вот временные сложности [3] различных структур данных кучи. Имена функций предполагают минимальную кучу. Значение « O ( f )» и « Θ ( f )» см в обозначении Big O. .
Операция | найти-мин | удаление-мин | вставлять | клавиша уменьшения | сливаться |
---|---|---|---|---|---|
Двоичный [3] | я (1) | Θ (логарифм n ) | О ( войти ) | О ( войти ) | Θ ( н ) |
Левый | я (1) | Θ (логарифм n ) | Θ (логарифм n ) | О ( войти ) | Θ (логарифм n ) |
Биномиальный [3] [4] | я (1) | Θ (логарифм n ) | я (1) [а] | Θ (логарифм n ) | О ( войти ) |
Наклонный бином [5] | я (1) | Θ (логарифм n ) | я (1) | Θ (логарифм n ) | О ( войти ) [б] |
Сопряжение [6] | я (1) | О ( войти ) [а] | я (1) | о ( войти ) [а] [с] | я (1) |
Сопряжение по рангам [9] | я (1) | О ( войти ) [а] | я (1) | я (1) [а] | я (1) |
Фибоначчи [3] [10] | я (1) | О ( войти ) [а] | я (1) | я (1) [а] | я (1) |
Строгий Фибоначчи [11] | я (1) | О ( войти ) | я (1) | я (1) | я (1) |
Мостовая долина [12] [д] | я (1) | О ( войти ) | я (1) | я (1) | я (1) |
2–3 кучи [14] | я (1) | О ( войти ) [а] | я (1) [а] | я (1) | О ( войти ) |
- ^ Перейти обратно: а б с д и ж г час я Амортизированное время.
- ^ в наихудшем случае Бродал и Окасаки описывают метод уменьшения сложности объединения до Θ (1); этот метод применим к любой структуре данных кучи, которая имеет вставку в Θ (1) и find-min , delete-min , объединение в O (log n ).
- ^ Нижняя граница [7] верхняя граница [8]
- ^ Бродал и Окасаки позже описывают постоянный вариант с теми же границами, за исключением клавиши уменьшения, которая не поддерживается. Кучи с n элементами могут быть построены снизу вверх за O ( n ). [13]
Ссылки [ править ]
- ^ Бродал, Герт Столтинг; Окасаки, Крис (ноябрь 1996 г.), «Оптимальные чисто функциональные очереди приоритетов», Journal of Functional Programming , 6 (6): 839–857, doi : 10.1017/s095679680000201x
- ^ Бухсбаум, Алабама; Тарьян, Р.Э. (май 1995 г.). «Конфлюэнтно устойчивые колоды посредством структурной начальной загрузки данных» . Журнал алгоритмов . 18 (3): 513–547. дои : 10.1006/jagm.1995.1020 . ISSN 0196-6774 .
- ^ Перейти обратно: а б с д Кормен, Томас Х .; Лейзерсон, Чарльз Э .; Ривест, Рональд Л. (1990). Введение в алгоритмы (1-е изд.). MIT Press и McGraw-Hill. ISBN 0-262-03141-8 .
- ^ «Биномиальная куча | Блестящая вики по математике и естественным наукам» . блестящий.орг . Проверено 30 сентября 2019 г.
- ^ Бродал, Герт Столтинг; Окасаки, Крис (ноябрь 1996 г.), «Оптимальные чисто функциональные очереди приоритетов», Journal of Functional Programming , 6 (6): 839–857, doi : 10.1017/s095679680000201x
- ^ Яконо, Джон (2000), «Улучшенные верхние границы для спаривания куч», Proc. 7-й скандинавский семинар по теории алгоритмов (PDF) , Конспекты лекций по информатике, том. 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
- ^ Фредман, Майкл Лоуренс (июль 1999 г.). «Об эффективности объединения куч и связанных структур данных» (PDF) . Журнал Ассоциации вычислительной техники . 46 (4): 473–501. дои : 10.1145/320211.320214 .
- ^ Петти, Сет (2005). К окончательному анализу парных куч (PDF) . FOCS '05 Материалы 46-го ежегодного симпозиума IEEE по основам информатики. стр. 174–183. CiteSeerX 10.1.1.549.471 . дои : 10.1109/SFCS.2005.75 . ISBN 0-7695-2468-0 .
- ^ Хёплер, Бернхард; Сен, Сиддхартха; Тарьян, Роберт Э. (ноябрь 2011 г.). «Кучи ранговых пар» (PDF) . СИАМ Дж. Компьютерные технологии . 40 (6): 1463–1485. дои : 10.1137/100785351 .
- ^ Фредман, Майкл Лоуренс ; Тарьян, Роберт Э. (июль 1987 г.). «Кучи Фибоначчи и их использование в улучшенных алгоритмах оптимизации сети» (PDF) . Журнал Ассоциации вычислительной техники . 34 (3): 596–615. CiteSeerX 10.1.1.309.8927 . дои : 10.1145/28869.28874 .
- ^ Бродал, Герт Столтинг ; Лагояннис, Джордж; Тарьян, Роберт Э. (2012). Строгие кучи Фибоначчи (PDF) . Материалы 44-го симпозиума по теории вычислений - STOC '12. стр. 1177–1184. CiteSeerX 10.1.1.233.1740 . дои : 10.1145/2213977.2214082 . ISBN 978-1-4503-1245-5 .
- ^ Бродал, Герт С. (1996), «Эффективные приоритетные очереди для наихудшего случая» (PDF) , Proc. 7-й ежегодный симпозиум ACM-SIAM по дискретным алгоритмам , стр. 52–58.
- ^ Гудрич, Майкл Т .; Тамассия, Роберто (2004). «7.3.6. Построение кучи снизу вверх». Структуры данных и алгоритмы в Java (3-е изд.). стр. 338–341. ISBN 0-471-46983-1 .
- ^ Такаока, Тадао (1999), Теория 2–3 куч (PDF) , стр. 12