Problem sortowania można zdefiniować następująco:
Transkrypt
Problem sortowania można zdefiniować następująco:
Problem sortowania można zdefiniować następująco: Danymi wejściowymi jest ciąg n liczb. Wynikiem jest taka ich permutacja (czyli zmiana kolejności), że tworzą one ciąg rosnący (niemalejący). Zadaniem algorytmu sortowania jest takie przestawienie elementów danego ciągu, aby były one uporządkowane rosnąco (niemalejąco). Opis Sortowanie jest jednym z najczęściej rozwiązywanych problemów informatycznych. Według różnych autorów, komputery spędzają od 25 do 80 procent czasu na porządkowaniu informacji. Porządek wśród elementów ułatwia i przyspiesza wykonywanie innych operacji (np. przeszukiwania). Sortowanie jest też przykładem problemu, który może być rozwiązany na wiele sposobów, a ich efektywność jest istotnie różna. Za efektywność algorytmów sortujących przyjmuje się liczbę porównań wykonywanych między elementami danych. Zwykle jest ona podawana jako zależność od liczby elementów do uporządkowania. Badanie efektywności metod sortowania. Przy jednym komputerze dwóch koordynatorów: Przygotowują tabelkę taką jak inni, ale do każdego rodzaju sortowania wpisują nazwiska osób od których dostaną wyniki. Pozostali są w trzech grupach A, B i C. Ci z grup testują sortowania: A: bąbelkowe, przez wstawianie, przez wstawianie binarne. B: Przez wybór, przez scalanie, przez scalanie rozszerzone. C: szybkie, stogowe, stogowe rozszerzone. Wielkość danych 300. Wprowadzić tez np. wielkość danych = 10 i obserwować krok po kroku. Stabilny algorytm porządkowania to taki, w którym kolejność elementów względem siebie w uporządkowanym ciągu jest taka sama, jak w ciągu danym do uporządkowania. Porządkowanie w miejscu (in situ) Algorytm porządkowania przez scalanie nie może być zapisany w tym samym miejscu w pamięci komputera, w którym były dane ciągi do scalenia, nie jest to algorytm działający „w miejscu” – in situ. Ta własność ma duże znaczenie, bo algorytmem działającym w miejscu można porządkować dwa razy dłuższe ciągi niż algorytmem przez scalanie Który z algorytmów porządkowania wykonuje najmniej działań na ciągu już uporządkowanym, czy któryś algorytm nie wykonuje na takim ciągu żadnych działań? Uporządkuj je w kolejności. Przecież ciąg jest uporządkowany. (niestety jest to cena jaką płacimy za uniwersalność algorytmów porządkowania, niezerowa liczba działań wykonywana nawet na ciągu uporządkowanym) Który algorytm wykonuje najmniej operacji na ciągach uporządkowanych w odwrotnej kolejności. Rodzaj sortowania Ciąg z danymi przypadkowymi 1. Bąbelkowe 43 893 (BubbleSort) 435 WD=30 2. Przez 21 975 wstawianie 226 (InsertonSort) WD=30 3. Wstawianie 2 473 binarne 144 4. Przez wybór – 45 150 wybieranie 465 (SelectionSort) WD=30 5. Przez scalanie 2 094 (MergeSort) 112 WD=30 Dane posortowane Dane odwrotnie posortowane 299 29 44 850 435 44 850 435 398 29 3 012 192 45 150 465 1 822 78 45 150 465 1 239 71 1 308 77 6. Scalanie rozszerzone 7. Szybkie (QuckSortHoare) WD=30 2 106 111 2 353 110 1 239 71 44 850 435 1 308 77 35 820 435 8. Stogowe (HeapSort – Floyd) WD=30 Stogowe rozszerzone Wielkość danych =30 4 052 204 4 227 211 3 771 188 203 211 188 Złożoność czasowa/ pamięciowa O(n2) O(n2) / O(1) stabilny nlog2n O(n2) / O(1) niestabilny O(nlog2n-n)/ O(n) stabilny, nie działa w miejscu pesymistyczny O(n2)/ O(n) oczekiwana O(nlogn)/ O(logn) niestabilny O(nlogn)/ O(1) niestabilny Dane przypadkowe: 5 (scalanie - 2094) i 6 (scalanie rozszerzone - 2106), 7 (szybkie - 2353), 3 (wstawianie binarne - 2473), 8 (stogowe - 4052), 2 (wstawianie – 21 975), 1 (bąbelkowe – 43893), 4 (wybór – 45150). Dane uporządkowane: 1 (Bąbelkowe – 299), 5 i 6 (scalanie i scalanie rozszerzone– 1239), 3 (wstawianie binarne – 3012), 8 (stogowe – 4227), 7 (szybkie – 44850), 2 (Wstawianie – 44850), 4 (wybór- 45 150). Dane odwrotnie uporządkowane: 2 (Wstawianie – 398), 5 i 6 (scalanie i scalanie rozszerzone– 1239), 3 (wstawianie binarne – 1822), 8 (stogowe – 3771), 7 (szybkie – 35820), 1 (Bąbelkowe – 44850), 4 (wybór- 45 1500). Rodzaj sortowania Ciąg z danymi przypadkowymi 1. Bąbelkowe Przestawianie kolejnych elementów i sprawdzanie czy nastąpiło Dane posortowane Dane odwrotnie posortowane Złożoność czasowa/ pamięciowa O(n2) (BubbleSort) WD=30 2. Przez wstawianie (InsertonSort) 3. Wstawianie binarne 4. Przez wybór – wybieranie (SelectionSort) przestawienie. Przyjęto, że nie sortuje się tą metodą więcej niż 5000 elementów. Dane posortowane O(n) Układanie kart w ręku. Wyjmujemy kolejny element i wstawiamy w posortowany ciąg. Polecany do krótkich ciągów. Dane posortowane O(n) A(n)= ¼ n2 + O(n) – oczekiwana zł. czasowa trochę lepsza niż SelectionSort, ale tego samego rzędu W(n)= ½ n2+O(n) Stosuje przeszukiwanie binarne dla znalezienia miejsca dla j-go elementu. Pomysłodawcą był Hugo Steinhaus w 1950 r. Bierze się 1 element i zamienia z najmniejszym z całego zbioru, potem 2 itd. Ustawianie książek na półce. Optymalny jeśli chodzi o liczbę przestawień – tylko n-1. U Diksa - Stabilność osiąga się kosztem zwiększenia współczynnika proporcjonalności złożoności W(n)= A(n)= ½ n2-O(n) Stabilny In situ O(n2) / O(1) Stabilny (zależy od implementacji) In situ O(nlogn) porównań O(n2) / O(1) In situ Stabilny (zależy od implementacji, często piszą, że niestabilny – Diks też) 5. Przez scalanie (MergeSort) łączenie 6. Scalanie rozszerzone 7. Szybkie (QuckSortHoare, 1962 r) 8. Stogowe (HeapSort – Floyd) Też rekurencyjny. Prosty podział ciągu na pół. Rekurencyjnie aż do 1 elementu, potem następuje łączenie, wstawianie w określonym porządku. Zaproponował tę metodę John von Neumann w 1945 r. O(nlogn)/ O(n) stabilny, nie działa w miejscu Rekurencyjny algorytm sortowania, zasada "dziel i zwyciężaj". Na każdym etapie rekurencji (przetwarzane coraz mniejsze fragmenty oryginalnej listy) przetwarzanie obejmuje 3 etapy: Umieszczanie (arbitralnie, np. ostatniego lub pierwszego, najlepiej wybrany losowo) wybranego elementu na jego pozycji docelowej. Umieszczanie na lewo od niego wszystkich elementów od niego mniejszych. Przesuwa się indeks w prawo Umieszczanie na prawo od niego wszystkich elementów od niego większych. Przesuwa się indeks w lewo. Dzielenie kończy się, gdy 2 wskaźniki się spotkają. Może być nierekurencyjne, wówczas poprawia się złożoność pamięciową z O(n) na O(logn). Jedno wywołanie rekurencyjne zastąpić iteracją W(n)=O(n2) A(n)=O(nlogn) Przez kopiec rozumiemy drzewo binarne, które spełnia warunek kopca, czyli jeśli węzeł x jest następnikiem węzła y, to element w węźle x jest nie większy niż element w węźle y. Kopiec zupełny ma wypełnione wszystkie poziomy całkowicie, z wyj. Ostatniego wypełnionego od strony lewej Pesymistyczny przypadek nie jest dużo gorszy od średniego. W(n)= 2nlogn+O(n) 2 fazy: faza budowy kopca i właściwe sortowanie. pesymistyczny O(n2)-przy już posortowanym/ oczekiwana O(nlogn)/ O(logn) niestabilny in situ pam. O(n), bo wymaga stosu O(nlogn)/ O(1) Niestabilny In situ Stogowe rozszerzone n2 jest górnym ograniczeniem na złożoność czasową problemu sortowania Stabilność tzn. zachowanie początkowego ustawienia elementów względem siebie Operacją dominującą przyjmuje się porównania elementów w ciągu. Złożoność pamięciowa to ilość dodatkowej pamięci (oprócz n miejsc dla elementów ciągu), potrzebnej do wykonania algorytmu. W(n) – pesymistyczna złożoność czasowa A(n) – oczekiwana złożoność czasowa