Datastrukturer och algoritmer Föreläsning 13 rie och ökträd Innehåll rie rådar rie ökträd tterligare en variant av träd. Vi har tidigare sett: Oordnat träd där barnen till en nod bildar en mängd Ordnat träd där barnen till en nod bildar en lista I rie är barnen till en nod organiserade som värden i en tabell som hör till noden rie kallas också diskrimineringsträd, codelink tree eller radix-search tree. 3 4 Organisation av rie Informell specifikation arnen (delträden) nås direkt genom namn, dvs argument/nycklar i barnnodens tabell ycklarna brukar skrivas direkt intill motsvarande båge I en rie har tabellerna en och samma nyckeltyp, t.ex. tecken I många tillämpningar av rie saknar de inre noderna etiketter, träden är lövträd rie är normalt nedåtriktade inära träd kan ses som ett specialfall av rie där ntyckelvärdena är left och right vå sätt: tgå från rträdets specifikation och låt typparametern sibling ha värdet abell. Då hanteras insättning, borttagning och värdekoll av abellen själv. I övrigt används de vanliga operationerna för att sätta in och ta bort barn etc. ätt in lämpliga tabelloperationer direkt i specifikationen av rie Insert-child blir tabellens insert, delete-child tabellens remove och hild tabellens lookup 5 6 1
Konstruktion av rie illämpningar med rie De flesta konstruktioner av träd går bra att använda Om det går att byta ut de delar som hanterar barnen (t.ex som element i en lista) till att hantera dessa som tabellvärden En länkad lista med 2-celler byts till 3-celler Implementerar man tabellen som en vektor eller som en hashtabell får man effektiva rieimplementationer 7 Används för att konstruera lexikon av sekvenser eller abeller där nycklarna är sekvenser För sekvenser med element av typ A väljer vi en rie med tabellnycklar av typ A. En sekvens motsvaras då av en väg i trädet från roten till ett löv Man lägger en slutmarkör i slutet av varje sekvens om en sekvens kan vara början på en annan En annan variant är att ha etiketter i de inre noderna också Ett viktigt/vanligt specialfall är lexikon/abell av textsträng. En sträng kan ju ses som en lista eller vektor av tecken. 8 Forts... Fördelar med att använda rie för Lexikon/abeller som lagrar sekvenser som startar med samma följd av elementvärden: Kompakt sätt att lagra lexikonet/tabellen ökningens tidskomplexitet proportionell mot sekvenslängden (en jämförelse per tecken) Den relativa kompelxiteten är oberoenda av storleken på lexikonet/tabellen Det blir inte dyrare att söka i ett stort lexikon jämfört med ett litet ild från sidan 284 i Janlert L-E., Wiberg., Datatyper och algoritmer, tudentlitteratur, 2000 9 10 illämpningar tavningskontroll kapa trie med alla ord som finns i språket Övesättningstabell Löven innehåller motsvarande ord i ett annat språk Filsystem på nix/p Datakomprimering LZ78-algoritmen - zip, gzip, png bland annat Huffman-kodning LZ78 eller Lempel-Ziv kodning Kodning: Låt frasen 0 vara den tomma strängen Gå igenom texten Om du stöter på en ny bokstav lägg till den på toppnivån i trien Om du stöter på en gammal bokstav gå nedåt i trien tills du inte kan matcha fler tecken, lägg till en nod i trien som representerar nya strängen toppa in paret (nodeindex, sistaokstaven) i den komprimerade strängen 11 12 2
How now brown cow in town. how now brown cow in town. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 9 2 3 4 5 0 h o w _ n r i t 15 w b c _ 6 7 n _. 11 10 13 0h 0o 0w 0_ 0n 2w 4b 0r 6n 4c 6_ 0i 5_ 0t 9. 8 12 13 14 LZ78 eller Lempel-Ziv kodning Avkodning: Varje gång du stöter på 0 (noll) i den komprimerade strängen lägg nästa bokstav direkt efter den föregående i resultatsträngen För varje index!= 0 stoppa in delsträngen som motsvaras av noden (med detta index) i resultatsträngen, följt av nästa tecken i den komprimerade strängen otera att man inte behöver skicka med trädet om man bygger upp det allt eftersom i avkodningen : 0h 0o 0w 0_ 0n 2w 4b 0r 6n 4c 6_ 0i 5_ 0t 9. h o w n ow b r own c ow i n t own. 14 Filkomprimering på ett annat sätt AII-filer är textfiler där varje bokstav representeras av en 8-bitars kod Det är alltås en fixlängdskodning Om man tittar på en textfil ser man att vissa bokstäver förkeommer oftare än andra E är vanligast i engelska jm Morse-alfabetet Om man lagrar vanligt förekommande tecken med färre bitar så skulle vi kunna spara plats 15 Filkomprimering Kodningen måste ske så att att man enkelt kan avkoda strängen entydigt med kännedom om hur de olika tecknen översätts : Antag att de tre tecknen a, b och c kodas som 0, 1, resp 01. Om en mottagare får strängen 001 vad betyder det? aab eller ac? Prefix-regeln: Ingen symbol kodas med en sträng som utgör prefix till en annan symbols kodsträng 16 okstäverna lagras i löven Den vänstra kanten betyder 0 Den högra betyder 1 Vi använder ett trie! Vi vill ha optimal komprimering å kort sträng som möjligt. trängen 01011011010000101001011011010 = 29 bitar kan kortas ned till 24 bitar (23 bitar som mest): 001011000100001100101100 med trädet Vad betyder 01011011010000101001011011010? 010 11 011 010 00 010 10 010 11 011 010 A A A D A A 17 land annat har A fått kortare kod och längre 18 3
Huffman-kodning örja med en serie träd bestående av ett endal löv. ill varje löv associeras en symbol och en vikt = symbolens frekvens i texten som skall kodas Väl de två träd som har minst vikt i roten. ygg ihop dem till ett nytt träd där de blir barn till en ny nod. Den nya noden innehåller en vikt = summan av barnens vikter. pprepa detta till vi har ett enda stort träd Jpeg, mp3 19 Huffman - AAADAA AAADAA A 5/11 A 5/11 D 1 AAADAA blir nu 23 bitar 0 100 101 0 110 0 111 0 100 101 0 4/11 6/11 D 20 ries för strängar Komprimerade tries Insättning tartar i roten och går nedåt i trädet så länge det finns en matchande väg är man hittar en skiljelinje, stanna och stoppa in resten av strängen som ett delträd Komprimerade tries: Liknande algoritm men där är löven strängar som kanske måste delas upp i två barn senare orttagning I princip samma algoritm som insättning fast tvärtom. ök upp strängen som ska tas bort och radera nerifrån i trädet upp till första förgreningen Alla enbarnsnoder konverteras till att innehålla hela strängen/sekvensen som ligger under t o ot 21 22 inärt sökträd Används för sökning i linjära samlingar av dataobjekt, specifikt för att konstruera tabeller och lexikon Organisation: Ett binärt träd som är sorterat med avseende på en sorteringsordning av etikett-typen så att I varje nod n gäller att alla etiketter i vänster delträd går före som i sin tur går före alla etiketter i höger delträd Alla noder är definierade 23 Informell specifikation kiljer sig från ett vanligt binärt träd: Alla noder måste ha etiketter a bort create, Has-Label och et-label och inför Make som skapar rotnod med värde Insert-operationerna utökas med ett etikettvärde Det skall gå att ta bort inre noder, inte bara löv Positionsparametern i delete-node behöver inte peka på ett löv är man tar bort en inre nod trasas trädet sönder. Hur lagar man det? Är nedåtriktat Parent kan utelämnas Eftersom trädet är sorterat kan man inte stoppa in ett nytt element var som helst Måste uppfylla sorteringsordningen 24 4
Varför sorterat träd? Det går snabbare att söka i strukturen För binärt sökträd: Kolla om det sökta värdet finns i den aktuella noden Om inte sök nedåt rekursivt i vänster eller höger delträd beroende på sorteringsordningen Om det binära trädet är komplett: Värstafallskomplexiteten för sökning är O(log(n)) för ett träd med n noder Hur ser man till att trädet blir komplett vid insättning? (vi tittar på det senare) 25 orttagning av nod i binärt sökträd Hur lagar man ett träd när man tagit bort en inre nod? Om den inre noden bara hade ett delträd Lyft upp det ett steg Om den borttagna noden hade två delträd: Välj noden med det minsta värdet i höger delträd som ersättning (alternativt noden med största värdet i vänster delträd) Detta är standardkonstruktionen, det är upp till den som implementerar att välja De vanligaste tillämpningarna är inte beroende av denna detalj Viktigt att man visar sitt beslut i specifikation och dokumentation 26 Vi har trädet a bort element. Det har bara ett delträd, lyft upp det: 27 28 a bort, alternativ 1 a bort, alternativ 2 29 30 5
Varför inte ändra gränsytan? Eftersom man inte får sätta in ett nytt element vart som helst så kanske man lika gärna kan ersätta insert-left och insert-right med en metod place som automatiskt placerar det rätt? På samma sätt ersätta delete-node(pos, bt) med remove(val, bt)? ägge dessa metoder ligger på en högre abstraktionsnivå än övriga metoder i gränsytan. Placa implementerar man i huvudsak med hjälp av andra metoder i gränsytan vilker är lite märkligt trukturen döljs (för oss) och blir mer lik en mängd illämpningar av inärt sökträd Framförallt till konstruktioner av lexikon och tabell otera att inorder-traversering av binärt sökträd ger en sorterad sekvens av de ingående elementen Kan alltså sortera element genom att stoppa in dem ett och ett i ett tomt binärt sökträd och sedan traversera det 31 32 Generaliseringar Quadtree (fyrträd) Ett binärt sökträd underlättar sökning i endimensionell datamängd Lätt att generalisera detta till sökning i en 2-dimensionell datamängd (quadtree) eller så hög dimension man önskar (t.ex octtree) Organiserat som ett binärt träd med förgreningsfaktor 4 i stället för 2 olkning (vanligast): otnoden delar in den givna ytan (oftast en kvadrat) i fyra lika stora kvadrater. Vart och ett av de fyra barnen delar i sin tur sin kvadrat i 4 osv. Inga koordinater behöver lagras i inre noder Kan användas för att lagra lägesinformation för punktformiga grafiska objekt 33 34 Quadtree forts. Man kan också använda det för att representera kurvor och ytor varta kvadranter fylls helt av objektet Grå kvadranter fylls delvis Vita kvadranter innehåller inte objektet på tilläpning GI Grafik för att representera många små objekt som är ojämt spridda. Inga delträd för de kvadranter som är tomma sparar minne 35 6