А я угадаю этот минимум за O(1) Назад
</figcaption>
На таком дереве несложно реализовать три основные операции, производимые с куче:
Аномалии могут возникнуть по двум причинам:
style A fill:pink
</figcaption>
style A fill:lightGreen
style C fill:pink
</figcaption>
style C fill:lightGreen
style H fill:pink
</figcaption>
style H fill:lightGreen
style M fill:pink
</figcaption>
style O fill:pink
</figcaption>
style J fill:pink
style O fill:lightGreen
</figcaption>
style D fill:pink
style J fill:lightGreen
</figcaption>
style A fill:pink
style D fill:lightGreen
</figcaption>
Добавим следующие ограничения:
style M opacity:0.2
style N opacity:0.2
style O opacity:0.2
</figcaption>
Для \(i\)-го узла
Высота дерева: \(\lceil 1 + \log n \rceil\)
class BinaryHeap:
_items = []
def peek(self):
if len(self._items) > 0:
return self._items[0]
def push(self, x):
self._items.append(x)
self._sift_up(len(self._items) - 1)
def _sift_up(self, i):
while i > 0:
j = (i - 1) // 2
if self._items[j] <= self._items[i]:
break
self._swap(i, j)
i = j
def pop(self):
if len(self._items) > 0:
x = self._items[0]
self._swap(0, len(self._items)-1)
self._items.pop()
self._sift_down(0)
return x
def _sift_down(self, i):
while True:
j = self._min_son(i)
if not j or self._items[i] <= self._items[j]:
break
self._swap(i, j)
i = j
def _min_son(self, i):
l_son = i * 2 + 1
r_son = i * 2 + 2
if len(self._items) <= l_son:
return None
if len(self._items) <= r_son or self._items[l_son] < self._items[r_son]:
return l_son
return r_son
_min_son
возвращает индекс меньшего сына, если хотя бы один из сыновей существует, отдавая предпочтение правому сыну среди равныхДинамические указатели на элементы структуры, поддерживаемые самой структурой.
Можно воспользоваться дополнительным массивом, где каждому элементу при вставке выдавать следующую ячейку массива, возвращая в качестве итератора индекс этой ячейки. В значение ячейки необходимо записывать индекс элемента в основном массиве. А рядом с элементом в основном массиве хранить его итератор.
class BinaryHeapWithIterators:
_items = []
_iterators = []
def peek(self):
if len(self._items) > 0:
return self._items[0][0]
def push(self, x):
p = len(self._iterators)
self._iterators.append(len(self._items))
self._items.append((x, p))
self._sift_up(len(self._items) - 1)
return p
def pop(self):
if len(self._items) > 0:
x = self._items[0]
self._swap(0, len(self._items)-1)
self._items.pop()
self._sift_down(0)
return x[0]
def decrease(self, p, x):
i = self._iterators[p]
self._items[i] = (self._items[i][0] - x, p)
self._sift_up(i)
def _swap(self, i, j):
self._iterators[self._items[i][1]] = j
self._iterators[self._items[j][1]] = i
self._items[i], self._items[j] = self._items[j], self._items[i]
\[ T(n, m) = O(n \log m) \]
Эффективные реализации:
Будем перестраивать входной массив так, чтобы он начал удовлетворять условиям кучи.
Пусть дан массив начальных элементов \((4, 2, 12, 83, 45, 3, 21, 67, 11, 32, 37, 9, 1, 15, 7)\)
</figcaption>
style G fill:lightGreen
style O fill:pink
</figcaption>
style F fill:lightGreen
style M fill:pink
</figcaption>
style E fill:lightGreen
style J fill:pink
</figcaption>
style D fill:lightGreen
style I fill:pink
</figcaption>
style D fill:lightGreen
style E fill:lightGreen
style F fill:lightGreen
style G fill:lightGreen
style H fill:lightGreen
style I fill:lightGreen
style J fill:lightGreen
style K fill:lightGreen
style L fill:lightGreen
style M fill:lightGreen
style N fill:lightGreen
style O fill:lightGreen
</figcaption>
style C fill:lightGreen
style D fill:lightGreen
style E fill:lightGreen
style F fill:lightGreen
style G fill:lightGreen
style H fill:lightGreen
style I fill:lightGreen
style J fill:lightGreen
style K fill:lightGreen
style L fill:lightGreen
style M fill:lightGreen
style N fill:lightGreen
style O fill:lightGreen
</figcaption>
style B fill:lightGreen
style C fill:lightGreen
style D fill:lightGreen
style E fill:lightGreen
style F fill:lightGreen
style G fill:lightGreen
style H fill:lightGreen
style I fill:lightGreen
style J fill:lightGreen
style K fill:lightGreen
style L fill:lightGreen
style M fill:lightGreen
style N fill:lightGreen
style O fill:lightGreen
</figcaption>
style A fill:lightGreen
style B fill:lightGreen
style C fill:lightGreen
style D fill:lightGreen
style E fill:lightGreen
style F fill:lightGreen
style G fill:lightGreen
style H fill:lightGreen
style I fill:lightGreen
style J fill:lightGreen
style K fill:lightGreen
style L fill:lightGreen
style M fill:lightGreen
style N fill:lightGreen
style O fill:lightGreen
</figcaption>
</figcaption>
\(\alpha\) и \(\beta\) являются кучами
style O fill:lightGreen, opacity:0.5
style A fill:pink
</figcaption>
style O fill:lightGreen, opacity:0.5
style A fill:yellow
style B fill:yellow
style D fill:pink
</figcaption>
style O fill:lightGreen, opacity:0.5
style N fill:lightGreen, opacity:0.5
style A fill:pink
</figcaption>
style O fill:lightGreen, opacity:0.5
style N fill:lightGreen, opacity:0.5
style A fill:yellow
style C fill:yellow
style F fill:yellow
style L fill:pink
</figcaption>
style O fill:lightGreen, opacity:0.5
style N fill:lightGreen, opacity:0.5
style M fill:lightGreen, opacity:0.5
style A fill:pink
</figcaption>
style O fill:lightGreen, opacity:0.5
style N fill:lightGreen, opacity:0.5
style M fill:lightGreen, opacity:0.5
style A fill:yellow
style C fill:yellow
style G fill:pink
</figcaption>