Sortowanie pozycyjne

Sortowanie pozycyjne liczb jest metodą sortowania opierającą się na porządkowaniu elementów ze względu na cyfry umieszczone na tych samych pozycjach.

W tej sekcji zapoznamy się z implementacją algorytmu sortowania pozycyjnego liczb, wykorzystującego sortowanie bąbelkoweP77EQCGCtsortowanie bąbelkowe. Ten algorytm, podobnie jak algorytm sortowania przez zliczanie, cechuje stabilność. Sortowanie bąbelkowe swoje działanie opiera na dwóch zagnieżdżonych pętlach. Jeżeli elementy nie zostały umieszczone w odpowiedniej kolejności, zamienia je miejscami.

Implementacja w języku C++

Zanim przystąpimy do implementacji, zapoznajmy się ze specyfikacją.

Specyfikacja:

Dane:

  • dane[] – jednowymiarowa tablica liczb naturalnych; dane do posortowania

  • liczbaElementow – liczba naturalna; długość tablicy dane

  • liczbaCyfr – liczba naturalna dodatnia; liczba cyfr tworzących największą liczbę z tablicy dane

Wynik:

  • dane – posortowana niemalejąco tablica liczb naturalnych

Mamy do posortowania następujący zbiór: {562, 3, 11, 25, 303, 4, 500}. Zaczynamy od stworzenia tablicy o nazwie dane, w której umieszczamy elementy zbioru. Ponadto tworzymy dwie zmienne: liczbaElementow, przechowującą liczbę elementów zbioru, a także liczbaCyfr, której przypiszemy liczbę cyfr, z jakiej składa się największa liczba w zbiorze.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. kratka include otwórz nawias ostrokątny cmath zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. int dane otwórz nawias kwadratowy zamknij nawias kwadratowy znak równości otwórz nawias klamrowy 562 przecinek 3 przecinek 11 przecinek 25 przecinek 303 przecinek 4 przecinek 500 zamknij nawias klamrowy średnik. Linia 6. int liczbaElementow znak równości 7 średnik. Linia 7. int liczbaCyfr znak równości 3 średnik.

Następnie implementujemy funkcję typu void, która jest odpowiedzialna za sortowanie liczb na danej pozycji za pomocą algorytmu sortowania bąbelkowegosortowanie bąbelkowesortowania bąbelkowego. Funkcja przyjmuje parametr równy numerowi aktualnej pozycji.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. kratka include otwórz nawias ostrokątny cmath zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. int dane otwórz nawias kwadratowy zamknij nawias kwadratowy znak równości otwórz nawias klamrowy 562 przecinek 3 przecinek 11 przecinek 25 przecinek 303 przecinek 4 przecinek 500 zamknij nawias klamrowy średnik. Linia 6. int liczbaElementow znak równości 7 średnik. Linia 7. int liczbaCyfr znak równości 3 średnik. Linia 9. void sortowanieBabelkowe otwórz nawias okrągły int pozycjaCyfry zamknij nawias okrągły otwórz nawias klamrowy. Linia 10. zamknij nawias klamrowy.

Algorytm sortowania bąbelkowego (ang. bubble sort) bazuje na utworzeniu zagnieżdżonej pętli for, w której sprawdzane jest, czy element poprzedni jest większy od następnego, to znaczy, czy ułożone są one w kolejności malejącej. Jeżeli jest to prawda, zamieniamy elementy ze sobą, ponieważ naszym celem jest posortowanie tablicy w porządku niemalejącym.

W algorytmie sortowania pozycyjnego sortujemy liczby na pojedynczych pozycjach. Tworzymy zatem dodatkowo zmienną wspolczynnikCyfry, która jest potrzebna do odczytania cyfry na odpowiedniej pozycji liczby ze zbioru. Nie będziemy sortować całych liczb, lecz tylko cyfry na konkretnej pozycji. Umożliwi nam to operacja polegająca na podzieleniu liczby przez wspolczynnikCyfry, a następnie obliczeniu reszty z dzielenia jej przez 10.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. kratka include otwórz nawias ostrokątny cmath zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. int dane otwórz nawias kwadratowy zamknij nawias kwadratowy znak równości otwórz nawias klamrowy 562 przecinek 3 przecinek 11 przecinek 25 przecinek 303 przecinek 4 przecinek 500 zamknij nawias klamrowy średnik. Linia 6. int liczbaElementow znak równości 7 średnik. Linia 7. int liczbaCyfr znak równości 3 średnik. Linia 9. void sortowanieBabelkowe otwórz nawias okrągły int pozycjaCyfry zamknij nawias okrągły otwórz nawias klamrowy. Linia 11. int wspolczynnikCyfry znak równości pow otwórz nawias okrągły 10 przecinek pozycjaCyfry zamknij nawias okrągły średnik. Linia 13. for otwórz nawias okrągły int i znak równości liczbaElementow minus 1 średnik i zamknij nawias ostrokątny znak równości 0 średnik i minus minus zamknij nawias okrągły otwórz nawias klamrowy. Linia 14. for otwórz nawias okrągły int j znak równości 0 średnik j otwórz nawias ostrokątny i średnik j plus plus zamknij nawias okrągły otwórz nawias klamrowy. Linia 15. if otwórz nawias okrągły otwórz nawias okrągły otwórz nawias okrągły dane otwórz nawias kwadratowy j zamknij nawias kwadratowy prawy ukośnik wspolczynnikCyfry zamknij nawias okrągły procent 10 zamknij nawias okrągły zamknij nawias ostrokątny otwórz nawias okrągły otwórz nawias okrągły dane otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy prawy ukośnik wspolczynnikCyfry zamknij nawias okrągły procent 10 zamknij nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 16. int temp znak równości dane otwórz nawias kwadratowy j zamknij nawias kwadratowy średnik. Linia 17. dane otwórz nawias kwadratowy j zamknij nawias kwadratowy znak równości dane otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy średnik. Linia 18. dane otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy znak równości temp średnik. Linia 19. zamknij nawias klamrowy. Linia 20. zamknij nawias klamrowy. Linia 21. zamknij nawias klamrowy. Linia 22. zamknij nawias klamrowy.

Możemy zoptymalizować kod, wprowadzając flagę, dzięki której zredukujemy liczbę niepotrzebnych iteracji pętli. Wystarczy, że dodamy zmienną logiczną bool o nazwie czyZmiana, która domyślnie będzie przyjmować wartość false – taką ustawiamy wartość początkową flagi.

Jeżeli chociaż w jednej iteracji pętli wewnętrznej zostaną zamienione ze sobą dwa elementy tablicy, ustawiamy wartość flagi na true. W przypadku, gdy pętla wewnętrzna zakończy swoje działanie, a w jednym całym przejściu nie zostaną zamienione ze sobą żadne elementy, wartość flagi nie zmieni się, tym samym kończąc sortowanie.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. kratka include otwórz nawias ostrokątny cmath zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. int dane otwórz nawias kwadratowy zamknij nawias kwadratowy znak równości otwórz nawias klamrowy 562 przecinek 3 przecinek 11 przecinek 25 przecinek 303 przecinek 4 przecinek 500 zamknij nawias klamrowy średnik. Linia 6. int liczbaElementow znak równości 7 średnik. Linia 7. int liczbaCyfr znak równości 3 średnik. Linia 9. void sortowanieBabelkowe otwórz nawias okrągły int pozycjaCyfry zamknij nawias okrągły otwórz nawias klamrowy. Linia 11. int wspolczynnikCyfry znak równości pow otwórz nawias okrągły 10 przecinek pozycjaCyfry zamknij nawias okrągły średnik. Linia 12. bool czyZmiana znak równości false średnik. Linia 14. for otwórz nawias okrągły int i znak równości liczbaElementow minus 1 średnik i zamknij nawias ostrokątny znak równości 0 średnik i minus minus zamknij nawias okrągły otwórz nawias klamrowy. Linia 15. for otwórz nawias okrągły int j znak równości 0 średnik j otwórz nawias ostrokątny i średnik j plus plus zamknij nawias okrągły otwórz nawias klamrowy. Linia 16. if otwórz nawias okrągły otwórz nawias okrągły otwórz nawias okrągły dane otwórz nawias kwadratowy j zamknij nawias kwadratowy prawy ukośnik wspolczynnikCyfry zamknij nawias okrągły procent 10 zamknij nawias okrągły zamknij nawias ostrokątny otwórz nawias okrągły otwórz nawias okrągły dane otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy prawy ukośnik wspolczynnikCyfry zamknij nawias okrągły procent 10 zamknij nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 17. int temp znak równości dane otwórz nawias kwadratowy j zamknij nawias kwadratowy średnik. Linia 18. dane otwórz nawias kwadratowy j zamknij nawias kwadratowy znak równości dane otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy średnik. Linia 19. dane otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy znak równości temp średnik. Linia 21. czyZmiana znak równości true średnik. Linia 22. zamknij nawias klamrowy. Linia 23. zamknij nawias klamrowy. Linia 25. if otwórz nawias okrągły wykrzyknik czyZmiana zamknij nawias okrągły otwórz nawias klamrowy. Linia 26. break średnik. Linia 27. zamknij nawias klamrowy. Linia 28. zamknij nawias klamrowy. Linia 29. zamknij nawias klamrowy.

Następnie w głównej funkcji programu używamy sortowania bąbelkowego w sortowaniu pozycyjnym zbioru liczb. Tworzymy pętlę for, która będzie iterować po pozycjach liczb – od pozycji 0 do pozycji równej wartości zapisanej w zmiennej liczbaCyfr. Dla każdej pozycji zostanie wywołana funkcja sortowanieBabelkowe z argumentem równym pozycji sortowanej cyfry.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. kratka include otwórz nawias ostrokątny cmath zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. int dane otwórz nawias kwadratowy zamknij nawias kwadratowy znak równości otwórz nawias klamrowy 562 przecinek 3 przecinek 11 przecinek 25 przecinek 303 przecinek 4 przecinek 500 zamknij nawias klamrowy średnik. Linia 6. int liczbaElementow znak równości 7 średnik. Linia 7. int liczbaCyfr znak równości 3 średnik. Linia 9. void sortowanieBabelkowe otwórz nawias okrągły int pozycjaCyfry zamknij nawias okrągły otwórz nawias klamrowy. Linia 11. int wspolczynnikCyfry znak równości pow otwórz nawias okrągły 10 przecinek pozycjaCyfry zamknij nawias okrągły średnik. Linia 13. for otwórz nawias okrągły int i znak równości liczbaElementow minus 1 średnik i zamknij nawias ostrokątny znak równości 0 średnik i minus minus zamknij nawias okrągły otwórz nawias klamrowy. Linia 14. for otwórz nawias okrągły int j znak równości 0 średnik j otwórz nawias ostrokątny i średnik j plus plus zamknij nawias okrągły otwórz nawias klamrowy. Linia 15. if otwórz nawias okrągły otwórz nawias okrągły otwórz nawias okrągły dane otwórz nawias kwadratowy j zamknij nawias kwadratowy prawy ukośnik wspolczynnikCyfry zamknij nawias okrągły procent 10 zamknij nawias okrągły zamknij nawias ostrokątny otwórz nawias okrągły otwórz nawias okrągły dane otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy prawy ukośnik wspolczynnikCyfry zamknij nawias okrągły procent 10 zamknij nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 16. int temp znak równości dane otwórz nawias kwadratowy j zamknij nawias kwadratowy średnik. Linia 17. dane otwórz nawias kwadratowy j zamknij nawias kwadratowy znak równości dane otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy średnik. Linia 18. dane otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy znak równości temp średnik. Linia 19. zamknij nawias klamrowy. Linia 20. zamknij nawias klamrowy. Linia 21. zamknij nawias klamrowy. Linia 22. zamknij nawias klamrowy. Linia 23. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 25. for otwórz nawias okrągły int numerCyfry znak równości 0 średnik numerCyfry otwórz nawias ostrokątny liczbaCyfr średnik numerCyfry plus plus zamknij nawias okrągły otwórz nawias klamrowy. Linia 26. sortowanieBabelkowe otwórz nawias okrągły numerCyfry zamknij nawias okrągły średnik. Linia 27. zamknij nawias klamrowy. Linia 29. return 0 średnik. Linia 30. zamknij nawias klamrowy.

Na koniec wyświetlamy posortowaną tablicę. Tak wygląda skończony kod programu sortującego zbiór liczb algorytmem sortowania pozycyjnego:

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. kratka include otwórz nawias ostrokątny cmath zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. int dane otwórz nawias kwadratowy zamknij nawias kwadratowy znak równości otwórz nawias klamrowy 562 przecinek 3 przecinek 11 przecinek 25 przecinek 303 przecinek 4 przecinek 500 zamknij nawias klamrowy średnik. Linia 6. int liczbaElementow znak równości 7 średnik. Linia 7. int liczbaCyfr znak równości 3 średnik. Linia 9. void sortowanieBabelkowe otwórz nawias okrągły int pozycjaCyfry zamknij nawias okrągły otwórz nawias klamrowy. Linia 11. int wspolczynnikCyfry znak równości pow otwórz nawias okrągły 10 przecinek pozycjaCyfry zamknij nawias okrągły średnik. Linia 13. for otwórz nawias okrągły int i znak równości liczbaElementow minus 1 średnik i zamknij nawias ostrokątny znak równości 0 średnik i minus minus zamknij nawias okrągły otwórz nawias klamrowy. Linia 14. for otwórz nawias okrągły int j znak równości 0 średnik j otwórz nawias ostrokątny i średnik j plus plus zamknij nawias okrągły otwórz nawias klamrowy. Linia 15. if otwórz nawias okrągły otwórz nawias okrągły otwórz nawias okrągły dane otwórz nawias kwadratowy j zamknij nawias kwadratowy prawy ukośnik wspolczynnikCyfry zamknij nawias okrągły procent 10 zamknij nawias okrągły zamknij nawias ostrokątny otwórz nawias okrągły otwórz nawias okrągły dane otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy prawy ukośnik wspolczynnikCyfry zamknij nawias okrągły procent 10 zamknij nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 16. int temp znak równości dane otwórz nawias kwadratowy j zamknij nawias kwadratowy średnik. Linia 17. dane otwórz nawias kwadratowy j zamknij nawias kwadratowy znak równości dane otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy średnik. Linia 18. dane otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy znak równości temp średnik. Linia 19. zamknij nawias klamrowy. Linia 20. zamknij nawias klamrowy. Linia 21. zamknij nawias klamrowy. Linia 22. zamknij nawias klamrowy. Linia 23. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 25. for otwórz nawias okrągły int numerCyfry znak równości 0 średnik numerCyfry otwórz nawias ostrokątny liczbaCyfr średnik numerCyfry plus plus zamknij nawias okrągły otwórz nawias klamrowy. Linia 26. sortowanieBabelkowe otwórz nawias okrągły numerCyfry zamknij nawias okrągły średnik. Linia 27. zamknij nawias klamrowy. Linia 28. for otwórz nawias okrągły int i znak równości 0 średnik i otwórz nawias ostrokątny liczbaElementow średnik i plus plus zamknij nawias okrągły otwórz nawias klamrowy. Linia 29. cout otwórz nawias ostrokątny otwórz nawias ostrokątny dane otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów cudzysłów średnik. Linia 30. zamknij nawias klamrowy. Linia 32. return 0 średnik. Linia 33. zamknij nawias klamrowy.

Algorytm sortowania bąbelkowego nie jest wykorzystywany w praktyce przy implementacji sortowania pozycyjnego z powodu jego kwadratowej złożoności czasowej. Program, który przeanalizowaliśmy, jest przykładowy, został przedstawiony w celu poznania możliwości sortowania pozycyjnego. Częściej wykorzystuje się inne algorytmy, np. sortowanie kubełkowesortowanie kubełkowesortowanie kubełkowe, czy sortowanie przez zliczanie, którego główną zaletą jest liniowa złożoność czasowa O(n+k), gdzie n to liczebność sortowanego zbioru, a k to rozpiętość danych. W przypadku sortowania przez zliczanie użytego w algorytmie sortowania pozycyjnego rozpiętość danych nie jest duża (sortujemy liczby dziesiętne, więc na każdej pozycji sortujemy liczby z zakresu 0–9).

Słownik

sortowanie bąbelkowe
sortowanie bąbelkowe

polega na porównywaniu ze sobą dwóch sąsiadujących elementów w kolejności od lewej do prawej i zamianie ich ze sobą, jeżeli znajdują się w nieprawidłowej kolejności

sortowanie kubełkowe
sortowanie kubełkowe

polega na umieszczaniu elementów sortowanej tablicy do kubełków, które zawierają liczby z określonego przedziału; każdy kubełek zostaje posortowany oddzielnie; w ostatnim kroku tworzona jest tablica końcowa, do której zapisywane są dane z kolejnych kubełków

sortowanie przez zliczanie
sortowanie przez zliczanie

polega na sprawdzeniu, ile wystąpień kluczy mniejszych od danego występuje w sortowanej tablicy; algorytm przystosowany jest do sortowania zbioru liczb, które mogą posiadać skrajnie różne, niepowtarzające się wartości

stabilny algorytm sortowania
stabilny algorytm sortowania

algorytm sortowania, w którym elementy o równej wartości po posortowaniu będą ułożone w takiej samej kolejności, w jakiej były w nieposortowanym zbiorze