TDT4120 Algoritmer og datastrukturer Interaktivt kompendium · H2026
Fremgang
0/15

05

Rotfaste trestrukturer

Kjernepensum

Et rotfast tre er en rekursiv dekomponering: hver node er rota i sitt eget deltre. Da kan du kreve noe av alle deltrærne på én gang. I et binært søketre er alt i venstre deltre mindre enn rota og alt i høyre deltre større. Egenskapen gir søk, innsetting og etterfølger i tid proporsjonal med høyden. I en haug kreves bare at rota er størst, og kravet gjelder rekursivt for hvert deltre. Haugegenskapen gir mindre funksjonalitet, men haugen er billigere å bygge og holder seg balansert av seg selv, så den brukes som prioritetskø og til å sortere.

Rotfaste trær

Et fritt tre er en sammenhengende graf uten sykler. Det har nøyaktig én sti mellom hvert par av noder, og ∣E∣=∣V∣−1|E| = |V| - 1. Velger du ut én node som rot, får du et rotfast tre, og da har kantene retning: rota har ingen forelder, hver annen node har nøyaktig én, og nodene rett under en node er barna dens.

Treet i figur 1 har rota 7. Barna til 7 er 5 og 6, og barna til 5 er 1, 2, 3 og 4. En node uten barn er en løvnode, som 1 og 6, og de andre er indre noder, her 5 og 7. Dybden til en node er antall kanter opp til rota, så 1 har dybde 2. Høyden hh til treet er den største dybden, her 2. Deltreet med rot xx er xx og alt under den, så deltreet med rot 5 har fem noder.

Et binærtre har to barneposisjoner per node, venstre og høyre, og en av dem kan stå tom. Du vet altså hvilket barn som mangler. Et komplett binærtre er fullt, alle indre noder har to barn, og alle løvnodene har samme dybde. Har treet høyde hh, har nivåene 1,2,4,…,2h1, 2, 4, \ldots, 2^h noder. Løvnodene på nederste nivå er 2h2^h, og nivåene over har 2h−12^h - 1 noder til sammen, så treet har n=2h+1−1n = 2^{h+1} - 1 noder i alt. Da er 2h≤n<2h+12^h \le n < 2^{h+1}, og h=⌊lg⁡n⌋h = \lfloor \lg n \rfloor. Balansert binærtre defineres på flere måter, men alle gir logaritmisk høyde.

En node i et binærtre har pekere left og right, og gjerne p til forelderen. Kan en node ha vilkårlig mange barn, holder det likevel med to pekere: én til første barn og én til neste søsken. Barna til en node er da en lenket liste som starter i første barn.

Det samme treet tegnet to ganger. Node 7 har barna 5 og 6, og 5 har barna 1, 2, 3 og 4. Til venstre går en grå pil fra hver forelder til hvert barn. Til høyre går en grønnblå pil fra 7 til første barn 5 og fra 5 til første barn 1, og røde piler fra 5 til søsken 6 og fra 1 til 2, 2 til 3 og 3 til 4.
Figur 1. Samme tre med to representasjoner. Til venstre har hver node én peker per barn, og 5 trenger fire. Til høyre har hver node to: første barn nedover og neste søsken bortover, så 5 finner alle barna sine ved å følge søskenpekerne fra 1.

Binære søketrær

Hver node har en nøkkel key. Du kan anta at nøklene er forskjellige.

Egenskapen gjelder for hver node, ikke bare rota, så hvert deltre er selv et binært søketre. Den er binærsøk lagret som datastruktur: fra hver node vet du hvilken side en nøkkel må ligge på.

Inorder-Tree-Walk skriver ut venstre deltre, så noden, så høyre deltre, rekursivt fra rota. Egenskapen gir at utskriften er sortert: alt til venstre kommer før noden og er mindre, alt til høyre kommer etter og er større. Hver node besøkes én gang, så det tar Θ(n)\Theta(n). Preorder og postorder skriver ut noden før eller etter de to rekursive kallene i stedet for mellom dem.

