• Nie Znaleziono Wyników

ALGORYTMY I STRUKTURY DANYCH

N/A
N/A
Protected

Academic year: 2021

Share "ALGORYTMY I STRUKTURY DANYCH"

Copied!
26
0
0

Pełen tekst

(1)

ALGORYTMY I STRUKTURY DANYCH

WYKŁAD 06 c.d. Sortowanie Grażyna Mirkowska

PJWSTK , semestr zimowy 2002

(2)

Plan wykładu

Szybkie sortowanie

Drzewa decyzyjne

Dolne oszacowanie złożoności problemu sortowania przez porównywanie elementów

Sortowanie z kosztem liniowym

Sortowanie koszykowe Sortowanie przez zliczanie

(3)

Szybkie sortowanie

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 3. Posortować elementy znajdujące się na prawo od mediany.

Krok 2. Posortować elementy na lewo od mediany.

Metoda :

(4)

Przykład wykonania

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

Stosujemy

rekurencyjnie tę samą zasadę do obu części

3 4 1 5 8 7

1 3 4 7 8

14 12

1 3 4 5 7 8 10 12 14

(5)

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

Algorytm Split

{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]

lewy  prawy

(6)

Najgorszy przypadek

Koszt Operacji rozdzielania SPLIT dla n elementowego ciągu wynosi n-1 porównań.

Koszt pesymistyczny algorytmu Quicksort mierzony liczbą porównań wynosi :

W(n) = (n 2)

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.

W(n) = (n-1) +W(n-1)= i=2...n (i-1) = (n2)

(7)

Koszt średni

Koszt średni algorytmu QuickSort, mierzony liczbą porównań, wynosi

A(n) = (n lg n)

A(n) = (n-1) + j=1...n (1/n (A(j-1) + A(n-j))) A(0) = 0

1 j n

j-1 n-j

Zakładamy, że wszystkie ustawienia elementów w ciągu i każdy podział w wyniku Split są jednakowo

prawdopodobne.

A(0) = 0

A(n) = (n-1) + j=1...n-1 A(j) 2/n A(n)=cn lg n

(8)

Drzewo decyzyjne

Niech SORT oznacza dowolny algorytm rozwiązujący problem sortowania przez porównywanie elementów.

Drzewem decyzyjnym dla algorytmu SORT nazywamy drzewo lokalnie pełne (tzn. każdy wierzchołek ma 0 albo 2 następniki) takie, że

- etykietami wierzchołków są zdania opisujące relacje między elementami,

- etykietami liści są uporządkowane permutacje wynikające z relacji między elementami na ścieżce prowadzącej do tego liścia.

(9)

Przykład

Drzewo decyzyjne dla algorytmu Selection_sort zastosowanego do ciągu 3 elementowego e1,e2, e3.

e1  e2

e1  e3 e2  e3

e2  e3 e2  e1 . . . e2  e1

e1,e2,e3 e1,e3, e2 e3,e2,e1

e3,e1,e2

Tak Nie

(10)

Przykład

Drzewo decyzyjne dla algorytmu Insertion_sort zastosowanego do 3 elementowego ciągu e1,e2, e3.

e1  e2

e2  e3 e3  e1

e1,e2, e3 e1  e3 e2  e3 e2, e1,e3

e1,e3,e2 e3,e1,e2

Tak Nie

e2,e3,e1 e3,e2,e1

(11)

Własności drzew decyzyjnych

Jeżeli f jest liczbą liści w drzewie binarnym, a h jego wysokością, to

(i) f  2 h (ii) h  lg f

(i) Indukcja po h.

h

h+1 y

(ii) Z (i) przez logarytmowanie.

Krok indukcyjny: f  2y + (2 h - y) = y+2 h  2 h + 2 h

y=Nie- liście na poziomie h

(12)

Oszacowanie w najgorszym przypadku

Każde drzewo decyzyjne dla algorytmu sortującego ciąg n- elementowy przez porównywanie elementów, ma co najmniej wysokość log n! 

Każdy algorytm sortujący ciąg n elementowy przez porównywanie elementów musi wykonać co najmniej log n!  porównań w najgorszym wypadku.

Drzewo decyzyjne ma co najmniej n! liści. Stąd i z lematu 1 - teza

W(n)   n lg n 

(13)

Własności c.d.

Niech D będzie drzewem binarnym, a p(x) - długość ścieżki od korzenia do liścia x.

Epl(D) = x D p(x)

Wśród drzew lokalnie pełnych o f liściach Df wartość epl(Df) jest najmniejsza, gdy liście znajdują się jedynie na dwóch ostatnich poziomach.

Df . . . . . .

. . . x

y1 y2

Poziom h -1 y

D*f . . . . . .

. . . x

y1 y2

y

