Upload
phamdien
View
234
Download
0
Embed Size (px)
Citation preview
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 (2)
3
• 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.
Algoritmanalys (3)
4
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?
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?
5
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?
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
6 0, 1, 2, 3 ... 50, 75, 62, 68 ...
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;
9
(dvs. punkten!)
Analys ... (1)
10
public static int harrysAlgorithm(int number, int n) {
int guess = 0;
while (guess != number && guess < n){
guess = guess + 1;
}
return guess;
}
1
1+1+1=3
1+1=2
1
5*n
THarry(n) = 5*n + 2
Analys ... (2)
11
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) {
return mid; //wohoo!
}
if (mid < number) {
start = mid + 1;
} else {
end = mid - 1;
}
}
}
1 1 1 1+1+1=3 1
ej intressant (ej värstafall)
1
max(2,2)=2 endast en per varv
8 *
TAnna(n) = 8*log2(n) + 2
log2(n)
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
12
THarry(n) = 5*n + 2
TAnna(n) = 8*log2(n) + 2
Algoritm n = 10^6
5002 s ≈ 1 h 20 min
0,16 s
n = 10^9
0,24 s
ca 58 dagar
0
10
20
30
40
50
60
70
80
90
100
0 2 4 6 8 10 12 14 16 18 20
Jämförelse mellan analyser • Studera körtiden som en funktion över storleken på indata
• När är två algoritmer lika effektiva?
• När är en bättre än en annan?
13
THarry(n) = 5*n + 2
TAnna(n) = 8*log2(n) + 2
”Går som f(n)=n”
”Går som f(n)=log(n)”
Ordo(1) Definition:
• Givet två funktioner f(n) och g(n)
• Om det finns positiva konstanter c och n0 sådana att f(n) ≤ cg(n) för n ≥ n0
• (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 n0 )
• Då f(n) ∈ O(g(n)) (dvs. f(n) tillhör Ordo(g(n))
14
• Antagande: g(n) = n • 5n +2 ≤ cn • (c-5)n ≥ 2
• 𝑛 ≥2
𝑐−5
• låt c = 6, n0=2 => 5n + 2 ≤ 6n för n ≥ 2
=> THarry(n) ∈ O(n)
• Antagande: g(n) = n • 8log2(n) + 2 ≤ cn
•8
𝑐log2(n)) +
2
𝑐 ≤ n
• låt c = 8, n0=2 => 8log2(n) + 2 ≤ 8n för n ≥ 2
=>TAnna(n) ∈ O(n)
THarry(n) = 5*n + 2 TAnna(n) = 8*log2(n) + 2
Ordo(2)
• Båda algoritmerna tillhör O(n), tillhör de O(log(n))?
15
THarry(n) = 5*n + 2 TAnna(n) = 8*log2(n) + 2
• Antagande: g(n) = log2(n) • 5n +2 ≤ c log2(n)
•5𝑛
log2(n)+
2
log2(n)≤ c
• Håller inte för något c då
lim n -> ∞ (dominerande faktor)
=> THarry(n) ∉ O(log(n))
• Antagande: g(n) = log2(n) • 8log2(n) + 2 ≤ clog2(n) • 8log2(n) ≤ clog2(n) − 2
• 8 ≤ c −2
log2(n)
• låt c = 10, n0=2 => 8log2(n)+2 ≤ 10log2(n) för n ≥ 2
=>TAnna(n) ∈ O(log(n))
Sortering - Motivering
• Varför så mycket fokus på detta?
16
25% av datorns CPU-cykler spenderas på
sortering
Vanligt att ADT innehåller sorterade
datastrukturer.
Bra som fallstudie för algoritmanalys
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
• Tinsertionsort?
• Stabil? O(n2)
Ja 18
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);
}
}
21
Vanligtvis brukar man definiera sin egen
fönsterklass som ärver från JFrame, istället för
att ha en JFrame-variabel
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)
23
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 } }
Graphics(2)
• En Graphics kan ses som en pensel associerad till en viss rityta
Relaterade klasser:
24
setColor, setPen, setBrush, setFont
drawLine
drawRect, fillRect
drawOval, fillOval
drawImage
drawString
Color Representerar en 24 bitars färg
Pen Beskriver en penna: tjocklek, stil..
Font Beskriver typsnitt
JComponent
• Användbara metoder:
• Dimension getSize() – Ger komponentens nuvarande storlek
• void setPreferredSize(Dimension dim) – Sätter komponentens önskade storlek
• void repaint() – Be om utritning
25
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…