Föreläsning 9 Innehåll Träd, speciellt binära träd egenskaper användningsområden implementering Datavetenskap (LTH) Föreläsning 9 HT 2017 1 / 31
Inlämningsuppgiften De föreläsningar som inlämningsuppgiften bygger på är nu klara. Det är lagom att börja titta på inlämningsuppgiften efter laboration 4. Schema för jourtider finns på kurssidan cs.lth.se/edaa01ht. Datavetenskap (LTH) Föreläsning 9 HT 2017 2 / 31
Datastrukturer i kursen Hittills har vi använt datastrukturerna vektor och enkellänkad lista. T.ex. för att implementera de abstrakta datatyperna lista, stack och kö. I kursen används också träd binära sökträd och hashtabeller för att implementera de abstrakta datatyperna mängd (eng. Set) och lexikon (eng. Map). heapar för att implementera den abstrakta datatypen prioritetskö. Datavetenskap (LTH) Föreläsning 9 HT 2017 3 / 31
Träd Icke-linjär struktur En nod i ett träd kan ha högst en föregångare (förälder), men flera efterföljare (barn). Jfr. listor som är linjära strukturer En nod i en lista kan ha högst en föregångare och en efterföljare. Datavetenskap (LTH) Föreläsning 9 HT 2017 4 / 31
Träd rekursiv definition Ett träd är antingen tomt (har inga noder) eller består av en speciell nod, roten, och noll eller flera subträd. rot tre subträd Datavetenskap (LTH) Föreläsning 9 HT 2017 5 / 31
Släkträd Exempel på användning av träd Karl XIV Johan 1763-1844 Oskar I 1799-1876 Karl XV 1826-1872 Gustaf 1827-1852 Oskar II 1829-1907 Eugenie 1830-1889 August 1831-1873 Datavetenskap (LTH) Föreläsning 9 HT 2017 6 / 31
Terminologi lånad från släktträd Antag att två noder n 1 och n 2 är förbundna med en båge och n 1 är den övre av dem n 1 är då förälder till n 2 och n 2 är barn till n 1 Noder som har samma förälder kallas syskon (eng: siblings) Antag att två noder n 1 och n 2 är förbundna med en serie bågar och n 1 är den övre av dem n 1 är då förfader (eng: ancestor) till n 2 n 2 är avkomling (eng: descendant) till n 1 Datavetenskap (LTH) Föreläsning 9 HT 2017 7 / 31
Terminologi lånad från naturen Rot den enda nod som saknar förälder I datavetenskap ritas träden upp och ned med roten överst. Löv noder som saknar barn Gren en serie noder förbundna med varandra rot löv En gren i trädet visas med: löv löv löv Datavetenskap (LTH) Föreläsning 9 HT 2017 8 / 31
Begreppen nivå eller djup för en nod Rotens nivå (djup) är 1. En nod som inte är rot har nivå (djup) = förälderns nivå (djup) + 1. nivå = djup = 1 nivå = djup = 2 nivå = djup = 3 Datavetenskap (LTH) Föreläsning 9 HT 2017 9 / 31
Begreppet höjd för ett träd Ett tomt träd har höjden 0. Ett träd som inte är tomt har höjd = maximala nivån (djupet) för noderna i trädet. trädets höjd = 3 nivå = djup = 3 Datavetenskap (LTH) Föreläsning 9 HT 2017 10 / 31
Binära träd Ett träd är binärt om varje nod har högst två barn (eller ekvivalent, två subträd). Ett träd är strikt binärt om varje nod har noll eller två barn. D.v.s. alla noder som inte är löv har två barn. Ej binärt, roten har tre barn Binärt, men ej strikt binärt Strikt binärt Datavetenskap (LTH) Föreläsning 9 HT 2017 11 / 31
Binära träd speciell terminologi För ett binärt träd brukar man tala om vänster respektive höger subträd till en nod vänster respektive höger barn till en nod Vänster barn till roten Vänster subträd till roten Höger barn till roten Höger subträd till roten OBS: en nod kan ha höger barn utan att ha vänster barn. Datavetenskap (LTH) Föreläsning 9 HT 2017 12 / 31
Huffmanträd Exempel på användning av (strikt) binära träd I Huffmankodning byts tecken ut mot koder av olika längd. Vanligt förekommande tecken ska ha kortare kod än mer sällsynta tecken. Tecken Kod a 0 b 100 c 101 d 11 a 0 1 0 1 d 0 1 b c Datavetenskap (LTH) Föreläsning 9 HT 2017 13 / 31
Aritmetiska uttryck Exempel på användning av (strikt) binära träd Ett aritmetiskt uttryck med (de binära) operationerna +,, * och / kan representeras av ett (strikt) binärt träd: + * 1 * + 3 2 3 1 2 1 + 2 * 3 (1 + 2) * 3 Operander lagras i löv, operatorer i övriga noder. Ett träds värde = operatorn i roten applicerad på värdet av subträden. Ett lövs värde är det värde som lagrats i lövet. Datavetenskap (LTH) Föreläsning 9 HT 2017 14 / 31
Binära sökträd Exempel på användning av binära träd Mona Hans Nora Ann Karl Tora Lagrar element med söknyckel för vilken jämförelseoperationer är definierade. Här: sträng. Nycklarna i vänster subträd är mindre än rotens nyckel som i sin tur är mindre än nycklarna i höger subträd. Fördel: Enkelt och snabbt att leta upp, sätta in och ta bort element. Datavetenskap (LTH) Föreläsning 9 HT 2017 15 / 31
Implementering av binära träd Klassen BinaryTree public class BinaryTree<E> { private Node<E> root; public BinaryTree() { root = null; root null... operationer på trädet... private static class Node<E> { // se nästa bild Datavetenskap (LTH) Föreläsning 9 HT 2017 16 / 31
Implementering av binära träd Klassen Node private static class Node<E> { private E data; private Node<E> left; private Node<E> right; private Node(E data) { this.data = data; left = right = null; data left right... Datavetenskap (LTH) Föreläsning 9 HT 2017 17 / 31
Skriv ut trädets noder public void print() { print(root); private void print(node<e> n) { if (n!= null) { System.out.println(n.data); print(n.left); print(n.right); M H S I vilken ordning skrivs noderna ut? A K N T Datavetenskap (LTH) Föreläsning 9 HT 2017 18 / 31
Rekursiva traverseringar av binära träd Traversering betyder att vi besöker varje nod i trädet. Många operationer på träd kan tolkas som traversering. Under traverseringen utför man operationer på noderna. Man kan traversera träd i olika ordningar, t ex följande rekursivt definierade: preorder: först roten, sedan vänster subträd i preorder, därefter höger subträd i preorder inorder: först vänster subträd i inorder, sedan roten och därefter höger subträd i inorder postorder: först vänster subträd i postorder, sedan höger subträd i postorder och därefter roten Datavetenskap (LTH) Föreläsning 9 HT 2017 19 / 31
Diskutera M H S A K N T I vilken ordning behandlas noderna om man traverserar trädet i preorder? inorder? postorder? Datavetenskap (LTH) Föreläsning 9 HT 2017 20 / 31
Algoritm för preordertraversering if trädet tomt return else besök roten traversera vänster subträd traversera höger subträd Exempel: Skriv ut innehållet i alla noder i preorder i det träd där n är rot. private void print(node<e> n) { if (n!= null) { System.out.println(n.data); print(n.left); print(n.right); Datavetenskap (LTH) Föreläsning 9 HT 2017 21 / 31
Algoritm för inorder- och postordertraversering Inorder: if trädet tomt return else traversera vänster subträd besök roten traversera höger subträd Postorder: if trädet tomt return else traversera vänster subträd traversera höger subträd besök roten Datavetenskap (LTH) Föreläsning 9 HT 2017 22 / 31
Traversera trädet rekursivt alternativ Publik metod i trädklassen Alternativt kan vi placera den rekursiva metoden i nodklassen. I klassen BinaryTree implementerar vi då endast följande publika metod: /** Skriver ut trädet i preorder */ public void print() { if (root!= null) { root.print(); Metoden print i klassen Node<E> finns på nästa bild. Datavetenskap (LTH) Föreläsning 9 HT 2017 23 / 31
Traversera trädet rekursivt alternativ Rekursiv metod i nodklassen /* Skriver ut det träd där noden är rot i preorder. */ private void print() { System.out.println(data); if (left!= null) { left.print(); if (right!= null) { right.print(); Datavetenskap (LTH) Föreläsning 9 HT 2017 24 / 31
Exempel: visualisera träd Visualisera innehåll och form på ett träd genom att översätta trädet till en sträng enligt: b d a e c a b c null d null null e null null null Strängen beskriver trädet i preorder Barn indenteras 2 blanksteg i förhållande till föräldern Varje nod på ny rad Tomma subträd representeras av delsträngen null Datavetenskap (LTH) Föreläsning 9 HT 2017 25 / 31
Visualisera träd implementering Enklare problem sträng med trädets innehåll public String tostring() { StringBuilder sb = new StringBuilder(); buildstring(root, sb); return sb.tostring(); private void buildstring(node<e> n, StringBuilder sb) { if (n!= null) { sb.append(n.data); sb.append( \n ); buildstring(n.left, sb); buildstring(n.right, sb); Observera att man skapar ett enda StringBuilder-objekt. Det måste skickas med som parameter till den rekursiva metoden. Datavetenskap (LTH) Föreläsning 9 HT 2017 26 / 31
Visualisera träd implementering public String tostring() { StringBuilder sb = new StringBuilder(); buildstring(root, 0, sb); return sb.tostring(); private void buildstring(node<e> n, int indent, StringBuilder sb) { for (int i = 0; i < indent; i++) { sb.append( ); if (n == null) { sb.append("null\n"); else { sb.append(n.data); sb.append( \n ); buildstring(n.left, indent + 2, sb); buildstring(n.right, indent + 2, sb); Datavetenskap (LTH) Föreläsning 9 HT 2017 27 / 31
Traversering i postorder Exempel Om vi har ett binärt träd som representerar aritmetiska uttryck kan vi beräkna trädets värde som en postorder-genomgång. Subträdens värden beräknas först. Därefter besöks roten genom att dess operator appliceras på subträdens värde. + * 1 * + 3 2 3 1 2 1 + 2 * 3 (1 + 2) * 3 Datavetenskap (LTH) Föreläsning 9 HT 2017 28 / 31
Traversering i inorder Exempel Om vi har ett binärt sökträd får vi elementen i stigande ordning vid en inorder-genomgång. Mona Hans Nora Ann Karl Tora Datavetenskap (LTH) Föreläsning 9 HT 2017 29 / 31
Nivå- för nivåtraversering Nivå- för nivåtraversering kan implementeras med hjälp av en kö: skapa en tom kö lägg in roten i kön så länge kön inte är tom tag ut och behandla första noden (actnode) om actnode.left!= null lägg in actnode.left i kön om actnode.right!= null lägg in actnode.right i kön Datavetenskap (LTH) Föreläsning 9 HT 2017 30 / 31
Exempel på vad du ska kunna Förklara begreppen träd och binära träd samt begrepp som rot, löv, subträd, förälder, barn. Förklara begreppen nivå/djup för en nod och begreppet höjd för träd. Implementera träd med en länkad datastruktur. Beskriva olika sätt att traversera träd: preorder, inorder, postorder. Implementera operationer på träd, speciellt rekursiva metoder. Datavetenskap (LTH) Föreläsning 9 HT 2017 31 / 31