Tree-Search sammenligner nøkkelen kk med nøkkelen i xx. Er de like, er xx svaret. Er kk mindre, kan den bare ligge i venstre deltre, så du søker videre der, ellers i høyre. Treffer du nil, finnes ikke kk. Ingenting skjer etter det rekursive kallet, så søket skrives like gjerne som en løkke. Stien går nedover fra rota og er høyst hh lang, så søket koster O(h)O(h).

Tree-Insert søker etter nøkkelen til den nye noden zz til søket treffer nil, og henger zz på der. Under søket følger yy ett steg bak xx, så når xx blir nil, er yy noden som skal bli forelder. Er yy nil, var treet tomt, og zz blir rot. Ellers blir zz venstre eller høyre barn av yy etter samme test som i søket. En ny node blir alltid en løvnode.

binaert_soketre.py
def tree_insert(T, z):
  x, y = T.root, None
  while x is not None:
      y = x
      if z.key < x.key:
          x = x.left
      else:
          x = x.right
  z.p = y
  if y is None:
      T.root = z
  elif z.key < y.key:
      y.left = z
  else:
      y.right = z

def inorder_tree_walk(x):
  if x is not None:
      inorder_tree_walk(x.left)
      print(x.key)
      inorder_tree_walk(x.right)
Tree-Insert og Inorder-Tree-Walk
0 / 0

Et binært søketre bygd med Tree-Insert av nøklene i raden under, i den rekkefølgen de står. Vannrett posisjon er nøkkelens plass i sortert rekkefølge. Rødt er xx eller den nye noden, oransje er yy, og grønt er skrevet ut av Inorder-Tree-Walk.

Tree-Minimum følger left til det ikke går lenger, for alt i et høyre deltre er større enn noden over. Tree-Maximum følger right. Etterfølgeren til xx er noden med den minste nøkkelen som er større enn nøkkelen til xx, altså den neste i Inorder-Tree-Walk. Har xx et høyre deltre, er etterfølgeren minimum der. Har xx ikke noe høyre deltre, er xx maksimum i et deltre, og etterfølgeren er den nærmeste noden over xx som har xx i sitt venstre deltre. Gå oppover så lenge du kommer fra et høyre barn. Forgjengeren finnes symmetrisk. Alle fire følger én sti opp eller ned, O(h)O(h).

soketre_operasjoner.py
def tree_search(x, k):
  while x is not None and k != x.key:
      x = x.left if k < x.key else x.right
  return x

def tree_minimum(x):
  while x.left is not None:
      x = x.left
  return x

def tree_successor(x):
  if x.right is not None:
      return tree_minimum(x.right)
  y = x.p
  while y is not None and x is y.right:
      x, y = y, y.p
  return y

Tree-Delete skiller på hvor mange barn zz har. Har zz høyst ett barn, kobles barnet inn der zz sto, med hjelpeprosedyren Transplant. Har zz to barn, er etterfølgeren yy minimum i høyre deltre og har ikke noe venstre barn, så yy kan kobles ut på samme måte og settes inn der zz sto. Tree-Delete følger også én sti, O(h)O(h).

Alt unntatt traverseringen følger én sti i treet, og koster derfor O(h)O(h).
OperasjonKjøretid
Inorder-Tree-WalkΘ(n)\Theta(n)
Tree-Search, Tree-Minimum, Tree-MaximumO(h)O(h)
Tree-Successor, Tree-PredecessorO(h)O(h)
Tree-Insert, Tree-DeleteO(h)O(h)

Alle operasjonene unntatt traverseringen koster altså O(h)O(h), og høyden avhenger av innsettingsrekkefølgen. Settes 1,2,…,71, 2, \ldots, 7 inn i stigende rekkefølge, blir hver ny nøkkel høyre barn av den forrige, og treet er en kjede med høyde n−1n - 1. Da koster søk Θ(n)\Theta(n), som i en lenket liste. Settes de samme nøklene inn i rekkefølgen 4,2,6,1,3,5,74, 2, 6, 1, 3, 5, 7, er treet komplett med høyde ⌊lg⁡n⌋\lfloor \lg n \rfloor.

