• Nie Znaleziono Wyników

Wykład 3

N/A
N/A
Protected

Academic year: 2021

Share "Wykład 3"

Copied!
21
0
0

Pełen tekst

(1)

Wykład 3

1. Sortowanie "kubełkowe"

2. Sortowanie pozycyjne

- porządkowanie słów jednakowej długości - porządkowanie słów o różnej długości - algorytm sortowania pozycyjnego

- złożoność algorytmu sortowania pozycyjnego 3. Sortowanie przez scalanie

Uwaga ! Wykorzystano obszerne fragmenty książki: M. Sysło "Algorytmy", Wyd. Szkolne i Pedagogiczne

(2)

Algorytmy i struktury danych dr inż. Tadeusz Jeleniewski

Zasada sortowania "kubełkowego" - analogia do sortowania przesyłek na poczcie. Kolejne listy są umieszczane w przegródkach odpowiadających ich adresom przeznaczenia, dokładniej np. miastom przy przesyłkach zamiejscowych, krajom lub dzielnicom miasta wreszcie. Zwykle liczba takich

przegródek jest niewielka, od 10 do 50.

Zasadę, algorytmu kubełkowego można wyjaśnić na przykładzie porządkowania liter słowa ABRAKADABRA.

Jest w nim pięć różnych liter: A, B, D, Ki R.

Tworzymy pięć "kubełków", oznaczamy je tymi literami i ustawiamy je w alfabetycznej (rys.3.1).

Krok 1o - "wrzucamy" litery do odpowiednich kubełków,

Krok 2o - tworzymy uporządkowany ciąg, opróżniając kubełki w kolejności ich ustawienia.

1. Sortowanie "kubełkowe"

(3)

Rys.3.1. Przykład sortowania liter metodą "kubełkową"

Na rysunku 3.1 kolejne wystąpienia tej samej litery oznaczono kolejnymi indeksami. Dzięki temu można łatwo odnaleźć poszczególne litery w kubełkach, a później w uporządkowanym ciągu.

Litery umieszcza się w "kubełkach" w kolejności występowania w słowie.

Kubełki w kroku 2o opróżnia się z liter w kolejności ich umieszczania (każdy kubełek jest kolejką).

Taki sposób opróżniania kubełków sprawia, że poszczególne wystąpienia danej litery są w takiej samej kolejności w słowie ABRAKADABRA i w uporządkowanym ciągu liter.

(4)

Algorytmy i struktury danych dr inż. Tadeusz Jeleniewski

2. Sortowanie pozycyjne

Jak rozszerzyć pomysł sortowania kubełkowego liter słowa na porządkowanie całych słów?

W tym celu należy najpierw ustalić, które z dwóch porównywanych słów powinno wystąpić wcześniej.

Najczęściej przyjmuje się naturalny porządek między słowami, nazywany porządkiem leksykograficznym lubsłownikowym, czyli taki, jaki jest w słownikach i w encyklopediach.

Jego definicja:

• jeżeli dwa słowa mają jednakową długość, to szukać w nich pierwszej pozycji, na której się różnią i wcześniejsze jest to słowo, które ma na tej pozycji wcześniejszą literę — np. ARAB jest wcześniejsze od ARAK, gdyż B występuje w alfabecie przed K, a DRAB jest wcześniejsze niż KRAB, gdyż D poprzedza K w alfabecie;

• jeżeli słowa mają różną długość, to albo szukać pierwszej pozycji, na której się różnią i litera na tej pozycji decyduje o miejscu ustawienia słowa (podobnie jak w przypadku słów o równej długości) — np.

słowo BAR jest wcześniejsze od BRDA, gdyż A poprzedza R, albo jedno słowo jest częścią drugiego, wtedy występuje w słowniku przed każdym słowem, w którym jest zawarte na początku — np. BAR poprzedza BARD i BARK.

(5)

Porządkowanie słów jednakowej długości

Z definicji porządku leksykograficznego wynika, że: jeśli słowa są jednakowej długości i różnią się tylko na ostatniej pozycji, to ich kolejność w słowniku jest wyznaczana przez kolejność ostatnich liter, np.

słowo ARAB poprzedza ARAK, a BARD poprzedza BARK. Podobnie, kolejność słów różniących się na dwóch ostatnich pozycjach jest wyznaczana przez kolejność par liter na tych pozycjach.

