krahets/hello-algo · error · IndexError

куча пуста

Error message

куча пуста

What it means

Raised by MaxHeap#pop (ru) — extract the maximum — when `is_empty?`. The guard runs before the swap-root-with-last-leaf, pop, and sift_down sequence, because there is no root to extract. This is the standard empty-heap precondition; pop is the only mutating accessor and does not delegate to a peek, so the raise is at the pop entry.

Source

Thrown at ru/codes/ruby/chapter_heap/my_heap.rb:83

  ### Начиная с узла i, выполнить просеивание снизу вверх ###
  def sift_up(i)
    loop do
      # Получение родительского узла для узла i
      p = parent(i)
      # Завершить heapify, когда «корневой узел уже пройден» или «узел не требует исправления»
      break if p < 0 || @max_heap[i] <= @max_heap[p]
      # Поменять два узла местами
      swap(i, p)
      # Циклическое просеивание вверх
      i = p
    end
  end

  ### Извлечение элемента из кучи ###
  def pop
    # Обработка пустого случая
    raise IndexError, "куча пуста" if is_empty?
    # Поменять корневой узел с самым правым листом местами (поменять первый и последний элементы)
    swap(0, size - 1)
    # Удаление узла
    val = @max_heap.pop
    # Просеивание сверху вниз
    sift_down(0)
    # Вернуть элемент с вершины кучи
    val
  end

  ### Начиная с узла i, выполнить просеивание сверху вниз ###
  def sift_down(i)
    loop do
      # Определить узел с максимальным значением среди i, l и r и обозначить его как ma
      l, r, ma = left(i), right(i), i
      ma = l if l < size && @max_heap[l] > @max_heap[ma]
      ma = r if r < size && @max_heap[r] > @max_heap[ma]

View on GitHub (pinned to 69932aed18)

Solutions

  1. Guard with `heap.is_empty?` (or `heap.size > 0`) before pop.
  2. Drive extract loops with `until heap.is_empty?`.
  3. If optional extraction is needed, wrap pop in a helper returning nil when empty.

Example fix

// before
max = heap.pop  # raises 'куча пуста' when empty

// after
max = heap.is_empty? ? nil : heap.pop
Defensive patterns

Strategy: validation

Validate before calling

max = heap.pop unless heap.is_empty?

Type guard

def heap_nonempty?(h) = !h.is_empty?

Try / catch

begin
  max = heap.pop
rescue IndexError
  max = nil
end

Prevention

When it happens

Trigger: Calling `heap.pop` on a freshly constructed heap, or after extracting all elements. Any extract-max loop that overshoots the heap's size triggers it.

Common situations: Heap-sort or top-k loop that pops N+1 times; draining a priority queue then popping again; a driver that pops before the first push.

Related errors


AI-assisted analysis of krahets/hello-algo@69932aed18 (2026-08-13). Data as JSON: /api/errors/596b6a58c2db3f4f. Report an issue: GitHub.