TDDC30 Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 5 Jonas Lindgren, Institutionen för Datavetenskap, LiU På denna föreläsning: Algoritmanalys, Ordo Sortering, Insertionsort Grafiska komponenter 1
Algoritmanalys Load the program into our high-tech system! Your algorithms are so slow 2
Algoritmanalys (2) Hur kan vi resonera om våra program när systemen som vi kör dem på är olika och hela tiden förändras? Vi får tänka oss en teoretisk dator som vi kör våra algoritmer på. Vi behöver verktyg för att kunna analysera algoritmerna. Vi behöver teoretiska mått på våra algoritmer som inte är knutna till hårdvara. 3
Algoritmanalys (3) public static void algorithm(int[] numbers) { int tmp; for (int i = 1; i < numbers.length; ++i) { for (int j = numbers.length; j >= i; ++j) { if (numbers[i] < numbers[j]) { tmp = numbers[i]; numbers[i] = numbers[j]; numbers[j] = tmp; Korrekt resultat? Ger den alltid en lösning? Hur snabb är den? Hur mycket extra minne kräver den? 4
Komplexitetsanalys Hur effektiv är algoritmen? I fråga om tid I fråga om extra minnesutrymme Med olika typer av indata Är det teoretiskt möjligt att konstruera en ännu effektivare algoritm för samma problem? Kommer dubbelt så mycket indata ge dubbelt så lång exekveringstid? Kommer dubbelt så mycket indata behöva dubbelt så mycket extra minne? Vad händer när indatat är sorterad? 5
Exempel två algoritmer Gissa talet: Givet att det rätta svaret ligger mellan 0 och n, gissa vilket nummer jag tänker på. Vid varje gissning svarar jag rätt, för stort eller för litet Försök få rätt svar på så få gissningar som möjligt 0, 1, 2, 3... 50, 75, 62, 68... 6
Komplexitetsteori Grundkrav: En algoritm ska fungera för indata av godtycklig storlek (n) Vi vill beräkna körtiden för algoritmen som en funktion av storleken på indata T(n) Fokusera på värsta fallet Ignorera konstanta faktorer Analysen ska vara maskinoberoende Kraftfulla maskiner ökar hastigheten med en konstant Vi tänker oss att vi kör algoritmen på vår teoretiska maskin Fokusera på dominerande faktorer vid stora indata Skalbarhet (asymptotiska beteendet) 7
Primitiva operationer På vår teoretiska maskin tar varje primitiv operation 1 enhet tid (alltid). T(n) blir antalet primitiva operationer som en funktion av storleken på indata 8
Primitiva operationer (2) Primitiva operationer: Tilldelning, t.ex. x = y; Metodanrop (endast själva anropet), ex. foo(); Aritmetiska operationer, ex. x+5; Jämförelser, t.ex. x < 5; Arrayindexeringar, t.ex. myarray[5]; Objektreferering, t.ex. myobject.name; Metodretur, t.ex. return 5; (dvs. punkten!) 9
Analys... (1) public static int harrysalgorithm(int number, int n) { int guess = 0; 1 while (guess!= number && guess < n){ 1+1+1=3 guess = guess + 1; 5*n 1+1=2 return guess; 1 T Harry (n) = 5*n + 2 10
Analys... (2) public static void annasalgorithm(int number, int n) { int start = 0; int end = n; while (start <= end) { int mid = (start+end)/2; if (mid == number) { 1 1 1 1+1+1=3 1 return mid; //wohoo! ej intressant (ej värstafall) if (mid < number) { 1 start = mid + 1; 8 * log 2 (n) else { endast en per varv max(2,2)=2 end = mid - 1; T Anna (n) = 8*log 2 (n) + 2 11
Jämförelse mellan analyser Spelar detta någon egentlig roll? Antag att vi skalar upp problemet, n = 1 000 000 = 10^6 Antag att varje primitv operation tar 1 millisekund = 10^-3 s Algoritm T Harry (n) = 5*n + 2 T Anna (n) = 8*log 2 (n) + 2 n = 10^6 5002 s 1 h 20 min 0,16 s n = 10^9 ca 58 dagar 0,24 s 12
Jämförelse mellan analyser Studera körtiden som en funktion över storleken på indata 100 När är två algoritmer lika effektiva? När är en bättre än en annan? 90 80 70 60 50 40 Går som f(n)=n T Harry (n) = 5*n + 2 Går som f(n)=log(n) 30 20 10 T Anna (n) = 8*log 2 (n) + 2 13 0 0 2 4 6 8 10 12 14 16 18 20
Ordo(1) Definition: Givet två funktioner f(n) och g(n) Om det finns positiva konstanter c och n 0 sådana att f(n) cg(n) för n n 0 (D.v.s. om man multiplicerar f(n) med någon konstant c, så håller sig f(n) under g(n) efter något n n 0 ) Då f(n) O(g(n)) (dvs. f(n) tillhör Ordo(g(n)) T Harry (n) = 5*n + 2 T Anna (n) = 8*log 2 (n) + 2 Antagande: g(n) = n 5n +2 cn (c-5)n 2 n 2 c 5 låt c = 6, n 0 =2 => 5n + 2 6n för n 2 => T Harry (n) O(n) Antagande: g(n) = n 8log 2 (n) + 2 cn 8 log c 2(n)) + 2 n c låt c = 8, n 0 =2 => 8log 2 (n) + 2 8n för n 2 =>T Anna (n) O(n) 14
Ordo(2) Båda algoritmerna tillhör O(n), tillhör de O(log(n))? T Harry (n) = 5*n + 2 T Anna (n) = 8*log 2 (n) + 2 Antagande: g(n) = log 2 (n) 5n +2 c log 2 (n) 5n log 2 (n) + 2 log 2 (n) c Håller inte för något c då lim n -> (dominerande faktor) Antagande: g(n) = log 2 (n) 8log 2 (n) + 2 clog 2 (n) 8log 2 (n) clog 2 (n) 2 2 8 c log 2 (n) låt c = 10, n 0 =2 => 8log 2 (n)+2 10log 2 (n) för n 2 => T Harry (n) O(log(n)) =>T Anna (n) O(log(n)) 15
Sortering - Motivering Varför så mycket fokus på detta? 25% av datorns CPUcykler spenderas på sortering Vanligt att ADT innehåller sorterade datastrukturer. Bra som fallstudie för algoritmanalys 16
Initiala problem Sortera ökande eller minskande? Svar: Enkelt problem, lätt att ändra algoritmen efteråt (byt ut < mot > ) Hur ska lika element hanteras? Går det bra att lika element byter plats? En stabil algoritm defineras som en som inte kommer att ha bytt inbördes plats mellan lika element efter sortering. Hur sorterar man bokstäver, djur, etc? Svar: Vi måste bestämma oss för hur vi jämför två element av dessa typer. I java: Implementera interfacet Comparable<E>, som innehåller en compareto-metod. 17
Insertionsort Strategi: Dela upp arrayen i en sorterad och en osorterad del Lägg successivt in varje osorterat element på rätt plats i den sorterade delen. Algoritm Ta ut det första elementet i den osorterade delen Skjut på de element som är större än det uttagna ett steg uppåt Sätt in elementet på den nu tomma platsen T insertionsort? Stabil? O(n 2 ) Ja 18
Grafiskt användargränssnitt Motivering För vanligt folk är följande inte ett program: 19
Grafiskt användargränssnitt(2) Fönster ser ut och konstrueras på olika sätt i olika operativsystem Java abstraherar bort detta med grafikpaketet Swing Swing ett uniformt sätt att skapa GUI Byggd ovanpå föregångaren AWT 20
Grafiskt användargränssnitt(3) Hur man får upp ett fönster: Vi använder JFrame import javax.swing.jframe; public class Main { public static void main(string[] args) { JFrame mywindow = new JFrame( Matrix GUI ); mywindow.setsize(300, 300); mywindow.setvisible(true); Vanligtvis brukar man definiera sin egen fönsterklass som ärver från JFrame, istället för att ha en JFramevariabel 21
Standardkomponenter public class Main { public static void main(string[] args) { String[] inpeople = { Neo, Trinity, Smith ; JList<String> inlist = new JList<>(inPeople); mywindow.add(inlist); mywindow.add(new JButton( Send into matrix )); mywindow.add(new JButton( Get out of matrix )); String[] outpeople = { Morpheus, Cypher, Switch ; JList<String> outlist = new JList<>(outPeople); mywindow.add(outlist); mywindow.setvisible(true); 22
Egna komponenter Problem: Ibland vill man inte använda standardkomponenter, utan behöver skapa något helt eget. Lösning: Skapa en egen komponent genom att ärva från JComponent Överskugga metoden paintcomponent(graphics g) public class Main { public static void main(string[] args) { mywindow.add(new MyPaintPanel()); public class MyPaintPanel extends JComponent { public void paintcomponent(graphics g)) g.drawline( // Kod som ritar ut 23
Graphics(2) En Graphics kan ses som en pensel associerad till en viss rityta setcolor, setpen, setbrush, setfont drawline drawrect, fillrect drawoval, filloval drawimage drawstring Relaterade klasser: Color Pen Font Representerar en 24 bitars färg Beskriver en penna: tjocklek, stil.. Beskriver typsnitt 24
JComponent Användbara metoder: Dimension getsize() Ger komponentens nuvarande storlek void setpreferredsize(dimension dim) Sätter komponentens önskade storlek void repaint() Be om utritning Vi ber systemets fönsterhanterare att rita ut. Systemet kommer sedan att anropa paintcomponent() på alla komponenter i rätt ordning. Eftersom komponenterna överskuggar metoden körs rätt utritningskod 25