Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Rodzaje sortowania (wg pamięci) Wewnętrzne Zbiór do posortowania mieści się w pamięci Zewnętrzne Zbiór do posortowania mieści się w pamięci zewnętrznej,

Podobne prezentacje


Prezentacja na temat: "Rodzaje sortowania (wg pamięci) Wewnętrzne Zbiór do posortowania mieści się w pamięci Zewnętrzne Zbiór do posortowania mieści się w pamięci zewnętrznej,"— Zapis prezentacji:

1 Rodzaje sortowania (wg pamięci) Wewnętrzne Zbiór do posortowania mieści się w pamięci Zewnętrzne Zbiór do posortowania mieści się w pamięci zewnętrznej, np. na dyskach (wykorzystuje się tylko stałą – małą – ilość pamięci wewnętrznej.

2 Rodzaje sortowania (wg operacji) Adaptacyjne Wykonuje się różne sekwencje operacji dla różnych układów danych Nieadaptacyjne Sekwencja wykonywanych operacji nie zależy od kolejności danych.

3 Parametry wydajnościowe sortowania: czas działania algorytmu ilość dodatkowej pamięci zużywanej przez algorytm Wykorzystuje tyle miejsca, ile potrzeba na zapisanie sortowanych danych + mały stos lub tablica Używa reprezentacji w postaci listy połączonej albo innego sposobu pośredniego dostępu do danych, czyli wymaga dodatkowej pamięci na n wskaźników lub indeksów Wymaga dodatkowej pamięci na pełną kopię sortowanych danych

4 Definicja. Sortowanie jest stabilne, jeśli zachowuje względną kolejność elementów o jednakowych kluczach. Przykład. Lista studentów uporządkowana alfabetycznie według nazwisk. Jeśli chcemy ją posortować wg ocen, to studenci mający taką samą ocenę nadal będą w liście ułożeni alfabetycznie.

5 Za operację dominującą będziemy przyjmować porównanie elementów w ciągu. Za złożoność pamięciową S(n) będziemy przyjmować ilość dodatkowej pamięci (oprócz n miejsc pamięci dla elementów w ciągu), potrzebnej do wykonania algorytmu. Zakładamy też, że elementy do posortowania są liczbami całkowitymi umieszczonymi w tablicy – dla ułatwienia.

6 Idea: Wyznaczamy najmniejszy element w ciągu (tablicy) i zamieniamy go miejscami z elementem pierwszym, następnie z pozostałego ciągu wybieramy element najmniejszy i ustawiamy go na drugie miejsce tablicy (zmieniamy), itd. Realizacja w C++ void selekcja (int a[],int l, int r) { for (int i=l; i

7 Przykład: SELEKCJA7 porównań AELEKCJS6 porównań ACLEKEJS5 porównań ACELKEJS4 porównania ACEEKLJS3 porównania ACEEJKLS2 porównania ACEEJKLS1 porównanie

8 Analiza: Załóżmy, że l=0 i r=n-1. W linii pierwszej przykładu mamy n-1 porównań a[j]

9 Policzmy teraz pesymistyczną wrażliwość tego algorytmu. Przypomnijmy, że Ponieważ w procedurze zawsze jest wykonywany ten sam ciąg operacji, niezależnie od danych wejściowych, to Δ(n)=0. Obliczmy na koniec miarę wrażliwości oczekiwanej algorytmu. w procedurze zawsze jest wykonywany ten sam ciąg operacji, niezależnie od danych wejściowych Ponadto S(n)=O(1) Mówimy, że algorytm sortuje w miejscu

10 Zalety: a)Liczba zamian w najgorszym przypadku: n-1. b)Prostota implementacji. c)Zadowalająca szybkość dla małych wartości n. d)Nie wymaga dodatkowej pamięci. Wady: a)Nie jest stabilny. b)Ma dużą złożoność (rzędu kwadratowego), więc nie nadaje się do sortowania długich tablic. c)Jest mało wrażliwy na wstępne uporządkowanie. Algorytm można uczynić stabilnym, zwiększając współczynnik proporcjonalności złożoności.

