هرم کمینه-بیشینه
هرمی که سطرهای زوجش هرم کمینه و سطرهای فردش هرم بیشینهاند؛ هم کمینه و هم بیشینه در O(1) پیدا و در O(log n) حذف میشوند (صف اولویت دوطرفه).
گاهی هم کمینه و هم بیشینه را لازم داریم (صف اولویت دوطرفه). هرم کمینه-بیشینه (Atkinson و همکاران) یک درخت دودویی کامل در آرایه است که سطرهایش یکیدرمیان «کمینه» و «بیشینه» اند:
ادامهی توضیح ↓- زمان:
O(log n) per insert or delete; O(1) to find the min or max - حافظه:
O(n) - هوروویتز–ساهنی، فصل ۹
ده درج، بعد حذف کمینه (۰) و حذف بیشینه (−۱). ریشه کمینه است و بیشینه یکی از دو فرزند ریشه.
def min_max_heap(ops):# A positive number is inserted, 0 deletes the minimum, a negative number deletes the maximum.heap = []removed = []for x in ops:if x > 0:heap.append(x)bubble_up(heap, len(heap) - 1)elif not heap:continueelif x == 0:removed.append(heap[0])remove_at(heap, 0)else:i = 0if len(heap) > 1:i = 1if len(heap) > 2 and heap[2] > heap[1]:i = 2removed.append(heap[i])remove_at(heap, i)return removeddef on_min_level(i):# Levels 0, 2, 4, ... are min levels; the root is the minimum, its children hold the maximum.return (i + 1).bit_length() % 2 == 1def better(a, b, low):if low:return a < breturn a > bdef bubble_up(heap, i):if i == 0:returnp = (i - 1) // 2low = on_min_level(i)if better(heap[p], heap[i], low):heap[i], heap[p] = heap[p], heap[i]i = plow = not lowwhile i > 2:g = ((i - 1) // 2 - 1) // 2if not better(heap[i], heap[g], low):breakheap[i], heap[g] = heap[g], heap[i]i = gdef remove_at(heap, i):last = heap.pop()if i < len(heap):heap[i] = lasttrickle_down(heap, i)def trickle_down(heap, i):low = on_min_level(i)while 2 * i + 1 < len(heap):# m: the best of i's children and grandchildren (the smallest on a min level, the largest on a max level).m = 2 * i + 1for c in [2 * i + 1, 2 * i + 2, 4 * i + 3, 4 * i + 4, 4 * i + 5, 4 * i + 6]:if c < len(heap) and better(heap[c], heap[m], low):m = cif not better(heap[m], heap[i], low):returnheap[i], heap[m] = heap[m], heap[i]if m <= 2 * i + 2:returnp = (m - 1) // 2if better(heap[p], heap[m], low):heap[m], heap[p] = heap[p], heap[m]i = m
شروع اجرا
متغیرهای محلی
نارنجی = در همین گام عوض شد
ops list
Call stack
- min_max_heap()خط 1
توضیح
ایده
گاهی هم کمینه و هم بیشینه را لازم داریم (صف اولویت دوطرفه). هرم کمینه-بیشینه (Atkinson و همکاران) یک درخت دودویی کامل در آرایه است که سطرهایش یکیدرمیان «کمینه» و «بیشینه» اند:
- عضوی روی سطر کمینه (سطر ۰، ۲، …) از همهی نوادگانش کوچکتر یا مساوی است؛
- عضوی روی سطر بیشینه (سطر ۱، ۳، …) از همهی نوادگانش بزرگتر یا مساوی است.
پس کمینه ریشه است و بیشینه بزرگترِ دو فرزند ریشه.
درج
عضو تازه ته آرایه میرود. اگر جایش روی سطر کمینه است ولی از پدرش (روی سطر بیشینه) بزرگتر است، با پدر جابهجا میشود. بعد فقط با پدربزرگها (که همنوع سطر خودشاند) مقایسه میشود و دو سطر دو سطر بالا میرود.
حذف
آخرین عضو به جای عضو حذفشده مینشیند و پایین میرود: در هر قدم بهترین عضو بین فرزندان و نوهها پیدا میشود. اگر نوه بود، ممکن است لازم باشد با پدرش هم جابهجا شود.
ورودی
عدد مثبت درج میشود، 0 یعنی حذف کمینه و عدد منفی یعنی حذف بیشینه.