Куча Бродала-Окасаки

Материал из Викиконспекты
Перейти к: навигация, поиск

Куча Бродала-Окасаки (англ. Brodal's and Okasaki's Priority Queue) — основана на использовании биномиальной кучи без каскадных ссылок, что позволяет делать [math]insert[/math] за [math]O(1)[/math], добавлении минимального элемента, позволяет получать минимальный элемент за [math]O(1)[/math], и идеи Data-structural bootstrapping, позволяющей выполнить [math]merge[/math] за [math]O(1)[/math]. Удаление минимума работает за [math]O(\log N)[/math] в худшем случае. Эти оценки являются асимптотически оптимальными среди всех основанных на сравнении приоритетных очередей.

Структура

Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping.

Определение:
Data-structural bootstrapping — это идея, позволяющая снизить время [math]merge[/math] до [math]O(1)[/math] путем разрешения хранить в очереди другую очередь.




Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента [math]T_{min}[/math] и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по [math]T_{min}[/math]. Это можно записать так:

[math] BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)[/math]

Куча из одного элемента будет выглядеть так

[math]create(x) = BPQ \left \langle x, null\right \rangle[/math]

Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений [math]T_{min}[/math].

Операции

Merge

Слияние выполняется выбором минимума из двух значений [math]T_{min}[/math] и добавлением в приоритетную очередь второго BPQ.

pair merge((x : int, q : bpq) : pair, (y : int, r : bpq) : pair)
    if x < y
        return (x, insert(q, (y, r)))
    else
        return (y, insert(r, (x, q)))

Здесь [math]insert[/math] это добавление в приоритетную очередь работает за [math]O(1)[/math], тогда [math]merge[/math] работает за [math]O(1)[/math].

Insert

Это создание нового BPQ и [math]merge[/math] его с основным деревом.

pair(int, bpq) insert((x : int, q : bpq), y : bpq)
    return merge((x,q), create(y))

Создание и [math]merge[/math] выполняются за [math]O(1)[/math], тогда [math]insert[/math] работает за [math]O(1)[/math].

getMin

Выполняется просто, так как BPQ хранит минимум.

getMin((x,q))
  return x;

Очевидно, работает за [math]O(1)[/math]

extractMin

Минимальный элемент хранится в верхнем BPQ, по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди BPQ'ов.

extractMin((x,q))
  ((y,r), t) = extractMin(q)
  return (y, merge(r, t))

Здесь [math]extractMin(q)[/math] — это функция, извлекающая минимальный элемент типа BPQ из приоритетной очереди, она возвращает [math](y,r)[/math] — минимальный элемент типа BPQ и остаток от приоритетной очереди после извлечение минимума — [math]t[/math]. [math]merge[/math] — функция, выполняющая слияние двух приоритетных очередей.

Возвращаем BPQ, где [math]y[/math] — новый минимальный элемент, и [math]merge(r, t)[/math] приоритетная очередь без элемента [math]y[/math].

Так как [math]extractMin[/math] и [math]merge[/math] выполняются за [math]O(\log N)[/math], тогда [math]extractMin[/math] выполняется за [math]O(\log N)[/math].

Смотри также

Ссылки

Лекция А.С. Станкевича по приоритетным очередям

Optimal Purely Functional Priority Queues