11 Idea: W i-tym kroku trzeba wstawić element tab[i] na właściwe miejsce w posortowanym fragmencie tab[0]…tab[i-1], wcześniej przesuwając wszystkie elementy większe od niego w tym fragmencie w prawo o 1; powstaje posortowany fragment tab[0]…tab[i+1]. Realizacja w C++ void InsertSort(int *tab) { for(int i=1; i0) && (tab[j-1]>temp)) { tab[j]=tab[j-1]; j--; } tab[j]=temp; }

12 WSTAWIANIE1 porównanie SWTAWIANIE<=2 porównania STWAWIANIE<=3 porównania ASTWWIANIE<= 4 porównania ASTWWIANIE<=5 porównań AISTWWANIE……. AAISTWWNIE AAINSTWWIE AAINNSTWWE<=9 porównań AAEINNSTWWGOTOWE

13 Analiza: W linii pierwszej mamy 1 porównanie, potem maksymalnie 2, itd., aż do maksymalnie n-1 porównań na końcu. Zatem możemy policzyć pesymistyczną złożoność : Ponieważ element tab[i] z równym prawdopodobieństwem może zająć każdą z i-tej pozycji w ciągu tab[0]

14 Jest to zatem kres górny zbioru liczb, które powstają jako różnice ilości operacji dominujących. Zatem od liczby największej z możliwych należy odjąć najmniejszą z możliwych, żeby otrzymać taki kres górny. Ponieważ najmniejszą ilością porównań w każdym kroku n-1iteracji jest jedno porównanie, a największa ilość wyrażą się obliczoną właśnie T max (n)=n(n-1)/2 to = =n(n-1)/2-(n-1)=Θ(n 2 ). Policzmy teraz pesymistyczną wrażliwość tego algorytmu. Przypomnijmy, że Pesymistyczna wrażliwość złożoności czasowej jest zatem duża i możemy się spodziewać dużej zmienności złożoności obliczeniowej.

15 Średnia wrażliwość (czyli miara wrażliwości oczekiwanej): w i-tym kroku mamy: Sumując po wszystkich n-1 iteracjach, dostajemy:

16 Zalety: a)Stabilność. b)Średnio algorytm jest 2 razy szybszy niż algorytm sortowania przez selekcję. c)Optymalny dla ciągów prawie posortowanych. d)Nie wymaga dodatkowej pamięci.

17 Udoskonalenia: Można przestać porównywać elementy, napotkawszy element, który jest nie większy niż wstawiany, bo podtablica z lewej strony jest posortowana – sortowanie adaptacyjne. W pierwszej pętli for wyznaczamy element najmniejszy i umieszczamy go na początku tablicy, następnie sortujemy pozostałe elementy. Standardowo sortuje się zamiany elementów, ale można zrobić przeniesienie większych elementów o jedną pozycję w prawo.

18 Ma prosty zapis. Na czym polega to sortowanie? Przykład 7-elementowej tablicy. Element zacieniowany w pojedynczym przebiegu głównej pętli ulatuje do góry jako najlżejszy. Tablica jest przemiatana od dołu do góry (pętla i) i analizowane są dwa sąsiadujące ze sobą elementy (pętla j); jeśli nie są uporządkowane, to następuje ich zamiana.

