ALGORYTMY I STRUKTURY DANYCH WYKŁAD 04 Problem Sortowania Grażyna Mirkowska PJWSTK, 2003/2004
G. Mirkowska, ASD 04 Sortowanie Plan wykładu Sformułowanie problemu Sortowanie przez porównywanie elementów Sortowanie przez wstawianie Sortowanie przez selekcję Operacja scalania ciągów uporządkowanych Sortowanie przez scalanie Szybkie sortowanie 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
Sformułowanie problemu Dany jest ciąg e elementów e1,e2,... , en należących do pewnej liniowo uporządkowanej przestrzeni <E, >. Znaleźć taką permutację i1, i2,... ,in liczb 1,..., n aby ei1ei2 ... ein lub Znaleźć taką funkcję różnowartościową i „na” f : {1,2...,n} {e1,e2,... , en }, że dla każdego i<n, f(i) f(i+1). 3 6 2 1 4 5 7 1 2 3 4 5 6 7 5 3 1 6 7 2 8 1 2 3 5 6 7 8 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
Sortowanie przez selekcję Metoda Sortowanie odbywa się w n-1 przebiegach. W i-tym przebiegu szukamy i-tego najmniejszego elementu. Algorytm { for i := 1 to n-1 do min := i; j := i+1; while j < n+1 do if e[j] < e[min] then min := j fi od; swap(e[i],e[min]); od } Selection_sort min e[i] Odcinek uporządkowany 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
G. Mirkowska, ASD 04 Sortowanie Diagram przepływu i := 1 e[1] ... e[i-1] {e[i],...,e[n]} nie i < n tak e[1] ... e[i-1] {e[i],...,e[n]} Niezmienik Znajdź x takie, że x = minimum( e[i],..., e[n]) i := i+1 x {e[i],...,e[n]} Zamień miejscami x i e[i] e[1] ... e[i-1] e[i] {e[i+1],...,e[n]} 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
G. Mirkowska, ASD 04 Sortowanie Koszt algorytmu Twierdzenie Algorytm Selection_sort jest poprawnym rozwiązaniem problemu sortowania. W dowolnej strukturze danych, której elementy są liniowo uporządkowane przez relację , algorytm zatrzymuje się dla dowolnych danych i daje w wyniku ciąg uporządkowany niemalejąco. A. Jeśli operacją dominującą jest porównywanie elementów: Koszt algorytmu T(n) = n-1 + n-2 + ... +2 + 1 = n(n-1)/2 = (n2) B. Jeśli operacją dominującą jest zamiana elementów T(n) = 1*(n-1) = n-1 = (n) 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
Sortowanie przez wstawianie Sortowanie odbywa się w n -1 przebiegach. W i-tym przebiegu elementy na pozycjach 1...(i-1) są już uporządkowane, a wstawiamy i-ty element przepychając go do przodu na właściwe miejsce, tak by stworzył wraz z innymi ciąg uporządkowany długości i. Metoda 4 8 5 3 9 6 4 8 5 Przykład 4 5 8 3 9 6 3 4 5 3 8 9 6 Odcinek uporządkowany i-ty element X 4 3 5 8 9 6 3 4 5 8 9 6 9 3 4 5 8 9 6 6 itd 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
G. Mirkowska, ASD 04 Sortowanie Schemat algorytmu start Niezmiennik i := 2 e[1]... e[i-1] , i < n+2 Nie i < n+1 stop Tak e[ 1]... e[i-1] , i<n +1 Umieść e[i] wśród elementów e[1],e[2],...e[i-1], przesuwając elementy większe o jedno miejsce w prawo, tak by ciąg i-pierwszych elementów był uporządkowany e[ 1]... e[i-1] e[i] , i<n +1 e[ 1]... e[i-2] e[i-1], i<n +2 i := i+1 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
Algorytm Insertion_sort {for i := 2 to n do j := i; pom := e[i]; while ( j>1 andif e[j-1]> pom ) do e[j] := e[j-1]; j := j-1 od; e[j] := pom od} e[ 1]... e[i-1] e[ 1]... e[j-1] pom=e[i], j=i pom< e[ j+1]... e[i], pom <e[j-1] Analiza pętli wewnętrznej Pom < e[ j]e[j+1]... e[i] pom< e[ j+1]... e[i] e[ 1] ... e[j-1] pom< e[ j+1]... e[i] e[ 1] ... e[j-1] e[j] < e[ j+1]... e[i] 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
Poprawność sortowania przez wstawianie Algorytm sortowania przez wstawianie poprawnie rozwiązuje problem sortowania w każdej liniowo uporządkowanej strukturze danych. Twierdzenie Algorytm sortowania przez wstawianie jest, w każdej liniowo uporządkowanej strukturze danych, całkowicie poprawny ze względu na warunek początkowy n>0 i warunek końcowy (1<i n) e[i-1] e[i] . 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
Koszt sortowania przez wstawianie Operacja dominująca - porównywanie elementów. W(n) = i=2...n (koszt maksymalny pętli wewnętrznej) = i=2...n (i-1) = n(n-1)/2 = O(n2) Element pom z prawdopodobieństwem 1/i może zająć dowolną z pozycji od 1 do i. A(n) = i=2...n (koszt średni pętli wewnętrznej)= = i=2...n (j=1...i j*(1/i)) = i=2...n (1/i)(i (i+1))/2 = (n+1)(n+2)/4 - 1.5 = (1/4)n2 +O(n) Algorytm sortuje w miejscu. 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
Sortowanie przez scalanie Idea : dziel i zwyciężaj ! (1) Dzielimy zadanie posortowania całego ciągu na dwa podzadania: posortowania jego lewej i prawej połowy. (2) Gdy obie części tworzą już ciągi uporządkowane, wtedy scalamy je otrzymując rozwiązanie. 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
G. Mirkowska, ASD 04 Sortowanie Przykład 16 5 12 4 10 6 1 13 15 7 1 14 9 3 8 11 16 5 12 4 10 6 1 13 15 7 1 14 9 3 8 11 16 5 12 4 10 6 1 13 15 7 1 14 9 3 8 11 16 5 12 4 10 6 1 13 5 16 4 12 6 10 1 13 i.t.d. 4 5 12 16 1 6 10 13 1 4 5 6 10 12 13 16 1 3 7 8 9 11 14 15 1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
G. Mirkowska, ASD 04 Sortowanie Operacja scalania Dane są dwa ciągi X i Y, uporządkowane niemalejąco, x1,...xn i y1,...ym. Utworzyć ciąg e=e1,...e n+m złożony z elementów obu ciągów uporządkowany niemalejąco. Wp = {n>0 m>0, x1... xn i y1... ym } Wk = { e1... en+m , (in+m)( j)( ei= xj lub ei = yj)} 2 4 5 8 9 X : 1 3 6 7 Y : Przykład 1 2 3 4 5 6 7 8 9 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
G. Mirkowska, ASD 04 Sortowanie Algorytm scalania {i:=1; j := 1; k :=1, while (i n and j m) do if x[i]< y[j] then e[k] := x[i]; i := i +1 else e[k] := y[j]; j := j +1 fi; k := k+1; od; Niezmiennik {k= i+j-1, e[1]... e[k-1] i wszystkie elementy x[1],...,x[i-1] oraz y[1],...,y[j-1] zostały już umieszczone na pozycjach od 1 do k-1 w ciągu e .} if ( j > m) then for i := i to n do e[k] := x[i]; k := k+1 od Else for j := j to m do e[k] := y[j]; k := k+1 od} Koszt : O(n+m) 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
Specyfikacja procedury scal(k,x,l) Wersja procedury scal (lewy,x,prawy) użyta w algorytmie Sortowania przez scalanie ma następującą specyfikację Wp = {lewy x prawy e[lewy] e[lewy+1] … e[x] e[x+1] e[x+2] … e[prawy]} Wk = {e[lewy] e[lewy+1] …e[x] e[x+1] … e[prawy] } Twierdzenie (*) Procedura scal(k, x,l) zastosowana do dowolnego ciągu e[1],...,e[n] jest całkowicie poprawna ze względu na podaną wyżej specyfikację. 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
Sortowanie przez scalanie Jeśli lewy = prawy, to jest tylko jeden element w naszym ciągu. procedure MS(lewy, prawy : integer); begin if prawy>lewy then x := (lewy+ prawy) div 2; MS(lewy,x); MS(x+1, prawy); scal (lewy, x, prawy) fi end MS; W tym wywołaniu rozważamy lewą „połowę” danego ciągu Merge-sort Z założenia indukcyjnego : e[lewy] ... e[x] Z założenia indukcyjnego :e[x+1] ... e[prawy] Na mocy Tw (*) : e[lewy] ... e[prawy] W tym wywołaniu rozważamy prawą „połowę” danego ciągu 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
Koszt algorytmu Merge_Sort Załóżmy, że n = 2 p. wtedy T(n) = T(n/2) + T(n/2) + cn T(1) = 0 Po podstawieniu mamy T(2 0) = 0 T(2 p) = 2 T(2 p-1) +c n T(2 p ) = 2 T(2 p-1) + c2 p = 2(2T(2 p-2) +c 2 p-1) + c2 p = 2 2 T(2p-2 ) + c2 p + c2 p = ...= 2 p T(2 0 ) + cp 2 p = ( n lg n) T(n) = (n lg (n)) Ostatecznie : 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
G. Mirkowska, ASD 04 Sortowanie Szybkie sortowanie Dziel i zwyciężaj Metoda : Krok 1. Rozdzielić elementy danego ciągu e1,e2,... ,en na dwie części względem pewnego ustalonego elementu, tzw. mediany, tak by a lewo od niego znajdowały się elementy mniejsze, a na prawo elementy większe. Krok 2. Posortować elementy na lewo od mediany. Krok 3. Posortować elementy znajdujące się na prawo od mediany. 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
G. Mirkowska, ASD 04 Sortowanie Przykład wykonania split 10 5 7 8 14 12 3 4 1 Rozdzielanie ze względu na wybraną medianę 5 7 8 1 4 3 10 12 14 3 4 1 5 8 7 12 14 Stosujemy rekurencyjnie tę samą zasadę do obu części 1 3 4 7 8 1 3 4 5 7 8 10 12 14 Ostatecznie : 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
Sortowanie szybkie - algorytm Dane: n>0, ciąg e[1],..., e[n]. procedure QS(lewy, prawy) {if (prawy > lewy) then Split (lewy, prawy,j); QS(lewy,j-1); QS(j+1,prawy); fi } lewy prawy Quick_sort {e[lewy],..., e[j-1]}< e[j] {e[j+1],...,e[prawy]} e[lewy] ... e[j-1] e[j] {e[j+1],...,e[prawy]} e[lewy] ... e[j-1] e[j] e[j+1] ... e[prawy] 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
Jak wygląda najgorszy przypadek ? Koszt pesymistyczny algorytmu Quicksort mierzony liczbą porównań wynosi : W(n) = (n 2) Twierdzenie Jak wygląda najgorszy przypadek ? 1 2 3 4 5 6 7 8 9 Jeśli Split jako medianę wybiera zawsze pierwszy element, to w wyniku rozdzielenia, jedna część „młodsza” będzie pusta , a druga „starsza” będzie zawierała o jeden element mniej niż w poprzednim kroku. Koszt Operacji rozdzielania SPLIT dla n elementowego ciągu wynosi n-1 porównań. Ostatecznie : W(n) = (n-1) +W(n-1)= S i=2...n (i-1) = (n2) 2019-05-04 G. Mirkowska, ASD 04 Sortowanie
G. Mirkowska, ASD 04 Sortowanie Koszt średni Zakładamy, że wszystkie ustawienia elementów w ciągu i każdy podział w wyniku Split są jednakowo prawdopodobne. Koszt średni algorytmu QuickSort, mierzony liczbą porównań, wynosi A(n) = (n lg n) Twierdzenie 1 n j j-1 n-j A(n) = (n-1) + S j=1...n (1/n (A(j-1) + A(n-j))) A(0) = 0 Przyjmijmy, że A(i) <= cilg i = c lg e i ln i. Udowodnimy, że A(n) <= cn lg n W dowodzie sume zastępujemy całką Ostatecznie : A(0) = 0 A(n) = (n-1) + S j=1...n-1 A(j) 2/n A(n)=cn lg n 2019-05-04 G. Mirkowska, ASD 04 Sortowanie