Prioritetskøer Binære heaper Venstrevridde heaper (Leftist) Binomialheaper Fibonacciheaper Prioritetskøer er viktige i bla. operativsystemer (prosesstyring i multitaskingssystemer), og søkealgoritmer (A, A*, D*, etc.), og i simulering.
Prioritetskøer Prioritetskøer er datastukturer som holder elementer med en prioritet (key) i en kø-aktig struktur, og som implementerer følgende operasjoner: insert() Legge et element inn i køen deletemin() Ta ut elementet med høyest prioritet Og kanskje også: b ild () L k d l t buildheap() Lage en kø av en mengde elementer increasekey()/decreasekey() Endre prioritet delete() Slette et element merge() Slå sammen to prioritetskøer
Prioritetskøer En usortert lenket liste kan brukes. insert() legger inn først i listen (O(1)) og deletemin() søker igjennom listen etter elementet med høyest prioritet (O(n)). En sortert liste kan brukes. (Omvendt kjøretid.) Ikke så veldig effektivt. For å lage en effektiv prioritetskø, holder det at elementene i køen er nogenlunde sorterte.
Binære heaper (vanligst) En binærheap er organisert som et komplett binærtre. (Alle nivåer fulle, med evt. unntak av det siste nivået) I en binærheap skal elementet i roten ha en key som er mindre eller lik key en til barna, i tillegg skal hvert deltre være en binærheap. i / 2 b c d e f g 2i 2i+1 h i j a 1 2 3 4 a b c d e f g h i j 0 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4
Binære heaper (vanligst) insert(14) 13 1 21 16 2 24 31 19 68 3 65 26 32 14 4 13 21 16 24 31 19 68 65 26 32 14 0 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4
Binære heaper (vanligst) insert(14) 13 1 14 16 2 23 21 19 68 3 65 26 32 31 4 13 14 16 24 21 19 68 65 26 32 31 0 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 percolateup()
Binære heaper (vanligst) deletemin() 1 14 16 2 19 21 19 68 3 65 26 32 31 4 14 16 19 21 19 68 65 26 32 31 0 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4
Binære heaper (vanligst) deletemin() 31 1 14 16 2 19 21 19 68 3 65 26 32 4 31 14 16 19 21 19 68 65 26 32 0 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4
Binære heaper (vanligst) deletemin() 14 1 19 16 2 26 21 19 68 3 65 31 32 4 14 19 16 19 21 26 68 65 31 32 0 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 percolatedown()
Binære heaper (vanligst) worst case gjennomsnitt insert() O(log N) O(1) deletemin() O(log N) O(log N) buildheap() O(N) (Legg elementene inn i tabellen i vilkårlig rekkefølge, og kjør percolatedown() på hver rot i deltrærne i heapen (treet) som oppstår, nedenifra og opp.) (Summen av høydene i et binærtre med N noder er O(N).) merge() O(N) (N = antall elementer)
Venstrevridde heaper For å implementere merge() effektivt, går vi bort fra tabell-metoden, og implementerer såkalte venstrevridde heaper (leftist heaps), som rene trær. Tanken er å gjøre heapen (treet) skeivt, slik at vi kan gjøre det meste av arbeidet på den laveste delen av treet. En venstrevridd heap er et binærtre med heap-struktur (røttene i deltrærne skal ha lavere key enn barna.) og et ekstra skeivhetskrav. For alle noder X i treet, definerer vi nullsti-lengde(x) (null path length) som lengden av korteste sti fra X til en node som ikke har to barn. Kravet er at for alle noder, skal nullsti-lengden til det venstre barnet være minst like lang som nullsti-lengden til det høyre barnet.
Venstrevridde heaper 1 1 0 0 0 0 LEFTIST 1 1 0 0 1 0 0 IKKE LEFTIST
merge() Venstrevridde heaper 3 6 10 8 12 7 21 14 17 18 24 37 18 23 26 33
merge() Venstrevridde heaper 3 6 10 8 12 7 21 14 17 18 24 37 18 23 26 33
merge() Venstrevridde heaper 3 6 10 8 12 7 21 14 17 18 24 37 18 23 26 33 3 10 21 14 12 6 37 7 17 8 18 23 18 24 26 33
merge() Venstrevridde heaper 3 6 10 8 12 7 21 14 17 18 24 37 18 23 26 33 3 10 21 14 12 6 37 7 17 8 18 23 18 24 26 33
merge() Venstrevridde heaper 3 6 10 8 12 7 21 14 17 18 24 37 18 23 26 33 3 10 21 14 12 6 37 7 17 8 18 23 18 24 26 33
merge() Venstrevridde heaper 3 6 10 8 12 7 21 14 17 18 24 37 18 23 26 33 3 10 6 7 37 21 14 12 8 23 18 24 17 18 33 26
merge() Venstrevridde heaper 3 6 10 8 12 7 21 14 17 18 24 37 18 23 26 33 3 12 6 10 7 18 24 33 17 8 18 37 21 14 23 26
Venstrevridde heaper insert(3) merge() 5 3 7 6 10 deletemin() 1 merge() 5 3 7 6 11 10
Venstrevridde heaper worst case merge() O(log N) insert() O(log N) deletemin() O(log N) buildheap() O(N) (N = antall elementer) I venstrevridde heaper med N noder, er høyre sti maksimalt log (N+1) lang.
Binomialheaper Venstrevridde / skeive heaper: merge(), insert() og deletemin() i tid O(log N) w.c. Binære heaper: insert() i tid O(1) i gjennomsnitt. Binomialheaper merge(), insert() og deletemin() i tid O(log N) w.c. insert() i tid O(1) i gjennomsnitt. Binomialheaper er ikke trær, men en skog av trær, hvert tre en heap.
Binomialheaper Binomialtrær B 0
Binomialheaper Binomialtrær B 0 B 1
Binomialheaper Binomialtrær B 0 B 1 B 2
Binomialheaper Binomialtrær B 0 B 1 B 2 B3
Binomialheaper Binomialtrær B 0 B 1 B 2 B3 B 4
Binomialheaper Binomialtrær B 0 B 1 B 2 B3 Et tre av høyde k har: 2 k noder, B 4 k antall noder på nivå d er d
Binomialheaper Binomialheap 16 12 18 21 24 65 Maks ett tre av hver størrelse: 6 elementer: 6bi binært = 011(0 (0+2+4) B X 0 B 1 B 2
Binomialheaper Binomialheap 16 12 18 21 24 65 Maks ett tre av hver størrelse: 6 elementer: 6bi binært = 011(0 (0+2+4) B X 0 B 1 B 2 Lengden av rot-listen for en heap med N elementer er O(log N). (Dobbelt lenket, sirkulær liste.)
Binomialheaper merge() 16 12 13 14 23 18 21 24 26 51 24 65 65
Binomialheaper merge() 16 12 13 14 23 18 21 24 26 51 24 65 65
Binomialheaper merge() 16 12 13 14 23 18 21 24 26 51 24 65 65 13
Binomialheaper merge() 16 12 13 14 23 18 21 24 26 51 24 65 65 13 14 26 16 18
Binomialheaper merge() 16 12 13 14 23 18 21 24 26 51 24 65 65 13 23 12 51 24 21 24 14 65 65 26 16 18 Trærne (rotlisten) holdes sortert etter høyde.
Binomialheaper deletemin() 13 23 12 51 24 21 24 14 65 65 26 16 18
Binomialheaper deletemin() 13 23 12 51 24 21 24 14 65 65 26 16 18 merge() 13 23 21 24 14 51 24 65 26 16 65 18
Binomialheaper worst case gjennomsnitt merge() O(log N) O(log N) insert() O(log N) O(1) deletemin() O(log N) O(log N) buildheap() O(N) O(N) (Kjør N insert() i en tom heap.) (N = antall elementer)
Binomialheaper Implementsjon Dobbeltlenkede, sirkulære lister 13 23 12 51 24 21 24 14 65 65 26 16 18
Binomialheaper Implementsjon Dobbeltlenkede, sirkulære lister 13 23 12 51 24 21 24 14 65 65 26 16 18 23 61 27 88
Binomialheaper Implementsjon Dobbeltlenkede, sirkulære lister 13 23 12 51 24 21 24 14 65 65 26 16 18 23 61 27 88
Fibonacciheaper Meget elegant, og i teorien effektiv, måte å implementere heaper på: De fleste operasjoner har amortisert kjøretid O(1). (Fredman & Tarjan 87) insert(), decreasekey() og merge() deletemin() O(1) amortisert tid O(log N) amortisert tid Kombinerer elementer fra venstrevridde heaper og binomialheaper. I praksis litt komplisert å implementere, og enkelte skjulte konstanter er litt høye. Best egnet når det er få deletemin() i forhold til de andre operasjonene. Datastrukturen utviklet i forbindelse med en korteste sti-algoritme. Også benyttet i spenntre-algoritmer.
Fibonacciheaper Fra venstrevridde heaper tar vi med en smart decreasekey() metode. 2 4 11 9 5 12 17 18 10 8 6 18 31 15 11 21
Fibonacciheaper Fra venstrevridde heaper tar vi med en smart decreasekey() metode. 2 4 11 0 5 12 17 18 10 8 6 18 31 15 11 21
Fibonacciheaper Fra venstrevridde heaper tar vi med en smart decreasekey() metode. 0 2 18 10 4 11 31 5 12 17 Leftist 8 6 18 15 11 21 Ikke leftist
Fibonacciheaper Fra venstrevridde heaper tar vi med en smart decreasekey() metode. 0 2 18 10 4 11 31 5 12 17 Leftist 8 6 18 15 11 21 Ikke leftist
Fibonacciheaper Fra venstrevridde heaper tar vi med en smart decreasekey() metode. 0 2 18 10 11 4 31 12 17 5 Leftist 18 8 6 15 11 21 Leftist
Fibonacciheaper Fra venstrevridde heaper tar vi med en smart decreasekey() metode. 0 2 18 11 4 31 12 17 5 10 18 8 6 15 11 21
Fibonacciheaper Fra venstrevridde heaper tar vi med en smart decreasekey() metode. Metoden må imidlertid modifiseres litt, ettersom vi ønsker å bruke trær som er, eller nesten er, binomialtrær. - Noder merkes første gang de mister ett barn. - Andre gang de mister ett barn blir noden kappet av og blir rot i et eget tre, og merket fjernes. min 38 18 7 41 39 21 23 17 24 52 30 46 26 35
Fibonacciheaper Fra venstrevridde heaper tar vi med en smart decreasekey() metode. Metoden må imidlertid modifiseres litt, ettersom vi ønsker å bruke trær som er, eller nesten er, binomialtrær. - Noder merkes første gang de mister ett barn. - Andre gang de mister ett barn blir noden kappet av og blir rot i et eget tre, og merket fjernes. min 38 18 7 41 39 21 23 17 24 52 30 5 26 35
Fibonacciheaper Fra venstrevridde heaper tar vi med en smart decreasekey() metode. Metoden må imidlertid modifiseres litt, ettersom vi ønsker å bruke trær som er, eller nesten er, binomialtrær. - Noder merkes første gang de mister ett barn. - Andre gang de mister ett barn blir noden kappet av og blir rot i et eget tre, og merket fjernes. min 38 18 7 5 41 39 21 23 17 24 52 30 26 35
Fibonacciheaper Fra venstrevridde heaper tar vi med en smart decreasekey() metode. Metoden må imidlertid modifiseres litt, ettersom vi ønsker å bruke trær som er, eller nesten er, binomialtrær. - Noder merkes første gang de mister ett barn. - Andre gang de mister ett barn blir noden kappet av og blir rot i et eget tre, og merket fjernes. min 38 18 7 5 41 39 21 23 17 24 52 30 13 35
Fibonacciheaper Fra venstrevridde heaper tar vi med en smart decreasekey() metode. Metoden må imidlertid modifiseres litt, ettersom vi ønsker å bruke trær som er, eller nesten er, binomialtrær. - Noder merkes første gang de mister ett barn. - Andre gang de mister ett barn blir noden kappet av og blir rot i et eget tre, og merket fjernes. min 38 18 7 5 13 41 39 21 23 17 24 35 52 30
Fibonacciheaper Fra venstrevridde heaper tar vi med en smart decreasekey() metode. Metoden må imidlertid modifiseres litt, ettersom vi ønsker å bruke trær som er, eller nesten er, binomialtrær. - Noder merkes første gang de mister ett barn. - Andre gang de mister ett barn blir noden kappet av og blir rot i et eget tre, og merket fjernes. min 38 18 7 5 13 24 41 39 21 23 17 35 52 30
Fibonacciheaper Vi bruker lazy merging / lazy binomial queue. 18 7 5 8 4 8 8 6 9 9 6 11 32
Fibonacciheaper Vi bruker lazy merging / lazy binomial queue. 18 7 5 8 4 8 8 6 9 9 6 11 32 18 7 5 8 4 8 8 6 9 9 6 11 32
Fibonacciheaper Problemet med decreasekey()-metoden vår og lazy merging er selvsagt at vi må rydde opp i etterkant. Dette gjøres i deletemin(), som derfor får høy kjøretid (O(log N) amortisert tid). Alle trærne gjennomgåes, de minste først, og slåes sammen, slik at vi får maks ett tre av hver størrelse. Hver rot vet hvor mange barn den har, og det er dette vi bruker som størrelse. (Husk hvordan binomialtrær bygges.) Trærne legges i lister en liste per størrelse og så begynner vi å spleise de Trærne legges i lister, en liste per størrelse, og så begynner vi å spleise, de minste først.
Amortisert tid insert() O(1) decreasekey() O(1) merge() O(1) deletemin() O(log N) Fibonacciheaper buildheap() O(N) (Kjør N insert() i en tom heap.) (N = antall elementer)