19 void bubble(int *tab) { for (int i=1;i=i;j--) if (tab[j]

20 void bubble(int *tab) { for (int i=1;i=i;j--) if (tab[j]=left; j--) if(tab[j-1]>tab[j]) { swap(tab[j-1],tab[j]); k=j; } left=k+1; for(j=left; j<=right; j++) if(tab[j-1]>tab[j]) { swap(tab[j-1],tab[j]); k=j; } right=k-1; } while (left<=right); } Algorytm poprawiony – sortowania przez wstrząsanie.

21 Idea: Jest to również metoda dziel i rządź, ponieważ dzieli tablicę na dwie części, które potem sortuje niezależnie. Algorytm składa się z dwóch kroków: Krok 1: procedura rozdzielania elementów tablicy względem wartości pewnej komórki tablicy służącej za oś podziału; proces sortowania jest dokonywany przez tę właśnie procedurę. Krok 2: procedura służąca do właściwego sortowania, która nie robi w zasadzie nic oprócz wywoływania samej siebie; zapewnia poskładanie wyników cząstkowych i w konsekwencji posortowanie całej tablicy.

22 Sednem metody jest proces podziału, który zmienia kolejność elementów w tablicy tak, że spełnione są trzy warunki: element a[i] znajduje się dla pewnego i na właściwej pozycji w tablicy; Żaden z elementów a[l], …, a[i-1] nie jest większy niż a[i] ; Żaden z elementów a[i+1], …, a[r] nie jest mniejszy niż a[i]. W kółku mamy element rozgraniczający, elementy mniejsze są na lewo, a większe na prawo.

23 Oś podziału

24 Implementacja funkcji partition w C++. ( W nagłówku funkcji tab jest adresem pierwszego elementu tablicy A do posortowania, l i r określają odpowiednio początek i koniec podtablicy A, która będzie dzielona przez funkcję partition.) int partition (int *tab, int l, int r) { int i=l-1, j=r, v=*(tab+r), s; for(;;) { i++; while (*(tab+i)

25 Przeprowadzimy dowód semantycznej poprawności tego algorytmu, stosując metodę niezmienników. Warunek γ ma miejsce, bo poprzedzająca go instrukcja while zakończy się dla i, przy którym v<=A[i], pozostałe nierówności są wynikiem działania tej pętli. Jeśli i=1, wtedy pozostałe nierówności nie wystąpią. Następny warunek δ jest uzupełnieniem γ o podobne jak w warunku γ nierówności A[j]

26 Uzasadnienie, że γ, δ, η, μ, β są niezmiennikami algorytmu partition pozwala na stwierdzenie o indeksie i będącym wartością funkcji partition: A[i] jest na właściwym miejscu w tablicy uporządkowanej, elementy tablicy od A[l] do A[i-1] są mniejsze od A[i], elementy A[i+1] do A[r] są większe lub równe A[i]. Zatem algorytm partition jest częściowo poprawny. Dobra określoność algorytmu jest oczywista. Posiadanie własności stopu wynika z obserwacji, że obie pętle while zawierają liczniki i oraz j, pierwszy rosnący, ograniczony z góry przez r, drugi malejący ograniczony z dołu przez 1. Pętla for będzie skończona ponieważ dla tak określonych liczników zawsze zajdzie warunek i==j.

27 Realizacja w C++ void quicksort (int *tab, int l, int r) { if(r<=l) return; //1-instrukcja int i=partition(tab, l, r); //2-instrukcja quicksort(tab, l, i-1); //3-instrukcja quicksort(tab, i+1, r); //4-instrukcja } Właściwe sortowanie Dowód poprawności: Własność: Dla dowolnej liczności n=r-l sortowanej tablicy algorytm jest semantycznie poprawny. Dowód: Krok1. Algorytm jest semantycznie poprawny dla n=0. Istotnie, wtedy r=l, a zatem r<=l i z postaci 1-instrukcji wynika, że tablica jednoelementowa nie ulegnie zmianie, pozostanie tablicą uporządkowaną. Oznacza to semantyczną poprawność dla n=0.

28 Krok 2. Ma miejsce następujące twierdzenie: jeżeli algorytm jest semantycznie poprawny dla dowolnych n<=k, gdzie k jest dowolną ustaloną liczbą naturalną nieujemną, to jest semantycznie poprawny dla n=k+1. Istotnie. Zauważmy, że 1<=k+1, zatem dla n=r-l=k+1 spełniony jest warunek początkowy α algorytmu partition i program wykona poprawnie instrukcję 1 i 2. Ponieważ l<=i<=r, zatem i-1-l<=r-l-1<=k oraz r-(i+1)=r-i-1<=r-l- 1<=k i na mocy założenia indukcyjnego wywołania algorytmu quicksort w instrukcji 3 i 4 tego algorytmu wykonają się poprawnie, a zatem wykona się poprawnie cały algorytm. Tablica będzie uporządkowana, ponieważ instrukcja 3 poprawnie uporządkuje elementy tablicy od od l-tego do i-1-szego, i-ty jest na właściwej pozycji wobec poprawności algorytmu podział, a instrukcja 4 uporządkuje poprawnie elementy tablicy od i+1-szego do r-tego, co kończy dowód twierdzenia w kroku 2. Wobec spełnienia obu kroków na mocy zasady indukcji matematycznej ma miejsce dowodzona własność.

29 Zależy od tego, czy podziały są zrównoważone, czy nie, a to z kolei zależy od tego, które elementy zostaną wybrane do dzielenia. Algorytm asymptotycznie ma taką złożoność jak sortowanie przez scalanie. Podziały zrównoważone Algorytm może działać tak wolno jak sortowanie przez wstawianie. Podziały niezrównoważone

30 Najgorszy przypadek podziałów: gdy procedura partition tworzy jeden obszar złożony z n-1 elementów, a drugi tylko z 1 elementu. Załóżmy, że takie niezrównoważone podziały będą wykonywane w każdym kroku algorytmu.

31 -koszt podziału -wykonanie dla tablicy jednoelementowej - równanie rekurencyjne Rozwiązujemy rekurencję, iterując: Czy to jest pesymistyczna złożoność obliczeniowa?

32 Niech T max (n) będzie najgorszym czasem działania algorytmu quicksort dla danych wejściowych rozmiaru n. Mamy równanie rekurencyjne: gdzie parametr q przyjmuje wartości od 1 do n-1, ponieważ mamy dwa obszary, z których każdy ma co najmniej 1 element. Zgadujemy, że dla pewnej stałej c. Zatem Przy odpowiednim doborze dużej stałej c

33 Najlepszy przypadek podziałów: T(n)=2T(n/2)+Θ(n) Przypadek 2 tw. o rekurencji uniwersalnej daje rozwiązanie: T(n)= Θ(nlgn) Podział na połowę

34 Jeśli zbadamy różnicę między przypadkiem pesymistycznym a najlepszym, to dostaniemy pesymistyczną wrażliwość algorytmu: Δ(n)=Θ(n 2 -nlg 2 n)

35 Podziały zrównoważone – przypadek średni Przykład podziału w stosunku 9 do1 Przypadek średni jest bliski przypadkowi najlepszemu – udowodnimy!

36 Podziały zrównoważone – przypadek średni (oczekiwana złożoność) Załóżmy, że -wystąpienie dowolnej permutacji n liczb całkowitych jako danych do sortowania jest jednakowo prawdopodobne, - podział permutacji na dwie podtablice i-1 elementową i n-i elementową jest również jednakowo prawdopodobny dla dowolnego i=1,2,…,n. Wtedy średnia złożoność obliczeniowa T sr (n) spełnia warunki: jednakowo prawdopodobne n

37 odejmujemy stronami Stosujemy iteracje…. n+1-sza suma szeregu harmonicznego lub wykorzystanie szacowania sumy za pomocą całki

38 Funkcja harmoniczna: stała Eulera Z całki natomiast: Stąd widać, że

39 Zalety: Praktycznie działa w miejscu (używa tylko niewielkiego stosu pomocniczego). Do posortowania n elementów wymaga średnio czasu proporcjonalnego do nlog 2 n. Ma wyjątkowo skromną pętlę wewnętrzną. Wady: Jest niestabilny. Zabiera około n2 operacji w przypadku najgorszym. Jest wrażliwy (tzn. prosty niezauważony błąd w implementacji może powodować niewłaściwe działanie w przypadku niektórych danych). Średnia złożoność obliczeniowa jest niemal optymalna. Od kiedy w 1960 C.A.R.Hoare go opublikował, zaczęły się pojawiać jego ulepszone wersje – ale algorytm jest tak zrównoważony, że poprawienie programu w jednym aspekcie, pogarsza jego parametry w innym. Jest często stosowany w bibliotekach standardowych. Można go usprawnić ograniczając rekurencję do pewnego ustalonego n, a tablice o mniejszej długości sortujemy nierekurencyjnym algorytmem sortowania.


Pobierz ppt "Rodzaje sortowania (wg pamięci) Wewnętrzne Zbiór do posortowania mieści się w pamięci Zewnętrzne Zbiór do posortowania mieści się w pamięci zewnętrznej,"

Podobne prezentacje


Reklamy Google