Porządkowanie słów o jednakowej długości sprowadza się więc do porządkowania ich od końca, pozycja po pozycji, z zastosowaniem do każdej pozycji algorytmu kubełkowego.

Jest to zasada algorytmu sortowania pozycyjnego.

Porządkowanie odbywa się tutaj względem każdej pozycji.

Rysunek 3.2 pokazuje kolejne iteracje algorytmu sortowania pozycyjnego zastosowane do

przykładowego zbioru czteroliterowych słów. Iteracje odpowiadają pozycjom, względem których odbywa się porządkowanie.

(6)

Algorytmy i struktury danych dr inż. Tadeusz Jeleniewski

Rys.3.2. Przykład pozycyjnego sortowania napisów jednakowej długości

(7)

Porządkowanie słów o różnej długości

Jak za pomocą algorytmu porządkowania pozycyjnego sortować słowa różnej długości?

Z definicji porządku leksykograficznego wynika, że i w tym przypadku słowa należy przeglądać od ostatnich liter.

Gdzie względem dłuższych słów należy umieścić słowa krótsze ?

Z drugiej części definicji wynika, że o kolejności słów różnej długości decydujemy, porównując je pozycja po pozycji, zaczynamy od pierwszej litery z lewej.

Zatem, najpierw należy zrównać pierwsze litery wszystkich słów, później — drugie itd.

Wszystkie słowa należy "dosunąć" do lewej strony.

Co zatem z krótszym słowem, gdy porządkujemy słowa względem pozycji, która wykracza poza jego ostatnią literę z prawej strony?

Dopisujemy wtedy słowo do tworzonego w danej iteracji ciągu wszystkich słów, do którego po zakończeniu wypełniania kubełków będziemy dopisywać słowa z opróżnianych kubełków.

W ten krótsze słowa będą po uporządkowaniu poprzedzały zawierające je słowa dłuższe.

Rysunek 3.3 pokazuje przykład sortowania pozycyjnego ciągu słów o różnej długości.

(8)

Algorytmy i struktury danych dr inż. Tadeusz Jeleniewski

Rys.3.3. Przykład sortowania pozycyjnego słów nierównej długości

Algorytm sortowania pozycyjnego nadaje się do porządkowania obiektów innego typu niż słowa.

W szczególności nadaje się do sortowania danych, w których można wyróżnić poszczególne pozycje (np. grupy znaków lub cyfr).

Porządkować ta metodą można zatem np. liczby zapisane w systemie pozycyjnym, daty itp.

(9)

Uporządkujmy przykładowo zbiór liczb, np.: 29, 157, 3, 37, 289, 104.

Po zastosowaniu zasad ustalania porządku leksykograficznego otrzymamy ciąg liczb w kolejności:

104, 157, 289, 29, 3, 37.

Kolejność leksykograficzna nie odpowiada kolejności tych liczb wg rosnących wartości.

Modyfikacja algorytmu - "dosunąć" wszystkie liczby do prawej i brakujące uzupełnić cyframi o najmniejszej wartości (nieznaczącymi zerami).

Po takiej "poprawce" algorytmu otrzymamy porządek przykładowego zbioru liczb:

3, 29, 37, 104, 157, 289.

Algorytm porządkowania pozycyjnego nie nadaje się do komputerowego sortowania liczb.

Algorytm sortowania pozycyjnego można łatwo wykorzystać do porządkowania dat.

Kolejne iteracje porządkujące daty zapisane jako dzień, miesiąc, rok wykonuje się najpierw na dniach, potem miesiącach i na końcu latach. Przykład ilustruje rys.3.4. Kolejne kolumny zawierają ciąg dat nieuporządkowanych, ułożonych według numeru dnia, miesiąca i roku. Po trzeciej takiej iteracji otrzymujemy zbiór dat posortowanych w kolejności rosnącej.

(10)

Algorytmy i struktury danych dr inż. Tadeusz Jeleniewski

Rys.3.4. Przykład pozycyjnego porządkowania ciągu dat [wg Sysło]

(11)

Opis algorytmu sortowania pozycyjnego [wg Sysło]:

Dane: Ciąg elementów, z których każdy jest układem pozycji wypełnionych znakami, dozwolonymi dla poszczególnych pozycji.

Wynik: Uporządkowanie danego ciągu zgodnie z relacją leksykograficzną, zdefiniowaną odpowiednio do kolejności pozycji i porządku znaków, które mogą wypełniać poszczególne pozycje.

Krok 1. Dla kolejnych pozycji w elementach, w kolejności od najmniej znaczącej do najbardziej znaczącej, wykonaj kroki 2,3 i 4.

Krok 2. Załóż "kubełki" dla każdego możliwego znaku, jaki może wystąpić na bieżącej pozycji w porządkowanych elementach. Ustaw te "kubełki" zgodnie z porządkiem tych znaków.

Krok 3. Dla wszystkich elementów z porządkowanego ciągu - jeśli rozważana pozycja w elemencie jest pusta, to dopisz ten element do końca porządkowanego ciągu, a w przeciwnym razie — włóż ten

element do "kubełka" oznaczonego znakiem stojącym na rozważanej pozycji.

Krok 4. Dla kolejnych "kubełków": przenieś elementy z "kubełka" na koniec porządkowanego

ciągu w takiej samej kolejności, w jakiej były w nim umieszczane. Słowo "element" w zależności od typu porządkowanych danych może oznaczać zarówno słowo (napis), liczbę, datę lub inny obiekt.

(12)

Algorytmy i struktury danych dr inż. Tadeusz Jeleniewski

Realizacja maszynowa sortowania np. napisów ma nieco inną postać.

W większości systemów programowania jest zdefiniowana funkcja, która porównuje ze sobą dwa słowa (napisy), oznaczmy je dalej jako A oraz B i orzeka o ich kolejności alfabetycznej, np. wg następującej reguły:



A poprzedza B

gdy 1

B identyczne A

gdy 0

B poprzedza A

gdy 1

B A strcmp( , )

W definicji funkcji strcmp relacja "poprzedza" oznacza, że słowo A występuje w kolejności alfabetycznej (leksykograficznej) wcześniej niż B.

Funkcję strcmp wykorzystuje się wówczas w dowolnym z poprzednio omówionych algorytmów sortowania (bąbelkowy, przez selekcję, wstawianie, szybkim, itp.) do sprawdzania, czy dwa porównywane słowa należy przemieścić w określony sposób. Algorytm porównywania słów realizowany w funkcji strcmp spełnia oczywiście warunki porządku leksykograficznego.

Rys. 3.5 przedstawia schemat blokowy algorytmu porównywania dwóch napisów A oraz B. symbole A[i], B[i] oznaczają w nim literę (znak) na i – tej pozycji słowa odpowiednio A oraz B. Długość napisów oznaczono tam odpowiednio a = |A| oraz b = |B|

(13)

Rys.4.5. Algorytm porównywania dwóch napisów A oraz B

(14)

Algorytmy i struktury danych dr inż. Tadeusz Jeleniewski

Złożoność algorytmu porządkowania pozycyjnego

W algorytmach sortowania liczb (bąbelkowy, selekcyjny, szybki itp.) podstawową operacją wykonywaną na porządkowanych elementach jest ich porównywanie parami. Ich

efektywność ocenia się biorąc pod uwagę liczbę wykonywanych porównań.

W algorytmach porządkowania "kubełkowego" i pozycyjnego nie wykonuje się operacji porównywania sortowanych elementów.

Podstawową operacją jest przemieszczanie elementu z porządkowanego ciągu do "kubełka"

lub na koniec ciągu. W rzeczywistości w maszynowej realizacji nie trzeba przenosić

elementów na koniec porządkowanego ciągu — wystarczy pozostawić je tam, gdzie są. Nie trzeba też pojedynczo przenosić elementów z kubełków do ciągu — wystarczy

„podoczepiać" całe zawartości kubełków do tworzonego ciągu [Sysło].

(15)

Niech s oznacza maksymalną długość porządkowanych elementów,

m

i

- liczbę różnych znaków jakie mogą wystąpić na i – tej pozycji porządkowanych elementów,

n – liczbę porządkowanych elementów, k

j

– liczbę znaków w j – tym elemencie.

W algorytmie porządkowania pozycyjnego należy wykonać:

K = k

1

+ k

2

+ . . . + k

n

umieszczeń porządkowanych elementów w "kubełkach"; każdy element jest tam umieszczany tyle razy ile ma znaków;

M = 2(m

1

+ m

2

+. . . + m

s

)

operacji na "kubełkach" – ich "otwierania" i dołączania zawartości do porządkowanego

ciągu.

(16)

Algorytmy i struktury danych dr inż. Tadeusz Jeleniewski

3. Sortowanie przez scalanie

Jedną z podstawowych operacji, wykonywanych na zbiorach informacji, jest ich scalanie (łączenie).

Terminu scalanieużywa się w wielu różnych znaczeniach.

W najprostszym przypadku, scalenie dwóch zbiorów danych oznacza dopisanie drugiego zbioru do końca pierwszego.

Dalej zakłada się, że scalane zbiory są uporządkowanymi ciągami liczb, a wynik scalania ma być również ciągiem uporządkowanym.

Scalenie dwóch uporządkowanych ciągów w jeden można wykonać w bardzo prosty sposób: patrzymy na początki danych ciągów i do tworzonego ciągu przenosimy mniejszy z elementów czołowych lub którykolwiek z nich, gdy są równe. Ilustruje to przykład pokazany na rys. 3.6.

1 5 18 27 31 95 5 13 21 31 45 88 95 107 1 5 5 13 18 21 27 31 31 45 88 95 95 107

Rys.3.6. Przykład scalania dwóch uporządkowanych ciągów liczb

(17)

Liczba wykonywanych w czasie scalania porównań na ogół zależy od wartości elementów.

Ile najwięcej porównań należy wykonać, aby scalić dwa ciągi ?

Rozważanie różnych możliwych układów wartości elementów w obu scalanych ciągach nie daje szybkiej odpowiedzi na to pytanie.

Z wyjątkiem elementu przeniesionego do niego na końcu, przeniesienie każdego innego elementu może być związane z wykonaniem porównania między elementami danych ciągów. Tak jest wtedy, gdy w kroku drugim do końca, oba scalane ciągi zawierają jeszcze po jednym elemencie.

Niech na początku jeden ciąg zawiera k elementów, a drugi — l elementów, razem n, czyli n = k + l.

Prowadzi to do wniosku, że bez względu na liczności danych ciągów, ich scalenie może wymagać wykonania n - l porównań i każde z tych porównań jest związane z przeniesieniem jednego elementu, z wyjątkiem elemen-tu, który trafia do scalonego ciągu na końcu.

Z góry nie wiadomo, który z ciągów i kiedy "wyczerpie się" w trakcie scalania. Tworzonego ciągu nie można zatem umieszczać na miejscu ciągów danych do scalenia.

Należy tworzyć go w nowym miejscu. Potrzebna jest więc dodatkowa pamięć — ta metoda nie działa

"w miejscu".

Konieczność zajęcia dodatkowego miejsca w pamięci jest słabą stroną operacji scalania.

(18)

Algorytmy i struktury danych dr inż. Tadeusz Jeleniewski

Algorytm scalania dwóch ciągów uporządkowanych można opisać w następujący sposób:

Dane: Dwa uporządkowane ciągi X oraz Y.

Wynik: Uporządkowany ciąg Z, będący połączeniem ciągów X, Y.

Krok 1. Dopóki oba ciągi X i Y są niepuste wykonuj następującą operację: przenieś mniejszy z najmniejszych elementów z ciągów X i Y do ciągu Z.

Krok 2. Do końca ciągu Z dopisz elementy pozostałe w jednym z ciągów X lub Y.

Algorytm scalania łączy już uporządkowane ciągi w jeden ciąg również uporządkowany.

Jak go zmodyfikować aby służył do sortowania dowolnych ciągów ? Należy najpierw uporządkować scalane podciągi.

Jeżeli założymy, że te podciągi zostały już uporządkowane tą samą metodą, to wystarczy zastosować zasadę rekurencji.

W takiej metodzie porządkowania ciągu ("dziel i zwyciężaj") scaleniu podlegają dwa prawie

równoliczne podciągi, uporządkowane tą samą metodą. Jej działanie ilustruje przykład pokazany na rysunku 3.6. Istnieje duże podobieństwo w schematach działania tej metody i rekurencyjnego

