Что такое куча (heap) как структура данных?

Ответ

Куча (heap) — это специализированная древовидная структура данных, которая удовлетворяет свойству кучи: если A является родительским узлом для B, то значение в узле A упорядочено относительно значения в узле B. Обычно куча реализуется на основе бинарного дерева.

Типы куч:

  • Min-heap (минимальная куча): Значение каждого родительского узла меньше или равно значениям его дочерних узлов. Таким образом, минимальный элемент всегда находится в корне дерева.
  • Max-heap (максимальная куча): Значение каждого родительского узла больше или равно значениям его дочерних узлов. Максимальный элемент — в корне.

Ключевые операции и их сложность:

  • insert (добавление): O(log n) — добавление нового элемента с сохранением свойства кучи.
  • extract-min / extract-max (извлечение): O(log n) — удаление корневого (минимального/максимального) элемента.
  • heapify (построение): O(n) — преобразование неупорядоченного массива в кучу.

Пример на Python (модуль heapq):

Модуль heapq в Python реализует min-heap.

import heapq

# Неупорядоченный список
data = [3, 1, 4, 1, 5, 9, 2, 6]

# Преобразуем список в min-heap (на месте)
heapq.heapify(data)
# Теперь data: [1, 1, 2, 3, 5, 9, 4, 6] (не отсортирован, но является кучей)

# Добавляем новый элемент
heapq.heappush(data, 0)
# data: [0, 1, 1, 3, 5, 9, 4, 6, 2]

# Извлекаем наименьший элемент
smallest = heapq.heappop(data) # smallest = 0
print(f"Извлечен элемент: {smallest}")
# data после извлечения: [1, 1, 2, 3, 5, 9, 4, 6]

Где применяется:

  • Приоритетные очереди (Priority Queues): Наиболее частое применение.
  • Алгоритм Дейкстры: Для эффективного выбора узла с наименьшим расстоянием.
  • Пирамидальная сортировка (Heapsort).
  • Поиск k-го наибольшего/наименьшего элемента в коллекции.

Ответ 18+ 🔞

А, куча! Ну это ж классика, блядь! Представь себе такое дерево, но не простое, а с характером — свойством кучи, ёпта. Суть в чём: если у тебя есть папа-узел А и сын-узел Б, то между ними строгая иерархия, блядь. Значение в папе всегда либо больше, либо меньше, чем в сыне, в зависимости от того, какая у тебя семья, блядь.

Какие бывают семейства куч, на:

  • Min-heap (куча для скромняг): Папа всегда меньше или равен своим детям. Самый мелкий элемент сидит на троне, в корне, как царёк. Всё для него.
  • Max-heap (куча для мажоров): Тут уже папаша больше или равен отпрыскам. Король-батюшка — самый большой элемент в дереве. Всё по понятиям.

Что с этим можно делать и за сколько:

  • insert (подселить нового члена семьи): O(log n) — аккуратно впихнуть элемент, чтобы иерархию не нарушить.
  • extract-min / extract-max (выгнать паханa): O(log n) — выкинуть корневого (самого мелкого или крупного) и навести новый порядок.
  • heapify (построить семью с нуля): O(n) — из беспорядочной толпы (массива) сделать дисциплинированную структуру.

Смотри, как в Питоне это выглядит (модуль heapq):

Там по умолчанию живут скромняги, min-heap.

import heapq

# Куча какого-то непонятного барахла
data = [3, 1, 4, 1, 5, 9, 2, 6]

# Делаем из этого дела порядок, на месте
heapq.heapify(data)
# Теперь data выглядит как куча: [1, 1, 2, 3, 5, 9, 4, 6] (не отсортирован, но правила соблюдает!)

# Подкидываем нового пацана
heapq.heappush(data, 0)
# data: [0, 1, 1, 3, 5, 9, 4, 6, 2] — ноль сразу пролез наверх, хитрожопый!

# Выковыриваем самого мелкого
smallest = heapq.heappop(data) # smallest = 0
print(f"Извлечен элемент: {smallest}")
# data после операции: [1, 1, 2, 3, 5, 9, 4, 6] — жизнь наладилась.

Где эта хуйня применяется в реальной жизни:

  • Приоритетные очереди: Самое, блядь, частое применение. Кто важнее — тот и вперёд.
  • Алгоритм Дейкстры: Чтобы быстро находить узел с самым коротким путём, а не перебирать всё, как дурак.
  • Пирамидальная сортировка (Heapsort): Само название говорит.
  • Поиск какого-нибудь k-го самого большого или самого мелкого элемента в куче данных. Овердохуища пользы, в общем!