To binære søketrær med nøklene 1 til 7. Til venstre er nøklene satt inn i stigende rekkefølge, og treet er en kjede der hver node er høyre barn av den forrige, med høyde 6. Til høyre er de satt inn i rekkefølgen 4, 2, 6, 1, 3, 5, 7, og treet er komplett med 4 i rota, 2 og 6 under, og 1, 3, 5, 7 nederst, med høyde 2.
Figur 2. De samme sju nøklene i to innsettingsrekkefølger. Sortert input gir høyde n−1n - 1, og søk koster Θ(n)\Theta(n). Rekkefølgen til høyre fyller treet nivå for nivå og gir høyde ⌊lg⁡n⌋\lfloor \lg n \rfloor.

Med en tilfeldig innsettingsrekkefølge finner du den forventede dybden ved å telle sammenligninger. Når zz settes inn, sammenlignes den med hver node på stien fra rota ned til forelderen, og den stien har like mange noder som dybden zz får. Summen av dybdene er altså antall sammenligninger i hele byggingen. Rota deler de senere nøklene i mindre og større, og hvert deltre deler sine videre på samme måte. Det er de samme sammenligningene som Quicksort gjør når pivoten i hvert segment er den nøkkelen som ble satt inn først. I en tilfeldig permutasjon er den pivoten tilfeldig, og da gjør Quicksort forventet Θ(nlg⁡n)\Theta(n \lg n) sammenligninger. Snittet av dybdene er derfor forventet Θ(lg⁡n)\Theta(\lg n), og det er kostnaden til et søk etter en tilfeldig nøkkel. Høyden er den største dybden, og en finere regning viser at også forventet høyde er Θ(lg⁡n)\Theta(\lg n). Verste tilfelle er fortsatt lineært. Det finnes søketrær som balanserer seg selv etter hver innsetting og sletting i logaritmisk tid, for eksempel rød-svarte trær, og de garanterer h=Θ(lg⁡n)h = \Theta(\lg n).

Eksamensoppgave Tree-Insert og Inorder-Tree-Walk
Ordinær eksamen, desember 2022, oppgave 8

Start med et tomt binært søketre, og sett så inn følgende verdier, i rekkefølge, med Tree-Insert:

⟨7,1,0,5,4,8,3,2,9,6⟩\langle 7, 1, 0, 5, 4, 8, 3, 2, 9, 6 \rangle

Utfør deretter Inorder-Tree-Walk på rotnoden i det resulterende treet. Hva skriver algoritmen ut?

Du skal her kun svare med output fra algoritmen.

Vis løsning Skjul løsning

Du kan bygge treet: 7 blir rot, 1 går til venstre, 0 til venstre for 1, 5 til høyre for 1, og så videre. Men det trengs ikke. Inorder-traversering av et binært søketre besøker alltid nodene i sortert rekkefølge, uansett hvilken rekkefølge de ble satt inn i.

Svar
0 1 2 3 4 5 6 7 8 9
Eksamensoppgave Søk i et tre du har bygd selv
Kontinuasjonseksamen, august 2025, oppgave 4

Om du bygger et binært søketre av nn elementer, hva blir kjøretiden til søk i treet etterpå, i beste og verste tilfelle, og i gjennomsnitt? Forklar.

Du bruker altså Tree-Insert for å sette inn ett og ett element, der treet til å begynne med er tomt, og vi er ute etter kjøretiden til Tree-Search på det ferdige treet (best-case, worst-case og average-case). Du kan anta at elementene er tallene 1…n1 \ldots n i en (uniformt) tilfeldig rekkefølge.

Vis løsning Skjul løsning

Søk følger én sti nedover fra rota og koster O(h)O(h), der hh er høyden.

Beste tilfelle er Θ(1)\Theta(1) uansett form på treet: nøkkelen du søker etter kan sitte i rota.

