![]() |
![]() ![]()
Autor artykułu: mgr Jerzy Wałaszek |
©2014 mgr
Jerzy Wałaszek
|
Sortowanie kubełkowe
|
Uwaga, pułapka:Algorytm wymaga ponumerowania
liczników kolejno od wmin do
wmax. Niektóre języki
programowania
Mamy wartość w i chcemy znaleźć indeks licznika, który ją zlicza:indeks ← w - wmin Mamy indeks licznika i chcemy znaleźć zliczaną wartość w:w ← indeks + wmin |
n | - liczba elementów w zbiorze, n
![]() |
d[ ] | - sortowany zbiór liczb całkowitych. Indeksy elementów rozpoczynają się od 0. |
wmin | - minimalna wartość elementów zbioru, wmin
![]() |
wmax | - maksymalna wartość elementów zbioru, wmax
![]() |
d[ ] | - posortowany zbiór liczb całkowitych. |
lw[ ] | - tablica liczników wartości o indeksach od 0 do wmax - wmin. Każdy licznik przechowuje liczbę całkowitą |
i, j | - zmienne licznikowe pętli, i,j
![]() |
K01: | Dla i = 0, 1,...,wmax - wmin: wykonuj lw[i] ← 0 |
K02: | Dla i = 0,1,...,n - 1: wykonuj lw[ d[i] - wmin] ← lw[ d[i] - wmin] + 1 |
K03: | j ← 0 |
K04: | Dla i = 0 , 1,...,wmax - wmin: wykonuj K05 |
K05: | Dopóki lw[i] > 0
wykonuj: d[j] ← i + wmin lw[i] ← lw[i] - 1j ← j + 1 |
K06: | Zakończ |
Algorytm ma klasę czasowej złożoności obliczeniowej
W sytuacji odwrotnej, gdy sortujemy mało elementów o dużym zakresie wartości klasa złożoności zredukuje się z kolei do O(m) - spróbuj uzasadnić ten wynik samemu na podstawie analizy działania poszczególnych fragmentów algorytmu.
Zasadę pracy algorytmu sortowania przez zliczanie jest najlepiej przedstawić za pomocą przykładu.
Przykład:
Posortować rosnąco zbiór danych:
{ 6 3 6 1 4 9 0 1 8 2 6 4 9 3 7 5 9 2 7 3 2 4 1 8 7 0 8 5 8 3 6 2
5 3 }
Dla każdej wartości w zbiorze przygotowujemy licznik i ustawiamy go na 0.
[0:0] [1:0] [2:0] [3:0] [4:0] [5:0]
[6:0] [7:0] [8:0] [9:0]
Przeglądamy kolejne elementy zbioru i zliczamy ich
wystąpienia w odpowiednich licznikach. Np. element 6 powoduje zwiększenie o
1 licznika nr 6. Po wykonaniu tego obiegu w poszczególnych licznikach mamy
ilość wystąpień każdej wartości. W naszym przykładzie otrzymamy:
[0:2] [1:3] [2:4] [3:5] [4:3] [5:3]
[6:4] [7:3] [8:4] [9:3]
Teraz poczynając od drugiego licznika sumujemy zawartość licznika
oraz jego poprzednika i otrzymujemy:
[0:2] [1:5] [2:9] [3:14] [4:17]
[5:20] [6:24] [7:27] [8:31] [9:34]
W wyniku tej operacji w każdym liczniku otrzymaliśmy ilość wartości mniejszych lub równych numerowi licznika, które występują w zbiorze wejściowym. Na przykład:
[0:2] - w zbiorze wejściowym są dwie wartości 0
[1:5] - w
zbiorze wejściowym jest pięć wartości mniejszych lub równych 1
[2:9] - w
zbiorze wejściowym jest dziewięć wartość mniejszych lub równych 2, itd.
Zwróć uwagę, iż stan licznika określa teraz ostatnią pozycję minus 1 w zbiorze uporządkowanym, na której należy umieścić wartość równą numerowi licznika:
Wartość: | 0 | 0 | 1 | 1 | 1 | 2 | 2 | 2 | 2 | 3 | 3 | 3 | 3 | 3 | 4 | 4 | 4 | 5 | 5 | 5 | 6 | 6 | 6 | 6 | 7 | 7 | 7 | 8 | 8 | 8 | 8 | 9 | 9 | 9 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Pozycja: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
Przeglądamy jeszcze raz zbiór wejściowy idąc od ostatniego elementu do pierwszego (aby zachować stabilność sortowania). 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. Dzięki temu następna taka wartość trafi na wcześniejszą pozycję.
W naszym przykładzie rozpoczynamy od ostatniej liczby 3. Jej licznik ma zawartość [3:14]. Zatem liczbę 3 umieszczamy w zbiorze wynikowym na pozycji 14 - 1 = 13 i zmniejszamy o 1 stan licznika otrzymując [3:13]. Kolejna liczba 3 trafi teraz na pozycję 12, itd.
Dla liczby 5 stan licznika wynosi [5:20]. Umieszczamy ją zatem na 20 - 1 = 19 pozycji i licznik zmniejszamy o 1 otrzymując [5:19].
Postępujemy w ten sam sposób z pozostałymi elementami zbioru. W efekcie zbiór wynikowy będzie posortowany rosnąco:
{ 0 0 1 1 1 2 2 2 2 3 3 3 3 3 4 4 4 5 5 5 6 6 6 6 7 7 7 8 8 8 8 9 9 9 }
Przyjrzawszy się dokładnie algorytmowi sortowania przez zliczanie możesz zastanawiać się, dlaczego postępujemy w tak dziwny sposób? Przecież mając zliczone wystąpienia każdej wartości w licznikach, możemy je od razu przepisać do zbioru wyjściowego, jak zrobiliśmy w algorytmie sortowania kubełkowego. Miałbyś rację, gdyby chodziło jedynie o posortowanie liczb. Jest jednak inaczej.
Celem nie jest posortowanie jedynie samych wartości elementów. Sortowane wartości są zwykle tzw. kluczami, czyli wartościami skojarzonymi z elementami, które wyliczono na podstawie pewnego kryterium Sortując klucze chcemy posortować zawierające je elementy. Dlatego do zbioru wynikowego musimy przepisać całe elementy ze zbioru wejściowego, gdyż w praktyce klucze stanowią jedynie część (raczej małą) danych zawartych w elementach. Zatem algorytm sortowania przez zliczanie wyznacza docelowe pozycje elementów na podstawie reprezentujących je kluczy, które mogą się wielokrotnie powtarzać. Następnie elementy są umieszczane na właściwym miejscu w zbiorze wyjściowym. Prześledź dokładnie podany poniżej algorytm oraz przykładowe programy, a wszystko powinno się wyjaśnić.
d[ ] | - | zbiór elementów do posortowania. Każdy element posiada pole klucz, wg którego dokonuje się sortowania. Pole klucz jest liczbą całkowitą. Indeksy elementów rozpoczynają się od 0. |
n | - | ilość elementów w zbiorze d[ ]. n
![]() |
kmin | - | minimalna wartość klucza, kmin
![]() |
kmax | - | maksymalna wartość klucza, kmax
![]() |
b[ ] | - zbiór z posortowanymi elementami ze zbioru d[ ]. Indeksy elementów rozpoczynają się od 0. |
i | - | zmienna dla pętli iteracyjnych, i
![]() |
L[ ] | - | tablica liczników wartości kluczy. Elementy są liczbami całkowitymi. Indeksy przebiegają kolejne wartości od 0 do kmax - kmin . |
K01: | Dla i = 0,1,...,kmax - kmin: wykonuj L[i] ← 0 |
K02: | Dla i = 0,2,...,n - 1: wykonuj L[d[i].klucz - kmin] ← L[d[i].klucz - kmin] + 1 |
K03: | Dla i = 1, 2,...,kmax - kmin: wykonuj L[i] ← L[i] + L[i - 1] |
K04: | Dla i = n - 1, n - 2,...,0: wykonuj K05...K06 |
K05: | b[ L[ d[i].klucz - kmin ] - 1] ← d[i] |
K06: | L[ d[i].klucz - kmin ] ← L[ d[i].klucz - kmin ] - 1 |
K07: | Zakończ |
![]() | I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe