Sökning och sortering Sökning och sortering - definitioner Att söka efter data man lagrat undan för senare användning är vanligt Egentligen har man ingen annan anledning för att lagra undan data Har man mycket data och många sökningar måste man fundera över hur man organiserar sina data Riktigt stora mängder data organiseras i specialapplikationer som kallas databaser (en annan kurs) Vi tittar på det mest grundläggande, leta i mindre datamängder, sortera mindre datamängder för snabbare sökning För att förenkla resonemanget tittar vi på numeriska data som vi organiserar på enklast möjliga sätt, i kontinuerliga listor CONST low = 1; {Kan variera, naturligtvis} high = 8; {Kan oxå variera} TYPE index = low..high; keytype = Integer; vector = ARRAY [index] OF keytype; VAR lista : vector; found : Boolean; location : index; DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 1 / 22 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 2 / 22 Sökning i oordnad lista Sökning med vaktpost i oordnad lista VAR i : index; i := first; WHILE (i <= last) AND (NOT found) DO IF lista[i] = key THEN found := TRUE; location := i END ELSE i := Succ(i) Man kan använda sig av ett trick för att förenkla villkoren i slingan. Man låter det finnas en extra plats (plats 0) där man lagrar det man söker. Då kan man söka bakifrån och slippa kolla index, man hittar ju senast på plats 0. Man kallar det för att använda vaktpost: location := last; lista[0] := key; WHILE lista[location] <> key DO location := Pred(location); found := (location > 0) AND (lista[location] = key) Om listan är ordnad behöver vi inte söka igenom hela listan. Elementen i listan är i stigande ordning. DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 3 / 22 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 4 / 22
Sökning i ordnad lista Sökning med vaktpost i sorterad lista Även här kan man använda vaktpost: VAR i: index; i := first; WHILE (IF i <= last) AND (lista[i] <= key) AND (NOT found) DO IF lista[i] = key THEN found := TRUE; location := i END ELSE i := Succ(i); location := last; lista[0] := key; WHILE lista[location] > key DO location := Pred(location); found := (location > 0) AND (lista[location] = key) Om vi har poster i vektorn: ändra lista[i] = key; resp lista[i] > key; till lista[i].key = key; resp lista[i].key > key; DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 5 / 22 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 6 / 22 Sökning i oordnad länkad lista Sökning i ordnad länkad lista PROCEDURE search(var lista: listptr; key: keytype; VAR found: Boolean; VAR location: elementptr); VAR elementref: elementptr; elementref := lista^.first; location := NIL; WHILE (elementref <> NIL) AND (NOT found) DO IF elementref^.key = key THEN found := true; location := elementref END ELSE elementref := elementref^.next; Och om den är sorterad i stigande ordning använder vi found för att hitta platsen där elementet borde finnas: PROCEDURE search(var lista: listptr; key: keytype; VAR found: Boolean; VAR location: elementptr); VAR elementref: elementptr; elementref := lista^.first; location := NIL; WHILE (elementref <> NIL) AND (NOT found) DO IF elementref^.key = key THEN found := true; location := elementref END ELSE IF elementref^.key > key THEN found := true ELSE elementref := elementref^.next; found:= location <> NIL; Vi får eventuellt definiera egna jämförelseoperatorer (=, <, >, osv.) DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 7 / 22 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 8 / 22
Sökning i sorterad lista binärsökning Binärsökning Om vi söker i en sorterad vektor kan vi söka på ett smartare sätt: Intervallhalveringsmetoden kallas vid sökning för binärsökning. 1. mid := (left+right) / 2 2. om v[mid] >= key så right := mid annars left := mid 3. Om left < right så fortsätt från 1 PROCEDURE binsearch(var v: vector; VAR found: Boolean; key: item; VAR location: index; left,right: index); VAR mid: index; WHILE left < right DO mid := (left + right + 1) DIV 2; IF key < v[mid] right := mid - 1 ELSE left := mid location := left; found := v[left] = key DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 9 / 22 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 10 / 22 Sortering Urvalssortering Så gott som varje program innehåller delar för att sortera data Om vi söker ofta i våra data och om vi har mycket data blir sortering viktig Eftersom sortering är ett vanligt och tidskrävande moment i bearbetningen har mycket arbete lagts ner på att ta fram bra metoder Vi skall titta på tre enkla (långsamma) metoder. 1. Sök reda på minsta elementet 2. Byt första och minsta elementen med varandra 3. Om det finns fler element: Sortera resten med samma metod. 23 17 5 13 9 22 2 15 2 17 5 13 9 22 23 15 2 5 17 13 9 22 23 15 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 11 / 22 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 12 / 22
Urvalssortering i Pascal Urvalssortering i Scheme PROCEDURE selectionsort(var lista: vector; first, last: index); VAR minpos, i, j : Index; FOR i := first TO last -1 DO minpos := i; FOR j := i + 1 TO last DO IF lista[j] < lista[minpos] THEN minpos := j; swap(lista, i, minpos) END (define (selection-sort lista) (define (sort lista sorterad-lista) (if (null? lista) sorterad-lista (let ((min (find-min (cdr lista) (car lista)))) (sort (delete min lista) (append sorterad-lista (list min)))))) (sort lista ())) DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 13 / 22 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 14 / 22 Utbytessortering Utbytessortering 1. Gå igenom vektorn, jämför grannar och byt om de står fel 2. Sista elementet står rätt, räkna bort! 3. Om det finns fler element: Sortera med samma metod. 23 17 5 13 9 22 2 15 17 5 13 9 22 2 15 23 5 13 9 17 2 15 22 23 5 9 13 2 15 17 22 23 5 9 2 13 15 17 22 23 5 2 9 13 15 17 22 23 PROCEDURE exchangesort(var lista: vector; first,last: index); VAR i, j : index; FOR i := last DOWNTO Succ(first) DO FOR j := first TO Pred(i) DO IF lista[j] > lista[succ(j)] THEN swap(lista, j, Succ(j)); Metoden kan förbättras genom att man avbryter om man inte utfört något byte under ett pass. 2 5 9 13 15 17 22 23 2 5 9 13 15 17 22 23 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 15 / 22 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 16 / 22
Bättre utbytessortering Insättningssortering PROCEDURE exchangesort(var lista: vector; first,last: index); VAR i, j : index; bytt : Boolean; i := last; bytt := true; WHILE bytt AND (i > first) DO bytt := false; FOR j := first TO Pred(i) DO IF lista[j] > lista[succ(j)] THEN swap(lista[j], lista[succ(j)]); bytt := true i := Pred(i); END 1. Betrakta vektorn som en redan sorterad del och en osorterad del. 2. Så länge den osorterade delen inte är tom ta ett tal ur den osorterade delen och sortera in i den sorterade delen. 23 17 5 13 9 22 2 15 17 23 5 13 9 22 2 15 5 17 23 13 9 22 2 15 Den här metoden blir elegantast med vaktpost eftersom det annars blir ganska komplicerade villkor; DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 17 / 22 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 18 / 22 Insättningssortering i Pascal Insättningssortering i Scheme I scheme blir det så här: PROCEDURE insertionsort(var v:vector; first,last: Index); VAR i, sorted: Index; FOR sorted := Succ(first) TO last DO v[0] := v[sorted]; i := Pred(sorted); WHILE v[0] < v[i] DO v[succ(i)] := v[i]; i := Pred(i) v[succ(i)] := v[0] END (define (insertion-sort lista) (define (sortin element lista) (cond ((null? lista) (list element)) ((< element (car lista)) (cons element lista)) (else (cons (car lista) (sortin element (cdr lista)))))) (define (iter-sort lista elements) (if (null? elements) lista (iter-sort (sortin (car elements) lista) (cdr elements)))) (iter-sort () lista)) Metoderna fungerar lika bra för alla typer av element. Ev måste man definiera egna motsvarigheter till >, < och = men i övrigt som förut. Det blir lite mer detaljer för att få ihop koden om vi har diskontinuerliga (länkade) listor men det är inte svårt. DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 19 / 22 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 20 / 22
Hur bra är det här? Enkel analys Alla tre metoderna består av dubbelloop för jämförelse och flyttning av element. För varje element med index 1 i n För varje element i j n <operationer på vektorn> (n i + 1) = n Finns det bättre metoder? i + 1 = n 2 n n + 1 2 + n = n2 2 + n 2 = O(n2 ) a<b a<c b<c c<b a<b a<c a<b b c a c<b a b a<c går inte c a<b a<c b går inte a<b<c Ja! Mer om det senare DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 21 / 22 DA2001 (Föreläsning 20) Datalogi 1 Hösten 2010 22 / 22