Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Wszelkie treści i zasoby edukacyjne publikowane na łamach Portalu www.szkolnictwo.pl mogą być wykorzystywane przez jego Użytkowników wyłącznie w zakresie.

Podobne prezentacje


Prezentacja na temat: "Wszelkie treści i zasoby edukacyjne publikowane na łamach Portalu www.szkolnictwo.pl mogą być wykorzystywane przez jego Użytkowników wyłącznie w zakresie."— Zapis prezentacji:

1 Wszelkie treści i zasoby edukacyjne publikowane na łamach Portalu mogą być wykorzystywane przez jego Użytkowników wyłącznie w zakresie własnego użytku osobistego oraz do użytku w szkołach podczas zajęć dydaktycznych. Kopiowanie, wprowadzanie zmian, przesyłanie, publiczne odtwarzanie i wszelkie wykorzystywanie tych treści do celów komercyjnych jest niedozwolone. Plik można dowolnie modernizować na potrzeby własne oraz do wykorzystania w szkołach podczas zajęć dydaktycznych.

2 Sortowanie przez scalanie Sortowanie przez zliczanie

3 Scalanie ciągów (łączenie) jest operacją połączenia dwóch uporządkowanych rosnąco (malejąco) ciągów elementów w jeden ciąg wynikowy, również uporządkowany rosnąco (malejąco). W informatyce sortowanie przez scalanie (ang. merge sort), to rekurencyjny algorytm sortowania danych. Zaliczany jest do algorytmów szybkich tzn. takich, które posiadają klasę czasowej złożoności obliczeniowej równą O(n log n) lub nawet lepszą. Odkrycie algorytmu przypisuje się Johnowi von Neumannowi - matematykowi, inżynierowi chemii, fizykowi i informatyk. Wniósł on znaczący wkład do wielu dziedzin matematyki, był głównym twórcą teorii gier, teorii automatów, i stworzył formalizm matematyczny mechaniki kwantowej. John von Neumann ( )

4 Najlepszy opis sortowania przez scalanie opiera się na rekurencji i ilustruje równocześnie bardzo korzystne zastosowanie techniki dziel i zwyciężaj. Scalaj Łączymy posortowane podciągi w jeden posortowany ciąg. Każdy ciąg o długości 1 jest posortowany Zwyciężaj Sortujemy otrzymane podciągi, używając rekurencyjnie sortowania przez scalanie Dziel Dzielimy n-elementowy ciąg na dwa podciągi po n=2 elementów każdy

5

6 Dla przykładu zostanie przedstawiony schemat rekurencyjnego obliczania silni. Silnią (n!) liczby naturalnej n nazywamy iloczyn wszystkich liczb naturalnych nie większych niż n. np. 4!=1*2*3*4=24 Do zapisu algorytmu potrzebujemy: Dane wejściowe n - liczba, której silnie liczymy na danym poziomie rekurencyjnym, n N Dane wyjściowe n! – wartość silni Lista kroków K01: jeśli n>2, silnia(n) 1 i Koniec K02: silnia(n) 1* silnia(n-1) i Koniec Sprawdzamy warunek zakończenia rekurencji – czyli czy wynik dla otrzymanych danych wejściowych jest oczywisty. Przypadek, w którym silnia przyjmie wartość 1 wystąpi dla n<2. Jeżeli powyższy warunek nie wystąpi, do obliczeń wykorzystujemy rekurencyjne wywołanie obliczania silni dla argumentu zmniejszonego o 1. Wynik tego wywołania mnożymy przez n i zwracamy jako wartość silni dla n.

7 Podstawową operacją algorytmu jest scalanie dwóch zbiorów uporządkowanych w jeden zbiór również uporządkowany. Operację scalania realizujemy wykorzystując pomocniczy zbiór, w którym będziemy tymczasowo odkładać scalane elementy dwóch zbiorów. Zasada scalania zbiorów: Przygotowanie pustego, tymczasowego zbioru Do zbioru wynikowego wpisujemy zawartość zbioru tymczasowego. Koniec algorytmu Porównujemy pierwsze elementy zbiorów i w zbiorze tymczasowym umieszczamy mniejszy z elementów, usuwając go ze scalanego zbioru. Czynność powtarzamy do momentu opróżnienia jednego ze zbiorów. W tymczasowym zbiorze umieszczamy zawartość tego scalanego zbioru, który zawiera jeszcze elementy

8 Scalmy dwa uporządkowane zbiory [1 4 7 ] i [2 3 8] 4 Pierwszym krokiem jest porównanie ze sobą najmniejszych elementów ze scalanych zbiorów. W zbiorze tymczasowym umieszczamy najmniejszy element, usuwając go ze zbioru sortowanego. W naszym przypadku będzie to liczba 1. Porównujemy kolejne elementy zbiorów. Za każdym razem najmniejszy element zostaje przeniesiony do zbioru tymczasowego. Zbiór tymczasowy

9 Poszczególne kroki porównywania najmniejszych elementów zbiorów scalanych powtarzamy do momentu gdy jeden ze zbiorów zostanie pusty. Zakończyliśmy proces porównywania poszczególnych elementów. Do zbioru tymczasowego wprowadzamy pozostałe elementy z drugiego zbioru. Uzyskaliśmy zbiór uporządkowany, którego zawartość możemy przepisać do zbioru docelowego. Zbiór tymczasowy

10 Dane wejściowe d[ ] - scalany zbiór i p - indeks pierwszego elementu w młodszym podzbiorze, i p N i s - indeks pierwszego elementu w starszym podzbiorze, i s N i k - indeks ostatniego elementu w starszym podzbiorze, i k N Dane wyjściowe d[ ] - scalony zbiór Zmienne pomocnicze p[ ] - zbiór pomocniczy, który zawiera tyle samo elementów, co zbiór d[ ] i 1 - indeks elementów w młodszej połówce zbioru d[ ], i 1 N i 2 - indeks elementów w starszej połówce zbioru d[ ], i 2 N i - indeks elementów w zbiorze pomocniczym p[ ], i N Lista kroków algorytmu scalania K01: i 1 i p ; i 2 i s ; i i p K02: Dla i = i p, i p + 1,..., i k : wykonuj jeśli (i 1 = i s ) (i 2 i k i d[i 1 ] > d[i 2 ]), to p[i] d[i 2 ]; i 2 i inaczej p[i] d[i 1 ]; i 1 i K03: Dla i = i p, i p + 1,...,i k : d[i] p[i] K04: Koniec

11 Aby przeprowadzić operację scalania dwóch zbiorów musimy zarezerwować określony obszar pamięci – w przypadku prezentowanego przykładu będzie to tablica p o rozmiarze równym rozmiarowi zbioru d[ ]. W tablicy p algorytm będzie zapisywał zbiór tymczasowy, który po scalaniu zostanie przeniesiony do zbioru d[ ], zastępując dwa scalane podzbiory. Na wejściu do algorytmu podane są parametry i p, i s oraz i k, które dokładnie określają scalanych położenie podzbiorów w tablicy d[ ]. Poszczególne elementy w podzbiorach zostały oznaczone w następujący sposób: i 1 - młodszy podzbiór od pozycji i p do i s - 1 oraz i 2 - starszy podzbiór od pozycji i s do i k. Na początku algorytmu przypisujemy tym zmiennym indeksy pierwszych elementów w każdym podzbiorze. Indeksy elementów wstawianych do tablicy p[ ] są zawarte w zmiennej i. Wewnątrz pętli sprawdzamy, czy indeksy i 1 i i 2 wskazują elementy podzbiorów. Jeśli któryś z nich wyszedł poza dopuszczalny zakres, to dany podzbiór jest wyczerpany - w takim przypadku do tablicy p przepisujemy elementy drugiego podzbioru. Elementy podzbiorów porównujemy tak długo dopóki jeden z nich nie będzie pusty.

12 Do tablicy p[ ] zawsze wpisujemy mniejszy z porównywanych elementów. Dzięki temu elementy są uporządkowane w tworzonym zbiorze wynikowym. Po zapisie elementu w tablicy p[ ], odpowiedni indeks i 1 lub i 2 jest zwiększany o 1. Rośnie także indeks i, aby kolejny zapisywany element w tablicy p[ ] trafił na następne wolne miejsce. Pętla jest kontynuowana aż do zapełnienia w tablicy p[ ] obszaru o indeksach od i p do i k. W końcowej pętli, zostaje przepisany ten obszar z tablicy p[ ] do tablicy wynikowej d[ ]. Scalane zbiory zostają zapisane zbiorem wynikowym, który jest posortowany rosnąco.

13 Dane wejściowe d[ ] - sortowany zbiór i p - indeks pierwszego elementu w młodszym podzbiorze, i p N i k - indeks ostatniego elementu w starszym podzbiorze, i k N Dane wyjściowe d[ ] - posortowany zbiór Zmienne pomocnicze i s - indeks pierwszego elementu w starszym podzbiorze, i s N Lista kroków algorytmu sortującego K01: i s (i p + i k + 1) div 2 K02: Jeśli i s - i p > 1, to podzbiór(i p, i s - 1) K03: Jeśli i k - i s > 0, to podzbiór(i s, i k ) K04: Scalaj(i p, i s, i k ) K05: Koniec

