Implementering af fundamentale datastrukturer 1 Plan Stakke og

  • Slides: 60
Download presentation
Implementering af fundamentale datastrukturer 1

Implementering af fundamentale datastrukturer 1

Plan • Stakke og køer Array-repræsentation Listerepræsentation • Hægtede lister • Træer Terminologi Traversering

Plan • Stakke og køer Array-repræsentation Listerepræsentation • Hægtede lister • Træer Terminologi Traversering 2

En stak (LIFO = Last. In. First. Out) En stak er en sekvens af

En stak (LIFO = Last. In. First. Out) En stak er en sekvens af dataelementer af samme type, som muliggør følgende to operationer: push(x): Læg dataelementet x øverst på stakken (dvs. i begyndelsen af stakken) pop: Fjern det øverste element på stakken push pop Kun stakkens øverste element (top) er tilgængeligt Stak 3

En stak er en abstrakt datatype package Data. Structures; import Exceptions. *; public interface

En stak er en abstrakt datatype package Data. Structures; import Exceptions. *; public interface Stack { void push(Object x); void pop() throws Underflow; Object top. And. Pop() throws Underflow; boolean is. Empty(); void make. Empty(); } 4

Implementering af en stak ved brug af et array top. Of. Stack = 2

Implementering af en stak ved brug af et array top. Of. Stack = 2 9 8 7 6 5 4 3 2 1 0 the. Array Object-instanser 5