Poziom k, k h-2

Epl(D*f) < Epl(Df)

(14)

Minimalne epl.

Min {epl(Df): Df D}= f lg f + 2( f-2 lg f )

Niech Df będzie drzewem, dla którego epl osiąga minimum.

Przypadek 1 f = 2p .

epl(Df)= f * lg f

Poziom p

Df

Wszystkie liście są na poziome p

(15)

Minimalne epl c.d.

Przypadek 2 2 p-1 < f < 2 p.

h

z

Z lematu 1 h  lg f

Z lematu 3 wszystkie liście są na poziomach h i h-1. Czyli h = lg f.

x Df

Liście na poziomie h

Liście na poziomie h- 1 x = f - z

Epl(Df)= x (h-1) + z h =

=(2 h -f)(h-1) + (2f -2h) h = hf + f - 2 h

(16)

Koszt średni

Średnia liczba porównań wykonywanych przez dowolny algorytm sortujący ciąg n-

elementowy przez porównywanie elementów jest nie mniejsza niż lg n! .

Średnia wysokość drzewa decyzyjnego h  epl min(D)/n!

h  (n! lg n! + 2( n!-2 lg n! ))/n!

Czyli 2( n!-2 lg n!  )/n! 0

Ale dla dowolnego x, x/2 2 lgx  x

h  lg n!

(17)

Wniosek

Dolnym ograniczeniem na liczbę porównań wykonanych przez algorytm sortujący przez

porównywanie elementów jest w przypadku średnim

(n lg n).

Algorytm QuickSort jest optymalnym

algorytmem ze względu na średnią złożoność czasową.

(18)

Sortowanie z kosztem liniowym

Załóżmy, że dane wejściowe a[1],...,a[n] są generowane losowo z rozkładem jednorodnym oraz że a[i]  {0,..., k-1}

dla pewnej ustalonej (niezbyt dużej) liczby k.

Krok 1. Utworzyć k pustych koszyków o numerach od 0 do k-1.

Krok2 i-ty element ciągu wkładamy do koszyka o numerze a[i].

Krok 3. Wyjmujemy elementy z kolejnych koszyków od 0 do k-1, otrzymując posortowany ciąg.

(k) Czasu na tworzenie koszyków

(n) Czasu na rozrzucanie elementów

(19)

Sortowanie przez zliczanie

Założenie: dany n elementowy ciąg o elementach z przedziału [1,k], k N.

Metoda polega na znalezieniu dla każdego x liczby

elementów mniejszych równych niż x. Pozwoli to ustalić właściwą pozycję x w tablicy wyjściowej.

6 7 3 2 9 1 8

Powinna trafić na pozycje 4, bo są 3 liczby mniejsze

1 2 3 4 5 6 7 6

7 ma trafić na pozycję 5, bo są 4 elementy od niej mniejsze

7

3 powinna trafić na pozycje trzecią,

3

(20)

Sortowanie przez zliczanie

{ // a- tablica danych, B tablica wyników, C tablica pomocnicza.

for i := 1 to k do C[i] := 0 od;

for j := 1 to n do C[a[j]] := C[a[j]] +1 od;

for i := 2 to k do

C[i] := C[i] + C[i-1]

od;

for j := n downto 1 do B[C[a[j]]] := a[j];

C[a[j]] := C[a[j]] –1 od;

}

C[i] = liczba elementów równych i

C[i] = liczba elementów mniejszych równych i

Na lewo od pozycji C[a[j]] leżą elementy

 od a[j], a na prawo > a[j].

C[a[j]] wskazuje liczbę jeszcze nie wpisanych elemementów  a[j]

O(k+n)

(21)

Przykład

Dana Tablica A: 1 2 3 4 5 6 7 8 --- k=6 n= 8 3 6 4 1 3 4 1 4

C:

1 2 3 4 5 6

B:

1 2 3 4 5 6 7 8 0 0 0 0 0 0

Po pierwszej pętli „for”

2 0 2 3 0 1 Po drugiej pętli „for”Po trzeciej pętli „for”

2 2 4 7 7 8

0 0 0 0 0 0 4 0 0 1 0 0 0 0 4 0 2 2 4 6 7 8

0 2 3 4 7 7 1 2 4 6 7 8

1 1 3 3 4 4 4 6 0 1 0 0 0 4 4 0 1 2 4 5 7 8

0 1 0 3 0 4 4 0 1 2 3 5 7 8

1 1 0 3 0 4 4 0 0 2 3 5 7 8

1 1 0 3 4 4 4 0 0 2 3 4 7 8

1 1 0 3 4 4 4 6 0 2 2 4 7 7

(22)

Sortowanie pozycyjne

Dany jest ciąg n-elementów do posortowania.

Elementy tego ciągu nie są po prostu liczbami naturalnymi, lecz same mają wewnętrzną strukturę, np.. są to skończone ciągi pewnych obiektów (np.. Liczb, cyfr, znaków itd..).

Metoda naiwnego rozrzucania

Rozrzucić elementy danego ciągu do

„koszyków” ze względu na kolejne pozycje w ciągach składowych, tzn.

tworzymy pewną liczbę „koszyków” , tak, że i-ty koszyk odpowiada i-tej pozycji w ciągach składowych.

Następnie sortujemy każdy z koszyków osobno tą samą metodą.

Takie postępowanie jest kosztowne: Dla elementów,

które są ciągami liczb o d cyfrach, trzeba utworzyć 10 d

koszyków!

Takie postępowanie nie zawsze daje poprawny wynik np.. Gdy ciągi nie są

równej długości.

(23)

Radix-Sort

Dane : tablica n-liczb całkowitych o d cyfrach.

For k := 1 to d do

// rozrzuć wszystkie liczby do ‘kubełków’ o numerach 0, //1, 2,...9 ze względu na k-tą od końca cyfrę .

//połącz kubełki w jeden ciąg.

od

T(n) = O(d* n)

Wszystkie elementy, obcięte do k-1 ostatnich pozycji, tworzą ciąg uporządkowany niemalejąco.

(24)

Radix-sort

Dany ciąg : 85 83 63 64 84 15

Stos 3

Po połączeniu : 63 83 84 64 15 85

Po połączeniu : 15 64 63 85 84 83 Stos 4 Stos 5

Stos 1 Stos 6 Stos 8

63 83

84 64

15 85

15

64 63

85 84 83

(25)

c.d. Radix Sort

For k := 1 to d do

// rozrzuć wszystkie liczby do ‘kubełków’ o //numerach 0, //1, 2,...9 ze względu na k-tą //od końca cyfrę .

//połącz kubełki w jeden ciąg.

od

Użyjmy

kolejek jako

‘kubełków’!

Dany ciąg : 85 83 63 64 84 15

Kolejka 3: 83 63 Kolejka 4: 64 84 Kolejka 5: 85 15 83 63 64 84 85 15

Kolejka 1: 15 Kolejka 6: 63 64 Kolejka 8: 83 84 85 15 63 64 83 84 85

(26)

Poprawność

Algorytm RadixSort zaimplementowany z kolejkami ma własność stabilności.

Jeżeli elementy x, y są uporządkowane ze względu na k-1 ostatnich cyfr i wpadają do tego samego ‘kubełka’ to po k-tym przebiegu nadal są w tym samym porządku.

Jeżeli wpadają do różnych kubełków, to po k-tym przebiegu są uporządkowane ze względu na k ostatnich cyfr.

x = x k+1 10 k+1 + xk 10 k + x’

y = y k+1 10 k+1 + yk 10 k + y’

x’ < y’, x’,y’< 10 k

Albo xk=yk i wtedy x i y trafiają do tej samej kolejki oraz x poprzedza y Albo xk<yk ale wtedy x trafi do kolejki o

mniejszym numerze niż y i w takiej kolejności ukażą się po połączeniu

Albo xk>yk ale wtedy x trafi do kolejki o numerze większym niż y i po połączeniu y ukaże się przed x

Cytaty

Powiązane dokumenty

Zadanie Do zbioru reprezentowanego przez drzewo D dołączyć element e, o ile nie należy on jeszcze do etykiet drzewa D.... Zastosowanie: wyszukiwanie

(3) Jeżeli tak otrzymane drzewo nie jest częściowo uporządkowane, to przechodząc wzdłuż drogi od liścia x do korzenia, poprawić etykiety zamieniając etykietę ojca z

Jeśli element e należy do kolejki q, to po skończonej liczbie usunięć kolejnych elementów minimalnych.. dotrę do tego

takie drzewo &lt;V, T&gt; rozpinające grafu G, że suma kosztów jego krawędzi  eT c (e) jest najmniejsza.. Mirkowska, ASD_12 Algorytmy na

Niech będzie tekst 100000 znakowy, w którym występują tylko litery a,b,c,d,e,f i a-45tys razy, b-13tys., c-12tys.,.. d-16tys., e -

Powiemy, że problem jest rozstrzygalny, jeśli istnieje algorytm, który dla dowolnych danych x po skończonej liczbie kroków daje rozwiązanie problemu. W przeciwnym

Dowód przez indukcję ze względu na liczbę wywołań rekurencyjnych funkcji min_max.. Dla jednego tylko wywołania

Problem Dany jest ciąg rosnący e[1],..,e[n] oraz element x pewnej przestrzeni liniowo uporządkowanej &lt;E, &gt;. Następnie porównujemy x z kolejnymi elementami ciągu