14 Algorytm sortowania przez scalanie, należy do grupy algorytmów rekurencyjnych. Wywołuje się go z określonymi wartościami parametrów i p oraz i k Podczas pierwszego wywołania funkcji indeksy powinny objąć cały zbiór d - zatem i p =1, natomiast i k =n. Aby podzielić sortowany zbiór na dwie części wyznacza indeks i s - dla młodszej połowy elementy od i p do i s -1, dla starszej o indeksach elementów od i s do i k. Kolejnym korkiem jest sprawdzenie czy w danej części zbioru jest więcej niż jeden element. Jeśli tak, to rekurencyjnie sortujemy ją tym samym algorytmem. Kiedy oba podzbiory zostaną posortowane scalamy je według schematu opisanego w poprzednim punkcie. Algorytm zostaje zakończony. Zbiór jest posortowany. START I s -i p >1 podzbiór (i p, i s – 1) I k -i s >0 podzbiór (i s,i k – 1) Scalaj (i p, i s,i k ) KONIEC TAK

15 Algorytm posiada liniową klasę złożoności obliczeniowej O(n+k) (n – oznacza liczebność zbioru, k – rozpiętość danych, czyli w przypadku liczb: powiększoną o 1 różnicę między maksymalną, a minimalną wartością, np. rozpiętość liczb w Dużym Lotku wynosi = 49). Sortowanie przez zliczanie, oprócz tego że jest szybki, ma swoje dwie poważne wady. Po pierwsze - do tego sortowania potrzebna jest dodatkowa pamięć n+k (czyli nie jest to sortowanie w miejscu), a po drugie - tym sposobem można sortować tylko liczby całkowite z ograniczonego zakresu. Zasada działania algorytmu - w tablicy A mamy zapisane wszystkie liczby do posortowania. W tablicy B będziemy zapisywać ile razy występują elementy z tablicy A. Na początku tablicę B wypełniamy zerami. Sprawdzamy kolejne pola w tablicy A. Jeśli element numer i jest równy np. 10, to powiększamy o 1 dziesiąty element tablicy B. Ogólnie idea algorytmu polega na sprawdzeniu ile wystąpień danego klucza występuje w sortowanej tablicy. Kolejny algorytm, którego zasadę działania poznamy to sortowanie przez zliczanie. W metodzie tej stosowane są pewne założenia wobec sortowanego zbioru.

16 Posortujmy rosnąco dany zbiór liczb: Następnie, dla każdej wartości w zbiorze dopisujemy licznik ustawiony na 0. [0:0] [1:0] [2:0] [3:0] [4:0] [5:0] [6:0] [7:0] [8:0] [9:0] Kolejnym krokiem, jest zliczanie poszczególnych elementów w zbiorze i przypisywanie ich do konkretnych wartości liczbowych, np. dla liczby 4, każdy element w zbiorze sortowanym o tej wartości zwiększa wartość licznika o 1. W tym konkretnym przykładzie otrzymamy: [0:1] [1:3] [2:3] [3:2] [4:2] [5:1] [6:4] [7:1] [8:5] [9:1] Teraz poczynając od drugiego licznika sumujemy zawartość licznika oraz jego poprzednika i otrzymujemy: [0:1] [1:4] [2:7] [3:9] [4:11] [5:12] [6:16] [7:17] [8:22] [9:23] Dzięki tej operacji licznik podaje nam ilość wartości mniejszych lub równych konkretnej wartości ze zbioru, np.: [2:7] - w zbiorze do sortowania jest siedem wartości mniejszych lub równych 2 [6:16] - w zbiorze do sortowania jest szesnaście wartości mniejszych lub równych 6 itd. Otrzymujemy uporządkowany zbiór elementów, w którym stan licznika określa ostatnią pozycję w zbiorze danego elementu : [ ] Sortowana liczba Pozycja w zbiorze

