420 likes | 654 Views
Datastrukturer och algoritmer. Föreläsning 12. Innehåll. Trie Tillämpningar LZ78- och Huffman-kodning Sökträd Flervägssökträd, B-träd (2-4 träd), Sökning Linjär Binär Kapitel 14.1-14.3 och 15.5 i kursboken. Trie. Ytterligare en variant av träd. Jmfr med:
E N D
Datastrukturer och algoritmer Föreläsning 12
Innehåll • Trie • Tillämpningar LZ78- och Huffman-kodning • Sökträd • Flervägssökträd, B-träd (2-4 träd), • Sökning • Linjär • Binär • Kapitel 14.1-14.3 och 15.5 i kursboken
Trie • Ytterligare en variant av träd. Jmfr med: • Oordnat träd - barnen till en nod bildar en mängd • Ordnat träd - barnen till en nod bildar en lista • I Trie är barnen till en nod organiserade som tabellvärden i en tabell som hör till noden. • Trie kallas också för diskrimineringsträd, code-link tree eller radix-search tree. • I radix-search tree är nycklarna specialiserade till siffror i ett talsystem med given bas.
Organisation av Trie • Man når barnen (delträden) direkt genom ”namn”, dvs argument/nycklar i barnnodens tabell. • När man ritar en trie brukar nycklarna skrivas direkt intill motsvarande båge. Bild från sidan 281 i Janlert L-E., Wiberg T., Datatyper och algoritmer, Studentlitteratur, 2000
Organisation av Trie • Tabellerna har en och samma nyckeltyp. • tex tecken • Ofta saknar de inre noderna etiketter. • Träden är lövträd. • Trie är normalt nedåtriktad. • Binära träd kan ses som ett specialfall av Trie där nyckelvärdena är left och right.
Informell specifikation, två sätt: • Utgå från Urträdets specifikation och låt typparametern sibling ha värdet Tabell. • Insättning, borttagning och värdeskontroll hanteras av Tabellen. • 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.
Konstruktion av Trie • De flesta konstruktioner av träd går bra • Om det går bra ändra så att barnen hanteras som tabellvärden i en tabell. • En länkad lista med 2-celler byts till 3-celler. • Tabellen konstruerad som vektor eller hashtabell ger effektiva Trieimplementationer.
Tillämpningar av Trie • 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 motsv. en väg i trädet från roten till ett löv. • Man lägger till en slutmarkör i slutet av varje sekvens om en sekvens kan vara början på en annan sekvens. • 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.
Exempel på Trie Bild från sidan 284 i Janlert L-E., Wiberg T., Datatyper och algoritmer, Studentlitteratur, 2000
Trie för Lexikon/Tabeller som lagrar sekvenser – fördelar • Kompakt sätt att lagra lexikonet/tabellen på. • Speciellt där sekvenserna är lika i början. • Sökningens tidskomplexitet proportionell mot sekvenslängden. • En jämförelse per elementtecken. • Den relativa komplexiteten är oberoende av lexikonet/tabellens storlek. • Det blir inte ”dyrare” att söka i ett stort lexikon jämfört med ett litet.
Tillämpningar • Stavningskontroll • Skapa ett trie med alla ord som finns i språket. • Översättningstabell • Löven innehåller motsvarande ord i ett annat språk. • Filsystem på Unix/PC • Datakomprimering • LZ78-algoritmen • Huffman-kodning
Komprimerade Tries • Alla enbarnsnoder konverteras till att innehålla hela strängen/sekvensen som är under. • Varje intern nod i ett komprimerat Trie har två barn och varje löv symboliserar en sträng. • Minnesutrymmet krymper från O(m) till O(n) • m är summan av längderna av strängarna • n är antalet strängar i strukturen
Variant utan slutmarkörer Bild från sidan 286 i Janlert L-E., Wiberg T., Datatyper och algoritmer, Studentlitteratur, 2000
Tries för strängar • Insättning • Starta i roten, gå nedåt så länge vägen matchar. • Vid en skiljelinje, stanna och stoppa in resten av strängen som ett delträd. • Insättning i komprimerade tries: • Är löven strängar kan dessa behöva delas upp i två barn • Borttagning • Samma algoritm 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.
LZ78 eller Lempel-Ziv Kodning • Låt frasen 0 vara strängen ”” • Skanna igenom texten • Om du stöter på en ”ny” bokstav lägg till den på toppnivån på 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 den nya strängen. • Stoppa in paret (nodeIndex, sistaBokstaven) i den komprimerade strängen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 h 1 Exempel: ”how now brown cow in town.” how now brown cow in town. 0 0 o w _ n r i t 2 3 4 5 8 12 14 _ w b c 7 10 13 6 _ n 9 11 . 0h 0o 0_ 0n 2w 0r 6_ 0i 5_ 0t 9. 0w 4b 6n 4c 15
LZ78 eller Lempel-Ziv Avkodning • Varje gång du stöter på ”0” i strängen lägg nästa bokstav i strängen direkt efter den föregående i den avkodade strängen. • För varje index < > 0 stoppa in delsträngen som motsvaras av den noden i den avkodade strängen, följt av nästa tecken i den komprimerade strängen. • Notera att man inte behöver skicka med trädet! • Exempel: 0h0o0w0_0n2w4b0r6n4c6_0i5_0t9. ow b r own t h o w n c ow i n own.
LZ78 eller Lempel-Ziv kodning • I praktiken är kompressionen ≥ 50%. • Vidareutvecklad kompression (tex tar bort nollor i strängen) ger varianter som i praktiken är snabbare än Huffman-kodning. • Läs mer om LZ78 i ”Data Structures and Algorithms in Java” av M. T. Goodrich och R. Tamassia, John Wiley & Sons, 1998.
Filkomprimering • ASCII-filer är textfiler där varje bokstav representeras av en 8-bitars ascii-kod. • Det är alltså en fixlängdskodning • Om man tittar på en textfil ser man att vissa bokstäver förekommer oftare än andra. • Om man lagrar vanligt förekommande bokstäver med färre bitar än ovanliga så skulle vi kunna spara utrymme.
Filkomprimering • Kodningen måste ske så 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 respektive 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.
Vi använder ett trie! • Bokstäverna lagras i löven. • Den vänstra kanten betyder 0 • Den högra betyder 1 • 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 kompression! • Så kort sträng som möjligt. Strängen 01011011010000101001011011010 = 29 bits kan kortas ned till 24 bitar 001011000100001100101100 med trädet • Gjort bokstäverna A och R kortare och C och D längre.
Huffman-kodning • Börja med en serie träd bestående av ett enda löv. • Till varje löv associeras en symbol och en vikt = symbolens frekvens i texten som ska kodas. • Välj de två träd som har minst vikt i roten. Bygg ihop dem till ett träd där de blir barn till en ny nod. • Nya nodens vikt = summan av barnens vikter. • Upprepa förra punkten tills vi har ett enda stort träd.
A 5/11 B 2/11 R 2/11 C 1/11 D 1/11 11/11 6/11 A 5/11 4/11 2/11 C 1/11 D 1/11 B 2/11 R 2/11 Exempel Huffmankodning • ABRACADABRA ABRACADABRA blir nu 23 bitar 0 100 101 0 110 0 111 0 100 101 0
Binärt sökträd -repetition • Ett binärt träd som är sorterat med avseende på en sorteringsordning R av etikettypen 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. • Om trädet är komplett så vet vi att både medel- och värstafallskomplexiteten är O(log n). • Men… • Det tar tid och kraft att se till att trädet är komplett. • Ibland kan man tvingas bygga om hela trädet.
Flervägs-sökträd • Ett m-vägs sökträd (m-way search tree, m-ary search tree) är en generalisering av ett binärt sökträd. • Ordnat träd där varje nod har högst m delträd. • Etiketterna är sekvenser av upp till m-1 värden i stigande sorteringsordning som fungerar som delningspunkter vid sökning. • Oftast är etiketterna nycklar och värdet till en viss nyckel finns i lövet.
Flervägs-sökträd • Till en nod med k+1 delträd, t0, t1, …, tk hör en sekvens med värden v1, v2, …, vk. Sorteringsvillkoret för trädet är att: • alla värden i t0 går före v1 (i sorteringsordningen) • alla värden i tj ligger mellan vj och vj+1 för 1<j<k • alla värden i tk går efter vk • Operationerna blir liknande de för binärt sökträd. • Plattare träd. Höjden = logm n • Mer jobb i noderna
Exempel Bild från sidan 323 i Janlert L-E., Wiberg T., Datatyper och algoritmer, Studentlitteratur, 2000
B-träd • Ett B-träd av ordning m är en typ av balanserat m-vägs sökträd som uppfyller följande: • Roten är antingen ett löv eller har minst två barn • Alla noder utom roten och löven har mellan m/2 och m barn • Alla löv är på samma djup
B-träd • Insättning av nya element görs alltid på den djupaste nivån, i rätt löv för att bevara sorteringsordningen. • En insättning kan leda till att noden blir för stor (dvs > m). Då måste noden delas upp. • Borttagning kan leda till att man måste justera värderna och slå ihop noder eller omfördela värden mellan dem. • B-träd av ordning 3 kallas också 2-3 träd
Exempel på B-träd: 2-4 träd • Varje nod har 1, 2 eller 3 nycklar och varje icke-löv har 2-4 barn. • Regel för insättning: • Man letar sig fram till rätt löv på liknande sätt som i ett vanligt sökträd. • Den nya nyckeln sätts in där. Om det blir för många nycklar i det lövet splittras det. • Animering: http://people.ksp.sk/~kuko/bak/big/Välj Btree
Insert i 2-4 träd • Stoppa in elementen 4, 6, 12 • Att stoppa in elementet 15 orsakar en split. • Ersätt den temporära 5-noden med en 3-nod och en 2-nod och flytta upp ett element till föräldern
Insert i 2-4 träd, forts • Sätt nu in först 3 och sen 5(som orsakar en ny split)
2-4 träd, borttagning • Man letar sig fram till rätt löv på liknande sätt som i ett vanligt sökträd. • Enkla fallet: Det finns flera nycklar i noden, ta bort den som ska bort. • Halvsvåra fallet: Syskonen har ”extra” element som vi kan sno. • Svåra fallet: Vi får tomt och syskonet har bara ett element. Då måste vi göra en ”fuse”-operation.
Halvsvåra fallet: Syskonen har ”extra” element som vi kan sno. Kallas ”transfer”
Svåra fallet: Måste göra en ”fuse”-operation somvandrar uppåt iträdet.
Linjär sökning • Starta från början och sök tills elementet hittat eller sekvensen slut. • Komplexitet • Elementet finns: I medel gå igenom halva listan, O(n) • Elementet saknas: I medel gå igenom hela listan, O(n) • Om listan är sorterad: • Elementet saknas: Räcker i medel att leta genom halva listan n/2, O(n)
Binär sökning • Om sekvensen har index (tex i en array eller numrerad lista) kan man söka binärt. • Successiv halvering av sökintervallet. • Vi får värsta-falls och medelkomplexitet O(log n). • Jämför med elementet närmast mitten i intervallet. • Om likhet – klart! • Om det sökta värdet kommer före i sorteringsordningen fortsätt sökningen rekursivt i det vänstra delintervallet. • Om det kommer efter i sorteringsordningen fortsätt sökningen rekursivt i det högra delintervallet.
Exempel: • 1 2 4 4 6 7 9 13 14 19 • Sök efter elementet 13. • Linjär sökning: 8 jämförelser innan träff. • Binär sökning: 2 jämförelser innan träff. • Sök efter elementet 10 • Linjär sökning: 8 jämförelser innan man ger upp. • Binär sökning: 4 jämförelser innan man ger upp.