I_R_W14_M27_Java Metoda Quicksort
Implementacja algorytmu w języku Java
Algorytm sortowania szybkiego oparty jest na dwóch funkcjach. Są to:
Funkcja wywoływana rekurencyjnie – nazwiemy ją
sortowanieSzybkie. Nie będzie ona zwracała żadnej wartości, jej nazwa zostanie poprzedzona słowem kluczowymvoid. Funkcja ta będzie przyjmowała trzy parametry:int tab[]– tablica zawierająca liczby całkowite do posortowania,int indeksPoczatkowy– indeks elementu początkowego fragmentu tablicy, od którego chcemy rozpocząć sortowanie tablicy,int indeksKoncowy– indeks końcowego elementu fragmentu tablicy, na którym chcemy zakończyć sortowanie tablicy.
Funkcja odpowiadająca za podział tablicy – wartością zwracaną przez funkcję będzie indeks miejsca podziału tablicy (indeks pivota). W naszym programie funkcja przyjmie nazwę
podzielTablice. Parametry tej funkcji będą identyczne jak w przypadku funkcjisortowanieSzybkie.
Oto obie zadeklarowane funkcje:
Zacznijmy od wypełnienia bloku funkcji sortowanieSzybkie. W instrukcji warunkowej sprawdzamy, czy podana jako argument tablica składa się z więcej niż jednego elementu. Jeżeli tak, następuje wywołanie funkcji podziału tablicy – podzielTablice. Do zmiennej indeksPodzialu zostanie zapisany punkt podziału tablicy (określony przez funkcję podzielTablice).
Po wywołaniu funkcji podziału następują dwa wywołania rekurencyjne funkcji sortowanieSzybkie():
sortowanieSzybkie(tab, indeksPoczatkowy, indeksPodzialu - 1);
– dla pierwszej (lewej) części tablicy,sortowanieSzybkie(tab, indeksPodzialu + 1, indeksKoncowy);
– dla drugiej (prawej) części tablicy.
Oto cały blok funkcji sortowanieSzybkie():
Kolejnym krokiem będzie przygotowanie funkcji podzielTablice.
Tworzymy zmienną pivot, do której zapisujemy wartość ostatniego elementu z sortowanego zakresu tablicy.
Pamiętajmy, że ten element możemy wybrać na inne sposoby, np. poprzez wskazanie elementu środkowego. Wybór pivota wraz ze sposobem uporządkowania tablicy mają znaczący wpływ na czas działania algorytmu. Jeżeli za każdym razem wybierany będzie element o wartości największej lub najmniejszej w tablicy, podział tablicy będzie nierównomierny. Jedna część tablicy będzie zawierała jeden element, natomiast druga część – wszystkie pozostałe. Ten pesymistyczny przypadek możemy otrzymać, gdy np. wybierzemy (pivot) o wartości ostatniego lub pierwszego elementu już posortowanej tablicy. Uzyskujemy wtedy kwadratową złożoność czasową algorytmu i liniową złożoność pamięciową , spowodowaną dużą głębokością drzewa wywołań rekurencyjnych. W przypadku optymistycznym, tzn. jeżeli tablica będzie dzielona za każdym razem na dwie równe części (element osiowy będzie medianą z sortowanego fragmentu tablicy), złożoność czasowa algorytmu wyniesie , natomiast pamięciowa – .
Następnym krokiem jest utworzenie zmiennej indeksElementuMniejszegoOdPivota, której ustawiamy wartość o 1 mniejszą od tej zapisanej w zmiennej indeksPoczatkowy. Będzie to iterator, spełniający dwa ważne zadania. Po pierwsze będzie wskazywał, na którą pozycję mamy przenieść element, gdy okaże się on mniejszy od pivota. Po drugie pomoże ustalić, w którym miejscu znajdują się elementy mniejsze od pivota. Tę zmienną wykorzystamy przy kolejnych podziałach tablicy.
Tworzymy pętlę for. Dla czytelności iterator sterujący pętlą określimy jako indeksPoszukujacy. Jego zadaniem będzie przejście po wszystkich elementach tablicy tab, które znajdują się w zadanym zakresie.
Wewnątrz pętli tworzymy instrukcję warunkową. Jeżeli wartość elementu tab[indeksPoszukujacy] jest mniejsza od wartości pivot, przenosimy ją na lewą stronę. Zwiększamy indeksElementuMniejszegoOdPivota i zamieniamy miejscami element znajdujący się w tablicy tab[indeksElementuMniejszegoOdPivota] z elementem tab[indeksPoszukujacy]. Pamiętajmy, że operacja ta jest powtarzana dla każdej komórki w tablicy, której indeks znajduje się w przedziale <indeksPoczatkowy, indeksKoncowy>.
Po przejściu pętli porządkujemy pivota – zamieniamy go miejscami z elementem wskazywanym przez indeksElementuMniejszegoOdPivota + 1.
Funkcję kończymy, zwracając indeks wskazujący na miejsce podziału: indeksElementuMniejszegoOdPivota + 1.
Przejdźmy teraz do głównej funkcji programu – main, w której utworzymy tablicę z liczbami całkowitymi, a następnie wywołamy funkcję sortowanieSzybkie w celu posortowania elementów. Wypiszemy też elementy tablicy przed sortowaniem i po sortowaniu, żeby zobaczyć, czy zostało ono wykonane poprawnie.
Oto pełen kod programu: