1. Wstęp Sortowaniem Sortowaniem (sorting) nazywamy proces
Transkrypt
1. Wstęp Sortowaniem Sortowaniem (sorting) nazywamy proces
Antoni M. Zajączkowski: Algorytmy i podstawy programowania – proste metody sortowania tablic 6 kwietnia 2014 PROSTE METODY SORTOWANIA SORTOWANIA TABLIC 1. Wstęp Sortowaniem (sorting) nazywamy proces ustawiania elementów pewnego niepustego zbioru według danego porządku (order). Inaczej mówiąc, sortowanie polega na ustawianiu pewnego zbioru skończonego w ciąg. Aby to zrealizować w rozważanym zbiorze musi być określona relacja liniowego porządku (patrz Dodatek). Metody sortowania dzielimy na metody sortowania tablic i metody sortowania plików sesekwencyjnych, kwencyjnych przy czym często te klasy metod sortowania nazywamy odpowiednio sortosortowaniem waniem wewnętrznym wewnętrznym (internal sorting) i sortowaniem zewnętrznym (external sorting). Dalej zajmiemy się prostymi algorytmami sortowania tablic. Przyjmiemy, że elementami zbioru, który chcemy sortować są rekordy, w których jedną składową jest klucz elementu (key). Klucze są porównywalne, a więc są danymi typu, w którym określono relację liniowego porządku. Prowadzi to do deklaracji: type Element is record Klucz : Typ_Klucza; Dane : Typ_Danych; end record; Składowa Dane zawiera informacje nieistotne przy formułowaniu algorytmów sortowania tablic i dalej nie będzie brana pod uwagę. Zakładamy też, że klucze elementów są wyznaczone. Tablica, którą chcemy sortować może być następującego typu: type Tablica is array (Typ_Indeksu range <>) of Element;, przy czym Typ_Indeksu musi być typem dyskretnym, podtypem dyskretnym, albo zakresem typu dyskretnego (porównaj definicję tablic jednowymiarowych). Przyjmiemy dalej w tym punkcie, że Typ_Indeksu jest typem Integer. Mówimy, że tablica A : Tablica (1..N); gdzie N jest daną liczbą całkowitą taką, że zakres 1..N nie określa pustej tablicy, jest posortowana w porządku niemalejącym (nondecreasing order), jeżeli dla dowolnego indeksu I ∈ 1..(N − 1) mamy A(I).Klucz ≤ A(I + 1).Klucz . Jeżeli relację ≤ zastąpimy relacją ≥ , to otrzymamy uporządkowanie nierosnące. nierosnące Dalej będziemy się zajmować wyłącznie sortowaniem według porządku niemalejącego. Przypuśćmy, że mamy dwa rekordy R1 , R2 umieszczone w A(I) i A(J). Mówimy, że R1 poprzedza R2 , jeżeli I < J . Jeżeli w nieposortowanej tablicy rekord R1 poprzedza rekord R2 i ich klucze są równe, czyli R1.Klucz = R2.Klucz, to w tablicy posortowanej metodą stabilną również rekord R1 poprzedza rekord R2 . Sortowanie zachowujące względne położenie rekordów o tych samych wartościach kluczy nazywamy sortowaniem stabilnym (stable sorting). Położenie względne może wynikać z poprzednio wykonanego sortowania według innego klucza (Sedgewick, 1983). Sortowaniem w miejscu, miejscu albo in situ nazywamy sortowanie, w którym tablice nieuporządkowana i uporządkowana zajmują ten sam obszar pamięci, przy czym do realizacji algorytmu sortowania dopuszcza się wykorzystanie pewnego, niewielkiego obszaru pomocni- 1 Antoni M. Zajączkowski: Algorytmy i podstawy programowania – proste metody sortowania tablic 6 kwietnia 2014 czego. Inaczej mówiąc, w przypadku sortowania in situ nie wykonuje się kopii sortowanej tablicy. 2. Sortowanie przez wybór Sortowanie przez wybór (selection sort) jest łatwym do zrozumienia algorytmem sortowania tablic, skutecznym przy ich niewielkich rozmiarach (Sedgewick, 1983). Przypuśćmy, że mamy daną deklarację A : Tablica (1..N); przy czym tablica wypełniona jest rekordami o wyznaczonych kluczach. Tablicę tę należy uporządkować niemalejąco. Algorytm sortowania przez wybór rozpoczynamy od wykonania dwóch etapów podstawowych: 1. Wybieramy z tablicy A element o najmniejszej wartości klucza, 2. Zamieniamy go miejscami z A(1). Następnie powtarzamy te etapy w przypadku tablicy 2..N , czyli N − 1 elementowej, 3..N , czyli N − 2 elementowej, aż pozostanie tablica jednoelementowa, zawierająca element o największym kluczu. Zamiana elementów następuje wtedy, gdy najmniejszy znaleziony klucz jest mniejszy od klucza elementu, z którym porównujemy klucze elementów nieposortowanej części tablicy. Przykład 1. 1. (Wirth, 2001). Mamy daną tablicę A: Tablica (1..8) z następującymi kluczami elementów: 1) 44 55 12 42 94 18 6 67 Nc = 7, Ne = 1. W pierwszym etapie okazuje się, że najmniejszy klucz ma rekord A(7), przy czym A(7).Klucz < A(1).Klucz. Następuje więc zamiana rekordu A(7) z rekordem A(1). Wynikiem tego jest tablica z następującym układem kluczy: 2) 6 55 12 42 94 18 44 67 Nc = 6, Ne = 1. Teraz przeglądamy tablicę w zakresie 2..8 . Najmniejszy klucz ma rekord A(3), przy czym klucz ten jest mniejszy od klucza rekordu A(2). Dokonujemy zamiany rekordów i otrzymujemy ciąg kluczy: 3) 6 12 55 42 94 18 44 67 Nc = 5, Ne = 1. Nc Nc Nc Nc Nc Ne Ne Ne Ne Ne Postępujemy tak dalej i kolejno dostajemy: 4) 5) 6) 7) 8) 6 6 6 6 6 12 12 12 12 12 18 18 18 18 18 42 42 42 42 42 94 94 44 44 44 55 55 55 55 55 44 44 94 94 67 67 67 67 67 94 = = = = = 4, 3, 2, 1, 0, = = = = = 0. 1. 0. 1. 0. end Przykład Niech N c (number of comparisons) oznacza liczbę porównań kluczy i niech N e (number of exchanges) oznacza liczbę zamian rekordów. Nietrudno zauważyć, że w podanym algorytmie liczba porównań kluczy nie zależy od początkowego ustawienia rekordów i wynosi 1 1 N c = (n 2 − n ) = n(n − 1) , (1) 2 2 natomiast liczba zamian rekordów spełnia oszacowanie Ne ≤ n − 1 , przy czym w przykładzie N c = 28 i N e = 5 ≤ 7 . 2 (2) Antoni M. Zajączkowski: Algorytmy i podstawy programowania – proste metody sortowania tablic 6 kwietnia 2014 Złożoność czasową algorytmów często oceniamy stosując notację dużego O (big O) (Aho, Hopcroft, Ullman, 2003; Banachowski, Diks, Rytter, 2006). W przypadku algorytmów sortowania wewnętrznego miarą ich efektywności czasowej mogą być liczba porównań kluczy i liczba przestawień elementów. Mówimy, że algorytm sortowania przez wybór ma złożo złożożoność czasową kwadratową ze względu na operację porównywania kluczy, co wyrażamy pisząc O(n 2 ) - wzór (1), natomiast ze względu na operację zamiany rekordów algorytm ten ma złożoność złożoność czasową liniową, liniową co zapisujemy symbolem O(n ) - wzór (2). Zadanie obliczeniowe 1. Napisać, uruchomić i przetestować program w Adzie implementujący algorytm sortowania przez wybór. Algorytm powinna realizować procedura z odpowiednio zaprojektowanym interfejsem (parametrami formalnymi). Procedura ta powinna wyznaczać liczbę porównań kluczy i liczbę zamian elementów oraz prezentować stan sortowanej tablicy po wykonaniu każdych dwóch etapów algorytmu. Wymianę elementów zrealizować przy pomocy procedury Wymien, którą należy zadeklarować w odpowiednim obszarze deklaracji. Wykonać też obliczenia dla przypadku posortowanej tablicy i tablicy posortowanej wg porządku malejącego. end Zadanie obliczeniowe Program 1. 1. Test_Selection_Sort 3. Sortowanie przez wstawianie Algorytm sortowania przez wstawianie (insertion sort) jest niemal równie prosty jak sortowanie przez wybór (Sedgewick, 1983; Wirth, 2001) i jest stosowany przez ludzi układających karty do gry w brydża. W danym kroku bierzemy pod uwagę jeden element, który wstawiamy w odpowiednie miejsce wśród elementów które poprzednio ustawiliśmy. Miejsce na wstawiany element otrzymujemy przesuwając elementy o większych kluczach w prawo. Przykład 2. 2. (Wirth, 2001). Niech A: Tablica (1..8) będzie tablicą z następującymi kluczami elementów: 1) 44 55 12 42 94 18 6 67. W pierwszym kroku bierzemy pod uwagę drugi element, traktując pierwszy jako tę część tablicy, która została wcześniej uformowana. Korzystając z lokalnej zmiennej pomocniczej Temp : Element; tworzymy kopię elementu A(2) i sprawdzamy, czy A(1).Key > Temp.Key. Ponieważ w rozważanym przypadku relacja ta jest fałszywa dostajemy układ kluczy jak poprzednio. 2) 44 55 12 42 94 18 6 67. Teraz bierzemy pod uwagę element Temp := A(3). Ponieważ Temp.Klucz < A(2).Klucz, przesuwamy A(2) na miejsce A(3)i sprawdzamy, czy Temp.Klucz < A(1).Klucz. Ponieważ relacja ta jest prawdziwa i osiągnęliśmy początek tablicy przesuwamy A(1) w miejsce A(2), a w wolne miejsce wstawiamy Temp = A(3). Wynikiem tych operacji jest następujący układ kluczy: 3) 12 44 55 42 94 18 6 67. Zauważmy, że proces porównywania kluczy i ewentualnego przesuwania elementów o większych kluczach wykonywany jest na przemian, a kończymy proces z dwóch powodów: 1. Znaleziono element z kluczem mniejszym od Temp.Klucz, 3 Antoni M. Zajączkowski: Algorytmy i podstawy programowania – proste metody sortowania tablic 6 kwietnia 2014 2. Osiągnięto początek poprzednio ułożonej części tablicy. Postępując dalej według opisanego schematu kolejno otrzymujemy: 4) 12 42 5) 12 42 6) 12 18 7) 6 12 8) 6 12 44 55 94 18 6 67 44 55 94 18 6 67 42 44 55 94 6 67 18 42 44 55 94 67 18 42 44 55 67 94 end Przykład Zadanie obliczeniowe 2. Napisać, uruchomić i przetestować program w Adzie implementujący algorytm sortowania przez wstawianie. Algorytm powinna realizować procedura z odpowiednio zaprojektowanym interfejsem (parametrami formalnymi). Procedura ta powinna wyznaczać liczbę przesunięć (zamian) elementów oraz prezentować stan sortowanej tablicy po wykonaniu każdego etapu algorytmu. Wykonać też obliczenia dla przypadku posortowanej tablicy i tablicy posortowanej wg porządku malejącego. end Zadanie obliczeniowe Program 2. 2. Test_Insertion_Sort Dodatek. Przypomnienie wybranych wiadomości z podstaw matematyki Definicja. Definicja. Niech S oznacza zbiór niepusty. Relacją częściowego porządku, porządku albo częścioczęściowym porządkiem (partial order relation, partial order) w S nazywamy relację dwuargumentową (binarną), którą oznaczamy ≤ i która posiada następujące własności: R1. x ≤ x dla każdego x ∈ S - zwrotność (reflexivity), R2. Jeżeli x ≤ y i y ≤ x , to x = y - antysymetria (antisymmetry), R3. Jeżeli x ≤ y i y ≤ z , to x ≤ z - przechodniość (transitivity). end Definicja Definicja. Niepusty zbiór S , w którym określono relację częściowego porządku nazywamy zbiorem częściowo uporządkowanym (partially ordered set). end Definicja Definicja. Dwa elementy x , y ∈ S nazywamy porównywalnymi (comparable), jeżeli x ≤ y , albo y ≤ x . end Definicja Z definicji relacji częściowego porządku nie wynika, że każde dwa elementy zbioru S są porównywalne. Jeżeli zbiór częściowo uporządkowany posiada własność R4. Każde dwa elementy zbioru S są porównywalne, to częściowy porządek nazywamy relacją porządku liniowego liniowego, go albo relacją porządku pełpełnego (linear order relation, total order relation), a zbiór nazywamy zbiorem liniowo upouporządkowanym, rządkowanym albo zbiorem w pełni uporządkowanym (linearly ordered set, totally ordered set). Stosowana jest też nazwa łańcuch (chain). Literatura Aho, A.V, Hopcroft, J.E., Ullman, J.D. (2003). Algorytmy i struktury danych. Helion, Gliwice, Polska (tłum. z ang.). Banachowski, Diks, L.K., Rytter, W. (2006). Algorytmy i struktury danych. WNT, Warszawa (wyd. V). 4 Antoni M. Zajączkowski: Algorytmy i podstawy programowania – proste metody sortowania tablic 6 kwietnia 2014 Birkhoff, G., Bartee, T.C. (1983). Współczesna algebra stosowana. PWN, Warszawa (tłum. z ang.). Sedgewick, R. (1983). Algorithms. Addison-Wesley, Reading, Mass. Wirth, N. (2001). Algorytmy + struktury danych = programy. WNT, Warszawa (tłum. z ang.). 5