De presentatie wordt gedownload. Even geduld aub

De presentatie wordt gedownload. Even geduld aub

Hoofdstuk 20: GEGEVENSSTRUCTUREN.

Verwante presentaties


Presentatie over: "Hoofdstuk 20: GEGEVENSSTRUCTUREN."— Transcript van de presentatie:

1 Hoofdstuk 20: GEGEVENSSTRUCTUREN

2 gegevensstructuren met een vaste lengte - Eéndimensionele arrays
H 20. GEGEVENSSTRUCTUREN 1.     INLEIDING Reeds gezien : gegevensstructuren met een vaste lengte - Eéndimensionele arrays - Meerdimensionele arrays

3 H 20: Dynamische gegevensstructuren
H 20. GEGEVENSSTRUCTUREN 1.     INLEIDING H 20: Dynamische gegevensstructuren Variabele lengte: lengte kan kleiner en groter worden tijdens runtime. Enkele dynamische gegevensstructuren: Gelinkte lijsten Stacks Queues Binaire bomen

4 2. ZELF-REFERENTIE KLASSE
Bevat een instantie-variabele dat refereert naar een object van dezelfde klasse. Bv: class Node { // Node = knoop private int data; private Node nextNode; public Node (int data) {…} // constructor public void setData (int data) {…} public int getData() {…} public void setNext (int data) {…} public Node getNext() {…} }

5 2. ZELF-REFERENTIE KLASSE
private Node nextNode; De instantie-variabele nextNode wordt een "link" genoemd. nextNode verbindt ("links") een Node object met een ander Node object.

6 2. ZELF-REFERENTIE KLASSE
Programma’s kunnen "zelf-referentie objecten" verbinden. Zo kan er een gegevensstructuur gecreëerd worden zoals lijsten, queues, stacks en bomen. Bv: 15 10

7 3. DYNAMISCHE GEHEUGENTOEWIJZING
Als we objecten aan de dynamische gegevensstructuur toevoegen, verzoeken we het systeem om meer geheugen. Als we een object niet meer nodig hebben, geven we de ruimte aan het systeem terug: JAVA heeft een automatische garbage collection.

8 3. DYNAMISCHE GEHEUGENTOEWIJZING
Declaratie en creatie van nodeToAdd Node nodeToAdd = new Node ( 10 ); - De expressie "new Node (10)" kent geheugen toe om het Node object te bewaren en geeft een referentie van het object terug. Deze referentie wordt toegekend aan nodeToAdd. - Indien geheugen tekort dan geeft deze expressie OutOfMemoryError terug.

9 4.     GELINKTE LIJSTEN Gelinkte lijst is een lineaire (sequentiële) collectie van zelf-referentie objecten (= nodes = knopen). Knopen kunnen toegevoegd en verwijderd worden aan het begin, midden of eind van de lijst. Elke knoop bevat een referentie naar de volgende, alleen de laatste knoop heeft niks om naar te verwijzen  de laatste knoop bevat null.

10 4.     ENKEL GELINKTE LIJST Een object bevat de referentie van de eerste knoop van de gelinkte lijst (firstNode). Het object kan ook de referentie van de laatste knoop bevatten (lastNode). firstNode lastNode H D ... Q

11 Bv: class Node { private Node previousNode;
4.     DUBBEL GELINKTE LIJST Bv: class Node { private Node previousNode; private int data; private Node nextNode; firstNode lastNode H D ... Q

12 4. VOORBEELD VAN EEN ENKEL GELINKTE LIJST
Drie domeinklassen: ListNode, List en EmptyListException Applicatie: ListTest ListNode is een zelf-referentie klasse. De objecten van deze klasse zijn de knopen van de gelinkte lijst. List zal verwerkingen met de gelinkte lijst uitvoeren: toevoegen en verwijderen van knopen. EmptyListException werpt een exception indien er een poging wordt gedaan om een knoop uit een lege lijst te verwijderen.

13 4.     KLASSE ListNode class ListNode { private Object data; private ListNode nextNode; // constructors ListNode( Object object ) { this( object, null ); } ListNode( Object object, ListNode node ) { data = object; nextNode = node; } // accessors en mutators Object getData() { return data; } void setData(Object data) { this.data = data;} ListNode getNext() { return nextNode; } void setNext(ListNode node) { nextNode = node; } } // einde klasse ListNode De zelf-referentie klasse ListNode bevat "data" en de link "nextNode". "data" is een referentie naar een object van de klasse Object, dus kan "data" refereren naar gelijk welk object.

14 4. KLASSE List Klasse List: Constructors
In de constructors wordt er een naam aan de gelinkte lijst toegekend. Methodes : isEmpty : controleren indien de lijst al dan niet leeg is; print : de inhoud van de gelinkte lijst wordt weergegeven; insertAtFront : knoop vooraan in de lijst toevoegen; insertAtBack : knoop achteraan in de lijst toevoegen; removeFromFront : knoop vooraan in de lijst verwijderen; removeFromBack : knoop achteraan in de lijst verwijderen.

15 4. KLASSE List : instantie-variabelen en constructors
public class List { private ListNode firstNode; private ListNode lastNode; private String name; // constructors public List() { this( "list" ); } public List( String listName ) { name = listName; // firstNode = lastNode = null; OVERBODIG } "firstNode" referereert naar de eerste knoop en "lastNode" refereert naar de laatste knoop van de gelinkte lijst. “name" zal de naam van de gelinkte lijst bijhouden. De attributen "firstNode" en "lastNode" worden automatisch op null gezet.

16 4. KLASSE List : accessors en mutators
protected ListNode getFirstNode() { return firstNode; } protected ListNode getLastNode() { return lastNode; } public String getName() { return name; } protected void setFirstNode(ListNode node) { firstNode = node; } protected void setLastNode(ListNode node) { lastNode = node; } public void setName(String name) { this.name = name; }

17 4. KLASSE List: methode isEmpty
// controleert indien de gelinkte lijst al dan niet leeg is public synchronized boolean isEmpty() { return firstNode == null; // return true indien de lijst // leeg is } De methode isEmpty is een "predicate method". Deze methode test een conditie van een object zonder dat object te wijzigen.

18 4. KLASSE List: methode print
// de inhoud van de knopen weergeven public synchronized void print() { if ( isEmpty() ) System.out.println( "Empty " + name ); return; } System.out.print( "The " + name + " is: " ); ListNode current = firstNode; // zolang niet einde lijst wordt de inhoud van de // huidige knoop (= current) weergegeven. Vervolgens wordt // de huidige knoop gelijkgesteld aan de volgende knoop while ( current != null ) System.out.print(current.getData().toString() + " " ); current = current.getNext(); System.out.println( "\n" ); } // einde methode print

19 4. KLASSE List : methode insertAtFront
// voegt een knoop toe aan het begin van de gelinkte lijst public synchronized void insertAtFront( Object insertItem ) { if ( isEmpty() ) firstNode = lastNode = new ListNode( insertItem ); else firstNode = new ListNode( insertItem, firstNode ); } Indien de gelinkte lijst leeg is dan zal firstNode en lastNode naar de nieuwe knoop wijzen. Indien de lijst niet leeg is dan zal firstNode naar de nieuwe eerste knoop wijzen.

20 4. KLASSE List : methode insertAtFront
Schematische voorstelling van insertAtFront: Indien de gelinkte lijst leeg is dan zal firstNode en lastNode naar de nieuwe knoop wijzen. (a) firstNode lastNode new Listnode 10 (b) firstNode lastNode new Listnode 10

21 4. KLASSE List : methode insertAtFront
Schematische voorstelling van insertAtFront Indien de gelinkte lijst niet leeg is dan zal firstNode naar de nieuwe knoop wijzen. (a) firstNode lastNode 7 11 new Listnode 12 lastNode (b) firstNode 7 11 new Listnode 12

22 4. KLASSE List : methode insertAtBack
// voegt een knoop toe aan het einde van de lijst public synchronized void insertAtBack( Object insertItem ) { if ( isEmpty() ) firstNode = lastNode = new ListNode( insertItem ); else // lastNode's nextNode zal naar de nieuwe node wijzen { lastNode.setNext(new ListNode( insertItem )); lastNode = lastNode.getNext();} } Indien de gelinkte lijst leeg is dan zal firstNode en lastNode naar de nieuwe knoop wijzen. Indien de lijst niet leeg is dan zal lastNode's nextNode naar de nieuwe knoop wijzen. M.a.w. de knoop die op de laatste plaats stond wijst nu naar de nieuwe knoop. Vervolgens wijst lastNode naar de nieuwe knoop.

23 4. KLASSE List : methode insertAtBack
Schematische voorstelling van insertAtBack: Indien de gelinkte lijst leeg is dan zal firstNode en lastNode naar de nieuwe knoop wijzen. (a) firstNode lastNode new Listnode 2 (b) firstNode lastNode new Listnode 2

24 4. KLASSE List : methode insertAtBack
Schematische voorstelling van insertAtBack: Indien de lijst niet leeg is dan zal lastNode's nextNode naar de nieuwe knoop wijzen. Vervolgens zal lastNode naar de nieuwe knoop wijzen. (a) firstNode lastNode new Listnode 12 7 11 5 (b) firstNode lastNode new Listnode 12 7 11 5

25 4. KLASSE List : methode removeFromFront
// verwijdert de eerste knoop van de gelinkte lijst public synchronized Object removeFromFront() throws EmptyListException { if ( isEmpty() ) // exception wordt gegooid indien de // gelinkte lijst leeg is throw new EmptyListException( name ); Object removedItem = firstNode.getData(); // de data van de // eerste knoop in de lijst wordt toegekend aan removedItem // firstNode wordt gewijzigd. lastNode wordt gewijzigd // indien de lijst maar één knoop bevat. if ( firstNode == lastNode ) firstNode = lastNode = null; else firstNode = firstNode.getNext(); return removedItem; // de data van de verwijderde knoop // wordt teruggegeven. } // einde methode removeFromFront

26 4. KLASSE List : methode removeFromFront
Schematische voorstelling van removeFromFront : Indien de gelinkte lijst één knoop bevat dan zal na deze methode firstNode en lastNode aan null worden toegekend. ab) firstNode lastNode 5 (b) firstNode lastNode removeItem 5

27 4. KLASSE List : methode removeFromFront
Schematische voorstelling van removeFromFront : Indien de lijst meer dan één knoop bevat dan zal firstNode naar de tweede knoop wijzen. (a) firstNode lastNode 12 7 11 5 (b) firstNode lastNode 12 7 11 5 removeItem

28 4. KLASSE List : methode removeFromBack
// verwijdert de laatste knoop van de gelinkte lijst public synchronized Object removeFromBack() throws EmptyListException { if ( isEmpty() ) // exception wordt gegooid indien de // gelinkte lijst leeg is throw new EmptyListException( name ); Object removedItem = lastNode.getData(); // de data van de // laatste knoop in de lijst wordt toegekend aan removedItem // lastNode wordt gewijzigd. firstNode wordt gewijzigd // indien de lijst maar één knoop bevat. if ( firstNode == lastNode ) firstNode = lastNode = null; else

29 4. KLASSE List : methode removeFromBack
// de lijst bevat meer dan één knoop : { // de nieuwe laatste knoop zoeken (m.a.w. de voorlaatste // knoop zoeken ListNode current = firstNode; // de gelinkte lijst doorlopen totdat de current.nextnode // (= de volgende knoop in de lijst) gelijk is aan lastnode while (current.getNext() != lastNode ) current = current.getNext(); lastNode = current; // current is de nieuwe laatste knoop current.setNext(null); // vermits current de nieuwe // laatste knoop is, is er geen volgende knoop meer } return removedItem; // de data van de verwijderde knoop // wordt teruggegeven. } // einde methode removeFromBack

30 4. KLASSE List : methode removeFromFront
Schematische voorstelling van removeFromBack : Indien de gelinkte lijst één knoop bevat dan zal na deze methode firstNode en lastNode aan null worden toegekend. ab) firstNode lastNode 7 (b) firstNode lastNode removeItem 7

31 4. KLASSE List : methode removeFromFront
Schematische voorstelling van removeFromBack : Indien de lijst meer dan één knoop bevat dan zal lastNode naar de nieuwe laatste knoop wijzen. (a) firstNode lastNode 12 7 11 5 (b) firstNode current lastNode 12 7 11 5 removeItem

32 4. KLASSE List : synchronized
Als we de klasse binnen één thread gebruiken, gaat alles goed, maar wat gebeurt er wanneer meerdere threads de methoden op precies (of bijna) dezelfde tijd kunnen benaderen? Stel bvb. dat één thread een knoop verwijdert en dat tegerlijkertijd een ander de inhoud opvraagt. Moet de geretourneerde inhoud, de verwijderde knoop, al dan niet bevatten? Eigenlijk worden de gegevens onbetrouwbaar. Door het sleutelwoord synchronized te gebruiken, weten we zeker dat slechts één thread tegerlijkertijd een methode benadert. Elke andere thread moet wachten totat het object weer vrij is.

33 4. KLASSE EmptyListException
public class EmptyListException extends RuntimeException { // constructors public EmptyListException() this( "List" ); // roept de constructor met één // parameter, van deze klasse, op } public EmptyListException( String name ) super( name + " is empty" ); // roept de // constructor van zijn superklasse op } // einde klasse EmptyListException Exception wordt gegooid indien het programma een knoop uit een lege lijst wenst te verwijderen.

34 4. KLASSE ListTest public class ListTest
{ public static void main( String args[] ) { List list = new List(); // de lege gelinkte lijst "list" is // gecreëerd. // objects creëren om nadien in de gelinkte lijst te zetten Boolean bool = Boolean.TRUE; Character character = new Character( '$' ); Integer integer = new Integer( ); String string = "hello"; // knopen in de lijst toevoegen en vervolgens de inhoud weergeven list.insertAtFront( bool ); list.print(); list.insertAtFront( character ); list.print(); list.insertAtBack( integer ); list.print(); list.insertAtBack( string ); list.print(); The list is: true The list is: $ true The list is: $ true 34567 The list is: $ true hello

35 4. KLASSE ListTest // knopen verwijderen uit de gelinkte lijst try {
Object removedObject = list.removeFromFront(); System.out.println( removedObject.toString() + " removed" ); list.print(); removedObject = list.removeFromFront(); ... removedObject = list.removeFromBack(); ... } // einde try blok // catch exception indien een poging werd uitgevoerd om een // knoop uit een lege lijst te verwijderen catch ( EmptyListException emptyListException ) emptyListException.printStackTrace(); } } // einde methode main } // einde klasse ListTest

36 4. KLASSE ListTest Uitvoer van : list.print();
Object removedObject = list.removeFromFront(); ... removedObject = list.removeFromFront(); ... removedObject = list.removeFromBack(); ... The list is: $ true hello $ removed The list is: true hello true removed The list is: hello hello removed The list is: 34567 34567 removed Empty list

37 OEFENING Gegeven : De klasse GesorteerdeLijst erft van List Gevraagd: Schrijf de methode toevoegen(naam) van de klasse GesorteerdeLijst: de naam wordt alfabetisch toegevoegd aan de gelinkte lijst.

38 5. STACKS Stack (= stapel)
is een gelinkte lijst waarbij de knopen slechts aan één uiteinde (de top van de stack) worden toegevoegd of verwijderd. Men kan zich een stack voorstellen al een stapel dienbladen die zich op de toonbank van een cafetaria bevindt. Klanten nemen boven van de stapel bladen weg en teruggekomen bladen worden weer boven op de stapel geplaatst. Het blad dat het laatst op de stapel geplaatst is, wordt er het eerst weer afgenomen. Het onderste blad is het eerst in de stapel geplaatst en wordt het laatste wegenomen.

39 5.     STACKS Stack (= stapel) is een LIFO gegevensstructuur: last-in, first-out. Push : nieuwe knoop wordt op de top van de stack geplaatst. Pop : knoop die op top van de stack staat, wordt verwijderd.

40 5.     STACKS: VOORBEELD 1 Voorbeeld 1: We zullen een stack implementeren door gebruik te maken van de klasse List De klasse StackInheritance zal erven van List.

41 5. KLASSE StackInheritance
public class StackInheritance extends List { // constructor public StackInheritance() { super( "stack" ); } // voegt een object aan de stack toe public synchronized void push( Object object ) { insertAtFront( object ); } // verwijdert een object van de stack public synchronized Object pop() throws EmptyListException { return removeFromFront();} } // einde klasse StackInheritance De klasse StackInheritance erft van List, omdat een stack een beperkte versie is van een gelinkte lijst. De methoden isEmpty en print kunnen gestuurd worden naar een object van StackInheritance, omdat deze erft van List

42 5. KLASSE StackInheritanceTest
public class StackInheritanceTest { ... StackInheritance stack = new StackInheritance(); Boolean bool = Boolean.TRUE; Character character = new Character( '$' ); stack.push( bool ); stack.push( character ); ... while ( true ) { removedObject = stack.pop(); ... } (1) (2) (3) (4) (5) ($ popped) (true popped) $ zie volgende slide true true true

43 5. KLASSE StackInheritanceTest
com.deitel.jhtp5.ch20.EmptyListException: stack is empty at com.deitel.jhtp5.ch20.List.removeFromFront(List.java:82) at com.deitel.jhtp5.ch20.StackInheritance.pop( StackInheritance.java:22) at StackInheritanceTest.main(StackInheritanceTest.java:33)

44 5.     STACKS: VOORBEELD 2 Andere manier om een stack te implementeren: De klasse StackComposition zal een referentie naar een List bevatten. Deze manier van implementatie heet "composition". Voordeel t.o.v. voorbeeld 1 (overerving): Deze stack bevat enkel de vier nodige methodes (push, pop, isEmpty en print). De methodes van List (removeFromBack, insertAtBack, …) zijn nu geen methodes van de stack. Terwijl dit bij overerving wel het geval was.

45 5. KLASSE StackComposition
public class StackComposition { private List stackList; public StackComposition() { stackList = new List( "stack" ); } public synchronized void push( Object object ) { stackList.insertAtFront( object ); } public synchronized Object pop() throws EmptyListException { return stackList.removeFromFront(); } public synchronized boolean isEmpty() { return stackList.isEmpty(); } public synchronized void print() { stackList.print(); } } // einde klasse StackComposition

46 6.     QUEUES Queue (= wachtrij) is ook een beperkte versie van een gelinkte lijst. Men kan zich een queue voorstellen als een rij bij een loket, waarbij de voorste in de rij als eerste geholpen wordt en nieuwkomers achter aansluiten. De persoon die het eerst in de rij staat, wordt het eerst bediend  queue is een FIFO gegevensstructuur: first-in, first-out.

47 6.     QUEUES Het element van de queue dat vooraan staat in de queue, dat dus als eerste zal worden verwijderd, heet de kop van de queue. Het element dat achteraan staat, dat dus als laatste aan de queue is toegevoegd, heet de staart van de queue We spreken hier niet van push en pop maar van enqueue en dequeue. enqueue : element toevoegen aan de queue dequeue : element verwijderen uit de queue

48 6.     QUEUE: VOORBEELD Voorbeeld: We zullen een queue implementeren door gebruik te maken van de klasse List De klasse Queue zal een referentie naar een List bevatten ("composition").

49 6. KLASSE QUEUE public class Queue { private List queueList;
public Queue() { queueList = new List( "queue" ); } // element toevoegen aan de queue public synchronized void enqueue( Object object ) { queueList.insertAtBack( object ); } // element verwijderen uit de queue public synchronized Object dequeue() throws EmptyListException { return queueList.removeFromFront(); } public synchronized boolean isEmpty() { return queueList.isEmpty(); } public synchronized void print() { queueList.print(); } } // einde klasse Queue

50 6. KLASSE QueueTest public class QueueTest { ...
Queue queue = new Queue(); Boolean bool = Boolean.TRUE; Character character = new Character( '$' ); queue.enqueue( bool ); queue.enqueue( character ); ... while ( true ) {removedObject = queue.dequeue(); ... } (1) (2) (3) (4) (5) (true dequeued) ($ dequeued) true true $ $ zie volgende slide kop staart kop staart kop staart

51 6.     KLASSE QueueTest com.deitel.jhtp5.ch20.EmptyListException: queue is empty at com.deitel.jhtp5.ch20.List.removeFromFront(List.java:88) at com.deitel.jhtp5.ch20.Queue.dequeue(Queue.java:23) at QueueTest.main(QueueTest.java:33)

52 OEFENING Gegeven : De queue bestaat uit een array van 5 elementen. De array houdt gehele getallen bij. Gevraagd: Schrijf de klasse Queue : constructor en de methodes enqueue en dequeue.

53 7.     BOMEN boom is niet lineaire gegevensstructuur (een gelinkte lijst is een lineaire gegevensstructuur). Knopen bevatten twee of meerdere "links". Elke link refereert naar een kind De eerste knoop in de boom heet de wortel ("root node"). Knoop zonder kinderen heet een blad ("leaf node").

54 7.     BINAIRE BOOM - Binaire boom is óf leeg óf zij bestaat uit de wortel, en twee binaire bomen, de linker subboom en de rechter subboom. M.a.w. de knopen bevatten twee "links". Het linkerkind is de eerste knoop in de linker subboom. Het rechterkind is de eerste knoop in de rechter subboom.

55 Voorbeeld van een binaire boom
- Een programma bevat de referentie van de wortel van de binaire boom (root). root B A D C

56 7.     BINAIRE ZOEKBOOM binaire zoekboom is een binaire boom die óf leeg is óf waarin elke knoop een sleutel bevat die voldoet aan de volgende voorwaarden: De sleutel van het linkerkind (als deze bestaat) van een knoop is kleiner dan de sleutel van de ouders. De sleutel van het rechterkind (als deze bestaat) van een knoop is groter dan de sleutel van de ouders.

57 Voorbeeld van een binaire zoekboom
47 11 43 65 93 25 77 7 17 31 44 68

58 Bv. (1) Voeg 22 toe (3) Voeg 35 toe
7.     BINAIRE ZOEKBOOM Hoe een binaire zoekboom eruit ziet hangt af van de volgorde van de ingegeven sleutels. Bv. (1) Voeg 22 toe (3) Voeg 35 toe (2) Voeg 10 toe (4) Voeg 15 toe 22 22 10 35 22 22 10 10 35 15

59 7.     BINAIRE ZOEKBOOM Voordeel van een binaire zoekboom t.o.v. gesorteerde gelinkte lijst Indien we een sleutel moeten opzoeken in een enkel gelinkte lijst dan kunnen we niets anders dan knoop voor knoop door de lijst te bewegen (sequentieel zoeken). Maar sequentieel zoeken is vergeleken bij binair zoeken erg langzaam. Indien we met de elementen van een gesorteerde lijst een binaire zoekboom construeren, zullen we zien dat we een sleutel kunnen opzoeken in O(log n) stappen, net zoals bij binair zoeken. Bovendien kunnen elementen in de tijd O(log n) toegevoegd of verwijderd worden.

60 7. DOORLOPEN VAN DE BINAIRE BOOM
Eén van de belangrijkste operaties bij binaire bomen is het doorlopen van de boom, waarbij elke knoop bezocht wordt. Het doorlopen van een gelinkte lijst gaat in de natuurlijke volgorde van de eerste tot de laatste knoop. Een boom kunnen we echter in vele verschillende volgorden doorlopen.

61 7. DOORLOPEN VAN DE BINAIRE BOOM
In een gegeven knoop zijn er drie taken die we in een of andere volgorde willen uitvoeren: het bezoeken van de knoop zelf, het doorlopen van zijn linker subboom en het doorlopen van zijn rechter subboom. Gewoonlijk beperkt men zich tot de gevallen waarin de linker subboom voor de rechter wordt doorlopen. M.a.w. men beperkt zich tot drie gevallen. Deze hebben speciale namen: preorder, inorder en postorder.

62 7. DOORLOPEN VAN DE BINAIRE BOOM
doorlopen in preorder : de knoop wordt eerst bezocht. Als tweede de linker subboom en al laatste de rechter subboom. Bv. 20, 8, 33, 27, 41 20 8 33 27 41

63 7. DOORLOPEN VAN DE BINAIRE BOOM
doorlopen in inorder : de linker subboom wordt eerst bezocht. Als tweede de knoop en al laatste de rechter subboom. Bv. 8, 20, 27, 33, 41 20 8 33 27 41

64 7. DOORLOPEN VAN DE BINAIRE BOOM
doorlopen in postorder : de linker subboom wordt eerst bezocht. Als tweede de rechter subboom en al laatste de knoop. Bv. 8, 27, 41, 33, 20 20 8 33 27 41

65 Bepaal de uitvoer indien de boom wordt doorlopen in:
7.     OEFENING Bepaal de uitvoer indien de boom wordt doorlopen in: (1) preorder (2) inorder (3) postoder 47 25 77 11 43 65 93 8 31 44 68

66 7.     OPLOSSING (1) preorder 47 25 77 11 43 65 93 8 31 44 68

67 7.     OPLOSSING (2) inorder 47 25 77 11 43 65 93 8 31 44 68

68 7.     OPLOSSING (3) postoder 47 25 77 11 43 65 93 8 31 44 68

69 7. VOORBEELD VAN EEN BINAIRE BOOM
Twee domeinklassen: TreeNode en Tree Applicatie: TreeTest TreeNode: De objecten van deze klasse zijn de knopen van de binaire zoekboom. Bevat de methode insert: een knoop wordt toegevoegd aan de boom. Tree bevat de instantie-variable "root". Deze zal refereren naar de wortel van de binaire zoekboom. Bevat methodes om de boom te doorlopen en om knopen toe te voegen.

70 leftNode is het linkerkind en rightNode is het rechterkind.
7.     KLASSE TreeNode class TreeNode { private TreeNode leftNode; private int data; private TreeNode rightNode; // constructor public TreeNode( int nodeData ) data = nodeData; leftNode = rightNode = null;// de knoop heeft geen kinderen } leftNode is het linkerkind en rightNode is het rechterkind. In de constructor wordt er een blad ("leaf node") gecreëerd. De ingegeven data wordt in het blad geplaatst.

71 7. KLASSE TreeNode : accessors
public void setLeftNode(TreeNode leftNode) { this.leftNode = leftNode; } public void setRightNode(TreeNode leftNode) { this.rightNode = rightNode; } public void setData(char data) { this.data = data; } public TreeNode getLeftNode() { return leftNode; } public TreeNode getRightNode() { return rightNode; } public int getData() { return data; } In het boek zijn de instantie-variabelen als package-toegankelijk gedeclareerd.

72 7. KLASSE TreeNode : methode insert
// locate insertion point and insert new node; ignore duplicate values public synchronized void insert( int insertValue ) { // insert in left subtree if ( insertValue < data ) // insert new TreeNode if ( leftNode == null ) leftNode = new TreeNode( insertValue ); else // continue traversing left subtree leftNode.insert( insertValue ); } // insert in right subtree else if ( insertValue > data ) if ( rightNode == null ) rightNode = new TreeNode( insertValue ); else // continue traversing right subtree rightNode.insert( insertValue ); } // end method insert } // end class TreeNode

73 7. KLASSE TreeNode : methode insert
Een knoop kan enkel toegevoegd worden in de binaire boom als een blad ("leaf node"). De methode insert is recursief. De toe te voegen waarde "insertValue" wordt vergeleken met de waarde, die in de wortel staat "data". Indien de toe te voegen waarde kleiner is "if (insertValue<data)" dan: indien de knoop geen linkerkind bevat dan wordt het nieuw blad toegevoegd "leftNode= new TreeNode(insertValue);" anders wordt de methode insert naar de linker subboom gestuurd "leftNode.insert( insertValue );" anders: idem als "dan", behalve rechterkind en rechter subboom i.p.v. linkerkind en linker subboom.

74 7. KLASSE Tree public class Tree { private TreeNode root;
// constructor: de binaire boom is leeg public Tree() { root = null; } public void setRoot(TreeNode root) this.root = root; } public TreeNode getRoot() return root;

75 7.     KLASSE Tree // een knoop toevoegen in de binaire zoekboom public synchronized void insertNode( int insertValue ) { if ( root == null ) root = new TreeNode( insertValue ); // de wortel // ("root node") wordt gecreëerd else root.insert( insertValue ); // methode insert oproepen } Indien de boom leeg is dan is de instantie-variable "root" gelijk aan null, anders refereert "root" naar de wortel.

76 7.     KLASSE Tree : inorder // doorlopen van de boom volgens inorder public synchronized void inorderTraversal() { inorderHelper( root ); } // recursieve methode om de boom te doolopen volgens inorder private void inorderHelper( TreeNode node ) { if ( node == null ) return; inorderHelper( node.getLeftNode()); // doorloop linker subboom System.out.print( node.getData()+ " " ); // inhoud van de // knoop weergeven inorderHelper( node.getRightNode());//doorloop rechter subboom } Indien de programmeur de boom wenst te doorlopen kan hij een methode oproepen, zonder dat hij de "root" dient door te geven (bv. methode inorderTraversal).

77 Voorbeeld: root  27 6 13 17 27 root  13
inorderHelper( node.getLeftNode() ); 1 System.out.print( node.getData()+" "); inorderHelper( node.getRightNode() ); root  13 2 System.out.print( node.getData()+" "); 8 inorderHelper( node.getRightNode()); root  root  null inorderHelper( node.getLeftNode() ); return; System.out.print( node.getData() + " " ); 5 root  17 4 root  null inorderHelper( node.getLeftNode() ); return; System.out.print( node.getData()+" " ); 7 inorderHelper( node.getRightNode()); 27 13 6 17

78 Preorder– data weergeven, vervolgens doorloop linker subboom
7.     KLASSE Tree : preorder // doorlopen van de boom volgens preorder public synchronized void preorderTraversal() { preorderHelper( root ); } // recursieve methode om de boom te doolopen volgens preorder private void preorderHelper( TreeNode node ) if ( node == null ) return; System.out.print( node.getData()+ " " ); // inhoud van de // knoop weergeven preorderHelper( node.getLeftNode()); //doorloop linker subboom preorderHelper(node.getRightNode());//doorloop rechter subboom Preorder– data weergeven, vervolgens doorloop linker subboom en als laatste doorloop rechter subboom

79 7. KLASSE Tree : postorder
// begin postorder traversal public synchronized void postorderTraversal() { postorderHelper( root ); } // recursive method to perform postorder traversal private void postorderHelper( TreeNode node ) { if ( node == null ) return; postorderHelper( node.getLeftNode()); //doorloop linker subboom postorderHelper(node.getRightNode());//doorloop rechter subboom System.out.print( node.getData() + " " ); // inhoud van de // knoop weergeven } } // einde klasse Tree Postorder – doorloop linker subboom, vervolgens doorloop rechter subboom en als laatste de data weergeven

80 7. KLASSE TreeTest ... public static void main( String args[] ) {
Tree tree = new Tree(); int value; // voeg 10 random getallen van 0-99 in de binare zoekboom for ( int i = 1; i <= 10; i++ ) { value = ( int ) ( Math.random() * 100 ); System.out.print( value + " " ); tree.insertNode( value ); } tree.preorderTraversal(); // doorlopen volgens preorder tree.inorderTraversal(); // doorlopen volgens inorder tree.postorderTraversal(); // doorlopen volgens postorder

81 uitvoer 7. KLASSE TreeTest Inserting the following values:
Preorder traversal Inorder traversal Postorder traversal 39 69 47 94 50 72 41 97 55 73


Download ppt "Hoofdstuk 20: GEGEVENSSTRUCTUREN."

Verwante presentaties


Ads door Google