|
5. TrærEt tre har en rotnode, og rotnoden har barn. Hvert barn kan ha barn igjen. En node uten barn kalles en løvnode. Et barn med sine barn (og deres barn igjen, osv) kalles et subtre.Dybden av en node N er lengden av stien fra rotnoden til N. Høyden av et tre er den lengste stien fra rotnoden til en løvnode. For eksempel syntaksen i språket er bygd opp som et tre. I eksemplene
må du selv tegne inn rotnoden, den heter "helsetning".
5.1 Binære trærEt binært tre er et tre der hver node kun kan ha 0-2 barn.Istedenfor å deklarere pekere til venstrebarn og høyrebarn, kan man deklarere dem til å peke på første barn og neste søsken. På den måten kan ett hvert tre implementeres som et binært tre. Binære trær kan degenerere til å bli lenkede lister. 5.2 BS-trærI et binært søketre er nøklene ordnet slik at du alltid finner høyere nøkler til høyre for noden, og lavere nøkler til venstre for noden.5.2.1 FinneFor å finne en node med en gitt nøkkel i treet, traverserer du treet slik at hvis nøkkelen du leter etter er større enn den du nå titter på, går du til i høyre i treet. Er den mindre, går du til venstre. Er den lik, har du funnet riktig node. Ender du opp hos en node uten barn uten å ha funnet nøkkelen, finnes den ikke i treet.5.2.2 Sette innDu startet som om du skulle prøve å finne noden i treet. Hvis den faktisk finnes, kan du velge mellom å ikke gjøre noe som helst, eller for eksempel øke en variabel kalt Antall i noden du fant. Finnes ikke noen node med en slik nøkkel fra før, settes den nye noden inn på det siste stedet der traverseringen endte.5.2.3 SletteFørst må vi finne noden som skal slettes. (Hvis den ikke finnes, returneres typisk en verdi som viser oss dette, for eksempel NULL.) Hvis noden er et løv (den har ingen barn) kan den slettes umiddelbart. Hvis den bare har ett barn, kan noden bli slettet etter at dens forelder har justert en link til å peke på barnet (til den noden som skal slettes). Med to barn blir det mer komplisert. Strategien er å bytte ut dataene i denne noden med de minste dataene i det høyre subtre, og så rekursivt slette den noden (som nå er tom). Fordi den minste noden i det høyre subtreet ikke kan ha noen venstre-barn (da hadde ikke denne noden vært den minste), er den andre slette-operasjonen grei.Fra filen bstree.cpp (etter Fongen): Position BStree::del(int a) { Position tmpcell; if (this == NULL) Error("!"); else if (a < key) left = left->del(a); else if (a > key) right = right->del(a); else // Found the element to be deleted if (right && left) { // Two children // Replace with the smallest in right subtree tmpcell = right->findMin(); key = tmpcell->key; right = right->del(key); } else { // one or zero children if (!left) tmpcell = right; else //if (!right) tmpcell = left; delete this; return tmpcell; } return this; } 5.2.4 To implementasjonerbts.cpp (Etter Sedgewick).bstree.cpp (Etter Fongen). 5.3 AVL-trærEt AVL (Adelson-Velskii & Landis) -tre er et binært søketre med en balansekondisjon: for hver node i treet kan forskjellen av høyden av venstre og høyre subtree ikke være mer enn 1. (Høyden av et tomt tre er definert til -1.) Hver node inneholder høydeinformasjon om seg selv. Høyden av et AVL-tre er ca. 1.44 log(N +2)-.328, men i praksis er den bare litt mer enn log N. (For informasjon om logaritmer, se 1.4 Logaritmer.)Minimumsnummer av noder, S(h), i et AVL-tre av høyden h er gitt ved S(h) = S(h-1) + S(h-2) +1. For h = 0, S(h) = 1. For h = 1, S(h) = 2. Funksjonen S(h) er nært beslektet med Fibonacci-nummerene. 5.3.1 InnsettingVed innsetting er det bare noder på veien fra innsettingspunktet til roten som kan ha fått sin balanse forandret, fordi bare disse nodenes subtrær er blitt forandret. Mens vi følger veien opp til roten og oppdaterer balanseinformasjonen, kan det hende vi finner noder der den nye balansen bryter med AVL-kravet. Vi kommer til å rebalansere treet ved den første (dvs. dypeste) slike noden. Denne rebalanseringen garanterer at hele treet tilfredstiller AVL-kravet. (-Etter Weiss, p. 145-146.)Det er fire tilfeller der det kan hende vi må rebalansere:
Tilfellene 1 & 4 og 2 & 3 er symmetriske med hensyn til foreldrenoden, men vi må likevel programmere for alle fire tilfellene. 5.3.1.1 Enkel rotasjonI de tilfellene der innsettingen skjer på yttersiden (venstre - venstre eller høyre - høyre) er det nok med en enkel rotasjon for å få orden på treet igjen.5.3.1.2 Dobbel rotasjon |
|