lgoritmer och datastrukturer 2012, föreläsning 6 Nu lämnar vi listorna och kommer till nästa datastruktur i kursen: träd. Här nedan är ett exempel på ett träd: Båge Rot De rosa noderna är ett exempel på underträd Nod Förälder (till de gröna noderna) Barn (till den mörkblå noden) Löv (har inga barn) Till skillnad från riktiga träd så är roten längst upp i datavetenskapens träd. Några exempel på träd är: Släktträd visar en persons efterkommande Spelträd visar alla utfall i ett spel Filträd visar hur filer är ordnade i kataloger i ett operativsystem Sökträd mer om dessa i nästa föreläsning Syntaxträd beskriver hur man får sätta samman ord i ett språk till meningar Ett träds höjd är antalet bågar från roten till det (eller de) löv som sitter längst från roten. En nods djup är antalet bågar från roten till noden. Detta innebär att ett träds höjd är detsamma som det maximala djupet. Träd implementeras oftast med hjälp av referenser. Träd där en nod kan ha ett godtyckligt (eller åtminstone stort antal) barn kan implementeras på följande sätt: B C D B C D E F G H I E F G H I Trädet till vänster är implementerat till höger. Lådorna till höger representerar en nodklass som förutom data som ska lagras innehåller referenserna firstchild (svart pil) och nextsibling (röd pil).
Fördelen med detta sätt att implementera träd är att man inte behöver ha ett varierande antal referenser till en nods barn. Binära träd I ett binärt träd får en nod ha 0, 1 eller 2 barn. tt implementera binära träd är enkelt, varje nod behöver två referenser. En nodklass kan se ut så här: class BinaryNode<E>{ private E element; private BinaryNode<E> left; private BinaryNode<E> right; public BinaryNode(){ element = null; left = null; right = null; public BinaryNode(E elem, BinaryNode<E>l, BinaryNode<E> r){ element = elem; left = l; right = r; public E getelement(){return element; public BinaryNode<E> getleft(){return left; public BinaryNode<E> getright(){return right; public void setelement(e x){element = x; public void setleft(binarynode<e> t){left = t; public void setright(binarynode<e> t){right = t; public static int size(binarynode<e> t){ public static int height(binarynode<e> t){ public BinaryNode<E> duplicate(binarynode<e> t){
public void printinorder(){ Som synes så är några av metoderna inte utskrivna ovan, mer om dem längre fram. En trädklass som använder BinaryNode<E> kan se ut på följande sätt: class BinaryTree<E>{ private BinaryNode<E> root; public BinaryTree(){ root = null; public BinaryTree(E x){ root = new BinaryNode<E>(x, null, null); public BinaryNode<E> getroot(){return root; public int size(){return BinaryNode.size(root); public int height(){return BinaryNode.height(root); root.printpreorder(); public void printinorder(){ root.printinorder(); root.printpostorder(); public void makeempty(){root = null;
public boolean isempty(){return root == null; public void merge(e x, BinaryTree<E> lt, BinaryTree<E> rt){ //Ej ännu implementerad; Observera att metoderna i BinaryTree<E> i många fall använder motsvarande metoder i BinaryNode<E>. Vi implementerar ett par av metoderna som finns i BinaryNode<E> med hjälp av rekursion: public static int size(binarynode<e> t){ if (t == null) return 0; return 1 + size(t.left) + size(t.right); public static int height(binarynode<e> t){ if (t == null) return 0; return 1 + Math.max(height(t.left), height(t.right)); tt gå igenom ett träd ntag att vi vill gå igenom alla noderna i ett träd. Tre sätt att göra detta är så vanliga att de har fått egna namn. ntag att trädet ser ut så här: R V H R är roten i trädet och V och H är vänster respektive höger underträd. De tre sätten som finns att gå igenom trädet ser ut så här: Preorder: först R, sedan V och sist H Inorder: först V, sedan R och sist H Postorder: först V, sedan H och sist R Som en minnesregel kan man ha att V och H alltid kommer i den ordningen (man läser från vänster till höger och det som skiljer är var R ska placeras.
Exempel Låt oss anta att ett träd ser ut så här: M E R F N T B S Då går man igenom noderna i följande ordning när man använder de tre sätten: Preorder: MEBFRNTS Inorder: BEFMNRST Postorder: BFENSTRM Vi kan enkelt skriva metoder för att gå igenom träd. Dessa metoder finns i BinaryNode<E>: System.out.prinln(element.toString()); if (left!= null) left.printpreorder(); if (right!= null) right.printpreorder(); public void printinorder(){ if (left!= null) left.printinorder(); System.out.println(element.toString()); if (right!= null) right.printinorder(); if (left!= null) left.printpostorder(); if (right!= null) right.printpostorder(); System.out.prinln(element.toString()); Läsanvisningar gamla boken Kapitel 18