Föreläsning 12 2I1027 1 FÖRELÄSNING 12 DATALOGI I Sortering Beatrice Åkerblom beatrice@dsv.su.se Institutionen för Data- och Systemvetenskap SU/KTH
Föreläsning 12 2I1027 2 Läsanvisningar Michael Main Data Structures & Other Objects Using Java (Upplaga: Second Edition), Addison Wesley, 2003, ISBN : 0-201-74093-1 Sortering kapitel 12
Föreläsning 12 2I1027 3 Olika sorteringsalgoritmer Selection Sort Insertion Sort Merge Sort Quick Sort Att sortera objekt Generella sorteringsmetoder Något om Generics i Java Föreläsningens innehåll
Föreläsning 12 2I1027 4 Exempel Vi har en array med heltal som ska sorteras int[]test = new int[15]; // Arrayen fylls med värden Sorteringen utförs i en metod som får arrayen som ska sorteras som argument: void selectionsort(int[]arr){ // metodens kropp int-arrayer av olika längd kan skickas till metoden! Var lägger vi metoden selectionsort??
Föreläsning 12 2I1027 5 Exempel, forts. Vi skapar en klass som innehåller de olika sorteringsmetoderna: class Sort{ public static void selectionsort(int[]arr){ // Metod-kroppen public static void insertionsort(int[]arr){ // Metod-kroppen Då metoderna är statiska kan vi smidigt anropa dem: int[]test = new int[100]; // Arrayen fylls med värden Sort.selectionSort(test);
Föreläsning 12 2I1027 6 Selection sort 19 23 8 17 82 36 43 4 61 12 Leta upp minsta värdet Byt plats på minsta och första 4 23 8 17 82 36 43 19 61 12 Första rutan är sorterad Leta upp minsta i resten av arrayen Byt med första osorterade 4 8 23 17 82 36 43 19 61 12 Fortsätt på samma sätt med resten 4 8 12 17 19 23 36 43 61 82
Föreläsning 12 2I1027 7 Selection sort 19 23 8 17 82 36 43 4 61 12 void selectionsort(int[]arr){ for (int x=0; x<arr.length-1; x++){ int min=x; for (int y=x+1; y<arr.length; y++) if (arr[y]<arr[min]) min=y; int temp=arr[x]; arr[x]=arr[min]; arr[min]=temp;
Föreläsning 12 2I1027 8 Insertion sort 19 23 8 17 82 36 43 4 61 12 Den första rutan är sorterad Tag den andra, lägg in den på rätt plats 8 19 23 17 82 36 43 4 61 12 Tag den tredje, lägg in den på rätt plats 8 17 19 23 82 36 43 4 61 12 Tag den fjärde, lägg in den på rätt plats 8 17 19 23 82 36 43 4 61 12 Fortsätt tills alla blivit insorterade
Föreläsning 12 2I1027 9 Insertion sort 19 23 8 17 82 36 43 4 61 12 void insertionsort(int[]arr){ for (int x=1; x<arr.length; x++){ int temp=arr[x], y=x; while (y>0 && arr[y-1]>temp){ arr[y]=arr[y-1]; y--; arr[y]=temp;
Föreläsning 12 2I1027 10 Merge sort 19 23 8 17 82 36 43 4 61 12 Dela upp arryen i två (lika stora) delar: 19 23 8 17 82 36 43 4 61 12 Sortera varje del 8 17 19 23 82 4 12 36 61 43 Slå ihop (merge) de två sorterade subarrayerna 4 8 12 17 19 23 36 43 61 82
Föreläsning 12 2I1027 11 Merge sort 19 23 8 17 36 4 61 12 19 23 8 17 36 4 61 12 19 23 8 17 36 4 61 12 19 23 8 17 36 4 61 12 19 23 8 17 4 36 12 61 8 17 19 23 4 12 36 61 4 8 12 17 19 23 36 61
Föreläsning 12 2I1027 12 Merge sort 19 23 8 17 82 36 43 4 61 12 void mergesort(int[]arr, int start, int stopp){ if (start<stopp){ int mitt=(start+stopp)/2; mergesort(arr, start, mitt); mergesort(arr, mitt+1, stopp); merge(arr, start, mitt, mitt+1, stopp);
Föreläsning 12 2I1027 13 Merge sort 19 23 8 17 82 36 43 4 61 12 void merge(int[]arr, int start1, int stopp1, int start2, int stopp2){ int[]sub1=new int[stopp1-start1+1], sub2=new int[stopp2-start2+1]; System.arraycopy(arr, start1, sub1, 0, sub1.length); System.arraycopy(arr, start2, sub2, 0, sub2.length); int s1=0, s2=0, a=start1; while (s1<sub1.length && s2<sub2.length) if (sub1[s1]<sub2[s2]) arr[a++]=sub1[s1++]; else arr[a++]=sub2[s2++]; while (s1<sub1.length) arr[a++]=sub1[s1++]; while (s2<sub2.length) arr[a++]=sub2[s2++];
Föreläsning 12 2I1027 14 Merge sort i klassen Sort, version I class Sort{ public static void mergesort(int[]arr, int start, int stopp){ //Metod-kroppen private static void merge(int[]arr, int start1, int stopp1, int start2, int stopp2){ //Metod-kroppen Anropet blir då: int[]test = new int[100]; //Arrayen fylls med värden Sort.mergeSort(test, 0, test.length-1);
Föreläsning 12 2I1027 15 Merge sort i klassen Sort, version II class Sort{ public static void mergesort(int[]arr){ mergesort(arr, 0, arr.length-1); public static void mergesort(int[]arr, int start, int stopp){ //Metod-kroppen private static void merge(int[]arr, int start1, int stopp1, int start2, int stopp2){ //Metod-kroppen Anropet blir då: int[]test = new int[100]; //Arrayen fylls med värden Sort.mergeSort(test);
Föreläsning 12 2I1027 16 Quick sort 19 23 8 17 82 36 43 4 61 12 Välj ett mittvärde (pivot-punkt), t. ex. första värdet Lägg alla mindre än pivot-värdet i början, större på slutet 8 17 4 12 19 23 82 36 43 61 Pivot-värdet ligger på rätt plats Sortera de mindre samt sortera de större Och voilà - den är sorterad! 4 8 12 17 19 23 36 43 61 82
Föreläsning 12 2I1027 17 Quick sort 13 45 18 11 63 14 21 43 11 13 18 45 63 14 21 43 11 14 18 45 63 21 43 14 21 43 45 63 21 43 63 43 11 13 14 18 21 43 45 63
Föreläsning 12 2I1027 18 Quick sort 19 23 8 17 82 36 43 4 61 12 void quicksort(int[]arr, int start, int stopp){ if (start<stopp){ int pivot=delaupp(arr,start,stopp); quicksort(arr,start,pivot-1); quicksort(arr,pivot+1,stopp);
Föreläsning 12 2I1027 19 Quick sort 19 23 8 17 82 36 43 4 61 12 int delaupp(int[]arr, int start, int stopp){ int pivotvalue=arr[start]; int pivot=start; for (int x=start+1; x<=stopp; x++) if (arr[x]<pivotvalue){ int temp=arr[x]; arr[x]=arr[++pivot]; arr[pivot]=temp; arr[start]=arr[pivot]; arr[pivot]=pivotvalue; return pivot;
Föreläsning 12 2I1027 20 Mer om sortering mergesort & quicksort snabbare än selectionsort & insertionsort Om arrayen redan är sorterad - insertionsort snabbast mergesort & quicksort s.k. Divide-and-Conquer algoritmer (Dela upp i två delar, Besegra (här sortera) de två delarna rekursivt) mergesort skapar två delarrayer dit värden måste kopieras. Detta kostar utrymme + tid varför quicksort räknas som snabbast mergesort & quicksort kan snabbas upp genom att om intervallet som skall sorteras är mindre än 7 stort - använd insertionsort quicksort - valet av pivot-värde flaskhals. En variant är att ta medianen av första, sista och mittersta värdet.
Föreläsning 12 2I1027 21 Sortera objekt Hittills har int-arrayer används (för enkelhets skull). Om man vill sortera en array med objekt då?? class Hund{ private String namn; private int age, vikt; public Hund(String n, int a, int v){ namn=n; age=a; vikt=v; public String getnamn(){ return namn; public int getage(){ return age;
Föreläsning 12 2I1027 22 Sortera hund-objekt Sortera en array med Hund-objekt ( Hund[] ) i åldersordning, yngsta hunden först: void selectionsort(hund[]arr){ for (int x=0; x<arr.length-1; x++){ int min=x; for (int y=x+1; y<arr.length; y++) if (arr[y].getage()<arr[min].getage()) min=y; Hund temp=arr[x]; arr[x]=arr[min]; arr[min]=temp;
Föreläsning 12 2I1027 23 Sortera hund-objekt Sortera en array med Hund-objekt ( Hund[] ) i bokstavsordning med avseende på hundarnas namn: void selectionsort(hund[]arr){ for (int x=0; x<arr.length-1; x++){ int min=x; for (int y=x+1; y<arr.length; y++) if (arr[y].getnamn().compareto(arr[min].getnamn())<0) min=y; Hund temp=arr[x]; arr[x]=arr[min]; arr[min]=temp;
Föreläsning 12 2I1027 24 Sortera vad som helst En generell sorteringsmetod, gäller för vilka objekt som helst! void selectionsort(object[]arr){ for (int x=0; x<arr.length-1; x++){ int min=x; for (int y=x+1; y<arr.length; y++) if (arr[y].??? <arr[min].??? ) min=y; Object temp=arr[x]; arr[x]=arr[min]; arr[min]=temp; Hur ska vi kunna jämföra två objekt - vi vet ju INTE vilken sorts objekt det är? Ibland hundar, en annan gång bilar... Vi måste skicka en jämförelse-metod till sorteringsmetoden
Föreläsning 12 2I1027 25 Sortera vad som helst Det vi i Java kan skicka är ett objekt. Detta objekt måste då innehålla metoden som jämför två objekt (t ex två Hundar). Hur kan vi få kompilatorn att fatta detta? Jo vi tvingar det objekt som skall skickas till sorteringsmetoden att implementera gränssnittet (interfacet) Comparator. I java.util-delbiblioteket finns: interface Comparator{ public int compare(object o1, Objekt o2); //Om o1 < o2 returneras ett negativt tal //Om o1 och o2 är lika returneras noll //om o1 > o2 returneras ett positivt tal
Föreläsning 12 2I1027 26 Comparator Vi ser nu till att ta emot ett Comparator-objekt i vår sorteringsmetod. I detta objekt VET vi nu att metoden compare finns och att den anger sorteringsordningen. Vår generella selectionsort: (OBS överst: import java.util.*; ) void selectionsort(object[]arr; Comparator comp){ for (int x=0; x<arr.length-1; x++){ int min=x; for (int y=x+1; y<arr.length; y++) if (comp.compare(arr[y], arr[min])<0) min=y; Object temp=arr[x]; arr[x]=arr[min]; arr[min]=temp;
Föreläsning 12 2I1027 27 Sortera hund-objekt igen Om vi till exempel vill sortera ett antal hundar i åldersordning: class HundSort implements Comparator{ public int compare(object o1, Object o2){ Hund h1=(hund)o1, h2=(hund)o2; int tal=h1.getage()-h2.getage(); return tal; ---- Hund[]alla = new Hund[100]; //Arrayen fylls med Hund-objekt HundSort hs = new HundSort(); Sort.selectionSort(alla, hs); //alternativt: Sort.selectionSort(alla, new HundSort());
Föreläsning 12 2I1027 28 Sortera bil-objekt Vi har Bilar som bland annat har årsmodell och pris. Vi vill sortera bilarna i första hand på årsmodell, i andra hand på pris. class Bil{ private int year, pris; public int getyear(){ return year; public int getpris(){ return pris; class HurSorteraBilar implements Comparator{ public int compare(object o1, Object o2){ Bil b1=(bil)o1, b2=(bil)o2; int tal=b1.getyear()-b2.getyear(); if (tal==0) return b1.getpris()-b2.getpris(); else return tal;
Föreläsning 12 2I1027 29 Sortera bil-objekt, forts. Bil[]allaBilar = new Bil[10000]; //Arrayen fylls med bilar Sort.selectionSort(allaBilar, new HurSorteraBilar());