Implementering uden fejlhåndtering public class Stack. Ar implements Stack { private Object[] the. Array;

Implementering uden fejlhåndtering public class Stack. Ar implements Stack { private Object[] the. Array; private int top. Of. Stack; static final int DEFAULT_CAPACITY = 10; public Stack. Ar() { the. Array = new Object[DEFAULT_CAPACITY]; top. Of. Stack = -1; } public void push(Object x) { the. Array[++top. Of. Stack] = x; } public void pop() { top. Of. Stack--; } public Object top() { return the. Array[top. Of. Stack]; } public Object top. And. Pop() { return the. Array[top. Of. Stack--]; } public boolean is. Empty() { return top. Of. Stack == -1; } void make. Empty() { top. Of. Stack = -1; } } 6

Fejlhåndtering Metoderne pop, top og top. And. Pop skal reagere fornuftigt, hvis de bliver

Fejlhåndtering Metoderne pop, top og top. And. Pop skal reagere fornuftigt, hvis de bliver kaldt, når stakken er tom. Vi vælger at lade dem kaste undtagelsen Underflow i dette tilfælde. I begyndelsen af hver af de tre metoder indsættes if (is. Empty()) throw new Underflow(" . . . "); 7

Array-udvidelse Hvis arrayet er fyldt, når push kaldes, fordobles dets størrelse. public void push(Object

Array-udvidelse Hvis arrayet er fyldt, når push kaldes, fordobles dets størrelse. public void push(Object x) { if (top. Of. Stack + 1 == the. Array. length) double. Array(); the. Array[++top. Of. Stack] = x; } private void double. Array() { Object[] new. Array = new Object[the. Array. length * 2]; for (int i = 0; i < the. Array. length; i++) new. Array[i] = the. Array[i]; the. Array = new. Array; } Alternativt kunne kopieringen ske således: System. arraycopy(the. Array, 0, new. Array, 0, the. Array. length); 8

Amortiseret køretid Fordobling af arrayet er kostbar i tid: O(N). Fordobling er imidlertid en

Amortiseret køretid Fordobling af arrayet er kostbar i tid: O(N). Fordobling er imidlertid en relativt sjældent forekommende foreteelse. En fordobling, der involverer N elementer, må nemlig være forårsaget af mindst N/2 kald af push. Vi kan fordele omkostningen O(N) fordoblingen på hvert af de N/2 push-operationer. Derved bliver omkostningen for hvert push kun multipliceret med en konstant faktor. I det “lange løb” er køretiden for såvel push som pop O(1). 9

Implementering af en stak ved brug af en hægtet liste top. Of. Stack List.

Implementering af en stak ved brug af en hægtet liste top. Of. Stack List. Node • class List. Node { List. Node(Object e, List. Node n) { element = e; next = n; } Object element; List. Node next; } 10

Implementering uden fejlhåndtering public class Stack. Li implements Stack { private List. Node top.

Implementering uden fejlhåndtering public class Stack. Li implements Stack { private List. Node top. Of. Stack; public Stack. Li() { make. Empty(); } public void push(Object x) top. Of. Stack = new List. Node(x, top. Of. Stack); } public void pop() { top. Of. Stack = top. Of. Stack. next; } public Object top() { return top. Of. Stack. element; } public Object top. And. Pop() { Object t = top(); pop(); return t; } public boolean is. Empty() { return top. Of. Stack == null; } void make. Empty() { top. Of. Stack = null; } } { 11

En kø (FIFO = First. In. First. Out) En kø er en sekvens af

En kø (FIFO = First. In. First. Out) En kø er en sekvens af dataelementer af samme type, som muliggør følgende to operationer: enqueue(x): Sæt dataelementet x bagest i køen dequeue: Fjern det første element fra køen dequeue enqueue Kø 12

En kø er en abstrakt datatype package Data. Structures; import Exceptions. *; public interface

En kø er en abstrakt datatype package Data. Structures; import Exceptions. *; public interface Queue { void enqueue(Object x); Object dequeue() throws Underflow; Object get. Front() throws Underflow; boolean is. Empty(); void make. Empty(); } 13

Implementering af en kø ved brug af en hægtet liste front back List. Node

Implementering af en kø ved brug af en hægtet liste front back List. Node • class List. Node { List. Node(Object e, List. Node n) { element = e; next = n; } Object element; List. Node next; } 14

Implementering uden fejlhåndtering public class Queue. Li implements Queue { private List. Node front,

Implementering uden fejlhåndtering public class Queue. Li implements Queue { private List. Node front, back; public Queue. Li() { make. Empty(); } public void enqueue(Object x) { (is. Empty()) = new List. Node(x, null); else back = back. next = new List. Node(x, null); public Object dequeue() { Object t = front. element; front = front. next; return t; } public Object get. Front() { return front. element; } public boolean is. Empty() { return front == null; } public void make. Empty() { front = back = null; } } if front = back } 15

Implementering af en kø ved brug af et array front = 0 0 back

Implementering af en kø ved brug af et array front = 0 0 back = 5 1 2 3 4 5 6 7 Undgå flytning af arrayelementer ved enqueue og dequeue 16

Cirkulær buffer front = 2 0 1 2 back = 5 3 4 5

Cirkulær buffer front = 2 0 1 2 back = 5 3 4 5 current. Size = 4 6 7 dequeue: front = 3 0 1 2 3 back = 5 4 5 current. Size = 3 6 7 17

enqueue: front = 3 0 1 2 3 back = 6 4 5 6

enqueue: front = 3 0 1 2 3 back = 6 4 5 6 current. Size = 4 7 enqueue med “wraparound” back = 0 0 front = 3 1 2 3 current. Size = 6 4 5 6 7 18

Implementering uden fejlhåndtering public class Queue. Ar implements Queue { private Object[] the. Array;

Implementering uden fejlhåndtering public class Queue. Ar implements Queue { private Object[] the. Array; private int front, back, current. Size; private static final int DEFAULT_CAPACITY = 10; public Queue. Ar() { the. Array = new Object[DEFAULT_CAPACITY]; make. Empty(); } public void enqueue(Object x) { back = (back + 1) % the. Array. length; current. Size++; } the. Array[back] = x; public Object dequeue() { Object t = the. Array[front]; + 1) % the. Array. length; current. Size--; return t; public Object get. Front() { return the. Array[front]; } public boolean is. Empty() { return current. Size == 0; } void make. Empty() { back = -1; front = 0; current. Size = 0; } } front = (front } 19

Array-udvidelse Hvis arrayet er fyldt, når equeue kaldes, fordobles dets størrelse. public void equeue(Object

Array-udvidelse Hvis arrayet er fyldt, når equeue kaldes, fordobles dets størrelse. public void equeue(Object x) { if (current. Size == the. Array. length) double. Queue(); back = (back + 1) % the. Array. length; current. Size++; the. Array[back] = x; } private void double. Queue() { Object[] new. Array = new Object[the. Array. length * 2]; for (int i = 0; i < current. Size; i++, front = (front + 1) % the. Array. length) new. Array[i] = the. Array[front]; the. Array = new. Array; front = 0; back = current. Size - 1; } 20

En hægtet liste front. Of. List. Node • class List. Node { List. Node(Object

En hægtet liste front. Of. List. Node • class List. Node { List. Node(Object e, List. Node n) { element = e; next = n; } Object element; List. Node next; } 21

Indsættelse og sletning Indsættelse af nyt element x efter current: current. next = new

Indsættelse og sletning Indsættelse af nyt element x efter current: current. next = new List. Node(x, current. next); Sletning af elementet efter current: current. next = current. next; current • 22

Brug af en header-knude forenkler indsættelse og sletning forrest i listen header • public

Brug af en header-knude forenkler indsættelse og sletning forrest i listen header • public class Linked. List implements List { public Linked. List() { header = new List. Node(null, null); } public boolean is. Empty() { header. next == null; } public void make. Empty() { header. next = null; } List. Node header; } 23

Iteratorer En iterator er et objekt, der benyttes til at gennemløbe elementerne i en

Iteratorer En iterator er et objekt, der benyttes til at gennemløbe elementerne i en datastruktur, uden at anvenderen behøver at kende til den konkrete implementering af datastrukturen. Fordele: (1) understøtter dataabstraktion (2) sikrer mod fejl og misbrug 24

En iterator til gennemløb af hægtede lister public interface List. Itr { void first();

En iterator til gennemløb af hægtede lister public interface List. Itr { void first(); boolean is. In. List(); void advance(); Object retrieve(); void zeroth(); void insert(Object x) throws Item. Not. Found; boolean find(Object x); void remove(Object x) throws Item. Not. Found; } public class Linked. List. Itr implements List. Itr { private Linked. List the. List; private List. Node current; . . . } 25

Eksempel på anvendelse af Linked. List. Itr static public void print(Linked. List list) {

Eksempel på anvendelse af Linked. List. Itr static public void print(Linked. List list) { if (list. is. Empty()) System. out. print("Empty list"); Linked. List. Itr itr = new Linked. List. Itr(list); for (itr. first(); itr. is. In. List(); itr. advance()) System. out. print(retrieve() + " "); System. out. println(); } 26

Implementation af Linked. List. Itr public class List. Itr { private Linked. List the.

Implementation af Linked. List. Itr public class List. Itr { private Linked. List the. List; private List. Node current; public List. Itr(Linked. List list) the. List = list; current = the. List. header. next; } public void first() { current = the. List. header. next; } public boolean is. In. List() { return current != null && current != the. List. header; } public void advance() current != null) current = current. next; } public Object retrieve() return is. In. List() ? current. element : null; } public void zeroth() { current = the. List. header; } public void insert(Object x) throws Item. Not. Found {. . . } public boolean find(Object x) {. . . } public void remove(Object x) throws Item. Not. Found {. . . } { { if { } 27

public void insert(Object x) throws Item. Not. Found { if (current == null) throw

public void insert(Object x) throws Item. Not. Found { if (current == null) throw new Item. Not. Found("insertion error"); else current = current. next = new List. Node(x, current. next); } public boolean find(Object x) { List. Node n = the. List. header. next; while (n != null && !n. element. equals(x)) n = n. next; if (n == null) return false; current = n; return true; } 28

public void remove(Object x) throws Item. Not. Found { List. Node n = the.

public void remove(Object x) throws Item. Not. Found { List. Node n = the. List. header; while (n. next != null && !n. next. element. equals(x)) n = n. next; if (n. next == null) throw new Item. Not. Found("remove fails"); n. next = n. next; current = the. List. header; } 29

Træer 30

Træer 30

Træer Et træ er en samling af knuder og kanter, (V, E), som opfylder

Træer Et træ er en samling af knuder og kanter, (V, E), som opfylder visse krav: En knude, v, er et simpelt dataobjekt, der kan have et navn og en tilknyttet information. En af knuderne er udpeget som rod i træet. En kant, (v 1, v 2), er en forbindelse imellem to knuder, v 1 og v 2. En vej er en liste af knuder, (v 1, v 2, . . . , vk), hvor alle successive knuder, vi og vi+1, er indbyrdes forbundne (dvs. tilhører E). For at udgøre et træ skal der mellem roden og enhver anden knude findes præcis én vej. 31

Terminologi R Niveau 0 Niveau 1 S Niveau 2 X Rod: R Niveau 3

Terminologi R Niveau 0 Niveau 1 S Niveau 2 X Rod: R Niveau 3 Y X er far til Y Y er søn til X (Y er barn af X) U, V og W er børn af T S er bedstefar til Z S er forgænger til Y (S er over Y) Y er efterkommer af S (Y er under S) Terminale knuder (blade): Y, Z, U, V, W Ikke-terminale knuder: R, S, X, T Ikke-terminal U Z Rod T V W Terminal (blad) 32

Terminologi (fortsat) Et træ kaldes ordnet, hvis rækkefølgen af sønnerne for enhver knude er

Terminologi (fortsat) Et træ kaldes ordnet, hvis rækkefølgen af sønnerne for enhver knude er specificeret. En knudes niveau er antallet af knuder på vejen fra knuden til roden (minus knuden selv). Et træs højde er det maksimale niveau for alle knuder i træet. 33

Binære træer Et binært træ er et ordnet træ, hvor hver knude har højst

Binære træer Et binært træ er et ordnet træ, hvor hver knude har højst 2 sønner. Rekursiv definition: Et binært træ er enten et tomt træ, eller en knude, som har et venstre og et højre binært undertræ. 34

Klassen Binary. Node class Binary. Node { Binary. Node left, right; Object element; Binary.

Klassen Binary. Node class Binary. Node { Binary. Node left, right; Object element; Binary. Node(Object e, Binary. Node lt, Binary. Node rt) element = e; left = lt; right = rt; } static Binary. Node duplicate(Binary. Node t) {. . . } static int size(Binary. Node t) {. . . } static int height(Binary. Node t) {. . . } static void pre. Order. Print(Binary. Node t) {. . . } static void in. Order. Print(Binary. Node t) {. . . } static void post. Order. Print(Binary. Node t) {. . . } } { 35

Klassen Binary. Tree class Binary. Tree { Binary. Node root; Binary. Tree() { root

Klassen Binary. Tree class Binary. Tree { Binary. Node root; Binary. Tree() { root = null; } void duplicate(Binary. Tree rhs) { if (this != rhs) root = rhs. duplicate(root); } int size() { return Binary. Node. size(root); } int height() { return Binary. Node. height(root); } void pre. Order. Print() { Binary. Node. pre. Order. Print(root); } void in. Order. Print() { Binary. Node. in. Order. Print(root); } void post. Order. Print() { Binary. Node. post. Order. Print(root); } } 36

Brug af rekursion static int size(Binary. Node t) { return t == null ?

Brug af rekursion static int size(Binary. Node t) { return t == null ? 0 : 1 + size(t. left) + size(t. right); } static int height(Binary. Node t) { return t == null ? -1 : 1 + Math. max(height(t. left), height(t. right)); } static Binary. Node duplicate(Binary. Node t) { return t == null ? null : new Binary. Node(t. element, duplicate(t. left), duplicate(t. right); } 37

Traversering af binære træer (besøg alle knuder) P M L G S A R

Traversering af binære træer (besøg alle knuder) P M L G S A R B E T F (1) Preorder: Besøg roden. Besøg venstre undertræ. Besøg højre undertræ. P M S A B L G R T E F (2) Inorder: Besøg venstre undertræ. Besøg roden. Besøg højre undertræ. A S B M P L G T R F E (3) Postorder: Besøg venstre undertræ. Besøg højre undertræ. Besøg roden. A B S M T F E R G L P 38

Traversering ved hjælp af rekursion Preorder: void pre. Order. Print(Binary. Node t) { if

Traversering ved hjælp af rekursion Preorder: void pre. Order. Print(Binary. Node t) { if (t != null) { System. out. printl(t. element); pre. Order. Print(t. left); pre. Order. Print(t. right); } } Inorder: void in. Order. Print(Binary. Node t) { if (t != null) { in. Order. Print(t. left); System. out. printl(t. element); in. Order. Print(t. right); } } Postorder: void post. Order. Print(Binary. Node t) { if (t != null) { post. Order. Print(t. left); post. Order. Print(t. right); System. out. printl(t. element); } } 39

Traversering ved brug af iterator abstract public class Tree. Iterator { Binary. Tree t:

Traversering ved brug af iterator abstract public class Tree. Iterator { Binary. Tree t: Binary. Node current; public Tree. Iterator(Binary. Tree t) this. t = t; current = null; } { abstract public void first(); abstract public void advance(); public final boolean is. Valid() { current != null; } public final Object retrieve() throws Item. Not. Found { if (current == null) throw new Item. Not. Found("Tree. Iterator retrieve"); return current. element; } } 40

Traversering ved hjælp af en stak Traverseringstypen er bestemt af antallet af gange et

Traversering ved hjælp af en stak Traverseringstypen er bestemt af antallet af gange et Binary. Nodeobjekt “poppes” fra stakken: 3 gange: 2 gange: 1 gang: postorder inorder preorder class St. Node { St. Node(Binary. Node n) { node = n; } Binary. Node node; int times. Popped; } 41

Klassen Post. Order public class Post. Order extends Tree. Iterator { private Stack s;

Klassen Post. Order public class Post. Order extends Tree. Iterator { private Stack s; public Post. Order(Binary. Tree t) { super(t); s = new Stack. Ar(); s. push(new St. Node(t. root)); } public void first() { s. make. Empty(); if (t. root != null) s. push(new St. Node(t. root)); try { advance(); } catch (Item. Not. Found e) {} } public void advance() throws Item. Not. Found {. . . } } 42

Metoden advance public void advance() throws Item. Not. Found { if (s. is. Empty())

Metoden advance public void advance() throws Item. Not. Found { if (s. is. Empty()) { if (current == null) throw new Item. Not. Found("Post. Order advance"); current = null; return; } try { for (; ; ) { St. Node cnode = (St. Node) s. top(); switch (++cnode. times. Popped) { case 1: if (cnode. left != null) s. push(new St. Node(cnode. left)); break; case 2: if (cnode. right != null) s. push(new St. Node(cnode. right)); break; case 3: s. pop(); current = cnode; return; } } } catch (Underflow e) {} } 43

Klassen In. Order public class In. Order extends Post. Order { public In. Order(Binary.

Klassen In. Order public class In. Order extends Post. Order { public In. Order(Binary. Tree t) { super(t); } } public void advance() throws Item. Not. Found { if (s. is. Empty()) { if (current == null) throw new Item. Not. Found("In. Order advance"); current = null; return; } try { for (; ; ) { St. Node cnode = (St. Node) s. top(); switch (++cnode. times. Popped) { case 1: if (cnode. left != null) s. push(new St. Node(cnode. left)); break; case 2: s. pop(); current = cnode; if (cnode. right != null) s. push(new St. Node(cnode. right)); return; } } } catch (Underflow e) {} } 44

Klassen Pre. Order Hjælpeklassen St. Node kan undværes public class Pre. Order extends Tree.

Klassen Pre. Order Hjælpeklassen St. Node kan undværes public class Pre. Order extends Tree. Iterator { private Stack s; public Pre. Order(Binary. Tree t) { super(t); s = new Stack. Ar(); s. push(t. root); } public void first() { s. make. Empty(); if (t. root != null) s. push(t. root); try { advance(); } catch (Item. Not. Found e) {} } public void advance() throws Item. Not. Found {. . . } } 45

Metoden advance public void advance() throws Item. Not. Found { if (s. is. Empty())

Metoden advance public void advance() throws Item. Not. Found { if (s. is. Empty()) { if (current == null) throw new Item. Not. Found("Pre. Order advance"); current = null; return; } try { current = s. top. And. Pop(); } catch (Underflow e) {} if (current. right != null) s. push(current. right); if (current. left != null) s. push(current. left); } Bemærk at current. right stakkes før current. left. 46

Niveau-traversering af træer P M L G S A R B E T F

Niveau-traversering af træer P M L G S A R B E T F (4) Level-order: Besøg knuderne fra top til bund, i stigende niveauorden, startende i roden og fra venstre mod højre på hvert niveau. P M L S G A B R T E F Niveau-traversering opnås ved i klassen Preorder at erstatte stakken med en kø. Bemærk at køen kan blive meget lang! Cirka N/2, hvor N er antallet af knuder i træet. 47

Traversering ved hjælp af korutiner En korutine er en rutine, der midlertidigt er i

Traversering ved hjælp af korutiner En korutine er en rutine, der midlertidigt er i stand til at standse sin udførelse. I mellemtiden kan en anden korutine blive udført. En standset korutine kan senere genoptage sin udførelse. Denne form for programsekvensering kaldes for alternering. coroutine a coroutine b resume(b) resume(a) 48

Klassen Coroutine public class abstract Coroutine { protected abstract void body(); } public static

Klassen Coroutine public class abstract Coroutine { protected abstract void body(); } public static void resume(Coroutine c); public static void call(Coroutine c); public static void detach(); 49

Rekursiv inorder-traversering ved hjælp af koroutinesekvensering public class In. Order. Iterator extends Tree. Iterator

Rekursiv inorder-traversering ved hjælp af koroutinesekvensering public class In. Order. Iterator extends Tree. Iterator { public In. Order. Iterator(Binary. Tree t) { super(t); } void traverse(Binary. Node t) { if (t != null) { traverse(t. left); current = t; detach(); traverse(t. right); } else current = null; } } 50

public abstract class Tree. Iterator extends Coroutine { Binary. Tree t; Binary. Node current;

public abstract class Tree. Iterator extends Coroutine { Binary. Tree t; Binary. Node current; public Tree. Iterator(Binary. Tree the. Tree) { t = the. Tree; current = null; call(this); } abstract void traverse(Binary. Node t) {. . . } protected void body() { traverse(t. root); } public boolean is. Valid() { return current != null; } public void advance() throws Item. Not. Found { if (current == null) throw new Item. Not. Found("Tree. Iterator advance"); call(this); } } public Object retrieve() throws Item. Not. Found { if (current == null) throw new Item. Not. Found("Tree. Iterator retrieve"); return current. element; } 51

Et testprogram public class In. Order. Test { public static void main(String[] args) {

Et testprogram public class In. Order. Test { public static void main(String[] args) { Binary. Search. Tree t = new Binary. Search. Tree(); try { t. insert(new My. Integer(4)); t. insert(new My. Integer(2)); t. insert(new My. Integer(6)); t. insert(new My. Integer(1)); t. insert(new My. Integer(3)); t. insert(new My. Integer(5)); t. insert(new My. Integer(7)); } catch(Exception e) {} In. Order. Iterator itr = new In. Order. Iterator(t); try { for ( ; itr. is. Valid(); itr. advance()) System. out. print(" " + itr. retrieve()); System. out. println(); } catch (Item. Not. Found e) {} } } Udskrift: 1 2 3 4 5 6 7 52

Designmønstre Designmønster: En model for samspillet imellem objekter, der indfanger nyttige strukturer ved løsning

Designmønstre Designmønster: En model for samspillet imellem objekter, der indfanger nyttige strukturer ved løsning af en række problemer Eksempler: Container: udgør en beholder for en mængde af objekter. Iterator: giver sekventiel tilgang til objekterne i en container, uden at dennes interne repræsentation afsløres for klienten. Adapter: tilpasser grænsefladen for en klasse til bestemte forventninger hos en klient. Visitor: repræsenterer en operation, der skal udføres på objekterne i en container. 53

Visitor-designmønsteret interface Visitor {) void visit(Object obj); boolean is. Done(); } class Container {

Visitor-designmønsteret interface Visitor {) void visit(Object obj); boolean is. Done(); } class Container { void accept(Visitor v) { for each object obj in this container { if (!v. is. Done()) return; v. visit(obj); } } } 54

Eksempel på en visitor class Printing. Visitor implements Visitor { public void visit(Object obj)

Eksempel på en visitor class Printing. Visitor implements Visitor { public void visit(Object obj) { System. out. println(obj); } public boolean is. Done() { return false; } } 55

Rekursiv dybde-først-traversering ved hjælp af en visitor interface Tree. Visitor { void pre. Visit(Object

Rekursiv dybde-først-traversering ved hjælp af en visitor interface Tree. Visitor { void pre. Visit(Object obj); void in. Visit(Object obj); void post. Visit(Object obj); boolean is. Done(); } public class Binary. Tree { Binary. Node root; . . . public void depth. First. Traversal(Tree. Visitor v) { if (root != null) root. depth. First. Traversal(v); } } 56

Rekursiv dybde-først-traversering i klassen Binary. Node class Binary. Node { Binary. Node left, right;

Rekursiv dybde-først-traversering i klassen Binary. Node class Binary. Node { Binary. Node left, right; Object element; . . . void depth. First. Traversal(Tree. Visitor v) { v. pre. Visit(element); if (left != null) left. depth. First. Traversal(v); v. in. Visit(element); if (right != null) right. depth. First. Traversal(v); v. post. Visit(element); } } 57

Visitor for inorder-traversering abstract class Tree. Visitor. Adapter implements Tree. Visitor { void pre.

Visitor for inorder-traversering abstract class Tree. Visitor. Adapter implements Tree. Visitor { void pre. Visit(Object obj) {} void in. Visit(Object obj) {} void post. Visit(Object obj) {} boolean is. Done() { return false; } } public class In. Order extends Tree. Visitor. Adapter { private Visitor visitor; public In. Order(Visitor v) { visitor = v; } public void in. Visit(Object obj) { visitor. visit(obj); } public boolean is. Done() { return visitor. is. Done(); } } 58

Eksempel på anvendelse Binary. Tree t = new Binary. Tree(); . . . t.

Eksempel på anvendelse Binary. Tree t = new Binary. Tree(); . . . t. depth. First. Traversal(new In. Order(new Printing. Visitor())); 59

Ugeseddel 8 30. oktober - 6. november • Læs kapitel 18 i lærebogen (side

Ugeseddel 8 30. oktober - 6. november • Læs kapitel 18 i lærebogen (side 489 -552) • Løs følgende opgaver 8 -1. Opgave 15. 1 8 -2. Opgave 15. 3 8 -3. Opgave 15. 5 8 -4. Opgave 16. 3 8 -5. Opgave 16. 8 8 -6. Opgave 16. 18 8 -7. Opgave 17. 3 8 -8. Opgave 17. 4 8 -9. Opgave 17. 9 60