Sortering och Länkade Listor - Varför ? Några algoritmer, kap 8 -En annan typ av datastruktur, Länkad lista, kap 17. Varför är sortering viktigt? Rekursiv binär sökning public static int binarySearch(Comparable [ ] a, Comparable x) { return binarySearch(a,x,0,a.length-1) ; } private static int binarySearch(Comparable [ ] a, Comparable x, int low, int hight){ if(low>hight) return -1; int mid=low+hight/2 else { if(a[mid].compareTo(x)<0) return binarySearch(a,x,mid+1,hight); // här anropar metod sig själv med högra halvan else if(a[mid].compareTo(x)>0 return binarySearch(a,x,low,mid-1); // här anropar metod sig själv med vänstra halvan else return mid; } Varför är sortering viktigt ? En annan exempel. public static boolean duplicates( int [] a) { for(int i=0;i<a.lenght;i++) for(int j=i+1;j<a.length; j++) if(a[i]==a[j]); return true ; return false; } Om en samling data är sorterad, effektiviteten av alla algoritmer på respektive datan ökar betydligt. Kvadratiska O(n^2) sorteringar public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ Ex.tiden O( ) a[j]=a[j-1]; Om arrayen är redan } sorterad? a[j]=temp; } Ex.tiden O( ) } insertionSort 8 4 2 7 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 temp=4 8 4 2 7 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 temp=4 8 8 2 7 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 temp=4 8 8 2 7 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 temp=4 4 8 2 7 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 temp=2 4 8 2 7 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 temp=2 4 8 8 7 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 temp=2 4 8 8 7 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 temp=2 4 4 8 7 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 temp=2 4 4 8 7 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 temp=2 2 4 8 7 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 2 4 8 7 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 temp=7 2 4 8 8 1 9 3 5 public static void insertionSort(int [] a) { for(int p=1;p<a.length;p++){ int temp=a[p]; int j=p; for (; j>0 && temp<a[j-1] ; j--){ a[j]=a[j-1]; } a[j]=temp; } } 6 temp=7 2 4 7 8 1 9 3 5 6 insertionSort()- speciellt fall 1 2 3 4 5 6 7 8 8 Vad blir exekveringstiden när arrayen är sorterad? Tidskomplexitet (värstafall): 1 + 2 + 3 + …. + n-1 = n(n-1)/2 = O(n2) Subkvadratiska sorteringsalgoritmer använder divade & conquer - strategi Merge Sort O( NlogN) Dela arrayen i två halvor, sortera halvorna och sedan sätter ihopp halvorna ( merge) i en sorterad array Quick Sort O(NlogN) Dela arrayen i två delar genom att välja ett element i arrayen som pivot. Element som är mindre en pivoten fyttas till enda delen, element som är större till den andra.Sortera delarna. Divade & Conquer - strategi Att dela ett problem i två mindre subproblem som kan lösas rekursivt Att sätta ihop lösningen till subproblemen för att lösa original problemet. MergeSort -algoritmen 8 4 8 4 8 4 8 2 2 1 9 7 2 4 7 2 3 1 7 1 7 1 9 9 9 6 3 6 3 6 3 6 MergeSort 8 4 4 8 2 1 4 2 2 7 7 7 8 1 9 1 1 3 9 3 6 3 6 6 9 MergeSort 8 4 4 8 2 1 2 2 4 2 7 7 7 8 1 9 1 1 3 9 3 6 3 6 6 9 MergeSort 8 4 4 8 2 1 2 2 4 2 7 7 7 8 1 9 1 1 3 9 3 6 3 6 6 9 MergeSort 8 4 4 8 2 1 2 2 4 2 7 3 7 7 8 1 9 1 1 3 9 3 6 3 6 6 9 MergeSort-algoritmen 8 4 4 8 2 1 2 2 4 2 7 3 7 7 8 1 1 1 9 3 9 3 3 6 6 6 9 Tidskomplexiteten? 7 5 9 7 3 6 9 0 0 2 3 5 2 0 2 3 4 5 6 0 2 3 4 5 6 4 4 Dela i två halvor 6 Sortera halvorna 7 9 Gör ”merge” till en temp array 7 9 Kopiera temp arrayen tillbaka till original arrayen Java implementation av Merge Sort public static void mergeSort( int [] a) { int [] temp= new int[a.length]; mergeSort(a, temp, 0, a.length-1); } private static void mergeSort( int [] a, int[] temp,int first,int last) { if(first<last){ int center=first+last/2; mergeSort(a,temp,first,center); mergeSort(a,temp,center+1,last) merge(a,temp,first,center+1,last); } } Se merge () i kurslitteraturen Quicksort Divide and conquer algoritm med flera variationer Bättre i medelfall än övriga algoritmer Dålig i värsta fall, som dock kan händer nästan aldrig Idé: Välj ut ett element (pivot) och se till att det hamnar på rätt plats genom att först flytta om övriga element så att alla som är mindre än pivotelementet hamnar till vänster och alla större hamnar till höger. Upprepa sedan (rekursivt) på vänster och höger delar av arrayen QuickSort- implementationsskiss <=pivot pivot >=pivot quickSort( a,first,last) { if(first<last) // välj pivot // dela arrayen quickSort(a,first,pivotindex-1) // sortera mindre quickSort(a,pivotindex+1,last) // sortera större } Quicksort med pivot = median av tre Antag vi skall sortera delvektorn a[low] ..a[high]. Mittplatsen mid = (low + high) / 2. Utred storleksordningen mellan elementen a[low], a[high] och a[mid]. Byt samtidigt platser så att platsen low kommer att innehålla det minsta av dem, mid det mittersta i storleksordning och high det största. low mid high 8149635270 low mid high 0149635278 Pivotelementet = medianen av de tre = elementet som nu QuickSort() 8 1 4 9 Median av tre ->6 6 3 5 2 7 0 QuickSort() 8 1 4 9 0 3 5 2 7 6 QuickSort() 2 1 4 9 0 3 5 8 7 6 QuickSort() 2 1 4 5 0 3 9 8 7 6 QuickSort() 2 1 4 5 0 3 6 8 7 9 Tidskomplexiteten 1)Bästa fall (kan man visa) : Delar vektorn i lika stora delar i varje pass. Rekursionsformeln blir T(n) = 2T(n/2) + n vilket ger T(n) n*log n. 2)Sämsta fall: Vektorn delas alltid i en tom del och en del som består av alla element utom pivot. Rekursionsformel: W(n) = W(n-1) + n ==> W(n) = n(n-1)/2 = O(n2)