Verste tilfelle er et helt ubalansert tre, som når elementene kom i sortert rekkefølge, og da er høyden n−1n - 1. Et søk etter en av de nederste nodene koster Θ(n)\Theta(n).

I gjennomsnitt, med tilfeldig innsettingsrekkefølge, er høyden Θ(lg⁡n)\Theta(\lg n), så et søk koster O(lg⁡n)O(\lg n). Et søk koster også Ω(lg⁡n)\Omega(\lg n): et binærtre har høyst 2d−12^d - 1 noder over dybde dd, så mer enn halvparten av nodene ligger på dybde ⌊lg⁡n⌋−1\lfloor \lg n \rfloor - 1 eller dypere.

Svar
Beste Θ(1)\Theta(1), verste Θ(n)\Theta(n), gjennomsnitt Θ(lg⁡n)\Theta(\lg n).

Hauger

En haug er et binærtre som er komplett ned til nest nederste nivå, og der det nederste nivået er fylt fra venstre. Nummererer du nodene nivå for nivå med rota som 1, har nivå dd numrene 2d2^d til 2d+1−12^{d+1} - 1. Node ii på nivå dd har i−2di - 2^d noder foran seg på nivået, og barna til dem, to per node, står først på nivået under. Det første barnet til ii får da nummeret 2d+1+2(i−2d)=2i2^{d+1} + 2(i - 2^d) = 2i, og det andre 2i+12i + 1. Barna 2i2i og 2i+12i + 1 har begge forelderen ii, så forelderen til en node jj er ⌊j/2⌋\lfloor j/2 \rfloor. Numrene er indekser i en tabell, så haugen trenger ingen pekere. A[1..n]A[1 .. n] er treet, Left, Right og Parent er regnestykker, og haugstørrelsen size sier hvor mye av tabellen som er haug.

Left(i)=2iRight(i)=2i+1Parent(i)=⌊i/2⌋\begin{aligned} \text{Left}(i) &= 2i \\ \text{Right}(i) &= 2i + 1 \\ \text{Parent}(i) &= \lfloor i/2 \rfloor \end{aligned}

Haugegenskapen sier ingenting om rekkefølgen mellom søsken, så en haug er langt fra sortert. Sorteringsgrensen gjelder når svaret er én bestemt av n!n! rekkefølger, og den gjelder derfor ikke for å bygge en haug.

Har haugen høyde hh, er nivåene 0,…,h−10, \ldots, h - 1 fulle og har 1+2+⋯+2h−1=2h−11 + 2 + \cdots + 2^{h-1} = 2^h - 1 noder til sammen, og det nederste nivået har fra 1 til 2h2^h noder. Da er 2h≤n≤2h+1−12^h \le n \le 2^{h+1} - 1, og h=⌊lg⁡n⌋h = \lfloor \lg n \rfloor.

Max-Heapify reparerer en haug der bare A[i]A[i] kan være for liten, altså der begge deltrærne under ii er maks-hauger. Finn den største av A[i]A[i] og de to barna. Er det A[i]A[i], er alt i orden. Ellers bytt A[i]A[i] med det største barnet, så den nye rota er større enn begge, og reparer deltreet der det mindre elementet havnet, rekursivt. Elementet synker til det er større enn begge barna eller er en løvnode. Byttet må være med det største barnet, ellers blir den nye rota mindre enn det andre barnet. Stien går nedover, høyst hh steg, så Max-Heapify koster O(lg⁡n)O(\lg n).

Node ii har et venstre barn bare når 2i≤n2i \le n, så nodene fra ⌊n/2⌋+1\lfloor n/2 \rfloor + 1 til nn har ingen barn. De er løvnoder og dermed maks-hauger alene. Build-Max-Heap kaller Max-Heapify på de indre nodene fra ⌊n/2⌋\lfloor n/2 \rfloor og ned til 1, nedenfra og opp i treet. Når turen kommer til ii, er barna 2i2i og 2i+12i + 1 løvnoder eller allerede behandlet, for de har høyere numre. Begge deltrærne under ii er da maks-hauger, så forutsetningen for Max-Heapify holder, og etter kallet er også deltreet med rot ii en maks-haug.

