Upload
hadat
View
214
Download
0
Embed Size (px)
Citation preview
Programmering för språkteknologer II, HT2014
Avancerad programmering för språkteknologer, HT2014
[email protected] 9-2035http://stp.ling.uu.se/~evelina/uv/uv14/pst2/
4
Sökalgoritmer – Vad är sökning?
- Hitta ett värde i en samling, till exempel i en array
- Returvärden: om värdet finns: det index värdet finns i om värdet inte finns: -1
- Algoritmer: om samling är osorterad: linjär sökning om samling är sorterad: binär sökning
5
Algoritm- och komplexitsteori
Algoritm Instruktioner som steg för steg beskriver hur man löser ett givet problem.
Pseudokod Beskrivning av en algoritm, påminner om kod som innehåller naturligt språk och/eller matematiska formler.
Tidskomplexitet Talar om hur lång tid algoritmen behöver för att lösa problemet
Minneskomplexitet Talar om hur mycket minne algoritmen behöver för för att lösa problemet.
6
Algoritm- och komplexitsteori
Algoritm Instruktioner som steg för steg beskriver hur man löser ett givet problem.
Pseudokod Beskrivning av en algoritm, påminner om kod som innehåller naturligt språk och/eller matematiska formler.
Exempel: linearSearch(array, target) FOR EACH i FROM 0 TO array.length - 1 IF(array[i] = target) THEN RETURN i;
RETURN -1;
7
Översätta pseudokod till JAVA
Exempel: linearSearch(array, target) FOR EACH i FROM 0 TO array.length - 1 IF(array[i] = target) THEN RETURN i;
RETURN -1;
int linearSearch(int array[], int target) {
}
8
Översätta pseudokod till JAVA
Exempel: linearSearch(array, target) FOR EACH i FROM 0 TO array.length - 1 IF(array[i] = target) THEN RETURN i;
RETURN -1;
int linearSearch(int array[], int array) { for(int i = 0; i < array.length; i++) { }
}
9
Översätta pseudokod till JAVA
Exempel: linearSearch(array, target) FOR EACH i FROM 0 TO array.length - 1 IF(array[i] = target) THEN RETURN i;
RETURN -1;
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) }
}
10
Översätta pseudokod till JAVA
Exempel: linearSearch(array, target) FOR EACH i FROM 0 TO array.length - 1 IF(array[i] = target) THEN RETURN i;
RETURN -1;
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
}
11
Översätta pseudokod till JAVA
Exempel: linearSearch(array, target) FOR EACH i FROM 0 TO array.length - 1 IF(array[i] = target) THEN RETURN i;
RETURN -1;
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
12
Översätta pseudokod till JAVA
Exempel: linearSearch(array, target) FOR EACH i FROM 0 TO array.length - 1 IF(array[i] = target) THEN RETURN i;
RETURN -1;
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
13
Linjär sökning
Huvudidé: Gå igenom samlingen tills man gjort en träff ellersamlingen är slut.
Användning: Används på osorterade samlingar.
14
Linjär sökning
Sök efter siffra 5 i arrayen.
8 4 1 5 7 2 3 6
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
15
Linjär sökning
Sök efter siffra 5 i arrayen.
8 4 1 5 7 2 3 6
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
16
Linjär sökning
Sök efter siffra 5 i arrayen.
8 4 1 5 7 2 3 6
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
17
Linjär sökning
Sök efter siffra 5 i arrayen.
8 4 1 5 7 2 3 6
8 == 5?
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
18
Linjär sökning
Sök efter siffra 5 i arrayen.
8 4 1 5 7 2 3 6
8 == 5? Nej
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
19
Linjär sökning
Sök efter siffra 5 i arrayen.
8 4 1 5 7 2 3 6
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
20
Linjär sökning
Sök efter siffra 5 i arrayen.
8 4 1 5 7 2 3 6
4 == 5?
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
21
Linjär sökning
Sök efter siffra 5 i arrayen.
8 4 1 5 7 2 3 6
4 == 5? Nej
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
22
Linjär sökning
Sök efter siffra 5 i arrayen.
8 4 1 5 7 2 3 6
1 == 5?
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
23
Linjär sökning
Sök efter siffra 5 i arrayen.
8 4 1 5 7 2 3 6
1 == 5? Nej
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
24
Linjär sökning
Sök efter siffra 5 i arrayen.
8 4 1 5 7 2 3 6
5 == 5?
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
25
Linjär sökning
Sök efter siffra 5 i arrayen.
8 4 1 5 7 2 3 6
5 == 5? Ja
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
26
Tidskomplexitet
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
- Varje jämförelse (array[i] == target) kostar 1
27
Tidskomplexitet
int linearSearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; }
return -1;}
- Varje jämförelse (array[i] == target) kostar 1
- I värsta fall behöver vi jämföra alla celler i array, dvs array.length = n gånger.
28
Tidskomplexitet – I värsta fall
1 – kostnad för en jämförelse (array[i] == target)
n – arrayens längd (array.length)
Tidskomplexitet i värsta fall:
Kallas för linjär komplexitet.
T=1⋅n≈O (n)
29
Linjär sökning – Tidskomplexitet
Fall Tidskomplexitet Kommentar
I värsta fall: Det sökta värdet finns inte i samlingen
I genomsnitt:
I bästa fall: Det sökta värdet finns i den första platsen I arrayen
O (n)
O (n)
O (1)
36
Exempel:
Sök efter talet 2.
1 2 3 4 5 6 7 8 9
Binär sökning
2
(Array[(0+3+1)/2] =Array[2] = 3) == 2 ?
37
Exempel:
Sök efter talet 2.
1 2 3 4 5 6 7 8 9
Binär sökning
2
(Array[(0+3+1)/2] =Array[2] = 3) == 2 ? Nej
38
Exempel:
Sök efter talet 2.
1 2 3 4 5 6 7 8 9
Binär sökning
2
(Array[(0+3+1)/2] =Array[2] = 3) == 2 ? Nej
3 > 2 ?
39
Exempel:
Sök efter talet 2.
1 2 3 4 5 6 7 8 9
Binär sökning
2
(Array[(0+3+1)/2] =Array[2] = 3) == 2 ? Nej
3 > 2 ? Ja
40
Exempel:
Sök efter talet 2.
1 2 3 4 5 6 7 8 9
Binär sökning
2
(Array[(0+1+1)/2] =Array[1] =2) == 2 ?
41
Exempel:
Sök efter talet 2.
1 2 3 4 5 6 7 8 9
Binär sökning
2
(Array[(0+1+1)/2] =Arra[1] =2) == 2 ? Ja
Returnera index 1
42
Binär sökning
Huvudidé:- Titta på datan i den mittersta cellen. Om den är lika med den data vi letar efter → returnera positionen Om den är större än den data vi letar efter → leta i den vänstra halvan Om den är mindre än den data vi letar efter → leta i den högra halvan
Användning: Används på sorterade samlingar.
43
Binär sökning – Skapa pseudokod
Huvudidé:- Titta på datan i den mittersta cellen. Om den är lika med den data vi letar efter → returnera positionen Om den är större än den data vi letar efter → leta i den vänstra halvan Om den är mindre än den data vi letar efter → leta i den högra halvan Pseudokod:int binarySearch(array, target)
44
Binär sökning – Skapa pseudokod
Huvudidé:- Titta på datan i den mittersta cellen. Om den är större än den data vi letar efter → leta i den vänstra halvan
Om den är mindre än den data vi letar efter → leta i den högra halvan
Om den är lika med den data vi letar efter → returnera positionen Pseudokod:int binarySearch(array, target) low = 0 high = array.length - 1 mid = (low + high + 1) / 2
45
Binär sökning – Skapa pseudokod
Huvudidé: Om den är större än den data vi letar efter → leta i den vänstra halvan
Om den är mindre än den data vi letar efter → leta i den högra halvan
Om den är lika med den data vi letar efter → returnera positionen Pseudokod:int binarySearch(array, target) low = 0 high = array.length - 1 mid = (low + high + 1) / 2 IF array[mid] > target THEN high = mid – 1
46
Binär sökning – Skapa pseudokod
Huvudidé: Om den är mindre än den data vi letar efter → leta i den högra halvan Om den är lika med den data vi letar efter → returnera positionen Pseudokod:int binarySearch(array, target) low = 0 high = array.length - 1 mid = (low + high + 1) / 2 IF array[mid] > target THEN high = mid – 1 IF array[mid] < target THEN low = mid
47
Binär sökning – Skapa pseudokod
Huvudidé: Om den är lika med den data vi letar efter → returnera positionen Pseudokod:int binarySearch(array, target) low = 0 high = array.length mid = (low + high + 1) / 2 IF array[mid] > target THEN high = mid – 1 IF array[mid] < target THEN low = mid IF array[low] = target THEN RETURN low ELSE RETURN -1
48
Binär sökning – Skapa pseudokod
Detta fungerar för ett steg, vi behöver även loopa. Pseudokod:int binarySearch(array, target) low = 0 high = array.length WHILE(high – low > 0) mid = (low + high + 1) / 2 IF array[mid] > target THEN high = mid – 1 IF array[mid] < target THEN low = mid
IF array[low] = target THEN RETURN low ELSE RETURN -1
49
Binär sökning – Skapa pseudokod
Justera IF-satserna Pseudokod:int binarySearch(array, target) low = 0 high = array.length WHILE(high – low > 0) mid = (low + high + 1) / 2 IF array[mid] > target THEN high = mid – 1 ELSE low = mid IF array[low] = target THEN RETURN low ELSE RETURN -1
50
Binär sökning – Översätt till Java Pseudokod:int binarySearch(array, target) low = 0 high = array.length WHILE(high – low > 0) mid = (low + high + 1) / 2 IF array[mid] > target THEN high = mid – 1 ELSE low = mid IF array[low] = target THEN RETURN low ELSE RETURN -1
int binarySearch(int array[], int target)
51
Binär sökning – Översätt till Java Pseudokod:int binarySearch(array, target) low = 0 high = array.length - 1 WHILE (high – low > 0) mid = (low + high + 1) / 2 IF array[mid] > target THEN high = mid – 1 ELSE low = mid IF array[low] = target THEN RETURN low ELSE RETURN -1
int binarySearch(int array[], int target) int low = 0; int high = array.length - 1;
52
Binär sökning – Översätt till Java Pseudokod: WHILE (high – low > 0) mid = (low + high + 1) / 2 IF array[mid] > target THEN high = mid – 1 ELSE low = mid IF array[low] = target THEN RETURN low ELSE RETURN -1
int binarySearch(int array[], int target) { int low = 0; int high = array.length – 1; while (high – low > 0){
}}
53
Binär sökning – Översätt till Java Pseudokod: mid = (low + high + 1) / 2 IF array[mid] > target THEN high = mid – 1 ELSE low = mid IF array[low] = target THEN RETURN low ELSE RETURN -1
int binarySearch(int array[], int target) { int low = 0; int high = array.length – 1; while (high – low > 0){ int mid = (low + hight + 1)/ 2; }}
54
Binär sökning – Översätt till Java Pseudokod: IF array[mid] > target THEN high = mid – 1 ELSE low = mid IF array[low] = target THEN RETURN low ELSE RETURN -1
int binarySearch(int array[], int target) { int low = 0; int high = array.length – 1; while (high – low > 0){ int mid = (low + hight + 1)/ 2; if(array[mid] > target) high = mid–1; else low = mid; }}
55
Binär sökning – Översätt till Java Pseudokod: IF array[low] = target THEN RETURN low ELSE RETURN -1
int binarySearch(int array[], int target) { int low = 0; int high = array.length – 1; while (high – low > 0){ int mid = (low + hight + 1)/ 2; if(array[mid] > target) high = mid–1; else low = mid; }
if(array[low] = target) return low; else return -1; }
56
Binär sökning – koden i Java int binarySearch(int array[], int target) { int low = 0; int high = array.length – 1; while (high – low > 0){ int mid = (low + hight + 1)/ 2; if(array[mid] > target) high = mid–1; else low = mid; }
if(array[low] = target) return low; else return -1; }
57
Binär sökning – Rekursiv variant Pseudokoden innan loopen:int binarySearch(array, target) low = 0 high = array.length mid = (low + high + 1) / 2 IF array[mid] > target THEN high = mid – 1 IF array[mid] <= target THEN low = mid IF array[low] = target THEN RETURN low ELSE RETURN -1
58
Binär sökning – Rekursiv variant Börja med att hitta basfallet, dvs när lösningen är enkel och vi kan därför stanna.
Pseudokod:int binarySearch(array, target) low = 0 high = array.length mid = (low + high + 1) / 2 IF array[mid] > target THEN high = mid – 1 IF array[mid] <= target THEN low = mid // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
59
Binär sökning – Rekursiv variant Leta efter rekursionsstegen, dvs vad gör vi om vi inte är i basfallet.
Pseudokod:int binarySearch(array, target, low, high) low = 0 high = array.length mid = (low + high + 1) / 2 //REKURSIONSSTEG IF array[mid] > target THEN binarySearch(array, target, low, mid -1) IF array[mid] <= target THEN low = mid // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
60
Binär sökning – Rekursiv variant Leta efter rekursionsstegen, dvs vad gör vi om vi inte är i basfallet.
Pseudokod:int binarySearch(array, target, low, high) low = 0 high = array.length mid = (low + high + 1) / 2 //REKURSIONSSTEG IF array[mid] > target THEN binarySearch(array, target, low, mid -1)
//REKURSIONSSTEG IF array[mid] <= target THEN binarySearch(array, target, mid, high) // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
61
Binär sökning – Rekursiv variant Städa pseudokoden.
Pseudokod:int binarySearch(array, target, low, high) //REKURSIONSSTEG IF array[mid] > target THEN binarySearch(array, target, low, mid -1) //REKURSIONSSTEG IF array[mid] <= target THEN binarySearch(array, target, mid, high)
// BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
62
Binär sökning – Rekursiv variant Lägg till if-sats så vi vet när vi ska använda basfall och rekursionssteg.Pseudokod:int binarySearch(array, target, low, high) IF (high – low > 0) THEN mid = (low + high +1) / 2 //REKURSIONSSTEG IF array[mid] > target THEN binarySearch(array, target, low, mid -1) //REKURSIONSSTEG IF array[mid] <= target THEN binarySearch(array, target, mid, high) ELSE // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
63
Binär sökning – Rekursiv variant Förfina if-satserna i pseudokoden.Pseudokod:int binarySearch(array, target, low, high) IF (high – low > 0) THEN mid = (low + high +1) / 2 //REKURSIONSSTEG IF array[mid] > target THEN binarySearch(array, target, low, mid -1) //REKURSIONSSTEG ELSE binarySearch(array, target, mid, high) ELSE // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
64
Rekursion
Metoden anropar anropar sig själv tills man kommitner till basfallet.
Skapas på följande sätt:- Basfall: – enkelt problem som kan lösas trivialt och resultatet returneras
- Rekursionssteget (kan finnas flera): – Metoden anropar sig själv med ett mindre problem.
65
Binär sökning – Översätt till Java Pseudokod:int binarySearch(array, target, low, high) IF (high – low > 0) THEN mid = (low + high +1) / 2 //REKURSIONSSTEG IF array[mid] > target THEN binarySearch(array, target, low, mid -1) //REKURSIONSSTEG ELSE binarySearch(array, target, mid, high) ELSE // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
int binSearch(int array[],int target, int low, int high)
66
Binär sökning – Översätt till Java Pseudokod: IF (high – low > 0) THEN mid = (low + high +1) / 2 //REKURSIONSSTEG IF array[mid] > target THEN binarySearch(array, target, low, mid -1) //REKURSIONSSTEG ELSE binarySearch(array, target, mid, high) ELSE // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
int binSearch(int array[],int target,int low, int high) if (high – low > 0) {}
67
Binär sökning – Översätt till Java Pseudokod: mid = (low + high +1) / 2 //REKURSIONSSTEG IF array[mid] > target THEN binarySearch(array, target, low, mid -1) //REKURSIONSSTEG ELSE binarySearch(array, target, mid, high) ELSE // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
int binSearch(int array[],int target,int low, int high) if (high – low > 0) { int mid = (low + high + 1)/2; }
68
Binär sökning – Översätt till Java Pseudokod: //REKURSIONSSTEG IF array[mid] > target THEN binarySearch(array, target, low, mid -1) //REKURSIONSSTEG ELSE binarySearch(array, target, mid, high) ELSE // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
int binSearch(int array[],int target,int low, int high) if (high – low > 0) { int mid = (low + high + 1)/2; if (array[mid] > target) binSearch(array, target, low, mid-1) }
69
Binär sökning – Översätt till Java Pseudokod: //REKURSIONSSTEG ELSE binarySearch(array, target, mid, high) ELSE // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
int binSearch(int array[],int target,int low, int high){ if (high – low > 0) { int mid = (low + high + 1)/2; if (array[mid] > target) binSearch(array, target, low, mid-1) else binSearch(array, target, mid, high) }}
70
Binär sökning – Översätt till Java Pseudokod: ELSE // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
int binSearch(int array[],int target,int low, int high){ if (high – low > 0) { int mid = (low + high + 1)/2; if (array[mid] > target) binSearch(array, target, low, mid-1) else binSearch(array, target, mid, high) } else {}}
71
Binär sökning – Översätt till Java Pseudokod: // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1
int binSearch(int array[],int target,int low, int high){ if (high – low > 0) { int mid = (low + high + 1)/2; if (array[mid] > target) binSearch(array, target, low, mid-1) else binSearch(array, target, mid, high) } else { if (array[low] == target) return low; else return -1; }}
72
Binär sökning – rekursiv version i Java
int binSearch(int array[],int target,int low, int high){ if (high – low > 0) { int mid = (low + high + 1)/2; if (array[mid] > target) binSearch(array, target, low, mid-1) else binSearch(array, target, mid, high) } else { if (array[low] == target) return low; else return -1; }}
73
Binärsökning – Tidskomplexitet
int binSearch(int array[],int target,int low, int high){ if (high – low > 0) { int mid = (low + high + 1)/2; if (array[mid] > target) binSearch(array, target, low, mid-1) else binSearch(array, target, mid, high) } else { if (array[low] == target) return low; else return -1; }}
- Varje jämförelse kostar 1: - high - low > 0 - array[mid] > target - array[low] == target
74
Binärsökning – Tidskomplexitet
int binSearch(int array, int target, int low, int high){ if (high – low > 0) { int mid = (low + high + 1)/2; if (array[mid] > target) binSearch(array, target, low, mid-1) else binSearch(array, target, mid, high) } else { if (array[low] == target) return low; else return -1; }}
Hur många jämförelser gör algoritmen?
75
Binärsökning – Tidskomplexitet
Hur många jämförelser gör algoritmen?
Datamängden halveras i varje iteration:
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
76
Binärsökning – Tidskomplexitet
Hur många jämförelser gör algoritmen?
Datamängden halveras i varje iteration:
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 1=202=21
4=22
9=23+1
77
Binärsökning – Tidskomplexitet
Hur många jämförelser gör algoritmen?
Datamängden halveras i varje iteration:
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 1=202=21
4=22
9=23+1
Talet 2 kommer från att samlingen halveras
78
Binärsökning – Tidskomplexitet
Hur många jämförelser gör algoritmen?
Datamängden halveras i varje iteration:
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 1=202=21
4=22
9=23+1
Antalet halveringar
79
Binärsökning – Tidskomplexitet
Hur många jämförelser gör algoritmen?
I vårt exempel behövde vi göra 3 halveringar och varjejämförelse gjordes max 3 gånger.
I det allmänna fallet gör vi m jämförelser och vi kan därför skriva:
Tidskomplexiteten blir:
Men kan vi mäta tidskomplexiteten på antalet element i samlingen istället?
2m=n
T=O (2m)
80
Binärsökning – Tidskomplexitet
Hur många jämförelser gör algoritmen?
I vårt exempel behövde vi göra 3 halveringar och varjejämförelse gjordes max 3 gånger.
I det allmänna fallet gör vi m jämförelser och vi kan därför skriva:
Tidskomplexiteten blir:
Men kan vi mäta tidskomplexiteten på antalet element i samlingen istället?
Ja, det kan vi.
2m=n
T=O (2m)
81
Binärsökning – Tidskomplexitet
Så här kan vi räkna:
2m=n⇔
log(2m)=log(n)⇔
m⋅log (2)=log(n)⇔
m=log (n)log (2)
⇔
m=log2(n)
82
Binärsökning – Tidskomplexitet
Tidskomplexiteten blir nu så här:
Tidskomplexiteten kallas för logaritmisk komplexitet.
T=O (m)=O (log2(n))≈O (log n)
83
Binärsökning – Tidskomplexitet
I värsta fall:
I genomsnitt:
I bästa fall:
O (log n)
O (log n)
O (1)
84
Jämförelse mellan linjär och binär sökning
Linjär Binär
Kan användas Alltid Endast på sorterade samlingar
För länkad lista Ja Nej
Tid(Värsta) n log(n)
implementering Mycket lätt Lite svårare
85
Sökning – Andra alternativ
- Både linjär och binär sökning fungerar bra för arrayer
- Sökningen kan underlättas genom att använda andra datastrukturer:
– Binära sökträd - Ett alternativ till array
– Hashtabeller: --- Det går snabbt att slå upp vilket värdet som är kopplad till respektive nyckel
86
Algoritmer vs datastrukturer
Algoritm: - Instruktioner som steg för steg beskriver hur man löser ett givet problem.
Datastruktur: - Ordnad data så att datorn kan bearbeta datan på ett effektivt sätt Exempel: Länkad lista, Träd, Hashtabell, Array
Datastrukturen påverkar vilken algoritm som är lämplig att använda.
87
Algoritmanalys
Korrekthet Ger algoritmen alltid ett korrekt resultat
Lösning Får vi någon lösning eller fastnar algoritmen någonstans, till exempel i en loop?
Algoritmkomplexitet – Tidskomplexitet: Talar om hur lång tid en algoritm behöver för att lösa problemet
– Minneskomplexitet: Talar om hur mycket minne algoritmen behöver för att lösa problemet
89
Tidskomplexitet
- Hur kan man avgöra vilken algoritm är snabbast på att lösa ett givet problem?
- Mäta den tid det tar för en dator att exekvera algoritmen?
90
Tidskomplexitet
- Hur kan man avgöra vilken algoritm är snabbast på att lösa ett givet problem?
- Mäta den tid det tar för en dator att exekvera algoritmen? Problem: Man blir beroende av samma hårdvara om man vill jämföra olika algoritmer
91
Tidskomplexitet
- Hur kan man avgöra vilken algoritm är snabbast på att lösa ett givet problem?
- Mäta den tid det tar för en dator att exekvera algoritmen? Problem: Man blir beroende av samma hårdvara om man vill jämföra olika algoritmer
- Lösning: Använd asymptotisk analys istället. → Då blir analysen långsiktig
92
Asymptotisk analys
- Matematisk analys över hur lång tid en algoritm behöver när storleken på indatan växer.
Exempel på storlekar: Sträng : antal tecken Array : antal celler Allmänna fallet: antal byte
- Tre olika fall: – I värsta fall : Den längsta tiden som behövs – I genomsnitt fall: Den tid som behövs i genomsnitt – I bästa fall : Den minsta tiden som behövs
94
Asymptotisk analys
- Grundkrav: Algoritm behöver för indata av godtycklig storlek(n)
- Analys ska vara maskinoberoende -- Hastigheten ökar med en konstant om maskin är kraftfull
95
Asymptotisk analys
- Grundkrav: Algoritm behöver för indata av godtycklig storlek(n)
- Analys ska vara maskinoberoende -- Hastigheten ökar med en konstant om maskin är kraftfull
- Exekveringstiden beräknas som en funktion av indatans storlek T(n)
96
Asymptotisk analys
- Grundkrav: Algoritm behöver för indata av godtycklig storlek(n)
- Analys ska vara maskinoberoende -- Hastigheten ökar med en konstant om maskin är kraftfull
- Exekveringstiden beräknas som en funktion av indatans storlek T(n)
- Konstanta faktorer ignoreras
97
Asymptotisk analys
- Grundkrav: Algoritm behöver för indata av godtycklig storlek(n)
- Analys ska vara maskinoberoende -- Hastigheten ökar med en konstant om maskin är kraftfull
- Exekveringstiden beräknas som en funktion av indatans storlek T(n)
- Konstanta faktorer ignoreras
- Man fokuserar på dominerande faktorer
98
Asymptotisk analys
En algoritm komplexitet analyseras med hjälp av matematik i följande steg givet algoritmens pseudokod:
0. Räkna primitiva operationer och låt varje operation kosta 1: – aritmetiska operationer (+,-,*,/) – jämförelser (==, !=,<=,...) – referera till en variabel/objekt – indexera i en array – tilldelning – anropa en metod – returnera från en metod
1. Ställ upp ett uttryck T(n) för antalet primitiva operationer som
behövs relativt storleken på indatan (n) i bästa, värsta eller i genomsnitt.
2. Förenkla uttrycket T(n)
3. Hitta en funktion som begränsar T(n) uppifrån.
99
Asymptotisk analys – Exempel
0. Räkna primitiva operationer och låt varje operation kosta 1:
sumArray(array) sum = 0 FOR EACH i FROM 0 TO array.length - 1 sum = sum + array[i] RETURN sum;
(1+1)⋅n(1+1+1)⋅n
1
1
100
Asymptotisk analys - Exempel
1. Ställ upp ett uttryck T(n) för antalet primitiva operationer som
behövs relativt storleken på indatan (n) i bästa, värsta eller i genomsnitt.
2. Förenkla uttrycket T(n)
sumArray(array) sum = 0 FOR EACH i FROM 0 TO array.length - 1 sum = sum + array[i] RETURN sum;
1+(1+1)⋅n(1+1+1)⋅n
1
1
T (n)=5⋅n+3
101
Asymptotisk analys – Ordo (big-O)
- Övre gräns (upper bound) för hur tiden för en algoritm växer
Definition:
Givet funktionerna och säger vi att
Där och är positiva konstanter
T (n)⩽c⋅g (n)
n⩾n0
T (n)∈O (g (n))
T (n) g (n)
n0,c
102
Asymptotisk analys – Ordo (big-O)
- Övre gräns (upper bound) för hur tiden för en algoritm växer
Definition:
Givet funktionerna och säger vi att
Där och är positiva konstanter
T (n)⩽c⋅g (n)
n⩾n0
T (n)∈O (g (n))
T (n) g (n)
n0,c
Notera: är en mängd av funktioner som har den egenskap definitionen beskriver.
O (g (n))
103
Asymptotisk analys - Exempel
3. Hitta en funktion som begränsar T(n) uppifrån.
Det är uppenbart att det finns flera funktioner som begränsar T(n) men vi ska hitta den minsta.
Antag; g(n)=n
T (n)=5⋅n+3
5⋅n+3⩽cn (c−5)⋅n⩾3 n⩾ 3c−5
104
Asymptotisk analys - Exempel
3. Hitta en funktion som begränsar T(n) uppifrån.
Det är uppenbart att det finns flera funktioner som begränsar T(n) men vi ska hitta den minsta.
Antag; g(n)=n
Låt och för
T (n)=5⋅n+3
5⋅n+3⩽cn (c−5)⋅n⩾3 n⩾ 3c−5
c=6 n0=3
n⩾3⇒5n+3⩽6n
⇒T (n)∈O (n)
105
Tidskomplexitet – Linjär sökning
- Tidskomplexiteten för de olika fallen: – I värsta fallet:
– I bästa fallet: Om det tar konstant tid så används 1
– I genomsnitt: Antag att i genomsnitt tar algoritmen
Då är en konstant vi kan bortse ifrån och resultet blir
därför:
O (n)
O (1)
O (n)
T ( n2)=T (n⋅1
2)
12
106
Tidskomplexitet – Binär sökning
- Tidskomplexiteten för de olika fallen: – I värsta fallet:
– I bästa fallet: Om det tar konstant tid så används 1
– I genomsnitt:
O (log n)
O (1)
O (log n)
107
Tidskomplexitet – Beräkning
Vid beräkning av komplexitet bortser man ifrån termer av lägre ordning och konstanter:
Exempel:
T (5+n)∈O(n)T (5+10n)∈O(n)T (5000+10000n)∈O(n)
108
Tidskomplexitet – Beräkning
Vid beräkning av komplexitet bortser man ifrån termer av lägre ordning och konstanter:
Exempel:
T (5+n)∈O(n)T (5+10n)∈O(n)T (5000+10000n)∈O(n)
T (n2+n)∈O(n2)
T (15n2+58n)∈O(n2)
T (n+log n)∈O (n)T (25n log n+800)∈O(n log n)
109
Tidskomplexitet - Ordoklasser
Ordo Benämning
konstant
logaritmisk
linjär
kvadratisk
kubisk
polynomisk (för x > 1)
Exponentiell (för c > 1)
faktoriell
O (1)O (log n)O (n)O (n log n)O (n2)O (n3)O (nx)O (cn)O (n !)
112
Ordo( ) , Theta(Θ) och Omega (Ω)
- övre gräns(upper bound)
Θ - Θ och Ω
Ω - undre gräns(lower bound)
O
O
T (n)∈ (n)⇔T∈O (n) T (n)∈ (n)
113
Asymptotisk analys - diskussion
- Bra verktyg för att jämföra algoritmer
- stor indata → En algoritm med högre komplexitet är alltid långsammare
- liten indata → En algoritm med högre komplexitet kan vara Snabbare
Exempel:Om vi söker i en kort array så kan linjär sökning varasnabbare eftersom vi inte behöver beräkna medelvärden
114
Asymptotisk analys - diskussion
- Bra verktyg för att jämföra algoritmer
- stor indata → En algoritm med högre komplexitet är alltid långsammare
- liten indata → En algoritm med högre komplexitet kan vara Snabbare
Exempel:Om vi söker i en kort array så kan linjär sökning varasnabbare eftersom vi inte behöver beräkna medelvärden
Vi kan använda samma resonemang när vi diskuterarminneskomplexitet
115
Asymptotisk analys – Vad ska ni kunna?
- Utföra grundläggande resonemang angående tidskomplexiteten för en algoritm/program för den övre gränsen i olika fall (Ordo)
– Detta gäller speciellt med avseende på följande som tas upp i kursen: –- sök- och sorteringsalgoritmer –- vanliga operationer för datastrukturer
- Givet enkel kod så ska ni kunna resonera er fram till dess Tidskomplexitet
(Se exemplet med att summera innehållet I en array)
117
Sorteringsalgoritmer – Vad är sortering?
- Objekten i en samling placeras i en viss ordning
- Vi kommer framförallt att arbeta med arrayer
- De viktigaste operationerna som används vid sortering är:
– jämföra två värden: compare(), ==, <, >, etc
– swap(i,j) – Byt plats på objekten vid indexarna i och j
118
Sorteringsalgoritmer – Algoritmer
- Enkla algoritmer som är mindre effektiva – Urvalssortering (Selection sort) – Bubbelsortering (Bubble sort) – Instickssortering (Insertion sort)
- Avancerade algoritmer som är mer effektiva – Merge sort – Quick sort – Shell sort
119
Urvalssortering – Algoritm
0. Dela upp arrayen i en sorterad del (tom från början) och en osorterad del (hela arrayen från början)
sorterad del osorterad del
4 5 2 1
120
Urvalssortering – Algoritm
0. Dela upp arrayen i en sorterad del (tom från början) och en osorterad del (hela arrayen från början)
sorterad del osorterad del
1. Leta efter det minsta element I den osorterade delen
sorterad del osorterad del
4 5 2 1
4 5 2 1
121
Urvalssortering – Algoritm
0. Dela upp arrayen i en sorterad del (tom från början) och en osorterad del (hela arrayen från början)
sorterad del osorterad del
1. Leta efter det minsta element i den osorterade delen
sorterad del osorterad del
2. Placera det sist i den sorterade delen
sorterad del osorterad del
4 5 2 1
4 5 2 1
1 5 2 4
122
Urvalssortering – Algoritm
3. Upprepa steg 1 och 2 tills hela arrayen är sorterad
sorterad del osorterad del
sorterad del osorterad del
sorterad del osorterad del
sorterad del osorterad del
1 5 2 4
1 2 5 4
1 2 4 5
1 2 4 5
123
Urvalssortering – Kod void selectionSort(int[] array) { for(int i = 0; i < array.length-1; i++){ int minIndex = i; for(int j = i+1; i < array.length; j++){ if(array[i] < array[minIndex]) { minIndex = j; } } swap(array,i,j); }}
void swap(int[] array, int x, int y){ int temp = array[x]; array[x] = array[y]; array[y] = temp;}
124
Urvalssortering – Tidskomplexitet void selectionSort(int[] array) { for(int i = 0; i < array.length-1; i++){ int minIndex = i; for(int j = i+1; i < array.length; j++){ if(array[i] < array[minIndex]) { minIndex = j; } } swap(array,i,j); }}
125
Urvalssortering – Tidskomplexitet void selectionSort(int[] array) { for(int i = 0; i < array.length-1; i++){ //n-1 int minIndex = i; for(int j = i+1; i < array.length; j++){ if(array[i] < array[minIndex]) { minIndex = j; } } swap(array,i,j); }}
126
Urvalssortering – Tidskomplexitet void selectionSort(int[] array) { for(int i = 0; i < array.length-1; i++){ //n-1 int minIndex = i; for(int j = i+1; i < array.length; j++){ // n-1+n-2+...+2+1 if(array[i] < array[minIndex]) { minIndex = j; } } swap(array,i,j); }}
127
Urvalssortering – Tidskomplexitet void selectionSort(int[] array) { for(int i = 0; i < array.length-1; i++){ //n-1 int minIndex = i; for(int j = i+1; i < array.length; j++){ // n-1+n-2+...+2+1 if(array[i] < array[minIndex]) { // konstant minIndex = j; } } swap(array,i,j); }}
128
Urvalssortering – Tidskomplexitet void selectionSort(int[] array) { for(int i = 0; i < array.length-1; i++){ //n-1 int minIndex = i; for(int j = i+1; i < array.length; j++){ // n-1+n-2+...+2+1 if(array[i] < array[minIndex]) { // konstant minIndex = j; // konstant } } swap(array,i,j); }}
129
Urvalssortering – Tidskomplexitet void selectionSort(int[] array) { for(int i = 0; i < array.length-1; i++){ //n-1 int minIndex = i; for(int j = i+1; i < array.length; j++){ // n-1+n-2+...+2+1 if(array[i] < array[minIndex]) { // konstant minIndex = j; // konstant } } swap(array,i,j); // konstant }}
130
Urvalssortering – Tidskomplexitet void selectionSort(int[] array) { for(int i = 0; i < array.length-1; i++){ //n-1 int minIndex = i; for(int j = i+1; i < array.length; j++){ // n-1+n-2+...+2+1 if(array[i] < array[minIndex]) { // konstant minIndex = j; // konstant } } swap(array,i,j); // konstant }}
= {Triangeltal} = =
=
Komplexiteten kallas för kvadratisk komplexitet.
(n−1)+2+1(n−1)2+n−1
2
n2−2n+1+n−12
n2−n2
∈O(n2)
131
Instickssortering – Algoritm
0. Dela upp arrayen i en sorterad del (tom från början) och en osorterad del (hela arrayen från början)
sorterad del osorterad del
4 5 2 1
132
Instickssortering – Algoritm
0. Dela upp arrayen i en sorterad del (tom från början) och en osorterad del (hela arrayen från början)
sorterad del osorterad del
4 5 2 1
1. Det första värdet i den osorterade delen flyttas till rätt plats i den sorterade delen.
sorterad del osorterad del
2. Upprepa tills hela arrayen är sorterad.
sorterad del osorterad del
4 5 2 1
4 5 2 1
133
Instickssortering – Algoritm
2. Upprepa tills hela arrayen är sorterad.
sorterad del osorterad del
sorterad del osorterad del
sorterad del osorterad del
4 5 2 1
2 4 5 1
1 2 4 5
134
Bubbelsortering – Algoritm
0. Dela upp arrayen i en sorterad del (tom från början) och en osorterad del (hela arrayen från början)
sorterad del osorterad del
4 5 2 1
135
Bubbelsortering – Algoritm
0. Dela upp arrayen i en sorterad del (tom från början) och en osorterad del (hela arrayen från början)
sorterad del osorterad del
4 5 2 1
1. Utför följande för varje par av värden från höger till vänster: – Byt plats om värdet till vänster är större än värdet till höger
4 5 2 1
4 5 1 2
4 1 5 2
136
Bubbelsortering – Algoritm
1. Utför följande för varje par av värden från höger till vänster: – Byt plats om värdet till vänster är större än värdet till höger
4 5 2 1
4 5 1 2
4 1 5 2
1 4 5 2
137
Bubbelsortering – Algoritm
1. Utför följande för varje par av värden från höger till vänster: – Byt plats om värdet till vänster är större än värdet till höger
2. Det minsta värdet bubblas upp till den sorterade arrayen och kan flyttas över till den
3. Upprepa tills arrayen är sorterad
1 4 5 2
140
Instickssortering och Bubbelsortering
Komplexitet:
Använd samma strategi som för urvalssortering
O (n2)
141
Sorteringsalgoritmer - Egenskaper
- Minneskomplexitet: Hur mycket minne behöver den?
De sorteringsalgoritmer vi tittat på hittills behöver:
Arrayen behöver:
Extraminne för swap:
O (n)
O (1)
142
Sorteringsalgoritmer - Egenskaper
- Stabilitet: Bevaras den relativa ordningen på element av samma nycklar?
Exempel: Antag att vi vill sortera följande tuplar enligt de vänstra siffrorna: (4,2); (1,6); (1,5); (2,8)
Om resultatet blir (1,6); (1,5); (2,8); (4,2) så är algoritmen stabil
Om resultatet blir (1,5); (1,6); (2,8); (4,2) så är algoritmen instabil
Det sorteringsalgoritmer vi tittat på hittills är stabila.
143
Sorteringsalgoritmer - Egenskaper
- Tidskomplexitet: Hur lång tid behöver algoritmen?
Det algoritmer vi tittat på har tidskomplexiteten
O (n2)
144
Avancerade sorteringsalgoritmer - Egenskaper
- Tidskomplexitet: som också är den gränsen för hur snabbt man kan sortera - Stabililitet: Olika
- Minneskomplexitet: Kan vara högre
O (n log n)
146
Avancerade sorteringsalgoritmer
Namn Tidskomplexitet Stabil? MinnesåtgångMerge sort Ja Kan behöva mer
minne
Quick sort I medelfallet:
I värsta fallet:
Ja Kan behöva mer minne
Shell sort Svåranalyserad
I värsta fallet:
Nej Inget extra minne
O (n log n)
O (n log n)
O (n2)
O (n3 /2)
147
Ordnade klasser
Om en klass implementerar gränssnittet ComparableTo<T>får klassen en naturlig ordning.
Klassen behöver implementera metodenint compareTo(T t) som ska returnera följande: - 0 om t och objektet är lika - >0 om t är större än objektet - <0 om t är mindre än objektet
148
Lab 2, del 1
Sortering av heltal i ett grafi skt labskal
– Implementera två sorteringslagoritmer själva: Kandidat: insertion och shell sort Master : insertion och merge sort
– Jämför olika sorteringsalgoritmer under olika förutsättningar
– Koppla till teorin
149
Lab 2, del 1
Labskalet begränsat för att kunna synkronisera algoritmerna
- Tillhandahåller följande metoder: – cmp(i,j) – jämför värdena på plats i och j i arrayen (jfr compareTo) – swap(i,j) – byter plats på värdena på plats j och i
– elementCount() – hur många element fi nns det i arrayen (jfr length/size())
150
Mer om sorteringsalgoritmer
- Vi har bara gått igenom kod för en sorteringsalgoritm idag
- Ni ska kunna följande: – Beskriva alla de algoritmer som vi gått igenom
– Kunna visa hur de fungerar genom ett exempel för en array
– Kunna skriva (pseudo)kod för dem
– I labben får ni skriva egen kod för två algoritmer
– Labben innehåller även given kod för andra algoritmer –- studera den
– Läs i kursböckerna om sorteringsalgoritmer
– Även (engelska) Wikipedia har bra material om sortering
151
I veckan
Onsdag: - Deadline för lab 1! - Onsdag: -- Generiska algoritmer och klasser (behövs för lab 2, del 2) -- Länkade listor mm (behövs för lab 3) -- Mer om komplexitet
- Lab:-- Jobba själv innan onsdag-- Sätt igång med del1 i lab2– Läs på om sökning, sortering, komplexitet– Komplexitet: grundläggande Eck 8.5, mer avancerat Shaffer 3.1–3.7