Datové struktury obsah přednášky 1. Úvod 2. Třídy Type-wrapper (obalový typ) pro primitivní typy automatické převody 3. Automatické převody mezi primitivními a obalovými typy 4. Třídy odkazující sama na sebe (self referential) 5. Dynamické přidělování paměti 6. Spojové seznamy 7. Zásobníky 8. Fronty 9. Stromy 1
Úvod 2 statické datové struktury typ array, jedno vícerozměrné spojové seznamy kolekce dat, kde rozšíření / zmenšení seznamu, je provedeno kdykoli za běhu programu
Třídy Type-Wrapper pro primitivní typy (obalový typ) 3 primitivní typy a objektové typy na primitivní typy se nedá odkazovat referencí každý primitivní typ má odpovídající třídu type wrapper obalovou třídu v balíčku (java.lang) třídy type-wrapper jsou: Boolean, Byte, Character, Double, Float, Integer, Long, Short třídy type wrapper (obalové třídy) nemohou manipulovat s proměnnými primitivních typů jako s objekty, ale dovolují manipulovat s objekty typových obalových tříd
Třídy Type-Wrapper pro primitivní typy (obalový typ) 4 Každá z type wrapper tříd (obalových tříd) je podtřídou třídy Number třídy type wrapper jsou final třídy, nemohou mít podtřídy (extends)
Automatické převody mezi primitivními a obalovými typy 5 třídy type wrapper jsou nutné pro ukládání primitivních typů do kolekcí předchozí verze Javy Integer[] integerarray = new Integer[5]; integerarray[0] = new Integer(10); int value = integerarray[0].intvalue(); Java verze 5.0 Integer[] integerarray = new Integer[5]; integerarray[0] = 10; int value = integerarray[0];
// drivejsi prirazeni public static void drive() int i2 = 12; Integer ctyri = new Integer(2 * i2); int i6 = 2*ctyri.intValue ctyri.intvalue();... } Osnova 6 public static void nyni() int i2 = 2; Integer ctyri = 2 * i2; int i6 = 2 + ctyri;... }
Třídy Self Referential (třídy odkazující se na své prvky) obsahují objekt, který odkazuje na jiný objekt stejné třídy class Node private int data; //datovy atribut private Node nextnode; //referencni atribut 7 public Node(int data) // konstruktor public void setdata(int data) //metody - datove atributy public int getdata() public void setnext( Node next) //metody ref. atributy public Node getnext() }
Třídy odkazující se sami na sebe 8 15 10 Self-referential-class objects spojené k sobě
Dynamické přidělení paměti 9 vytváření a manipulace s dynamickými datovými strukturami vyžaduje dynamické přidělení paměti schopnost programu získat za běhu programu paměťový prostor a posléze ho uvolnit (není-li třeba) Java automaticky čistí paměť od již nepotřebných objektů (nejsou na ně odkazy) Node nodetoadd = new Node(10);
Spojové seznamy 10 Spojový seznam Lineární kolekce samoodkazujících tříd (uzlů) Propojení pomocí odkazů Uzly mohou být vkládány nebo rušeny kdekoli ve spojovém seznamu Poslední uzel ukazuje na null (k označení konce seznamu)
Spojové seznamy 11 firstnode lastnode... H D Q Spojový seznam grafická reprezentace
// ListNode and List class definitions. // class to represent one node in a list class ListNode // package access members; List can access these directly Object data; //datovy atribut ListNode nextnode; // referencni atribut Osnova 12 Třída ListNode // constructor creates a ListNode that refers to object ListNode( Object object ) this( object, null ); } // end ListNode one-argument constructor // constructor creates ListNode that refers to // Object and to next ListNode ListNode( Object object, ListNode node ) data = object; nextnode = node; } // end ListNode two-argument constructor // return reference to data in node Object getobject() return data; // return Object in this node } // end method getobject
// return reference to next node in list ListNode getnext() return nextnode; // get next node } // end method getnext } // end class ListNode Osnova 13 // class List definition public class List private ListNode firstnode; private ListNode lastnode; private String name; // string like "list" used in printing // constructor creates empty List with "list" as the name public List() this( "list" ); } // end List no-argument constructor // constructor creates an empty List with a name public List( String listname ) name = listname; firstnode = lastnode = null; } // end List one-argument constructor
// insert Object at front of List public void insertatfront( Object insertitem ) if ( isempty() ) // firstnode and lastnode refer to same object firstnode = lastnode = new ListNode( insertitem ); else // firstnode refers to new node firstnode = new ListNode( insertitem, firstnode ); } // end method insertatfront Osnova 14 // insert Object at end of List public void insertatback( Object insertitem ) if ( isempty() ) // firstnode and lastnode refer to same Object firstnode = lastnode = new ListNode( insertitem ); else // lastnode's nextnode refers to new node lastnode = lastnode.nextnode = new ListNode( insertitem ); } // end method insertatback // remove first node from List public Object removefromfront() throws EmptyListException if ( isempty() ) // throw exception if List is empty throw new EmptyListException( name ); Object removeditem = firstnode.data; // retrieve data being removed
// update references firstnode and lastnode if ( firstnode == lastnode ) firstnode = lastnode = null; else firstnode = firstnode.nextnode nextnode; Osnova 15 return removeditem; // return removed node data } // end method removefromfront // remove last node from List public Object removefromback() throws EmptyListException if ( isempty() ) // throw exception if List is empty throw new EmptyListException( name ); Object removeditem = lastnode.data; // retrieve data being removed // update references firstnode and lastnode if ( firstnode == lastnode ) firstnode = lastnode = null; else // locate new last node ListNode current = firstnode; // loop while current node does not refer to lastnode while ( current.nextnode nextnode!= lastnode ) current = current.nextnode nextnode; lastnode = current; // current is new lastnode current.nextnode nextnode = null; } // end else
return removeditem; // return removed node data } // end method removefromback Osnova 16 // determine whether list is empty public boolean isempty() return firstnode == null; // return true if List is empty } // end method isempty // output List contents public void print() if ( isempty() ) System.out out.printf printf( "Empty" %s\n", name ); return; } // end if System.out out.printf printf( "The" %s is: ", name ); ListNode current = firstnode; // while not at end of list, output current node's data while ( current!= null ) System.out out.printf printf( "%s ", current.data ); current = current.nextnode nextnode; } // end while System.out out.println println( "\n"" ); } // end method print } // end class List
// Class EmptyListException definition. public class EmptyListException extends RuntimeException // no-argument constructor public EmptyListException() this( "List" ); // call other EmptyListException constructor } // end EmptyListException no-argument constructor Osnova 17 Třída EmptyException // one-argument constructor public EmptyListException( String name ) super( name + " is empty" ); // call superclass constructor } // end EmptyListException one-argument constructor } // end class EmptyListException
// ListTest class to demonstrate List capabilities. public class ListTest public static void main( String args[] ) List list = new List(); // create the List container Osnova 18 Třída ListTest // insert integers in list list.insertatfront insertatfront( -1 ); list.print print(); list.insertatfront insertatfront( 0 ); list.print print(); list.insertatback insertatback( 1 ); list.print print(); list.insertatback insertatback( 5 ); list.print print(); // remove objects from list; print after each removal try Object removedobject = list.removefromfront removefromfront(); System.out out.printf printf( "%s removed\n", removedobject ); list.print print(); removedobject = list.removefromfront removefromfront(); System.out out.printf printf( "%s removed\n", removedobject ); list.print print();
removedobject = list.removefromback removefromback(); System.out out.printf printf( "%s removed\n", removedobject ); list.print print(); Osnova 19 removedobject = list.removefromback removefromback(); System.out out.printf printf( "%s removed\n", removedobject ); list.print print(); } // end try catch ( EmptyListException emptylistexception ) emptylistexception.printstacktrace printstacktrace(); } // end catch } // end main } // end class ListTest
The list is: -1 The list is: 0-1 Osnova 20 The list is: 0-1 1 The list is: 0-1 1 5 0 removed The list is: -1 1 5-1 removed The list is: 1 5 5 removed The list is: 1 1 removed Empty list
Spojové seznamy 21 (a) firstnode 7 11 new Listnode 12 (b) firstnode 7 11 new Listnode 12
Spojové seznamy 22 (a) firstnode lastnode new Listnode 12 7 11 5 (b) firstnode lastnode new Listnode 12 7 11 5
Spojové seznamy 23 (a) firstnode lastnode 12 7 11 5 (b) firstnode lastnode 12 7 11 5 removeitem
Spojové seznamy 24 (a) firstnode lastnode 12 7 11 5 (b) firstnode lastnode 12 7 11 5 removeitem
Zásobníky - stacks 25 Zásobník Omezená verze spojového seznamu Přidává a odstraňuje uzly pouze z vrcholu zásobníku Metoda push přidává uzel na vrchol zásobníku Metoda pop odstraňuje uzel z vrcholu zásobníku
// Derived from class List. public class StackInheritance extends List // no-argument constructor public StackInheritance() super( "stack " stack" ); } // end StackInheritance no-argument constructor Osnova 26 Zásobník dědičnost // add object to stack public void push( Object object ) insertatfront( object ); } // end method push // remove object from stack public Object pop() throws EmptyListException return removefromfront(); } // end method pop } // end class StackInheritance
// Class StackInheritanceTest. import com.deitel deitel.jhtp6.ch17..jhtp6.ch17.stackinheritance StackInheritance; import com.deitel deitel.jhtp6.ch17..jhtp6.ch17.emptylistexception EmptyListException; public class StackInheritanceTest public static void main( String args[] ) StackInheritance stack = new StackInheritance(); Osnova 27 Třída ZasobnikTest // use push method stack.push push( -1 ); stack.print print(); stack.push push( 0 ); stack.print print(); stack.push push( 1 ); stack.print print(); stack.push push( 5 ); stack.print print(); // remove items from stack try Object removedobject = null;
while ( true ) removedobject = stack.pop(); // use pop method System.out out.printf printf( "%s popped\n", removedobject ); stack.print print(); } // end while } // end try catch ( EmptyListException emptylistexception ) emptylistexception.printstacktrace printstacktrace(); } // end catch } // end main } // end class StackInheritanceTest Osnova 28
The stack is: -1 The stack is: 0-1 Osnova 29 The stack is: 0 0-1 The stack is: 5 1 0-1 5 popped The stack is: 1 0-1 1 popped The stack is: 0-1 0 popped The stack is: -1-1 popped Empty stack struktury.emptylistexception: : stack is empty at struktury.list.removefromfront(list.java:79) at struktury.stackinheritance.pop(stackinheritance.java:20) at struktury.stackinheritancetest.main (StackInheritanceTest.java:26)
// Class StackComposition definition with composed List object. public class StackComposition private List stacklist; //datovy atribut seznam Osnova 30 Zásobník skládání // no-argument constructor public StackComposition() stacklist = new List( "stack" stack" ); } // end StackComposition no-argument constructor // add object to stack public void push( Object object ) stacklist.insertatfront insertatfront( object ); } // end method push // remove object from stack public Object pop() throws EmptyListException return stacklist.removefromfront removefromfront(); } // end method pop // determine if stack is empty public boolean isempty() return stacklist.isempty isempty(); } // end method isempty
// output stack contents public void print() stacklist.print print(); } // end method print } // end class StackComposition Osnova 31
Fronty queues 32 Fronta Podobná frontě ze supermarketu u pokladny Uzly jsou vkládány pouze na konec (tail) Metoda enqueue Uzly jsou odstraňovány z čela fronty (head of the front) Metoda dequeue
// Class Queue. public class Queue private List queuelist; // datovy atribut seznam Osnova 33 Fronta skládání // no-argument constructor public Queue() queuelist = new List( "queue" queue" ); } // end Queue no-argument constructor // add object to queue public void enqueue( Object object ) queuelist.insertatback insertatback( object ); } // end method enqueue // remove object from queue public Object dequeue() throws EmptyListException return queuelist.removefromfront removefromfront(); } // end method dequeue // determine if queue is empty public boolean isempty() return queuelist.isempty isempty(); } // end method isempty
// output queue contents public void print() queuelist.print print(); } // end method print } // end class Queue Osnova 34
// Class QueueTest. import com.deitel deitel.jhtp6.ch17..jhtp6.ch17.queue Queue; import com.deitel deitel.jhtp6.ch17..jhtp6.ch17.emptylistexception EmptyListException; public class QueueTest public static void main( String args[] ) Queue queue = new Queue(); Osnova 35 Třída FrontaTest // use enqueue method queue.enqueue enqueue( -1 ); queue.print print(); queue.enqueue enqueue( 0 ); queue.print print(); queue.enqueue enqueue( 1 ); queue.print print(); queue.enqueue enqueue( 5 ); queue.print print();
// remove objects from queue try Object removedobject = null; Osnova 36 while ( true ) removedobject = queue.dequeue dequeue(); // use dequeue method System.out out.printf printf( "%s dequeued\n", removedobject ); queue.print print(); } // end while } // end try catch ( EmptyListException emptylistexception ) emptylistexception.printstacktrace printstacktrace(); } // end catch } // end main } // end class QueueTest
The queue is: -1 Osnova 37 The queue is: -1 0 The queue is: true -1 0 1 The queue is: -1 0 1 5-1 dequeued The queue is: 0 1 5 0 dequeued The queue is: 1 5 1 dequeued The queue is: 5 5 dequeued Empty queue struktury.emptylistexception: : queue is empty at struktury.list.removefromfront(list.java:79) at struktury.queue.dequeue(queue.java:22) at struktury.queuetest.main(queuetest.java:26)
Stromy trees 38 Strom Nelineární, dvoudimenzionální datová struktura se speciálními vlastnostmi (spojové seznamy, zásobníky, fronty jsou lineární datové struktury) Uzly stromu obsahují dva nebo více odkazů (referencí) Kořenový uzel (Root node) je první uzel (počátek) Každá reference odkazuje na dítě (child) Levé dítě je prvním uzlem v levém podstromu (subtree) Pravé dítě je prvním uzlem v pravém podstromu Děti v uzlech se nazývají sourozenci (siblings) Uzly, které nemají pokračování (děti) jsou uzly listů (leaf nodes)
Stromy - pokračování 39 Binary search tree Speciálnířazení uzlů bez duplikátů (hodnot uzlů) Hodnoty v levých podstromech jsou menší než hodnoty v pravých podstromech Inorder traversal - průchod Prochází levý podstrom, získá hodnotu uzlu, prochází pravý podstrom Preorder traversal - průchod Získá datový atribut uzlu, prochází levý podstrom, prochází pravý podstrom Postorder traversal - průchod Prochází levý podstrom, prochází pravý podstrom, získá datový atribut (hodnotu) uzlu
Stromy - pokračování 40 B A D C Binární strom grafická reprezentace.
Stromy - pokračování 41 47 25 77 11 43 65 93 7 17 31 44 68 Binary search tree obsahující 12 hodnot.
// Definition of class TreeNode and class Tree. Osnova 42 // class TreeNode definition class TreeNode // package access members TreeNode leftnode; // left node int data; // node value TreeNode rightnode; // right node // constructor initializes data and makes this a leaf node public TreeNode( int nodedata ) data = nodedata; leftnode = rightnode = null; // node has no children } // end TreeNode no-argument constructor // locate insertion point and insert new node; ignore duplicate values public 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 ); } // end if
else if ( insertvalue > data ) // insert in right subtree // insert new TreeNode if ( rightnode == null ) rightnode = new TreeNode( insertvalue ); else // continue traversing right subtree rightnode.insert( insertvalue ); } // end else if } // end method insert } // end class TreeNode Osnova 43 // class Tree definition public class Tree private TreeNode root; // constructor initializes an empty Tree of integers public Tree() root = null; } // end Tree no-argument constructor // insert a new node in the binary search tree public void insertnode( int insertvalue ) if ( root == null ) root = new TreeNode( insertvalue ); // create the root node here else root.insert( insertvalue ); // call the insert method } // end method insertnode
// begin preorder traversal public void preordertraversal() preorderhelper( root ); } // end method preordertraversal Osnova 44 // recursive method to perform preorder traversal private void preorderhelper( TreeNode node ) if ( node == null ) return; System.out out.printf printf( "%d ", node.data ); // output node data preorderhelper( node.leftnode ); // traverse left subtree preorderhelper( node.rightnode ); // traverse right subtree } // end method preorderhelper // begin inorder traversal public void inordertraversal() inorderhelper( root ); } // end method inordertraversal
// recursive method to perform inorder traversal private void inorderhelper( TreeNode node ) if ( node == null ) return; Osnova 45 inorderhelper( node.leftnode ); // traverse left subtree System.out out.printf printf( "%d ", node.data ); // output node data inorderhelper( node.rightnode ); // traverse right subtree } // end method inorderhelper // begin postorder traversal public void postordertraversal() postorderhelper( root ); } // end method postordertraversal // recursive method to perform postorder traversal private void postorderhelper( TreeNode node ) if ( node == null ) return; postorderhelper( node.leftnode ); // traverse left subtree postorderhelper( node.rightnode ); // traverse right subtree System.out out.printf printf( "%d ", node.data ); // output node data } // end method postorderhelper } // end class Tree
// This program tests class Tree. import java.util util.random Random; public class TreeTest public static void main( String args[] ) Tree tree = new Tree(); int value; Random randomnumber = new Random(); Osnova 46 Třída TreeTest System.out out.println println( "Inserting" the following values: " ); // insert 10 random integers from 0-99 in tree for ( int i = 1; i <= 10; i++ ) value = randomnumber.nextint nextint( 100 ); System.out out.print print( value + " " ); tree.insertnode insertnode( value ); } // end for System.out out.println ( "\n\npreorder" npreorder traversal" ); tree.preordertraversal preordertraversal(); // perform preorder traversal of tree System.out out.println ( "\n\ninorder" ninorder traversal" ); tree.inordertraversal inordertraversal(); // perform inorder traversal of tree
System.out out.println ( "\n\npostorder" npostorder traversal" ); tree.postordertraversal postordertraversal(); // perform postorder traversal of tree System.out out.println println(); } // end main } // end class TreeTest Osnova 47 Inserting the following values: 92 73 77 16 30 30 94 89 26 80 Preorder traversal 92 73 16 30 26 77 89 80 94 Inorder traversal 16 26 30 73 77 80 89 92 94 Postorder traversal 26 30 16 80 89 77 73 94 92 System.out.println ( "\n\npostorder traversal" ); tree.postorertraversal(); // perform postorder traversal of tree System.out.println(); } // end main } // end class TreeTest