{"record":{"id":"d0b1f5b5b021f695","repo":"krahets/hello-algo","slug":"error-d0b1f5","errorCode":null,"errorMessage":"堆積為空","messagePattern":"堆積為空","errorType":"exception","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"zh-hant/codes/ruby/chapter_heap/my_heap.rb","lineNumber":83,"sourceCode":"\n  ### 從節點 i 開始，從底至頂堆積化 ###\n  def sift_up(i)\n    loop do\n      # 獲取節點 i 的父節點\n      p = parent(i)\n      # 當“越過根節點”或“節點無須修復”時，結束堆積化\n      break if p < 0 || @max_heap[i] <= @max_heap[p]\n      # 交換兩節點\n      swap(i, p)\n      # 迴圈向上堆積化\n      i = p\n    end\n  end\n\n  ### 元素出堆積 ###\n  def pop\n    # 判空處理\n    raise IndexError, \"堆積為空\" if is_empty?\n    # 交換根節點與最右葉節點（交換首元素與尾元素）\n    swap(0, size - 1)\n    # 刪除節點\n    val = @max_heap.pop\n    # 從頂至底堆積化\n    sift_down(0)\n    # 返回堆積頂元素\n    val\n  end\n\n  ### 從節點 i 開始，從頂至底堆積化 ###\n  def sift_down(i)\n    loop do\n      # 判斷節點 i, l, r 中值最大的節點，記為 ma\n      l, r, ma = left(i), right(i), i\n      ma = l if l < size && @max_heap[l] > @max_heap[ma]\n      ma = r if r < size && @max_heap[r] > @max_heap[ma]\n","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/zh-hant/codes/ruby/chapter_heap/my_heap.rb#L65-L101","documentation":"Raised by the pop method of the MyHeap teaching class (a max-heap backed by an array) when is_empty? is true. The guard prevents swapping or popping from an empty backing array, which would produce nil or an out-of-bounds access. It fires before any structural mutation.","triggerScenarios":"Calling heap.pop on a freshly-constructed heap (no elements pushed yet), calling pop more times than elements were pushed, or calling pop in a drain loop without checking emptiness.","commonSituations":"Draining a heap with a fixed-count loop instead of an emptiness check; popping after a failed or partial push sequence; using heap.pop where peek was intended.","solutions":["Check heap.is_empty? (or heap.size.zero?) before calling pop.","Use a while !heap.is_empty? loop to drain the heap safely.","Wrap the call in begin/rescue IndexError for defensive draining.","Log or track push/pop counts to detect push/pop imbalance."],"exampleFix":"# before\n10.times { max_val = heap.pop }  # crashes when heap has fewer than 10 elements\n\n# after\nresults = []\nresults << heap.pop until heap.is_empty?  # drains safely","handlingStrategy":"validation","validationCode":"return nil if heap.is_empty?\nheap.pop","typeGuard":"# Ruby: safe pop\ndef safe_pop(heap)\n  heap.is_empty? ? nil : heap.pop\nend","tryCatchPattern":"begin\n  max_val = heap.pop\nrescue IndexError\n  max_val = nil  # heap was empty\nend","preventionTips":["Use 'until heap.is_empty?' to drain a heap instead of a fixed count.","Track push/pop counts to detect imbalance early.","Always check is_empty? before peek or pop."],"tags":["ruby","index-error","data-structures","heap","empty-state","max-heap"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}