build_max_heap.py
def max_heapify(A, i, size):
  l, r = 2 * i + 1, 2 * i + 2  # indekser fra 0: rota er A[0]
  m = i
  if l < size and A[l] > A[m]:
      m = l
  if r < size and A[r] > A[m]:
      m = r
  if m != i:
      A[i], A[m] = A[m], A[i]
      max_heapify(A, m, size)

def build_max_heap(A, n):
  for i in range(n // 2 - 1, -1, -1):
      max_heapify(A, i, n)
Build-Max-Heap
0 / 0

Tabellen AA tegnet som tre og som celler, med indekser fra 0 som i koden. Stiplede noder har Build-Max-Heap ikke nådd ennå. Rødt er noden Max-Heapify står på eller de to som bytter. Barna den sammenlignes med er oransje, og det største av dem er fylt.

⌊n/2⌋\lfloor n/2 \rfloor kall til Max-Heapify som hvert koster O(lg⁡n)O(\lg n), gir O(nlg⁡n)O(n \lg n). Det er riktig, men ikke stramt, for nesten alle kallene er langt nede i treet, der det er lite å synke. Høyden til en node er høyden til deltreet med noden som rot, og en node med høyde kk synker høyst kk steg. Følger du venstre barn kk ganger fra node ii, kommer du til node 2ki2^k i, det laveste nummeret kk nivåer under ii, så ii har høyde minst kk nøyaktig når 2ki≤n2^k i \le n. Nodene 11 til ⌊n/2k⌋\lfloor n/2^k \rfloor har derfor høyde minst kk, og de med høyde nøyaktig kk er nodene fra ⌊n/2k+1⌋+1\lfloor n/2^{k+1} \rfloor + 1 til ⌊n/2k⌋\lfloor n/2^k \rfloor, altså høyst ⌈n/2k+1⌉\lceil n/2^{k+1} \rceil av dem.

T(n)=∑k=0⌊lg⁡n⌋⌈n2k+1⌉O(k)=O ⁣(n∑k=0∞k2k)=O(n)\begin{aligned} T(n) &= \sum_{k=0}^{\lfloor \lg n \rfloor} \left\lceil \frac{n}{2^{k+1}} \right\rceil O(k) \\ &= O\!\left( n \sum_{k=0}^{\infty} \frac{k}{2^k} \right) = O(n) \end{aligned}

Arbeidet per node vokser lineært med høyden, men antallet noder synker eksponentielt med den, og den geometriske faktoren dominerer. Hver indre node besøkes, så Ω(n)\Omega(n) gjelder også, og Build-Max-Heap er Θ(n)\Theta(n).

Hvorfor rekken konvergerer

For ∣x∣<1|x| < 1 er ∑k≥0kxk=x/(1−x)2\sum_{k \ge 0} k x^k = x/(1 - x)^2. Med x=1/2x = 1/2 er summen (1/2)/(1/4)=2(1/2)/(1/4) = 2, så T(n)=O(2n)=O(n)T(n) = O(2n) = O(n).

Prioritetskøer

En prioritetskø holder en mengde elementer med nøkler og støtter Insert, Maximum, Extract-Max og Increase-Key, eller min-variantene. Nøklene er prioriteter, så duplikater er vanlige, i motsetning til i en oppslagstabell. En lenket liste gir innsetting i konstant tid, men lineær tid for å finne maksimum. En maks-haug gir alle fire i logaritmisk tid eller bedre.

Max-Heap-Maximum er A[1]A[1], i konstant tid. Max-Heap-Extract-Max tar vare på rota, flytter det siste elementet i haugen opp i rota, minsker haugstørrelsen med én og kaller Max-Heapify på rota, for nå er rota det eneste som kan være feil. Å forskyve resten av tabellen ett hakk i stedet ville kostet Θ(n)\Theta(n) og gitt hvert element en ny forelder.

Max-Heap-Increase-Key gir elementet på plass ii en større nøkkel. Nå kan det være større enn forelderen, så det stiger: bytt med forelderen så lenge den er mindre. Max-Heap-Insert legger det nye elementet sist i haugen med nøkkel −∞-\infty og øker nøkkelen til den riktige verdien, så det stiger på plass. Synking og stiging følger begge én sti i treet, O(lg⁡n)O(\lg n). Increase-Key trenger indeksen ii til elementet, så er elementene objekter, må haugen bokføre hvor hvert av dem står, og oppdatere det ved hvert bytte.

prioritetsko.py
from math import inf

def max_heap_maximum(A):
  if len(A) < 1:
      raise ValueError("heap underflow")
  return A[0]

def max_heap_extract_max(A):
  m = max_heap_maximum(A)
  A[0] = A[-1]
  A.pop()
  max_heapify(A, 0, len(A))
  return m

def max_heap_increase_key(A, i, key):
  if key < A[i]:
      raise ValueError("new key is smaller")
  A[i] = key
  # indekser fra 0: forelderen til i er (i - 1) // 2
  while i > 0 and A[(i - 1) // 2] < A[i]:
      A[i], A[(i - 1) // 2] = A[(i - 1) // 2], A[i]
      i = (i - 1) // 2

def max_heap_insert(A, key):
  A.append(-inf)
  max_heap_increase_key(A, len(A) - 1, key)
Haugoperasjonene. Alt som synker eller stiger følger én sti av lengde høyst ⌊lg⁡n⌋\lfloor \lg n \rfloor.
OperasjonKjøretid
Max-HeapifyO(lg⁡n)O(\lg n)
Max-Heap-MaximumΘ(1)\Theta(1)
Max-Heap-Extract-MaxO(lg⁡n)O(\lg n)
Max-Heap-Increase-KeyO(lg⁡n)O(\lg n)
Max-Heap-InsertO(lg⁡n)O(\lg n)
Build-Max-HeapΘ(n)\Theta(n)

Heapsort

Sortering ved utvelgelse plukker ut det største av de usorterte elementene og legger det bakerst, nn ganger, og bruker Θ(n)\Theta(n) per plukk. Heapsort gjør det samme med en maks-haug som usortert del, så hvert plukk er en Extract-Max. Bygg haugen av hele AA. Så, for ii fra nn ned til 2: bytt rota A[1]A[1] med A[i]A[i], minsk haugstørrelsen med én og kall Max-Heapify på rota.

Invarianten er at A[i+1..n]A[i+1 .. n] er de n−in - i største elementene, sortert, og at A[1..i]A[1 .. i] er en maks-haug. Rota er det største elementet i A[1..i]A[1 .. i], så byttet legger det på plass ii, rett foran de n−in - i elementene som allerede er sortert. Etter byttet er bare den nye rota feilplassert i A[1..i−1]A[1 .. i - 1], og Max-Heapify flytter den på plass. Sorteringen skjer på plass: haugen ligger foran i tabellen, og den sorterte delen vokser bakfra.

heapsort.py
def heapsort(A, n):
  build_max_heap(A, n)
  size = n
  for i in range(n - 1, 0, -1):
      A[0], A[i] = A[i], A[0]
      size = size - 1
      max_heapify(A, 0, size)
Heapsort
0 / 0

Tabellen AA tegnet som tre og som celler, med indekser fra 0 som i koden og haugen bygd på forhånd. Rødt er noden Max-Heapify står på eller de to som bytter. Barna den sammenlignes med er oransje, og grønt er utenfor haugen og ferdig sortert.

Byggingen koster Θ(n)\Theta(n), og så følger n−1n - 1 kall til Max-Heapify på O(lg⁡n)O(\lg n) hver, altså O(nlg⁡n)O(n \lg n). Heapsort er sammenligningsbasert, så sorteringsgrensen gir Ω(nlg⁡n)\Omega(n \lg n) i verste tilfelle, og verste tilfelle er derfor Θ(nlg⁡n)\Theta(n \lg n). Er alle elementene like, stopper hvert Max-Heapify med en gang, og beste tilfelle er Θ(n)\Theta(n). Med forskjellige elementer er også beste tilfelle Θ(nlg⁡n)\Theta(n \lg n), så sortert input gjør ikke Heapsort raskere.

Sorteringsalgoritmene så langt. Beste tilfelle for Heapsort er input der alle elementene er like. Snitt er gjennomsnittet over input, for Quicksort over alle rekkefølger og for Bucket-Sort over uniformt fordelt input. Randomized-Quicksort har forventet Θ(nlg⁡n)\Theta(n \lg n) over sine egne tilfeldige valg, for enhver input.
AlgoritmeVersteSnittBeste
Insertion-SortΘ(n2)\Theta(n^2)Θ(n2)\Theta(n^2)Θ(n)\Theta(n)
Merge-SortΘ(nlg⁡n)\Theta(n \lg n)Θ(nlg⁡n)\Theta(n \lg n)Θ(nlg⁡n)\Theta(n \lg n)
HeapsortΘ(nlg⁡n)\Theta(n \lg n)Θ(nlg⁡n)\Theta(n \lg n)Θ(n)\Theta(n)
QuicksortΘ(n2)\Theta(n^2)Θ(nlg⁡n)\Theta(n \lg n)Θ(nlg⁡n)\Theta(n \lg n)
Counting-SortΘ(n+k)\Theta(n + k)Θ(n+k)\Theta(n + k)Θ(n+k)\Theta(n + k)
Radix-SortΘ(d(n+k))\Theta(d(n + k))Θ(d(n+k))\Theta(d(n + k))Θ(d(n+k))\Theta(d(n + k))
Bucket-SortΘ(n2)\Theta(n^2)Θ(n)\Theta(n)Θ(n)\Theta(n)
Eksamensoppgave Første iterasjon av Heapsort
Kontinuasjonseksamen, august 2023, oppgave 13

Tabellen A=⟨9,8,5,7,1,3,2,4,6⟩A = \langle 9, 8, 5, 7, 1, 3, 2, 4, 6 \rangle representerer en haug. Hvordan ser tabellen ut etter første iterasjon av Heapsort?

Du skal altså utføre den første av n−1n - 1 iterasjoner. Svar ved å liste opp elementene i tabellen. Oppgi hele tabellen, inkludert deler som ikke lenger er en del av haugen.

Vis løsning Skjul løsning

Første iterasjon bytter rota med siste element og krymper haugen med én: ⟨6,8,5,7,1,3,2,4,9⟩\langle 6, 8, 5, 7, 1, 3, 2, 4, 9 \rangle med haugstørrelse 8. Så synker 6 med Max-Heapify. Barna til 6 er 8 og 5, så 6 bytter med 8: ⟨8,6,5,7,1,3,2,4⟩\langle 8, 6, 5, 7, 1, 3, 2, 4 \rangle. Barna til 6 er nå 7 og 1, så 6 bytter med 7: ⟨8,7,5,6,1,3,2,4⟩\langle 8, 7, 5, 6, 1, 3, 2, 4 \rangle. Barna til 6 på plass 4 ville vært plass 8 og 9. Plass 9 er utenfor haugen og 4 er mindre enn 6, så 6 blir stående.

Svar
⟨8,7,5,6,1,3,2,4,9⟩\langle 8, 7, 5, 6, 1, 3, 2, 4, 9 \rangle

Sjekk deg selv

Tabellen A=⟨10,7,9,3,6,8,2⟩A = \langle 10, 7, 9, 3, 6, 8, 2 \rangle er en maks-haug. Hvordan ser AA ut etter første runde i løkka i Heapsort?
Oppdatert 27. september 2026 Foreslå endring