Programmering för språkteknologer II, HT2014 Avancerad programmering för språkteknologer, HT2014 evelina.andersson@lingfil.uu.se Rum 9-2035 http://stp.ling.uu.se/~evelina/uv/uv14/pst2/
Idag - Sökalgoritmer - Algoritmanalys - Sorteringsalgoritmer 2
Sökalgoritmer 3
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 4
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. 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. Exempel: linearsearch(array, target) FOR EACH i FROM 0 TO array.length - 1 IF(array[i] = target) THEN RETURN i; RETURN -1; 6
Ö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) { 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 array) { for(int i = 0; i < array.length; i++) { 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 target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) 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) return i; 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; return -1; 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
Linjär sökning Huvudidé: Gå igenom samlingen tills man gjort en träff eller samlingen är slut. Användning: Används på osorterade samlingar. 13
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; 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 8 == 5? 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? Nej 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 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 4 == 5? 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? Nej 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 1 == 5? 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? Nej 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 5 == 5? 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? Ja int linearsearch(int array[], int target) { for(int i = 0; i < array.length; i++) { if(array[i]== target) return i; return -1; 25
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 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 - I värsta fall behöver vi jämföra alla celler i array, dvs array.length = n gånger. 27
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: T =1 n O(n) Kallas för linjär komplexitet. 28
Linjär sökning Tidskomplexitet Fall Tidskomplexitet Kommentar I värsta fall: I genomsnitt: O(n) O(n) Det sökta värdet finns inte i samlingen I bästa fall: O(1) Det sökta värdet finns i den första platsen I arrayen 29
Binär sökning 30
Binär sökning Exempel: Sök efter talet 2. 1 2 3 4 5 6 7 8 9 31
Binär sökning Exempel: Sök efter talet 2. 2 1 2 3 4 5 6 7 8 9 5 == 2? 32
Binär sökning Exempel: Sök efter talet 2. 2 1 2 3 4 5 6 7 8 9 5 == 2? Nej 33
Binär sökning Exempel: Sök efter talet 2. 2 1 2 3 4 5 6 7 8 9 5 == 2? Nej 5 > 2? 34
Binär sökning Exempel: Sök efter talet 2. 2 1 2 3 4 5 6 7 8 9 5 == 2? Nej 5 > 2? Ja 35
Binär sökning Exempel: Sök efter talet 2. 2 1 2 3 4 5 6 7 8 9 (Array[(0+3+1)/2] =Array[2] = 3) == 2? 36
Binär sökning Exempel: Sök efter talet 2. 2 1 2 3 4 5 6 7 8 9 (Array[(0+3+1)/2] =Array[2] = 3) == 2? Nej 37
Binär sökning Exempel: Sök efter talet 2. 2 1 2 3 4 5 6 7 8 9 (Array[(0+3+1)/2] =Array[2] = 3) == 2? Nej 3 > 2? 38
Binär sökning Exempel: Sök efter talet 2. 2 1 2 3 4 5 6 7 8 9 (Array[(0+3+1)/2] =Array[2] = 3) == 2? Nej 3 > 2? Ja 39
Binär sökning Exempel: Sök efter talet 2. 2 1 2 3 4 5 6 7 8 9 (Array[(0+1+1)/2] =Array[1] =2) == 2? 40
Binär sökning Exempel: Sök efter talet 2. 2 1 2 3 4 5 6 7 8 9 (Array[(0+1+1)/2] =Arra[1] =2) == 2? Ja Returnera index 1 41
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. 42
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) 43
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 44
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 45
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 46
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 47
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 48
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 49
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) 50
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; 51
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){ 52
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; 53
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; 54
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; 55
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; 56
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 57
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 58
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 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) //REKURSIONSSTEG IF array[mid] <= target THEN binarysearch(array, target, mid, high) // BASFALL IF array[low] = target THEN RETURN low ELSE RETURN -1 60
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 61
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 62
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 63
Rekursion Metoden anropar anropar sig själv tills man kommit ner 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. 64
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) 65
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) { 66
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; 67
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) 68
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) 69
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 { 70
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; 71
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; 72
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 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; Hur många jämförelser gör algoritmen? 74
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 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 9=2 3 +1 4=2 2 2=2 1 1 2 3 4 5 6 7 8 9 1=2 0 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 9=2 3 +1 4=2 2 1 2 3 4 5 6 7 8 9 2=2 1 1 2 3 4 5 6 7 8 9 1=2 0 Talet 2 kommer från att samlingen halveras 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 9=2 3 +1 4=2 2 1 2 3 4 5 6 7 8 9 2=2 1 1 2 3 4 5 6 7 8 9 1=2 0 Antalet halveringar 78
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 varje jä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: 2 m =n Tidskomplexiteten blir: T =O(2 m ) Men kan vi mäta tidskomplexiteten på antalet element i samlingen istället? 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 varje jä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: 2 m =n Tidskomplexiteten blir: T =O(2 m ) Men kan vi mäta tidskomplexiteten på antalet element i samlingen istället? Ja, det kan vi. 80
Binärsökning Tidskomplexitet Så här kan vi räkna: 2 m =n log(2 m )=log(n) m log(2)=log(n) m= log(n) log(2) m=log 2 (n) 81
Binärsökning Tidskomplexitet Tidskomplexiteten blir nu så här: T =O(m)=O(log 2 (n)) O (log n) Tidskomplexiteten kallas för logaritmisk komplexitet. 82
Binärsökning Tidskomplexitet I värsta fall: O(log n) I genomsnitt: O(log n) I bästa fall: O(1) 83
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 84
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 85
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. 86
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 87
Tidskomplexitet - Hur kan man avgöra vilken algoritm är snabbast på att lösa ett givet problem? 88
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? 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? Problem: Man blir beroende av samma hårdvara om man vill jämföra olika algoritmer 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 - Lösning: Använd asymptotisk analys istället. Då blir analysen långsiktig 91
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 92
Asymptotisk analys - Grundkrav: Algoritm behöver för indata av godtycklig storlek(n) 93
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 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 - Exekveringstiden beräknas som en funktion av indatans storlek T(n) 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) - Konstanta faktorer ignoreras 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 - Man fokuserar på dominerande faktorer 97
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. 98
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+1) n (1+1+1) n 1 99
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+1) n (1+1+1) n 1 T (n)=5 n+3 100
Asymptotisk analys Ordo (big-o) - Övre gräns (upper bound) för hur tiden för en algoritm växer Definition: T (n) g (n) Givet funktionerna och säger vi att T (n) O(g (n)) T (n) c g (n) n n 0 n 0, c Där och är positiva konstanter 101
Asymptotisk analys Ordo (big-o) - Övre gräns (upper bound) för hur tiden för en algoritm växer Definition: T (n) g (n) Givet funktionerna och säger vi att T (n) O(g (n)) T (n) c g (n) n n 0 n 0, c Där och är positiva konstanter Notera: O(g (n)) är en mängd av funktioner som har den egenskap definitionen beskriver. 102
Asymptotisk analys - Exempel 3. Hitta en funktion som begränsar T(n) uppifrån. T (n)=5 n+3 Det är uppenbart att det finns flera funktioner som begränsar T(n) men vi ska hitta den minsta. Antag; g(n)=n 5 n+3 cn (c 5) n 3 n 3 c 5 103
Asymptotisk analys - Exempel 3. Hitta en funktion som begränsar T(n) uppifrån. T (n)=5 n+3 Det är uppenbart att det finns flera funktioner som begränsar T(n) men vi ska hitta den minsta. Antag; g(n)=n 5 n+3 cn (c 5) n 3 n 3 c 5 Låt c=6 och n 0 =3 5n+3 6n för n 3 T (n) O (n) 104
Tidskomplexitet Linjär sökning - Tidskomplexiteten för de olika fallen: I värsta fallet: O (n) I bästa fallet: O (1) Om det tar konstant tid så används 1 I genomsnitt: Antag att i genomsnitt tar algoritmen T ( n 2 )=T (n 1 2 ) Då 1 2 är en konstant vi kan bortse ifrån och resultet blir därför: O (n) 105
Tidskomplexitet Binär sökning - Tidskomplexiteten för de olika fallen: I värsta fallet: O (log n) I bästa fallet: O (1) Om det tar konstant tid så används 1 I genomsnitt: O (log n) 106
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) 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) T (n 2 +n) O(n 2 ) T (15n 2 + 5 8 n) O(n2 ) T (n+log n) O (n) T (25 nlog n+800) O(n log n) 108
Tidskomplexitet - Ordoklasser Ordo O(1) O(log n) O(n) O(n log n) O(n 2 ) O(n 3 ) O(n x ) O(c n ) O(n!) Benämning konstant logaritmisk linjär kvadratisk kubisk polynomisk (för x > 1) Exponentiell (för c > 1) faktoriell 109
Tidskomplexitet asymtotisk storlek spelar roll 110
Tidskomplexitet asymtotisk storlek spelar roll trots konstanter 111
Ordo( O), Theta(Θ) och Omega (Ω) O - övre gräns(upper bound) Θ - T (n) Θ (n) T O(n) och T (n) Ω (n) Ω - undre gräns(lower bound) 112
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 vara snabbare eftersom vi inte behöver beräkna medelvärden 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 vara snabbare eftersom vi inte behöver beräkna medelvärden Vi kan använda samma resonemang när vi diskuterar minneskomplexitet 114
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) 115
Sorteringsalgoritmer 116
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 117
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 118
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 4 5 2 1 osorterad del 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 4 5 2 1 osorterad del 1. Leta efter det minsta element I den osorterade delen sorterad del 4 5 2 1 osorterad del 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 4 5 2 1 osorterad del 1. Leta efter det minsta element i den osorterade delen sorterad del 4 5 2 1 osorterad del 2. Placera det sist i den sorterade delen sorterad del 1 5 2 4 osorterad del 121
Urvalssortering Algoritm 3. Upprepa steg 1 och 2 tills hela arrayen är sorterad 1 5 2 4 sorterad del osorterad del 1 2 5 4 sorterad del osorterad del 1 2 4 5 sorterad del osorterad del 1 2 4 5 sorterad del osorterad del 122
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; 123
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); 124
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); 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++){ // n-1+n-2+...+2+1 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]) { // konstant 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; // konstant 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); // konstant 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 (n 1)+2+1 (n 1) 2 +n 1 = {Triangeltal = = 2 n 2 2n+1+n 1 2 = n 2 n 2 O(n 2 ) Komplexiteten kallas för kvadratisk komplexitet. 130
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 4 5 2 1 osorterad del 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 4 5 2 1 osorterad del 1. Det första värdet i den osorterade delen flyttas till rätt plats i den sorterade delen. sorterad del 4 5 2 1 osorterad del 2. Upprepa tills hela arrayen är sorterad. 4 5 2 1 sorterad del osorterad del 132
Instickssortering Algoritm 2. Upprepa tills hela arrayen är sorterad. 4 5 2 1 sorterad del osorterad del 2 4 5 1 sorterad del osorterad del 1 2 4 5 sorterad del osorterad del 133
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 4 5 2 1 osorterad del 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 4 5 2 1 osorterad del 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 135
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 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 2. Det minsta värdet bubblas upp till den sorterade arrayen och kan flyttas över till den 1 4 5 2 3. Upprepa tills arrayen är sorterad 137
Bubbelsortering Algoritm 3. Upprepa tills arrayen är sorterad 1 4 5 2 1 4 2 5 1 2 4 5 1 2 4 5 138
Bubbelsortering Algoritm 3. Upprepa tills arrayen är sorterad 1 2 4 5 1 2 4 5 139
Instickssortering och Bubbelsortering Komplexitet: O(n 2 ) Använd samma strategi som för urvalssortering 140
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) 141
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. 142
Sorteringsalgoritmer - Egenskaper - Tidskomplexitet: Hur lång tid behöver algoritmen? Det algoritmer vi tittat på har tidskomplexiteten O(n 2 ) 143
Avancerade sorteringsalgoritmer - Egenskaper O(nlog n) - Tidskomplexitet: som också är den gränsen för hur snabbt man kan sortera - Stabililitet: Olika - Minneskomplexitet: Kan vara högre 144
Avancerade sorteringsalgoritmer 145
Avancerade sorteringsalgoritmer Namn Tidskomplexitet Stabil? Minnesåtgång Merge sort Ja Kan behöva mer O(n log n) minne Quick sort I medelfallet: O(n log n) Ja Kan behöva mer minne I värsta fallet: O(n 2 ) Shell sort Svåranalyserad Nej Inget extra minne I värsta fallet: O(n 3/2 ) 146
Ordnade klasser Om en klass implementerar gränssnittet ComparableTo<T> får klassen en naturlig ordning. Klassen behöver implementera metoden int 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 147
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 148
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()) 149
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 150
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 151