Fronta (Queue) Úvod do programování Michal Krátký 1,Jiří Dvorský 1 1 Katedra informatiky VŠB Technická univerzita Ostrava Úvod do programování, 2004/2005 Fronta uplatňuje mechanismus přístupu FIFO first in, first out. Tj. jako první je z fronty odebrán prvek, který byl do fronty první vložen. Operace Put vložení prvku. Get odebrání prvku. Empty test na prázdnost fronty. Podtečení /přetečení fronty. c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 1/33 c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 2/33 Fronta implementace Fronta implementace pomocí pole 1/4 Pro implementaci fronty jsou potřeba dva ukazatele. Jeden ukazatel určuje hlavu fronty (head), začátek. Hlava ukazuje na prvek, který je na řadě pro odebrání. Druhým ukazatelem je ocas fronty (tail), konec. Tento ukazatel ukazuje na poslední prvek ve frontě. public class Queue int mdata[]; int mtail; public Queue(int capacity) mdata = new int[capacity]; mtail = -1; c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 3/33 c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 4/33 Fronta implementace pomocí pole 2/4 public boolean Put(int value) boolean ret = false; if (mtail < mdata.length-1) mdata[++mtail] = value; ret = true; return ret; c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 5/33 Fronta implementace pomocí pole 3/4 public int Get() if (mtail == -1) return -1; int value = mdata[0]; for (int i = 0 ; i < mtail ; i++) mdata[i] = mdata[i+1]; mtail--; return value; c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 6/33
Fronta implementace pomocí pole 4/4 Fronta Queue queue = new Queue(10); queue.put(10); // queue: 10 queue.put(20); // queue: 10,20 System.out.println(queue.Get()); // queue: 20 queue.put(30); // queue: 20, 30 System.out.println(queue.Get()); // queue: 30 Výstup: 10,20 c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 7/33 Problémy Složitost operace Get O(n). Řešení pomocí kruhové fronty. Dynamická fronta (implementace pomocí seznamu). Implementace pomocí zásobníku. Perzistentní fronta. Aplikace Vyrovnávací pamět. c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 8/33 Strukturované programovací jazyka (Pascal, C,...). Program: data + algoritmy. Uživatelsky definované datové typy (např. struktury v C++). Třída: zapouzdření dat. Metody pracují s členskými proměnnými instance třídy. c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 9/33 Zapouzdření. Kčlenským proměnným přistupujeme pomocí metod. Většina OOPJ umožňuje pracovat přímo s daty. Dědičnost znovupoužití proměnných a metod. B dědí z A, B můžeme použít tam kde je deklarováno A. Mnohotvárnost. Stejné jméno metody, různá implementace. public class Queue extends LinearDS int mtail; public Queue(int capacity) mdata = new int[capacity]; mtail = -1;... c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 10/33 Statické/členské prvky Ukazatel Členské metody a proměnné proměnné instance třídy, metody pracují s těmito proměnnými. Statické metody a proměnné není nutné vytvářet instanci třídy. Proměnné jsou sdíleny všemi instancemi třídy. public class IntNumber int mvalue; public static final int MIN_UINT = 0; public intvalue() return mvalue; // IntNumber in; in.intvalue(); public static int Add(int a, int b) return a + b; // int c = IntNumber.Add(1,3); c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 11/33 Ukazatel (pointer) neobsahuje data samotná, obsahuje adresu v paměti obsahující data. // C++ int *pa = &a; c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 12/33
Ukazatel - Java Ukazatel - C++ Primitivní vs. objektové datové typy. Set(a); // a = 60 public void Set(int b) b = 80; Set(&a); // a = 80 public void Set(int *pa) *pa = 80; c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 13/33 c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 14/33 Ukazatel - Java 1/3 Ukazatel - Java 2/3 Primitivní datové typy (int, float,...) jsou odkazovány hodnotou, pole a objektové datové typy pomocí ukazatelů. IntNumber value = new IntNumber(a); Set(value); a = value.intvalue(); // a = 80 public void Set(IntNumber val) val.setint(80); c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 15/33 Integer value=new Integer(a); Set(value); a = value.intvalue(); // a = 60 public void Set(Integer val) val = new Integer(80); c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 16/33 Ukazatel - Java 3/3 Seznam - list Integer value = new Integer(a); Integer []intarray = new Integer[1]; intarray[0] = value; Set(intArray); a = value.intvalue(); // a = 60 value = intarray[0]; a = value.intvalue(); // a = 80 public void Set(Integer []array) array[0] = new Integer(80); c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 17/33 Spojový seznam (linked list) je datová struktura, ve které jsou data uložena lineárním způsobem. Na rozdíl od pole, kde lineární uspořádání je určeno indexem pole, pořadí prvku v seznamu je určeno ukazateli mezi prvky seznamu. Spojový seznam umožňuje jednoduchou, pružnou reprezentaci (ovšem ne nutně efektivní) všech typických operací s dynamickými množinami. Prvek seznamu obsahuje ukazatel na další prvek (next). c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 18/33
Seznam - list Seznam implementace 1/6 Obousměrný spojový seznam prvek seznamu obsahuje ukazatel na předchozí (previous) a následující prvek (next). První prvek seznamu (hlava head): previous = NULL. Poslední prvek seznamu (ocas tail): next = NULL. Seznam: jednosměrný/obousměrný, setříděný/nesetříděný, cyklický/acyklický. c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 19/33 public class ListItem private ListItem mnext; private int mdata; public ListItem(int data) mdata = data; public void SetNext(ListItem item) mnext = item; c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 20/33 Seznam implementace 2/6 Seznam implementace 3/6 public ListItem GetNext() return mnext; public int GetData() return mdata; public class List ListItem mhead; public List() mhead = null; c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 21/33 c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 22/33 Seznam implementace 4/6 public void InsertFirst(int data) ListItem item = new ListItem(data); ListItem oldfirstitem = mhead; item.setnext(oldfirstitem); mhead = item; c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 23/33 Seznam implementace 5/6 public int Find(int data) ListItem item = mhead; for ( ; ; ) if (data == item.getdata()) return data; item = item.getnext(); if (item == null) break; return -1; c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 24/33
Seznam implementace 6/6 Seznam List list = new List(); for (int i = 0 ; i < 12 ; i++) list.insertfirst(i); list.print(); System.out.println(list.Find(1)); System.out.println(list.Find(12)); 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1-1 Problémy Složitost operace InsertFirst O(1). Složitost operace Find O(n). Implementace obousměrného cyklického seznamu. Implementace dynamického pole, zásobníku a fronty. Perzistentní seznam. c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 25/33 c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 26/33 Operace Insert O(1). Find O(n). Motivace Mějme databázi 10mil. záznamů o klientech bankovního ústavu. Našim úkolem je napsat algoritmus pro vyhledání nějakého klienta (např. František Novák), t = 1s. O(n) - provedeme 10 7 porovnání. Vyhledání záznamu by trvalo necelé 4 měsíce. O(log n) - provedeme log(10 7 )=7 porovnání. Vyhledání záznamu by tedy trvalo 7s. Množina, uspořádaná množina (prvek je porovnatelný se všemi prvky množiny, < Z, >). Uspořádání prvků umožní implementovat vyhledávání prvku algoritmem půlení intervalu s O(log n). c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 27/33 c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 28/33 Pole 1/4 public class SortedArray int mdata[]; int msize = 0; public SortedArray(int capacity) mdata = new int[capacity]; msize = 0; Pole 2/4 public void Insert(int value) int order = 0; for ( ; order < msize ; order++) if (value <= mdata[order]) break; for (int i = msize-1; i >= order ; i--) mdata[i+1] = mdata[i]; mdata[order] = value; msize++; // capacity overflow? c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 29/33 c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 30/33
Pole 3/4 public int Find(int value) int lo = 0, hi = msize, order; do order = (lo + hi)/2; // 1,5,10,25,36,78; 12 if (value < mdata[order]) hi = order-1; else if (value > mdata[order]) lo = order+1; else return order; while (lo <= hi); return -1; c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 31/33 Pole 4/4 SortedArray sortedarray = new SortedArray(10); sortedarray.insert(90); for (int i = 0 ; i < 8 ; i++) int value = (int)(math.random() * 100); sortedarray.insert(value); sortedarray.insert(value); queue.sortedarray.print(); System.out.println(sortedArray.Find(90)); System.out.println(sortedArray.Find(100)); Výstup: 5, 40, 58, 58, 67, 76, 89, 90, 98, 7-1 c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 32/33 Složitost Insert O(n). Find O(log n). Problémy Lepší složitost pro nalezení indexu při vložení prvku použití binárního vyhledávání. Možné velké přesuny dat při vkládání stromové datové struktury. c 2005 Michal Krátký, Jiří Dvorský Úvod do programování 33/33