Ce face container/heap.Init
Un heap este o structură care îți dă mereu rapid elementul „cel mai mic” (după Less), chiar dacă adaugi și scoți elemente des. Este baza unei cozi de priorități: pacienți după urgență, sarcini după termen, drumuri după distanță (algoritmul lui Dijkstra).
Pachetul container/heap nu are un tip gata făcut. Tu definești un tip (de obicei un slice) cu metodele Len, Less, Swap, Push și Pop, iar pachetul se ocupă de ordine. heap.Init(h) organizează datele existente, heap.Push(h, x) adaugă un element, iar heap.Pop(h) scoate și returnează elementul minim. Ambele durează O(log n).
Atenție: metodele Push/Pop ale tipului tău doar adaugă și scot la finalul slice-ului. Le apelează pachetul. Tu apelezi întotdeauna funcțiile heap.Push(h, x) și heap.Pop(h), nu metodele h.Push/h.Pop. Pentru maxim în loc de minim, inversează comparația din Less.
Parametri
| Parametru | Descriere |
|---|---|
h |
Heap-ul: un pointer la tipul tău care implementează heap.Interface. |
x |
Pentru Push: elementul adăugat. |
Ce returnează
Init și Push: nimic. Pop: elementul minim, ca any (faci conversia cu .(int) etc.).
Exemple
Exemplul 1: Heap de întregi: scoaterea în ordine crescătoare
package main
import (
"container/heap"
"fmt"
)
type MinHeap []int
func (h MinHeap) Len() int { return len(h) }
func (h MinHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h MinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *MinHeap) Push(x any) { *h = append(*h, x.(int)) }
func (h *MinHeap) Pop() any {
vechi := *h
n := len(vechi)
x := vechi[n-1]
*h = vechi[:n-1]
return x
}
func main() {
h := &MinHeap{8, 3, 10, 1}
heap.Init(h)
heap.Push(h, 5)
fmt.Println("Minimul:", (*h)[0])
for h.Len() > 0 {
fmt.Print(heap.Pop(h), " ")
}
fmt.Println()
}
Rezultat
Minimul: 1
1 3 5 8 10
Exemplul 2: Coada de la urgențe
Less folosește >, deci iese întâi pacientul cu urgența cea mai mare.
package main
import (
"container/heap"
"fmt"
)
type Pacient struct {
Nume string
Urgenta int
index int
}
type Coada []*Pacient
func (c Coada) Len() int { return len(c) }
func (c Coada) Less(i, j int) bool { return c[i].Urgenta > c[j].Urgenta }
func (c Coada) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
c[i].index = i
c[j].index = j
}
func (c *Coada) Push(x any) {
p := x.(*Pacient)
p.index = len(*c)
*c = append(*c, p)
}
func (c *Coada) Pop() any {
vechi := *c
n := len(vechi)
p := vechi[n-1]
vechi[n-1] = nil
p.index = -1
*c = vechi[:n-1]
return p
}
func main() {
c := &Coada{}
heap.Init(c)
heap.Push(c, &Pacient{Nume: "Ana", Urgenta: 2})
heap.Push(c, &Pacient{Nume: "Mihai", Urgenta: 5})
heap.Push(c, &Pacient{Nume: "Ioana", Urgenta: 3})
heap.Push(c, &Pacient{Nume: "Radu", Urgenta: 1})
for c.Len() > 0 {
p := heap.Pop(c).(*Pacient)
fmt.Printf("%s (urgență %d)\n", p.Nume, p.Urgenta)
}
}
Rezultat
Mihai (urgență 5)
Ioana (urgență 3)
Ana (urgență 2)
Radu (urgență 1)
Greșeli frecvente
- Apelezi metoda
h.Pop()în loc de funcțiaheap.Pop(h): primești ultimul element din slice, nu minimul, iar heap-ul se strică. - Definești
PushșiPoppe valoare (func (h MinHeap) Push): modificarea slice-ului se pierde. Trebuie receptor pointer (*MinHeap). - Uiți
heap.Initcând pornești de la un slice cu date: primelePoppot da elemente greșite.
Comenzi înrudite
container/heap.Fix: Fix reorganizează heap-ul după ce elementul de la indicele i s-a schimbat; Remove scoate elementul de la indicele i.sort.Sort: Sortează orice colecție care implementează sort.Interface (Len, Less, Swap); Stable păstrează ordinea elementelor egale.container/list.New: Lista dublu înlănțuită din biblioteca standard: tipul list.List și funcția list.New care creează o listă goală.