Tema
/
Algoritmai ir duomenų struktūros GO
Pamoka 13 / 15 Krūvos ir prioritetinės eilės ~55 min
Kodas

heap.go — karkasas

Sukurk heap.go. Karkasas kaip įprasta; kūnai tavo.

Ką verta pasižymėti:

  • Peek privalo būti O(1). Jokio ciklo, jokio palyginimo — a[0]. Jei ieškai, dar kartą perskaityk krūvos savybę.
  • Pop į šaknį kelia paskutinį masyvo elementą, ne vaiką. Antro žingsnio spąstai.
  • Push lygina su tėvu, Pop — su abiem vaikais. Todėl Pop atlieka apie dvigubai daugiau palyginimų vienam lygiui nei Push.
  • Sukeitimai nėra palyginimai. c.Hit() kviečiamas tik lyginant įvertinimus; sukeitimai kaupiami į Swaps. Šeštas žingsnis remiasi šiuo skirtumu.
  • NewMinHeap gauna talpos užuominą ir ja privalo pasinaudoti (make([]Item, 0, capacity)). Iš to gimsta vienas paskirstymas visai struktūrai — skaičius, kurį šeštame žingsnyje statysi prieš 20 020.

TopKHeap — kur reikia pagalvoti

TopKHeap naudoja min-krūvą k geriausių elementų, ir čia sukasi visa esmė.

Krūvoje laikai k geriausių iki šiol matytų. Jos mažiausias elementas yra silpniausias iš tų k. Naujas įrašas turi įveikti tik jį:

jei krūvoje mažiau nei k: Push ir toliau
worst ← Peek()
c.Hit()
jei naujas ≤ worst: praleisk        // negali išstumti silpniausio iš k geriausių
Pop(); Push(naujas)

Daugumai įrašų tai vienas palyginimas ir viskas. Todėl kaina yra O(n log k), o ne O(n log n).

Min-krūva „geriausiems" atrodo apversta ir turi taip atrodyti: laikai geriausius, o žiūri į blogiausią iš jų, nes būtent jis pasitraukia pirmas.

Pabaigoje krūva ištuštinama, o rezultatas apverčiamas — Pop duoda mažiausią pirmą, o tau reikia geriausio pirmo.