Получить доступ

Что такое двоичная куча и очередь с приоритетом?

JuniorСтруктуры данных
Ещё спрашивают так:
  • Как найти k наибольших элементов?
  • Как устроена PriorityQueue?
  • Как куча хранится в массиве?
Коротко

Двоичная куча — дерево, где родитель не больше потомков (min-heap): минимум всегда в корне, вставка и извлечение — O(log n).

  • Хранится в массиве: потомки элемента i — 2i+1 и 2i+2, родитель — (i−1)//2
  • Очередь с приоритетом почти всегда реализуют кучей

А ещё Применения: планировщик задач, алгоритм Дейкстры, k наибольших, слияние отсортированных потоков

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Попробуйте сами

Двоичная куча: вставка и извлечение

Подробно

Куча — полное двоичное дерево с правилом: значение в каждом узле не больше значений его потомков (для min-кучи; в max-куче наоборот). Это слабее порядка в дереве поиска — между братьями порядка нет, — зато поддерживать такое правило дешевле.

Хранение в массиве. Полное дерево ложится в массив без пропусков: корень — в позиции 0, потомки элемента i — в 2i+1 и 2i+2, родитель — в (i−1)//2. Ссылки не нужны.

Операции:

  • посмотреть минимум — O(1), это корень;
  • вставка — кладём элемент в конец и «поднимаем» (sift up), пока он меньше родителя: O(log n);
  • извлечение минимума — ставим последний элемент в корень и «опускаем» (sift down), меняя с меньшим потомком: O(log n);
  • построение кучи из массива — O(n), а не O(n log n), если просеивать снизу вверх.

Очередь с приоритетом — структура «положить с приоритетом, достать самый приоритетный». Её почти всегда реализуют кучей: heapq в Python, PriorityQueue в Java.

Применения: планировщики задач, алгоритм Дейкстры и A*, поиск k наибольших элементов (куча размера k — O(n log k)), слияние k отсортированных списков, медиана потока (две кучи), пирамидальная сортировка.

Пример

import heapq

def top_k(nums, k):
    heap = []                       # min-куча из k наибольших
    for x in nums:
        heapq.heappush(heap, x)
        if len(heap) > k:
            heapq.heappop(heap)     # выкидываем наименьший
    return sorted(heap, reverse=True)

top_k([5, 1, 9, 3, 7, 2], 3)        # [9, 7, 5]

Что хотят услышать

  • Свойство кучи и где находится минимум.
  • Хранение в массиве и формулы индексов.
  • Сложность операций, построение за O(n) — плюс.
  • Применения, особенно очередь с приоритетом и задача о k наибольших.

Частые ошибки

  • Путать кучу с деревом поиска — в куче нет полного порядка.
  • Считать, что поиск произвольного элемента в куче O(log n) — он O(n).

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем