Sortowanie Grzebieniowe (ang. combsort) opiera się na idei sortowania bąbelkowego. Różnica jednak polega na wykonywaniu zamian w inny sposób - staramy się w każdej iteracji przesunąć wszystkie duże elementy na sam koniec. Można to porównać do czesania z grzebieniem. Początkowo rozczesujemy włosy grzebieniem z dużym odstępem pomiędzy ząbkami - w ten sposób będzie łatwiej i szybciej rozczesać pojedyncze grupki.
Algorytm sortowania Grzebieniowego zawiera element empiryczny - czyli wyliczony doświadczalnie. Jest to współczynnik w:=1.3. Nie ma on znaczenia dla poprawności posortowania listy, ale ma znaczący wpływ na szybkość wykonywania algorytmu. W ten sposób zwykłe sortowanie bąbelkowe poprawiamy prawdopodobnie do złożoności . Niemniej jest on prawdopodobnie wolniejszy od sortowania szybkiego.
Podczas korzystania z tej metody sortowania korzystamy z wyliczanej w każdej iteracji rozpiętości. Rozpiętość to początkowo długość listy. Na początku iteracji dzielimy aktualną wartość rozpiętości przez współczynnik w=1.3. Część ułamkową po wyliczeniach odrzucamy. Rozpiętość ma kluczowe znaczenie dla ilości wykonywanych porównań w każdej iteracji. Mianowicie porównujemy tylko pary elementów, które są odległe o rozpiętość. Jeśli spełniają kryteria to je zamieniamy tak jak w przypadku sortowania bąbelkowego. Niestety algorytm ten nie wie w ten sposób, kiedy skończyć, dlatego potrzebujemy dodatkowej zmiennej w każdej iteracji, która sprawdzi czy wykonaliśmy jakąkolwiek zamianę, kiedy rozpiętość wynosi 1.
Weźmy teraz listę L:={5, 3, 4, 1, 2}. Prześledzimy teraz działanie algorytmu. Przechodzimy do pierwszej iteracji - rozpiętość dla niej to . Po odrzuceniu części ułamkowej rozpiętość wynosi 3. Przechodzimy do porównania par o odległości równej 3:
(Pogrubione zostały elementy porównywane, a kursywą zamienione)
Lista | Porównanie | Nowa lista |
---|---|---|
5, 3, 4, 1, 2 | 5 > 1, zamiana 5 z 1 | 1, 3, 4, 5, 2 |
1, 3, 4, 5, 2 | 3 > 2, zamiana 3 z 2 | 1, 2, 4, 5, 3 |
Rozpiętość > 1 i dokonaliśmy zamiany, więc przechodzimy do drugiej iteracji. Na początek wyliczamy rozpiętość: . Na podstawie obliczeń przyjmujemy rozpiętość 2.
Lista | Porównanie | Nowa lista |
---|---|---|
1, 2, 4, 5, 3 | 1 < 4, nie zamieniamy | 1, 2, 4, 5, 3 |
1, 2, 4, 5, 3 | 2 < 5, nie zamieniamy | 1, 2, 4, 5, 3 |
1, 2, 4, 5, 3 | 4 > 3, zamieniamy 4 z 3 | 1, 2, 3, 5, 4 |
Przechodzimy do kolejnej iteracji: wyliczamy rozpiętość: czyli rozpiętość wynosi 1. W tym momencie rozpoczynamy sortowanie bąbelkowe. Różnica tkwi w tym, że za każdym razem przeglądamy wszystkie elementy.
Lista | Porównanie | Nowa lista |
---|---|---|
1, 2, 3, 5, 4 | 1 < 2, nie zamieniamy | 1, 2, 3, 5, 4 |
1, 2, 3, 5, 4 | 2 < 3, nie zamieniamy | 1, 2, 3, 5, 4 |
1, 2, 3, 5, 4 | 3 < 5, nie zamieniamy | 1, 2, 3, 5, 4 |
1, 2, 3, 5, 4 | 5 > 4, zamieniamy 5 z 4 | 1, 2, 3, 4, 5 |
Nasza lista jest już posortowana. Jednak program wykonałby jeszcze jedną pętlę, aby się upewnić. Dla takiej listy zmienna sprawdzająca, ile zamian zostało wykonanych, nie zgłosi żadnej. Podsumowując, mamy posortowaną listę L:={1, 2, 3, 4, 5}.
Sortowanie rozpoczynamy od zadeklarowania zmiennych. Sortowanie będzie odbywać się w miejscu, więc nie będziemy zwracać żadnej tablicy. Zmodyfikujemy podaną, jako argument, listę liczb rzeczywistych:
(1.) Przyjmujemy dwa argumenty: lista - lista do posortowania oraz n - długość listy sortowanej. (2.) Przyjmujemy, że space - to rozpiętość, a temp - przyda nam się do zamieniania elementów miejscami. (3.) Ostatnia zadeklarowana zmienna, to next_i. Jest to wspomniana zmienna, która będzie wykrywać czy w danej iteracji zostały zamienione miejscami jakieś dwa elementy. Jeśli tak to by świadczyło, że jest potrzebna dodatkowa iteracja, która sprawdzi czy lista została posortowana prawidłowo.
(4.) Rozpoczynamy główną pętle while. Wykonujemy ją dopóki rozpiętość space będzie różna od 1 oraz wykonano conajmniej jedną operację zamiany w poprzedniej iteracji. (5.) Wyliczamy aktualną rozpiętość dzieląc space przez 1.3. (6.) Jeśli rozpiętość jest równa 0 to zwiększamy do 1, ponieważ inaczej algorytm porównałby element stojący na pozycji i z elementem na pozycji i.
(8.) Resetujemy wskaźnik next_i do wartości domyślnej. (9.) Dla każdej pary elementów pomiędzy którymi jest odległość space: (10.) jeśli spełniają kryteria sortowania to (11. - 13.) zamieniamy miejscami i (14.) sygnalizujemy, że potrzebna jest dodatkowa iteracja.
Program można przetestować przy pomocy poniższej funkcji main(), która posortuje wprowadzoną listę n liczb rzeczywistych.
Zmodyfikuj funkcję, aby sortowała liczby całkowite malejąco.
Przykładowo dla listy [5 2 4 4 6] program wypisze na ekran: