Heap-egenskapen och arrayrepresentation
Förstå strukturen hos ett komplett binärt träd som lagras i en array, härled formler för index till föräldrar och barn och visualisera sift-up- och sift-down-operationer.
Heap-egenskapen och arrayrepresentation är en gratis lektion i Förberedelse inför kodningsintervjuer på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Förberedelse inför kodningsintervjuer, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Förberedelse inför kodningsintervjuer innehåller totalt 4 lektioner.
Vad är en heap?
En heap är ett specialiserat komplett binärt träd som uppfyller heap-egenskapen: i en min-heap är varje förälder mindre än eller lika med sina barn; i en max-heap är varje förälder större än eller lika med sina barn. Denna egenskap garanterar att det minsta (eller största) elementet alltid finns i roten, vilket möjliggör åtkomst till extremvärdet på O(1). Heaps är datastrukturen bakom prioritetsköer.
# Min-heap example:
# 1
# / \
# 3 2
# / \ / \
# 7 4 5 6
# Every parent <= its children
# Root (1) is always the minimum
# Max-heap example:
# 9
# / \
# 7 8
# / \ / \
# 3 4 5 6
# Every parent >= its children
# Root (9) is always the maximum
print('Heap property: parent dominates all descendants')Strukturen hos ett komplett binärt träd
En heap lagras som ett komplett binärt träd — alla nivåer är helt fyllda utom möjligen den sista, som fylls från vänster till höger. Det är denna struktur som möjliggör den eleganta arrayrepresentationen utan slösat utrymme och utan pekare. Egenskapen att trädet är komplett säkerställer att heapens höjd alltid är floor(log₂ n), vilket garanterar push- och pop-operationer på O(log n).
# Complete binary tree properties:
# 1. All levels filled except possibly the last
# 2. Last level filled from LEFT to right
# 3. For n nodes: height = floor(log2(n))
# NOT complete (last level not left-filled):
# 1
# / \
# 2 3
# \
# 4 <- right child without left sibling
# Valid complete binary tree with 4 nodes:
# 1
# / \
# 2 3
# /
# 4
print('Complete BT: height = floor(log2(n)) always')Arrayrepresentation av en heap
Strukturen hos det kompletta binära trädet gör att en heap kan lagras i en vanlig array utan några pekare. För en nod på index i (0-indexerat) finns föräldern på (i-1) // 2, vänster barn på 2i+1 och höger barn på 2i+2. Denna heltalsaritmetik ersätter pekartraversering och gör heaps mycket cacheeffektiva.
# Array representation (0-indexed):
# Index: 0 1 2 3 4 5 6
# Array: [1, 3, 2, 7, 4, 5, 6]
# Tree: 1 (index 0)
# / \
# 3 2 (indices 1, 2)
# / \ / \
# 7 4 5 6 (indices 3,4,5,6)
# Index formulas (0-based):
def parent(i): return (i - 1) // 2
def left_child(i): return 2 * i + 1
def right_child(i): return 2 * i + 2
heap = [1, 3, 2, 7, 4, 5, 6]
print('Parent of index 3:', parent(3), '-> value', heap[parent(3)])
print('Left child of 1:', left_child(1), '-> value', heap[left_child(1)])Sift-up: återställ heapen efter insättning
Sift-up (även kallat bubble-up eller heapify-up) används efter att ett nytt element har lagts till i slutet av heap-arrayen. Jämför det nya elementet med dess förälder; om heap-egenskapen bryts byter ni plats på dem och fortsätter uppåt. Upprepa tills elementet har rätt position eller når roten. Detta tar O(log n), eftersom trädets höjd är O(log n).
def sift_up(heap, i):
while i > 0:
p = (i - 1) // 2 # parent index
if heap[p] > heap[i]: # min-heap: parent should be smaller
heap[p], heap[i] = heap[i], heap[p]
i = p
else:
break # heap property restored
# Demonstrate: insert 0 into an existing min-heap
heap = [1, 3, 2, 7, 4, 5, 6]
heap.append(0) # add at end
print('Before sift-up:', heap)
sift_up(heap, len(heap) - 1)
print('After sift-up:', heap) # 0 should bubble to rootSift-down: återställ heapen efter pop
Sift-down (heapify-down) används efter att roten har tagits bort. Flytta det sista elementet till roten och flytta sedan ned det genom att upprepade gånger byta plats med det mindre barnet (för en min-heap) tills heap-egenskapen är återställd. Även detta tar O(log n). Sift-up och sift-down är grundstenarna i alla heap-operationer.
def sift_down(heap, i, n):
while True:
smallest = i
l = 2 * i + 1 # left child
r = 2 * i + 2 # right child
if l < n and heap[l] < heap[smallest]:
smallest = l
if r < n and heap[r] < heap[smallest]:
smallest = r
if smallest == i:
break # already in correct position
heap[i], heap[smallest] = heap[smallest], heap[i]
i = smallest
heap = [1, 3, 2, 7, 4, 5, 6]
# Pop min: move last to root, then sift-down
heap[0] = heap[-1]
heap.pop()
print('After move last to root:', heap)
sift_down(heap, 0, len(heap))
print('After sift-down:', heap) # valid min-heap againBygga en heap från en array: Floyds algoritm
Att naivt lägga in n element ett i taget tar O(n log n). Floyds heapify-algoritm bygger en heap på O(n) genom att tillämpa sift-down på varje nod som inte är ett löv, med början vid det sista lövet (index n//2 - 1) och bakåt till roten. Lövnoder är redan triviala heaps, så vi behöver bara korrigera de inre noderna — därför summerar den totala arbetsmängden till O(n) i stället för O(n log n).
def build_heap(arr):
n = len(arr)
# Start from last non-leaf node: index n//2 - 1
for i in range(n // 2 - 1, -1, -1):
sift_down(arr, i, n)
return arr
arr = [5, 3, 8, 1, 9, 2, 7]
print('Before:', arr)
build_heap(arr)
print('After (min-heap):', arr) # root should be 1
# Why O(n)? Most nodes are near the bottom (leaves).
# Level k from bottom has ~n/2^k nodes, each needing
# at most k swaps. Sum = n * sum(k/2^k) = O(n).Heap sort med array-heapen
Heap sort körs på O(n log n) med O(1) extra utrymme. Fas 1: bygg en max-heap från arrayen på O(n). Fas 2: extrahera det största elementet upprepade gånger genom att byta plats på roten och det sista osorterade elementet och sedan utföra sift-down på den förminskade heapen. Efter n extraktioner är arrayen sorterad i stigande ordning. Denna in-place-algoritm visar hur arrayrepresentationen möjliggör sortering utan att en separat datastruktur behöver allokeras.
def sift_down_max(arr, i, n):
while True:
largest = i
l, r = 2*i+1, 2*i+2
if l < n and arr[l] > arr[largest]: largest = l
if r < n and arr[r] > arr[largest]: largest = r
if largest == i: break
arr[i], arr[largest] = arr[largest], arr[i]
i = largest
def heap_sort(arr):
n = len(arr)
# Build max-heap
for i in range(n // 2 - 1, -1, -1):
sift_down_max(arr, i, n)
# Extract elements one by one
for end in range(n - 1, 0, -1):
arr[0], arr[end] = arr[end], arr[0] # move max to end
sift_down_max(arr, 0, end)
arr = [5, 3, 8, 1, 9, 2, 7]
heap_sort(arr)
print(arr) # [1, 2, 3, 5, 7, 8, 9]Min-heap kontra max-heap
I en min-heap finns det minsta elementet i roten; en pop-operation returnerar alltid minimum. I en max-heap finns det största elementet i roten; en pop-operation returnerar alltid maximum. Båda har identisk struktur och identiska operationer — endast jämförelseriktningen ändras. Pythons heapq-modul implementerar endast en min-heap, så värdena måste negeras för att simulera en max-heap.
import heapq
# Python heapq is a MIN-HEAP
min_heap = []
heapq.heappush(min_heap, 5)
heapq.heappush(min_heap, 1)
heapq.heappush(min_heap, 3)
print('Min-heap min:', heapq.heappop(min_heap)) # 1
# Simulate MAX-HEAP by negating values
max_heap = []
for val in [5, 1, 3]:
heapq.heappush(max_heap, -val) # negate on push
print('Max-heap max:', -heapq.heappop(max_heap)) # 5 (negate on pop)
# For tuples: heapq sorts by first element
print(min_heap, max_heap)Sammanfattning av heap-operationernas komplexitet
Alla heap-operationer bygger på sift-up och sift-down, som båda tar O(log n). Push: lägg till + sift-up = O(log n). Pop: byt plats på roten och det sista elementet + sift-down = O(log n). Peek: åtkomst till index 0 = O(1). Build heap: O(n) med Floyds algoritm. Heap sort: O(n log n). Dessa komplexiteter gör heaps till den idealiska strukturen när ni upprepade gånger behöver hitta minimum eller maximum i en dynamisk samling.
# Heap complexity summary:
# Operation | Time | Space
# --------------|------------|-------
# Push | O(log n) | O(1)
# Pop (min/max) | O(log n) | O(1)
# Peek | O(1) | O(1)
# Build from n | O(n) | O(1) in-place
# Heap sort | O(n log n) | O(1)
# nlargest(k,n) | O(n log k) | O(k)
import heapq
data = [5, 3, 8, 1, 9, 2, 7]
print('Top 3 largest:', heapq.nlargest(3, data)) # [9, 8, 7]
print('Top 3 smallest:', heapq.nsmallest(3, data)) # [1, 2, 3]Praktiska heapmönster vid intervjuer
Heaps löser en familj av intervjuproblem med ett gemensamt mönster: underhåll en prioritetskö med k kandidater medan ni strömmar genom n element. De k mest frekventa elementen, de k närmaste punkterna till origo och en aktivitetsschemaläggare använder alla detta mönster. Känn igen det när ni ser: ”givet en ström med n objekt, underhåll de k bästa” — då behövs alltid en heap med storlek k, vilket ger en total tidskomplexitet på O(n log k).
import heapq
# Top-K closest points to origin using a max-heap of size k
def k_closest(points, k):
# Use max-heap (negate distance) of size k
heap = []
for x, y in points:
dist = -(x*x + y*y) # negate for max-heap
heapq.heappush(heap, (dist, x, y))
if len(heap) > k:
heapq.heappop(heap) # remove farthest
return [[x, y] for _, x, y in heap]
points = [[1,3], [-2,2], [5,8], [0,1]]
print(k_closest(points, 2)) # 2 closest to originAvvägningar mellan heap och sorterad array
Välj en heap när ni bara behöver upprepad åtkomst till minimum eller maximum och samlingen förändras dynamiskt. Välj en sorterad array när ni behöver slumpmässig åtkomst via index eller intervallfrågor. Heapens svaghet är att sökning efter godtyckliga element tar O(n); dess styrka är insättning/borttagning på O(log n) och åtkomst till min/max på O(1). En sorterad array har insättning på O(n), men sökning via binärsökning på O(log n).
# Trade-off comparison:
# Structure | insert | delete_min | search | range_query
# --------------|---------|------------|--------|------------
# Min-heap | O(logn) | O(logn) | O(n) | O(n)
# Sorted array | O(n) | O(n) | O(logn)| O(logn+k)
# BST (balanced)| O(logn) | O(logn) | O(logn)| O(logn+k)
# Hash map | O(1) | O(1) | O(1) | O(n)
# Interview heuristic:
# 'Find minimum repeatedly from dynamic collection' -> HEAP
# 'Binary search or range query' -> sorted array or BST
# 'Fast lookup by key' -> hash map
print('Heap = dynamic collection with priority access')Snabbkontroll
Testa er förståelse av begreppen Data Structures & Algorithms — Coding Interview Prep från den här lektionen.
Sammanfattning av lektionen
I den här lektionen lärde ni er: heap-egenskapen och strukturen hos kompletta binära träd, arrayrepresentation med indexformler för föräldrar och barn samt sift-up och sift-down som grundstenarna i alla heap-operationer, inklusive Floyds O(n)-algoritm för att bygga en heap. Nästa steg är att implementera heapify och utforska Pythons heapq-modul.
Lär dig Förberedelse inför kodningsintervjuer med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 90
- Lektioner
- 360
Vanliga frågor
Är lektionen ”Heap-egenskapen och arrayrepresentation” gratis?
Ja – hela texten till ”Heap-egenskapen och arrayrepresentation” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Förberedelse inför kodningsintervjuer, kan Ni uppgradera till CoddyKit PRO. Kursen i Förberedelse inför kodningsintervjuer innehåller totalt 4 lektioner.
Vad lär jag mig i ”Heap-egenskapen och arrayrepresentation”?
Förstå strukturen hos ett komplett binärt träd som lagras i en array, härled formler för index till föräldrar och barn och visualisera sift-up- och sift-down-operationer. Ni övar på Förberedelse inför kodningsintervjuer med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Förberedelse inför kodningsintervjuer?
Du behöver inga förkunskaper. Utbildningen i Förberedelse inför kodningsintervjuer på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.
Hur lång tid tar lektionen ”Heap-egenskapen och arrayrepresentation”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Förberedelse inför kodningsintervjuer-lektionen?
Ja. Varje Förberedelse inför kodningsintervjuer-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Heap-egenskapen och arrayrepresentation
- Heapify, push och pop från grunden
- Pythons heapq och knep för max-heap
- Median från dataström och k-vägs-sammanfogning