Przeczytaj
Algorytmy sortowania – właściwości
Mówiąc o algorytmach sortowaniasortowania, powinniśmy pamiętać o tym, jak można je scharakteryzować oraz ze względu na co podzielić.
Możemy wyróżnić działania, na których bazuje większość algorytmów sortowania, które poznamy – są to np.: wstawianie, zamiana, wybór oraz łączenie. Algorytmy najczęściej wykorzystują kilka z nich.
Sortowanie w miejscu
Algorytmy sortowania, które sortują w miejscu (in situ) to takie algorytmy, które niezależnie od tego, jaki jest rozmiar danych wejściowych, do wykonania sortowania potrzebują stałej ilości pamięci komputera.
Przykłady algorytmów sortowania, które sortują dane w miejscu: sortowanie przez wybieraniesortowanie przez wybieranie, sortowanie przez wstawianiesortowanie przez wstawianie, sortowanie bąbelkowesortowanie bąbelkowe, sortowanie szybkiesortowanie szybkie.
Przykłady algorytmów sortowania, które nie sortują danych w miejscu: sortowanie kubełkowesortowanie kubełkowe, sortowanie pozycyjne (np. sortowanie pozycyjne datsortowanie pozycyjne dat, sortowanie pozycyjne liczbsortowanie pozycyjne liczb, sortowanie pozycyjne słówsortowanie pozycyjne słów), sortowanie przez zliczaniesortowanie przez zliczanie, sortowanie przez scalaniesortowanie przez scalanie.
Algorytmy iteracyjne i rekurencyjne
Niektóre z algorytmów sortowania wykorzystują rekurencję. Może to powodować sytuację, w której ich wykorzystanie jest ograniczone, np. dla przypadku pesymistycznego algorytm sortowania szybkiego ma kwadratową złożoność.
Przykłady algorytmów sortowania, które wykorzystują rekurencję: sortowanie przez scalaniesortowanie przez scalanie, sortowanie szybkiesortowanie szybkie.
Inne algorytmy wykorzystują techniki iteracyjne, to jest pętle, których celem jest powtarzanie bloków instrukcji aż do spełnienia pewnego warunku.
Przykłady algorytmów sortowania, które wykorzystują iterację: sortowanie przez wybieraniesortowanie przez wybieranie, sortowanie przez wstawianiesortowanie przez wstawianie, sortowanie bąbelkowesortowanie bąbelkowe, sortowanie kubełkowesortowanie kubełkowe, sortowanie pozycyjne (np. sortowanie pozycyjne datsortowanie pozycyjne dat, sortowanie pozycyjne liczbsortowanie pozycyjne liczb, sortowanie pozycyjne słówsortowanie pozycyjne słów), sortowanie przez zliczaniesortowanie przez zliczanie.
Algorytmy liniowe i wykorzystujące metodę „dziel i zwyciężaj”
Algorytmy wykorzystujące metodę „dziel i zwyciężaj” składają się z trzech etapów – najpierw należy podzielić problem na podproblemy, następnie znaleźć rozwiązanie dla każdego problemu, a następnie połączyć rozwiązania poszczególnych podproblemów w rozwiązanie problemu głównego. Metoda została dokładniej omówiona w e‑materiale Rozwiązywanie problemów informatycznych – strategia „dziel i zwyciężaj”Rozwiązywanie problemów informatycznych – strategia „dziel i zwyciężaj”.
Przykłady algorytmów sortowania, które wykorzystują metodę „dziel i zwyciężaj”: sortowanie przez scalaniesortowanie przez scalanie, sortowanie szybkiesortowanie szybkie.
Algorytmy liniowe natomiast przechodzą przez dane sekwencyjnie (element po elemencie) w celu uporządkowania ich w odpowiedniej kolejności
Przykłady algorytmów sortowania, które przetwarzają dane sekwencyjnie: sortowanie przez wybieraniesortowanie przez wybieranie, sortowanie przez wstawianiesortowanie przez wstawianie, sortowanie bąbelkowesortowanie bąbelkowe, sortowanie kubełkowesortowanie kubełkowe, sortowanie pozycyjne (np. sortowanie pozycyjne datsortowanie pozycyjne dat, sortowanie pozycyjne liczbsortowanie pozycyjne liczb, sortowanie pozycyjne słówsortowanie pozycyjne słów), sortowanie przez zliczaniesortowanie przez zliczanie.
Algorytmy oparte na porównywaniu i zliczaniu
Wyróżnia się algorytmy sortowania bazujące na porównywaniu elementów oraz zliczaniu ich.
Algorytmy bazujące na porównywaniu elementów określają, czy dany element jest większy, mniejszy od danego innego elementu czy mu równy. Na tej podstawie elementy są zamieniane miejscami, by uporządkować je w odpowiedniej kolejności
Przykłady algorytmów sortowania, które wykorzystują porównywanie elementów: sortowanie przez wybieraniesortowanie przez wybieranie, sortowanie przez wstawianiesortowanie przez wstawianie, sortowanie bąbelkowesortowanie bąbelkowe, sortowanie przez scalaniesortowanie przez scalanie, sortowanie szybkiesortowanie szybkie.
Algorytmy wykorzystując zliczanie działają w taki sposób, że zliczają wystąpienia poszczególnych wartości, zamiast porównywać je bezpośrednio. Na podstawie informacji o liczbie wystąpień wartości, elementy są umieszczane na odpowiednich pozycjach.
Przykłady algorytmów sortowania, które wykorzystują zliczanie elementów: sortowanie kubełkowesortowanie kubełkowe, sortowanie pozycyjne (np. sortowanie pozycyjne datsortowanie pozycyjne dat, sortowanie pozycyjne liczbsortowanie pozycyjne liczb, sortowanie pozycyjne słówsortowanie pozycyjne słów), sortowanie przez zliczaniesortowanie przez zliczanie.
Stabilność
Algorytmy sortowania stabilnego to takie algorytmy, w których elementy o takiej samej wartości podczas sortowania nie zmieniają kolejności względem siebie.
Przykłady algorytmów sortowania, które są stabilne: sortowanie przez wstawianiesortowanie przez wstawianie, sortowanie bąbelkowesortowanie bąbelkowe, sortowanie pozycyjne (np. sortowanie pozycyjne datsortowanie pozycyjne dat, sortowanie pozycyjne liczbsortowanie pozycyjne liczb, sortowanie pozycyjne słówsortowanie pozycyjne słów), sortowanie przez zliczaniesortowanie przez zliczanie, sortowanie przez scalaniesortowanie przez scalanie.
Przykłady algorytmów sortowania, które nie są stabilne: sortowanie przez wybieraniesortowanie przez wybieranie, sortowanie kubełkowesortowanie kubełkowe, sortowanie szybkiesortowanie szybkie.
Złożoność obliczeniowa i pamięciowa
Informacje na temat złożoności obliczeniowej oraz pamięciowej znajdziesz w e‑materiałach Jak wybrać odpowiedni algorytm sortowania?Jak wybrać odpowiedni algorytm sortowania? oraz Porównanie algorytmów sortowaniaPorównanie algorytmów sortowania.
Sposób sortowania elementów
Wyrazy sortowanego zbioru mogą być sortowane rosnąco, niemalejąco, malejąco lub nierosnąco. Domyślnym przypadkiem jest sortowanie niemalejące lub rosnące.
Chociaż terminy kolejność niemalejąca i rosnąca oraz nierosnąca i malejąca bywają używane zamiennie, ich znaczenia nie są tożsame.
O sortowaniu rosnącym mówimy wtedy, gdy każdy kolejny posortowany element jest większy od poprzedniego – nie ma równych elementów.
O sortowaniu niemalejącym mówimy wtedy, gdy każdy kolejny posortowany element jest większy lub równy poprzedniemu (w zbiorze są równe sobie elementy).
O sortowaniu malejącym mówimy wtedy, gdy każdy kolejny posortowany element jest mniejszy od poprzedniego – nie ma równych elementów.
O sortowaniu nierosnącym mówimy wtedy, gdy każdy kolejny posortowany element jest mniejszy lub równy poprzedniemu (w zbiorze są równe sobie elementy).
Podsumowanie
Większość wspomnianych algorytmów opisujemy w e‑materiałach.
Różne właściwości algorytmów mogą być powiązane w różny sposób, a wiele algorytmów można przypisać do kilku kategorii, np. sortowanie szybkie (quicksort) jest algorytmem porównawczym, który wykorzystuje technikę dziel i zwyciężaj i może być zaimplementowany za pomocą iteracji lub rekurencji (choć w e‑materiałach przedstawimy jego rekurencyjną implementację).
Często decyzja o wyborze strategii zależy od konkretnych wymagań i ograniczeń problemu, który próbujemy rozwiązać. O tym, w jaki sposób dobrać algorytm sortowania, przeczytasz w e‑materiale Jak wybrać odpowiedni algorytm sortowania?Jak wybrać odpowiedni algorytm sortowania?.
Wyszukiwanie elementu w zbiorze posortowanym i nieposortowanym
Zaprezentujmy na przykładzie, jak ważne jest sortowanie elementów i jak bardzo może usprawnić pracę programu. Porównajmy liczbę operacji, jakie będą musiały zostać wykonane podczas wyszukiwania elementu w zbiorze zarówno posortowanym, jak i nieposortowanym.
Specyfikacja problemu:
Dane:
tab
– przeszukiwana tablica liczbszukana_liczba
– liczba której szukamy
Wynik:
informacja, czy
szukana_liczba
znajduje się w tablicytab
By porównać przykładową liczbę operacji, działanie programu przetestujemy dla tablicy, w skład której wchodzą następujące liczby: 30, 3, 20, 28, 21, 18, 5, 6, 1, 14
.
Będziemy szukać liczby 18
.
Wyszukiwanie liniowe – wyszukiwanie w zbiorze nieposortowanym. Ten algorytm realizowany jest liniowo – element po elemencie. Algorytm będzie prezentował się w następujący sposób:
Przebieg algorytmu dla podanych danych:
Inicjalizujemy zmienne.
Rozpoczynamy pętlę:
tab[0] = 30
- nie jest to szukana liczba, zwiększamyi
o 1. Wykonaliśmy 1 porównanie.tab[1] = 3
- nie jest to szukana liczba, zwiększamyi
o 1. Wykonaliśmy 2 porównania.tab[2] = 20
- nie jest to szukana liczba, zwiększamyi
o 1. Wykonaliśmy 3 porównania.tab[3] = 28
- nie jest to szukana liczba, zwiększamyi
o 1. Wykonaliśmy 4 porównania.tab[4] = 21
- nie jest to szukana liczba, zwiększamyi
o 1. Wykonaliśmy 5 porównania.tab[5] = 18
- jest to szukana liczba. WypisujemyZnaleziono liczbę na pozycji: 5
. Ustawiamyznaleziono <-- prawda
. Wykonaliśmy 6 porównań. Kończymy działanie algorytmu.
Podsumowując, wykonaliśmy 6 porównań wewnątrz pętli i żadnego porównania po pętli.
Wyszukiwanie liniowe z wartownikiem – na końcu przeszukiwanego zbioru dodajemy element równy poszukiwanemu.
Algorytm będzie prezentował się w następujący sposób:
Przebieg algorytmu dla podanych danych:
Inicjalizujemy zmienne (pamiętamy o dodaniu wartownika).
Rozpoczynamy pętlę:
tab[0] = 30
- nie jest to szukana liczba, zwiększamyi
o 1. Wykonaliśmy 1 porównanie.tab[1] = 3
- nie jest to szukana liczba, zwiększamyi
o 1. Wykonaliśmy 2 porównania.tab[2] = 20
- nie jest to szukana liczba, zwiększamyi
o 1. Wykonaliśmy 3 porównania.tab[3] = 28
- nie jest to szukana liczba, zwiększamyi
o 1. Wykonaliśmy 4 porównania.tab[4] = 21
- nie jest to szukana liczba, zwiększamyi
o 1. Wykonaliśmy 5 porównania.tab[5] = 18
- jest to szukana liczba. Wykonaliśmy 6 porównań.
Po wyjściu z pętli:
sprawdzamy warunek
i < długość(tab) - 1
:i = 5
długość(tab) - 1 = 10
(ponieważ długość tablicy wynosi 11 po dodaniu wartownika)Ponieważ
5 < 10
, więc wypisujemyZnaleziono liczbę na pozycji: 5
.
Podsumowując, wykonaliśmy 6 porównań wewnątrz pętli i 1 porównanie po pętli (porównanie wartości i
z wartością długość(tab) - 1
).
Wyszukiwanie binarneWyszukiwanie binarne – wyszukiwanie w zbiorze posortowanym. Pierwszym krokiem, jaki musimy wykonać, jest posortowanie zbioru. Jest to wymóg zastosowania wyszukiwania binarnego.
Posortowany zbiór będzie wyglądał następująco: {1, 3, 5, 6, 14, 18, 20, 21, 28, 30}
.
Następnie wykonujemy algorytm wyszukiwania binarnego:
Przebieg algorytmu dla podanych danych:
Inicjalizujemy zmienne (pamiętamy o dodaniu wartownika).
Rozpoczynamy pętlę:
i <-- (9 + 0) // 2
to4,
czylitab[4] = 14
.14 < 18
zatem wykonujemylewo <-- i + 1
, co dajelewo <-- 5
. Wykonaliśmy 1 porównanie.
i <-- (9 + 5) / 2
to7
. Czylitab[7] = 21
.21 < 18
zatem wykonujemyprawo <-- i - 1
, co dajeprawo <-- 6
. Wykonaliśmy 2 porównania.
i <-- (6 + 5) // 2
to5,
czylitab[5] = 18
. WypisujemyZnaleziono liczbę na pozycji: 5
.
Podsumowując, wykonaliśmy 3 porównania (podziały) wewnątrz pętli.
Zadanie typu maturalnego, które wymaga odnalezienia konkretnego elementu, w którym wykorzystujemy wyszukiwanie liniowego oraz binarne, znajdziesz w e‑materiale Przerywanie pętli – zadania maturalnePrzerywanie pętli – zadania maturalne.
Jak widzimy, algorytm wyszukiwania binarnego zadziałał szybciej niż algorytm liniowyalgorytm liniowy.
Aby można było skorzystać z algorytmu wyszukiwania binarnego, zbiór danych musi być posortowany. W sytuacji, gdy zbiór, w którym jest niewiele elementów, nie będzie często przeszukiwany (np. chcemy wyłącznie raz sprawdzić, czy znajduje się w nim dany element), metoda liniowa (czyli taka, która nie wymaga od nas wcześniejszego posortowania zbioru) może okazać się w zupełności wystarczająca.
Warto jednak pamiętać, że utrzymywanie dużego posortowanego zbioru danych, w którym często szukamy informacji, jest znacznie korzystniejsze ze względu na czas, jaki zajmuje każde wyszukanie. Nawet jeżeli sam proces sortowania okaże się czasochłonny – wykonamy go tylko raz, za to zaoszczędzimy sporo czasu na wielokrotnym przeszukiwaniu zbioru. Dlatego też tak ważna jest znajomość i umiejętność skutecznego użycia podstawowych algorytmów sortowania.
Słownik
w programowaniu: nadanie wartości początkowych
element algorytmu pozwalający na sprawdzenie jednego lub kilku warunków, a następnie zdefiniowanie, jakie czynności mają być wykonane, jeśli dane warunki są spełnione lub niespełnione (służy do sterowania programem)
proces polegający na porządkowaniu zbioru elementów według ich wybranych cech
inaczej in situ; sortowanie, w którym niezależnie od rozmiaru danych wejściowych potrzebna jest stała ilość pamięci komputera
sortowanie, w którym elementy o takiej samej wartości nie zmienią pozycji względem siebie
ilość zasobów komputerowych potrzebnych do wykonania zadania
ilość czasu potrzebnego do wykonania zadania, wyrażona jako funkcja ilości danych