Datastrukturer och algoritmer
Föreläsning 13 Trie och Sökträd
Innehåll
• Trådar
• Trie
• Sökträd
3
Trie
• Ytterligare 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 Trie är barnen till en nod organiserade som värden i en tabell som hör till noden
• Trie kallas också diskrimineringsträd, code-
link tree eller radix-search tree.4
Organisation av Trie
• Barnen (delträden) nås direkt genom ’namn’, dvs argument/nycklar i barnnodens tabell
– Nycklarna brukar skrivas direkt intill motsvarande båge
• I en Trie har tabellerna en och samma nyckeltyp, t.ex. tecken
• I många tillämpningar av Trie saknar de inre noderna etiketter, träden är lövträd
• Trie är normalt nedåtriktade
• Binära träd kan ses som ett specialfall av Trie där ntyckelvärdena är ’left’ och ’right’
5
Informell specifikation
• Två sätt:
– Utgå från Urträdets specifikation och låt typparametern sibling ha värdet Tabell.
• Då hanteras insättning, borttagning och värdekoll av Tabellen själv.
• I övrigt används de vanliga operationerna för att sätta in och ta bort barn etc.
– Sätt in lämpliga tabelloperationer direkt i specifikationen av Trie
• Insert-child blir tabellens insert, delete-child tabellens remove och Child tabellens lookup
6
Konstruktion av Trie
• 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
Trieimplementationer
7
Tillämpningar med Trie
• Används för att konstruera lexikon av sekvenser eller Tabeller där nycklarna är sekvenser
• För sekvenser med element av typ A väljer vi en Trie 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/Tabell av textsträng. En sträng kan ju ses som en lista eller vektor av tecken.
8
Forts ...
• Fördelar med att använda Trie för
Lexikon/Tabeller som lagrar sekvenser som startar med samma följd av elementvärden:
– Kompakt sätt att lagra lexikonet/tabellen – Sö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
9
Exempel
10
Bild från sidan 284 i Janlert L-E., Wiberg T., Datatyper och algoritmer, Studentlitteratur, 2000
Tillämpningar
• Stavningskontroll
– Skapa trie med alla ord som finns i språket
• Övesättningstabell
– Löven innehåller motsvarande ord i ett annat språk
• Filsystem på Unix/PC
• Datakomprimering
– LZ78-algoritmen - zip, gzip, png bland annat – Huffman-kodning
11
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
• Stoppa in paret (nodeindex, sistaBokstaven) i den komprimerade strängen
12
How now brown cow in town.
13
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0
2 3 4 5
6 7
8
9
10 11
12 13
14
15 1
h o w _ n r i t
w b c _
n _
. 0h 0o 0w 0_ 0n 2w 4b 0r 6n 4c 6_ 0i 5_ 0t 9.
how now brown cow in town.
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
– Notera att man inte behöver skicka med trädet om man bygger upp det allt eftersom i avkodningen
• Exempel:
0h 0o 0w 0_ 0n 2w 4b 0r 6n 4c 6_ 0i 5_ 0t 9.
14
h o w n ow b r own c ow i n t own.
Filkomprimering på ett annat sätt
• ASCII-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
– Exempel: 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
Vi använder ett trie !
• Bokstäverna lagras i löven
• Den vänstra kanten betyder 0
• Den högra betyder 1
17
Vad betyder
01011011010000101001011011010 ? 010 11 011 010 00 010 10 010 11 011 010 A B R A C A D A B R A
Vi vill ha optimal komprimering
• Så kort sträng som möjligt. Strängen
01011011010000101001011011010 = 29 bitar kan kortas ned till 24 bitar (23 bitar som mest):001011000100001100101100 med trädet
• Bland annat har A fått kortare kod och C längre
18
Huffman-kodning
• Börja med en serie träd bestående av ett endal löv. Till 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.
Bygg 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.
• Upprepa detta till vi har ett enda stort träd
• Jpeg, mp3
19Huffman - ABRACADABRA
• ABRACADABRA
20
A 5/11 B
2/11 R 2/11 C
1/11 D 1/11
C 1/11 D
1/11 2/11 2/11 B R
2/11 4/11
6/11 5/11 A
11/11 ABRACADABRA blir nu 23 bitar 0 100 101 0 110 0 111 0 100 101 0
Tries för strängar
• Insättning
– Startar i roten och går nedåt i trädet så länge det finns en matchande väg
– Nä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
• Borttagning
– I princip samma algoritm som insättning fast tvärtom. Sök upp strängen som ska tas bort och radera nerifrån i trädet upp till första förgreningen
21
Komprimerade tries
• Alla enbarnsnoder konverteras till att innehålla hela strängen/sekvensen som ligger under
22
o
t
ot
Binä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 R av etikett-typen så att
• I varje nod n gäller att alla etiketter i vänster delträd går före N som i sin tur går före alla etiketter i höger delträd
• Alla noder är definierade
23
Informell specifikation
• Skiljer sig från ett vanligt binärt träd:
– Alla noder måste ha etiketter
• Ta bort create, Has-Label och Set-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
• Nä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
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
Borttagning 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
Exempel
• Vi har trädet
27
R B
N
T
S Y
C U
Exempel
• Ta bort element B. Det har bara ett delträd, lyft upp det:
28
R
N T
S Y
U C
Exempel
• Ta bort R, alternativ 1
29
S B
N
T Y C U
Exempel
• Ta bort R, alternativ 2
30
N B
C
T
S Y
U
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)?
• Bä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
– Strukturen döljs (för oss) och blir mer lik en mängd
31
Tillämpningar av Binärt sökträd
• Framförallt till konstruktioner av lexikon och tabell
• Notera 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
32
Generaliseringar
• Ett binärt sökträd underlättar sökning i en- dimensionell 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)
33
Quadtree (fyrträd)
• Organiserat som ett binärt träd med förgreningsfaktor 4 i stället för 2
• Tolkning (vanligast):
– Rotnoden 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
34
Quadtree – forts.
• Man kan också använda det för att representera kurvor och ytor
– Svarta kvadranter – fylls helt av objektet – Grå kvadranter – fylls delvis
– Vita kvadranter – innehåller inte objektet
• Exempel på tilläpning
– GIS– 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