17 W zasadzie proces sortowania moglibyśmy zakończyć na tym etapie, jednak jeżeli chcemy aby nasz algorytm był stabilny podczas sortowania wartości kluczy (czyli takich wartości, które są przypisane pewnym większym strukturom danych) musimy wykonać obieg dystrybucyjny. Obieg dystrybucyjny ma za zadanie obliczyć dystrybuantę, czyli ilość elementów mniejszych lub równych od danej wartości. W tym celu ponownie przeglądamy zbiór danych wejściowych idąc od ostatniego elementu do pierwszego – inaczej algorytm nie byłby stabilny. Po kolei, każdy element umieszczamy w zbiorze wynikowym na pozycji równej zawartości licznika dla tego elementu. Po wykonaniu tej operacji licznik zmniejszamy o 1. Na przykładzie będzie to wyglądało w następujący sposób: np. dla liczby 4 – jej licznik ma zawartość [4:11] – dlatego liczbę 4 umieszczamy w zbiorze wynikowym na pozycji 11 i zmniejszamy stan licznika o 1, w wyniku czego otrzymamy [4:10]. Kolejna liczba 4 trafi na pozycję 10, itd. Dla liczby 6 wartość licznika wynosi [6:16] – czyli 6 będzie na 16 pozycji, zmniejszamy licznik o 1 i otrzymujemy [6:15]. Analogicznie postępujemy ze wszystkimi liczbami w sortowanym zbiorze, do momentu za zbiór zostanie całkowicie uporządkowany w sposób rosnący. [ ]

18 Dane wejściowe d[ ] - zbiór elementów do posortowania. Każdy element posiada pole klucz, według którego dokonuje się sortowania. Pole klucz jest liczbą całkowitą Indeksy elementów rozpoczynają się od 1 n - ilość elementów w zbiorze d[ ], n N k min - minimalna wartość klucza, k min C k max - maksymalna wartość klucza, k max C Dane wyjściowe b[ ] - zbiór z posortowanymi elementami ze zbioru d[ ] Indeksy elementów rozpoczynają się od 1 Zmienne pomocnicze i - zmienna dla pętli iteracyjnych, i C L[ ] - tablica liczników wartości kluczy. Elementy są liczbami całkowitymi. Indeksy przyjmują kolejne wartości od k min do k max

19 K01: Dla i = k min, k min + 1,...,k max : wykonuj L[i] 0 K02: Dla i = 1,2,...,n: wykonuj L[d[i].klucz] L[d[i].klucz] + 1 K03: Dla i = k min + 1, k min + 2,...,k max : wykonuj L[i] L[i] + L[i - 1] K04: Dla i = n, n - 1,...,1: wykonuj K05...K06 K05: b[ L[ d[i].klucz ] ] d[i] K06: L[ d[i].klucz ] L[ d[i].klucz ] - 1 K07: Zakończ

20 Algorytm sortowania przez zliczanie zbudowany jest z kolejno następujących po sobie pętli iteracyjnych. W pętli nr 1 tworzymy dla każdej liczby lub klucza w zbiorze licznik i ustawiamy go na 0. W pętli nr 2 następuje zliczenie kolejnych elementów zbioru, w wyniku czego zwiększamy liczniki poszczególnych kluczy o 1. Po zakończeniu tej pętli w licznikach mamy ilość wystąpień poszczególnych kluczy. W pętli numer 3 przekształcamy zliczone wartości wystąpień kluczy na ostatnie pozycje elementów z danym kluczem w zbiorze wyjściowym. W kolejnej pętli – 4, ponownie przeglądamy zbiór wejściowy i przenosimy elementy ze zbioru wejściowego do zbioru wyjściowego, umieszczając go w miejscu o numerze zawartym w liczniku dla danego klucza. Po przesłaniu licznik zmniejszamy o 1, aby kolejny element o tej samej wartości klucza trafił na poprzednią pozycję. Zbiór został posortowany rosnąco. Kończymy algorytm.

21 Zarówno algorytm sortowania przez scalanie jak i algorytm sortowania przez zliczanie zaliczamy do algorytmów stabilnych czyli elementy w zbiorach sortowanych, o tych samych wartościach występują w tablicy wynikowej w takiej samej kolejności jak w tablicy wejściowej. Klasa złożoności obliczeniowej dla algorytmu sortowania przez scalanie wynosi O(n log n), natomiast algorytmu sortowania przez zliczanie O(n + k). Obydwa algorytmy wymagają dodatkowej pamięci – dla pierwszego O(n), natomiast w drugim przypadku O(n + k). Oba algorytmy zalicza się do grupy algorytmów szybkich, z tym że sortowanie przez zliczanie nie wykonuje żadnych porównań elementów sortowanych, czyli może osiągać lepszą klasę złożoności obliczeniowej.

22 Sysło M.: Algorytmy, WSiP, Warszawa 1997 Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein: Wprowadzenie do algorytmów, Wydawnictwo Naukowo- Techniczne, wyd. VI 2004 Wróblewski P.: Algorytmy, struktury danych i techniki programowania, Wyd. Helion,


Pobierz ppt "Wszelkie treści i zasoby edukacyjne publikowane na łamach Portalu www.szkolnictwo.pl mogą być wykorzystywane przez jego Użytkowników wyłącznie w zakresie."

Podobne prezentacje


Reklamy Google