znajdowania maksimum i minimum jednocześnie.

(19)

Rys.3.7. Ilustracja zasady działania algorytmu sortowania przez scalanie

(20)

Algorytmy i struktury danych dr inż. Tadeusz Jeleniewski

Porządkowany ciąg dzielimy w każdym kroku na dwa, niemal równej długości podciągi, które rekurencyjnie porządkuje się tą samą metodą.

Warunkiem zakończenia rekurencji jest sytuacja, gdy ciąg ma jeden element, wtedy nie można go już podzielić na podciągi, jest to ciąg już uporządkowany.

Powrót z serii wywołań rekurencyjnych rozpoczyna się z ciągami złożonymi z pojedynczych elementów, które są scalane w ciągi o długości dwa, następnie w ciągi o długości trzy lub cztery elementy itd.

Jak zwykle, w opisie algorytmu rekurencyjnego, po nazwie algorytmu występuje układ parametrów określających rozwiązywany problem, który jest wykorzystany w treści algorytmu, w odwołaniu do niego samego przy rozwiązywaniu mniejszych podproblemów [Sysło].

Algorytm porządkowania przez scalanie ciągu (X, l, p)

Dane: Ciąg liczbowy xl, ...,xp.

Wynik: Uporządkowanie tego ciągu liczb w kolejności niemalejącej.

Krok 1. Jeśli l < p, to przyjmij s := (l + p) / 2 i wykonaj trzy następne kroki.

Krok 2. Zastosuj ten sam algorytm dla (X, l, s).

Krok 3. Zastosuj ten sam algorytm dla (X, s+1, p).

Krok 4. Zastosuj algorytm scalania do ciągów xl, ..., xs oraz xs+i, ..., xp a wynik umieść w ciągu xl, ...,xp.

(21)

1 n n n

n

r ( )  log

2

 

Złożoność

Oznaczmy symbolem r(n] liczbę porównań w algorytmie porządkowania przez scalanie i załóżmy, że n jest potęgą liczby 2, czyli n = 2kdla pew-nego k. Otrzymujemy następującą zależność rekurencyjną:

Gdy n = l, nie wykonujemy żadnego porównania, gdy n = 2 — wykonujemy jedno porównanie w kroku 4 podczas scalania ciągów jednoelementowych, a gdy n > 2 — wykonujemy dwa razy porządkowanie tą samą metodą ciągów o połowę krótszych (w krokach 2 i 3) oraz scalamy te ciągi, wykonując co najwyżej n - l porównań (o jedno mniej niż jest elementów w obu podciągach).

Po wyeliminowaniu rekurencji w powyższej zależności otrzymamy wyrażenie na liczbę porównań w algorytmie sortowania przez scalanie:

   





2 n 1 n 2

n r 2

2 n 1

1 n 0

n r

/ )

(

Cytaty

Powiązane dokumenty

Na samochód o masie 1 tony, jadący z prędkością 72 km/h w pewnej chwili zaczęła działać siła o wartości 5000 N przeciwnie do zwrotu prędkości, zmniejszając ją do 36

13 W przestrzeniach metrycznych można zdefiniować symetralną (jako zbiór tych punk- tów, które są równoodległe od dwóch ustalonych punktów)?. Jak wyglądają symetralne w

Otóż pod opieką proboszcza Niedzicy była fundacja na dom starców w Łapszach Niżnych i Frydmanie. O Frydmanie mamy tylko nieliczne wzmianki, jak

zyka niż człowieka, wtedy jednak powoływałoby się do istnienia nową total ­ ność, na gruncie której możliwa byłaby ciągła historia, historia dyskursu jako nauka

2. Trzech studentów przygotowywało się niezależnie do egzaminu z rachunku prawdopodobieństwa. Rzucamy n razy kostką do gry. Obliczyć prawdopodobieństwo tego, że: a) szóstka

2. Trzech studentów przygotowywało się niezależnie do egzaminu z rachunku prawdopodobieństwa. Rzucono 10 razy kostką. Rzucono 10 razy symetryczną kostką. Jakie

5. Losujemy jedną kulę, a następnie wrzucamy ją ponownie do urny dorzucając dodatkowo k kul białych, jeśli była to kula biała lub k kul czarnych, jeśli była czarna.

[r]