INF1010 Sortering Marit Nybakken marnybak@ifi.uio.no 1. mars 2004 Dette dokumentet skal tas med en klype salt og forfatter sier fra seg alt ansvar. Dere bør ikke bruke definisjonene i dette dokumentet på eksamen, de er bare ment som en forklaring, ingen streng definisjon. Sortering av kort Sortering brukes i mange sammenhenger når vi programmerer, Vi skal nå se på en enkel form for sortering av en array, kalt innstikkssortering. Navnet kommer av sorteringen man gjør når man spiller kort og har fått utdelt en ny hånd, og vi skal se på nettopp en slik korthånd når vi skal lære oss denne metoden. Forfatteren har her ikke giddet å tegne bildekort, og det må bare beklages. Vi har her fem kort på hånden, og rekkefølgen er nå usortert (se figur 1). Ess regnes nå som 1. Kortene representeres i programmet som en array på 5 heltall: int [] kort = {5, 1, 10, 3, 7 Over kortene ser vi hvilken indeks tallene ligger på i arrayen. Kløver 5 ligger på indeks 0, kløver 7 ligger på indeks 4 (se figur 1). Algoritmen for å sortere kortene i stigende rekkefølge går som følger: 1
Plukk ut det første usorterte kortet fra venstre. Flytt det mot venstre helt til vi finner en plass der kortet til venstre igjen er mindre enn kortet vi prøver å sette inn. Disse kortene er nå sortert. Kløver 5 er sortert med hensyn på seg selv, så vi går videre til hjerteresset. Vi plukker det ut av hånden (se figur 2) Hjerteresset skal nå flyttes til venstre for kløver fem. Først må kløver fem flyttes en plass til høyre, fra indeks 0 til indeks 1. Deretter kan vi putte inn hjerteress på indeks 0, helt til venstre. Nå er de to første kortene sortert (se figur 3) Deretter plukker vi ut det tredje kortet, ruter ti, på indeks 2 (se figur 4) Dette sto allerede på riktig sted, da ti er større enn fem. Vi putter det derfor inn igjen (se figur 4). Deretter plukker vi ut det fjerde kortet på indeks 3, ruter tre. Ruter ti er høyere, så vi flytter ruter ti en plass mot høyre, fra indeks 2 til indeks 3. Så ser vi på kløver fem. Denne er også høyere, så vi flytter den en indeks mot høyre, fra 1 til 2. Deretter ser vi på esset. Dette er lavere. Dermed skal ruter tre inn på indeks 1 (se figur 5). Nå er de fire første kortene sortert (se figur 6). Til slutt plukker vi ut kløver 7. 7 er lavere enn 10, så ruter 10 flyttes en plass mot høyre, fra indeks 3 til 4. Kløver 7 er høyere enn kløver 5, så vi kan putte inn kortet der (se figur 7). Nå er alle kortene sortert (se figur 8). 2
Figur 1: Den opprinnelige korthånden Figur 2: Plukker ut hjerteress, som er mindre enn kløver fem 3
Figur 3: De to første kortene er sortert Figur 4: 10 plukkes ut og puttes tilbake på samme sted 4
Figur 5: Plukker ut ruter tre, og flytter det inn etter hjerter ess. Kløver fem og ruter ti flyttes mot høyre Figur 6: De fire første kortene er sortert 5
Figur 7: Plukker ut kløver syv, og flytter det inn etter kløver 5. Ruter ti flyttes en plass mot høyre. Figur 8: Alle fem kortene er sortert. 6
Sortering av heltall, kode Nå skal vi skrive kode som gjør det samme som vi gjorde med kortene, altså: for(i=1:siste indeks i kortarray) { <plukk ut kort på indeks i>; // første usorterte while(indeks >= 0 && <funnet riktig plassering>) { if(<kort på indeks > utplukket kort>) { <flytt kort på indeks et hakk til høyre>; else { <riktig plassering funnet, avbryt>; 10 <putt inn kortet på indeks>; Nå prøver vi oss på ekte java-kode og sorterer alle kortene i en array kort: // Gå gjennom alle kortene. // Det første er sortert i forhold til seg selv, så vi starter // på det andre kortet. for(int i = 1; i < kort.length; i++) { // Plukk ut kortet på denne plassen int kort plukket ut = kort[i]; // Start på kortet til venstre for i og gå til venstre 10 // Fortsett til vi har kommet til den første plassen // eller kortet til venstre er større enn kortet vi plukket ut int j=i 1; boolean plass funnet = false; while(j >= 0 &&!plass funnet) { // kortet er større enn det vi plukket ut if(kort[j] > kort plukket ut) { // Da må dette kortet flyttes til høyre kort[j+1] = kort[j]; 20 // Gå enda et hakk til venstre for å se på neste kort 7
j ; else { // avbryt, vi har funnet riktig plassering plass funnet = true; // Nå kan vi putte inn kortet på den ledige plassen 30 // telleren j tellet seg et hakk for // langt før den stoppet, så den må økes med 1 kort[j+1] = kort plukket ut; Vi legger koden inn i en metode, og tester ut metoden: // Enkelt eksempel på innstikkssortering class Sortering { // Denne metoden ser ikke helt lik ut som den i boken, men // den fungerer nesten helt likt, og er forhåpentligvis // litt enklere å lese void sorter(int [ ] kort) { 10 // Gå gjennom alle kortene. // Det første er sortert i forhold til seg selv, så vi starter // på det andre kortet. for(int i = 1; i < kort.length; i++) { // Plukk ut kortet på denne plassen int kort plukket ut = kort[i]; // Start på kortet til venstre for i og gå til venstre 20 // Fortsett til vi har kommet til den første plassen // eller kortet til venstre er større enn kortet vi plukket ut int j=i 1; boolean plass funnet = false; while(j >= 0 &&!plass funnet) { // kortet er større enn det vi plukket ut if(kort[j] > kort plukket ut) { // Da må dette kortet flyttes til høyre kort[j+1] = kort[j]; 30 // Gå enda et hakk til venstre for å se på neste kort 8
j ; else { // avbryt, vi har funnet riktig plassering plass funnet = true; // Nå kan vi putte inn kortet på den ledige plassen 40 // telleren j tellet seg et hakk for // langt før den stoppet, så den må økes med 1 kort[j+1] = kort plukket ut; // Her tester vi ut sorteringsmetoden public static void main(string [ ] args) { // Liten hånd med kort int [ ] kort = {5, 1, 10, 3, 7; 50 Sortering s = new Sortering(); // Sorter kortene // (Sender vi en array over til en metode, synes // endringene arrayen har gjort på metoden etter // metoden har kjørt ferdig. Trenger derfor ikke å få den // returnert) 60 s.sorter(kort); // Skriv ut de sorterte kortene for(int i=0;i<kort.length;i++) { System.out.print(kort[i] + ","); 70 Denne metoden er den raskeste når vi har færre enn 50(?) elementer. Den fungerer også fint for andre ting enn heltall, det eneste som må endres er linjen der vi sammenligner et element med et annet. 9