sammenligninger, hvor Programmering 1999 Forelæsning 17, tirsdag 2 november 1999 Søgning efter en given værdi i en tabel Lineær søgning og binær søgning Effektivitet: maskinuafhængig vurdering af køretid Korrekthed: Øjebliksbilleder Udvalgssortering Programmering 1999 KVL Side 17-1 Søgning At finde en dataværdi i en liste eller tabel Feks opslag i en telefonbog Sortering At ordne elementerne i en liste eller tabel, så små værdier forekommer før store Feks at omarrangere listen (95, 69, 33, 84, 17, 39, 97, 88, 39, 51, 2, 84, 62, 52, 35, 74, 28, 57, 86) til (17, 2, 28, 33, 35, 39, 39, 51, 52, 57, 62, 69, 74, 84, 84, 86, 88, 95, 97) Programmering 1999 KVL Side 17-2 Programmering 1999 KVL Side 17-4 Vi skriver for at sige: højst proportional med Ved, i gennemsnit 5 sammenligninger I gennemsnit: sammenligninger I værste fald: = antal elementer i listen Lineær søgning: vurdering af tidsforbrug Programmering 1999 KVL Side 17-3 Ulempe: Data skal være sorterede Fordel: Hurtig 11, 11, 28, 35, 45, 5, 62, 78, 79, 117, 117, 251 Eksempel: Søg efter i listen Kig på midterste element, smid den ene halvdel af elementerne væk 2 Binær søgning Ulempe: Langsom Fordel: Nem at programmere 35, 5, 79, 45, 11, 117, 78, 62, 28, 251, 11, 117 Eksempel: Søg efter i listen Søg fra ende af, sammenlign med hvert element 1 Lineær søgning To søgemetoder
, så forøges i Programmering 1999 KVL Side 17-6 hvis found er lig false, så er det søgte element ikke i hvis found er lig true, så er lig det søgte element; Ønsket tilstand efter at søgningen er afsluttet: static int i; static boolean found; Klassevariable som skal indeholde resultatet af søgningen: Tabellen kan vises således Vi skal søge efter et element i tabellen Programmering af søgealgoritmer Programmering 1999 KVL Side 17-5 Vi skriver for at sige: højst proportional med logaritmen til Vi har Generelt, højst sammenligninger, hvor er totals-logaritmen Kan beregnes ved Det er 25 gange hurtigere end lineær søgning Dvs højst 2 sammenligninger 396, 1953, 976, 488, 244, 122, 61, 3, 15, 7, 3, 1 elementer Eksempel: Ved haves 1, 5, 25, 125, 625, 3125, 15625, 7812, Antal tilbageværende elementer halveres hver gang, indtil Binær søgning: vurdering af tidsforbrug Programmering 1999 KVL Side 17-8 I begge tilfælde gælder øjebliksbilledet fortsat ved pp3 (2) Hvis med 1: (1) Hvis, så sættes found true, færdig To muligheder: Efter gennemløb, ved pp2: Til start, ved pp1, gælder dette øjebliksbillede: Lineær søgning efter Programmering 1999 KVL Side 17-7 static void linsearch(int x, int[] arr, int n) i = ; found = false; / pp1 / while (!found && i < n) / pp2 / if (arr[i]!= x) i++; else found = true; / pp3 / Lineær søgning
findes ikke i ikke i, så i Programmering 1999 KVL Side 17-1 Så Men ifølge løkkeinvarianten findes Dvs dækker Dvs Så må i < n være falsk Eller found er false, dvs!found er sandt Enten er found true, og så Betingelsen (!found && i < n) må være falsk Når løkken er standset Programmering 1999 KVL Side 17-9 fortsætter Når det gælder ved pp3, så også efter løkken, hvis den standser; eller ved pp2 i næste runde, hvis den Når det gælder ved pp2, så også ved pp3 Hvis det gælder ved pp1, så også ved pp2 Derfor gælder det altid ved pp2 og pp3, og lige efter løkken (b) Hvis det gælder i begyndelsen af løkken, ved pp2, så også i slutningen af løkken, ved pp3 (a) Gælder før løkken, ved pp1 Følgende øjebliksbillede er altså en løkkeinvariant: Når løkken kører Programmering 1999 KVL Side 17-12 Ved pp1 gælder øjebliksbilledet Binær søgning efter Programmering 1999 KVL Side 17-11 static void binsearch(int x, int[] arr, int n) int a =, b = n-1; found = false; / pp1 / while (!found && a <= b) / pp2 / i = (a+b) / 2; if (x < arr[i]) b = i-1; else if (arr[i] < x) a = i+1; else found = true; / pp3 / Tabellen skal være sorteret voksende Binær søgning
midt mellem findes ikke i ikke være i Programmering 1999 KVL Side 17-14 I alle tilfælde gælder øjebliksbilledet fra pp2 igen ved pp3; det er en løkkeinvariant (3) Ellers, så sættes found true; færdig (2) Hvis, så sæt : (1) Hvis, så sæt : Ellers betragt og Tre muligheder:, så findes Hvis ikke i ; færdig Generelt, ved pp2: Løkkeinvariant for binær søgning Programmering 1999 KVL Side 17-13 (3) Ellers, så found sættes true, færdig (2) Hvis, så sæt : (1) Hvis, så sæt : Tre muligheder: Første gang ved pp2; vi betragter midterste element (indeks ): Programmering 1999 KVL Side 17-16 Hvis vi nogensinde når ned efter while-løkken, så findes ikke i tabellen Der returneres direkte fra while-løkken hvis findes static int binsearch(int x, int[] arr, int n) int a =, b = n-1; / pp1 / while (a <= b) / pp2 / int i = (a+b) / 2; if (x < arr[i]) b = i-1; else if (arr[i] < x) a = i+1; else return i; / pp3 / return -1; Så kan variablene found og i med klassevirkefelt undværes: hvis det søgte ikke findes, så returnér -1 (kan ikke være indeks) hvis det søgte findes, så returnér indekset i (som er ); Lad derfor søgerutinen (feks binsearch) returnere søgeresultatet direkte: Undgå klassevariable hvis muligt alle klassens metoder kan se og ændre dem Bedre programmeringsstil Programmering 1999 KVL Side 17-15 Så Men ifølge løkkeinvarianten kan, og heller ikke i Dvs og dækker hele, så Dvs Så må (a <= b) være falsk, altså falsk Eller found er lig false, dvs!found er sandt Enten er found lig true, og så Så må betingelsen (!found && a <= b) være falsk Når løkken er standset
" " #!!elementer kræver Brug af den forbedrede søgemetode Test altid resultatet af søgningen Det giver mere robuste programmer Eksempel på brug: public static void main(string[] args) int[] myarray = 17, 2, 28, 33, 35, 39, 39, 51, 52, 57, 62, 69, 74, 84, 84, 86, 88, 95, 97; int key = IntegerparseInt(args[]); int r = binsearch(key, myarray, myarraylength); if (r >= ) Systemoutprintln("Found at index " + r + "\n"); else Systemoutprintln("Not found\n"); static int binsearch(int x, int[] arr, int n) Programmering 1999 KVL Side 17-17 Nu til noget helt andet: Sortering Der er mange, grundlæggende forskellige, måder at sortere en liste af tal eller navne på En af de simpleste (og langsomste) er udvalgssortering Udvalgssortering Find mindste element, sæt det på 1 plads Find næstmindste element, sæt det på 2 plads Find tredjemindste element, sæt det på 3 plads osv Programmering 1999 KVL Side 17-18 Programmering 1999 KVL Side 17-2 static void swap(int[] arr, int s, int t) int tmp = arr[s]; arr[s] = arr[t]; arr[t] = tmp; Ombyt elementerne i (og ): Hjælpeerklæringer Programmering 1999 KVL Side 17-19 Vi skriver " er asymptotisk begrænset af en funktion proportional med Men dominerer for store, så Dvs $% &! ' '' Totale antal sammenligninger:, så Tidsforbrug At finde det mindste af Vi skal finde det mindste af,, så 2, så 1 elementer sammenligninger
Programmering 1999 KVL Side 17-22 Efter den ydre løkke, ved pp4: de mindste elementer, sorteret øvrige elementer Ved pp3 (som er løkkeinvariant): øvrige elementer Ved pp2 (som er løkkeinvariant), efter gentagelser: usorterede elementer Før den ydre løkke, ved pp1: Øjebliksbilleder for den ydre løkke Programmering 1999 KVL Side 17-21 public static void selsort(int[] arr, int n) / pp1 / for (int i = ; i < n; i++) / pp2 / int least = i; for (int j = i+1; j < n; j++) if (arr[j] < arr[least]) least = j; swap(arr, i, least); / pp3 / Programmering 1999 KVL Side 17-24 +, )( Efter den indre løkke, ved pp24: +, )( Ved pp23 (som er løkkeinvariant): +, )( Ved pp22 (som er løkkeinvariant): Før den indre løkke, ved pp21: Øjebliksbilleder for den indre løkke Programmering 1999 KVL Side 17-23 for (int j = i+1; j < n; j++) / pp22 / if (arr[j] < arr[least]) / pp23 / least = j; / pp24 / int least = i; / pp21 / Den indre løkke
Programmering 1999 KVL Side 17-26 Husk at scompareto(t) er negativ hvis s kommer før t i leksikografisk ordning public static void selsort(string[] arr, int n) / pp1 / for (int i = ; i < n; i++) / pp2 / int least = i; for (int j = i+1; j < n; j++) if (arr[j]compareto(arr[least]) < ) least = j; swap(arr, i, least); / pp3 / Metoden selsort skal sammenligne to strenge: private static void swap(string[] arr, int s, int t) String tmp = arr[s]; arr[s] = arr[t]; arr[t] = tmp; Metoden swap skal ombytte to strenge (ikke heltal): - tering af tabeller af tegnstrenge Sor Programmering 1999 KVL Side 17-25 Hvordan sortere tabeller af tegnstrenge eller noget andet Indtil nu har vi sorteret tabeller af heltal Læs alle linier fra en fil, sortér dem alfabetisk, og skriv dem ud Karl-Erik Lillegade 15 Børge Lillegade 9 Peter Ørnebakken 4 Anna Lillegade 8 Dines Fredsvej 11 Neil Bukkeballevej 88 Jørgen Skjoldagervej 2 Christian Bondehavevej 135 Peter Begoniavej 2 En adresseliste: Eksempel 1: Sortering af tekstlinier Brug af udvalgssortering Programmering 1999 KVL Side 17-28 Der findes meget bedre sorteringsalgoritmer end udvalgssortering (se næste gang) Udvalgssortering er simpel men langsom: Et givet problem (feks søgning) kan løses på vidt forskellige måder Data skal være sorterede for at binær søgning virker (sortering er nyttig) Binær søgning er meget hurtig: Lineær søgning er simpel men langsom: Husk: Læs noterne Searching and sorting with Java, side 1 17 Programmering 1999 KVL Side 17-27 public static void main(string[] args) throws FileNotFoundException, IOException String[] lines = new String[1]; int n = readfile(lines, "addrlisttxt"); selsort(lines, n); printout(lines, n); Indlæs, sortér og udskriv: Hovedprogrammet (metoden main) public static void printout(string[] arr, int n) for (int i=; i < n; i++) Systemoutprintln(arr[i]); Udskrift af en tabel af strenge Effekt: gemmer de læste linier i arr Resultat returnerer antallet af læste linier Indlæser tekstlinier fra filen filename til tabellen arr; returnerer antal læste linier public static int readfile(string[] arr, String filename) Indlæsning af strenge fra en tekstfil til en tabel