W poprzedniej sekcji zaprezentowano, na czym polega sortowanie pozycyjne oraz jak przebiega jego implementacja w języku Java. W tej sekcji pokażemy, że nie zawsze algorytmem pomocniczym jest sortowanie przez zliczanie. Zaimplementujemy algorytm sortowania pozycyjnego, używając pomocniczo sortowania bąbelkowego. Pamiętajmy jednak, że możemy wykorzystać dowolny stabilny algorytm sortujący, np. sortowanie przez wstawianie lub sortowanie przez scalanie.
Algorytm sortowania pozycyjnego w języku Java
Zacznijmy od stworzenia funkcji, która będzie przechowywała tablicę zawierającą łańcuchy znaków – będą to przykładowe słowa.
Ponieważ sortowane słowa mogą być różnej długości, zanim przystąpimy do właściwej implementacji algorytmu, znajdziemy najdłuższe słowo. W tym celu zapiszemy długość pierwszego słowa do zmiennej maxDlugosc. Następnie w pętli będziemy porównywali długości kolejnych słów ze zmienną maxDlugosc. Jeżeli sprawdzane słowo okaże się dłuższe, zmienimy wartość zmiennej maxDlugosc na długość obecnie sprawdzanego słowa. Pamiętajmy, że interesuje nas tylko długość najdłuższego słowa, a nie to, które słowo jest najdłuższe – dlatego wystarczy tylko jedna zmienna.
Linia 1. prawy ukośnik prawy ukośnik funkcja sortowania pozycyjnego.
Linia 2. static void sortowaniePozycyjneSlow otwórz nawias okrągły String otwórz nawias kwadratowy zamknij nawias kwadratowy slowa zamknij nawias okrągły otwórz nawias klamrowy.
Linia 3. prawy ukośnik prawy ukośnik znajdujemy najdłuższe słowo w tablicy.
Linia 4. int maxDlugosc znak równości slowa otwórz nawias kwadratowy 0 zamknij nawias kwadratowy kropka length otwórz nawias okrągły zamknij nawias okrągły średnik.
Linia 5. for otwórz nawias okrągły int i znak równości 1 średnik i otwórz nawias ostrokątny slowa kropka length minus 1 średnik i plus plus zamknij nawias okrągły otwórz nawias klamrowy.
Linia 6. if otwórz nawias okrągły slowa otwórz nawias kwadratowy i zamknij nawias kwadratowy kropka length otwórz nawias okrągły zamknij nawias okrągły zamknij nawias ostrokątny maxDlugosc zamknij nawias okrągły otwórz nawias klamrowy.
Linia 7. maxDlugosc znak równości slowa otwórz nawias kwadratowy i zamknij nawias kwadratowy kropka length otwórz nawias okrągły zamknij nawias okrągły średnik.
Linia 8. zamknij nawias klamrowy.
Linia 9. zamknij nawias klamrowy.
Linia 10. zamknij nawias klamrowy.
// funkcja sortowania pozycyjnego
static void sortowaniePozycyjneSlow(String[] slowa) {
// znajdujemy najdłuższe słowo w tablicy
int maxDlugosc = slowa[0].length();
for (int i = 1; i < slowa.length - 1; i++) {
if(slowa[i].length() > maxDlugosc) {
maxDlugosc = slowa[i].length();
}
}
}
Teraz możemy napisać właściwy algorytm sortowania pozycyjnego. W pętli for będziemy wywoływać funkcję sortującą – w tym przypadku będzie to funkcja sortowanieBabelkowe. Funkcja ta będzie zawierać pomocniczy stabilny algorytm sortowania. Wykonywanie pętli rozpocznie się od znaku o indeksie maxDlugosc - 1, a zakończy na indeksie 0.
Linia 1. prawy ukośnik prawy ukośnik funkcja sortowania pozycyjnego.
Linia 2. static void sortowaniePozycyjneSlow otwórz nawias okrągły String otwórz nawias kwadratowy zamknij nawias kwadratowy slowa zamknij nawias okrągły otwórz nawias klamrowy.
Linia 3. prawy ukośnik prawy ukośnik znajdujemy najdłuższe słowo w tablicy.
Linia 4. int maxDlugosc znak równości slowa otwórz nawias kwadratowy 0 zamknij nawias kwadratowy kropka length otwórz nawias okrągły zamknij nawias okrągły średnik.
Linia 5. for otwórz nawias okrągły int i znak równości 1 średnik i otwórz nawias ostrokątny slowa kropka length minus 1 średnik i plus plus zamknij nawias okrągły otwórz nawias klamrowy.
Linia 6. if otwórz nawias okrągły slowa otwórz nawias kwadratowy i zamknij nawias kwadratowy kropka length otwórz nawias okrągły zamknij nawias okrągły zamknij nawias ostrokątny maxDlugosc zamknij nawias okrągły otwórz nawias klamrowy.
Linia 7. maxDlugosc znak równości slowa otwórz nawias kwadratowy i zamknij nawias kwadratowy kropka length otwórz nawias okrągły zamknij nawias okrągły średnik.
Linia 8. zamknij nawias klamrowy.
Linia 9. zamknij nawias klamrowy.
Linia 11. prawy ukośnik prawy ukośnik sortujemy dla każdej kolejnej pozycji.
Linia 12. for otwórz nawias okrągły int i znak równości maxDlugosc 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 13. sortowanieBabelkowe otwórz nawias okrągły slowa przecinek i zamknij nawias okrągły średnik.
Linia 14. zamknij nawias klamrowy.
Linia 15. zamknij nawias klamrowy.
// funkcja sortowania pozycyjnego
static void sortowaniePozycyjneSlow(String[] slowa) {
// znajdujemy najdłuższe słowo w tablicy
int maxDlugosc = slowa[0].length();
for (int i = 1; i < slowa.length - 1; i++) {
if(slowa[i].length() > maxDlugosc) {
maxDlugosc = slowa[i].length();
}
}
// sortujemy dla każdej kolejnej pozycji
for(int i = maxDlugosc - 1; i >= 0; i--) {
sortowanieBabelkowe(slowa, i);
}
}
Po przygotowaniu pierwszej funkcji – wskazującej, po którym znaku będziemy układać elementy w tym wywołaniu, wybieramy stabilny algorytm sortowania i przechodzimy do implementacji algorytmu sortowania wewnętrznego. Funkcja realizująca ten algorytm będzie przyjmować dwa argumenty: jednowymiarową tablicę znaków slowa oraz liczbę całkowitą indeksZnaku. Pamiętajmy, że algorytm w niej zawarty musi być stabilnystabilny algorytm sortowaniastabilny.
Algorytmem sortowania, który spełnia nasze wymagania jest między innymi sortowanie bąbelkowe.
Opis tego algorytmu możesz znaleźć w odpowiednim e‑materiale. W tej sekcji potrzebujemy wprowadzić jedynie odpowiednią modyfikację, która zapobiegnie wyświetlaniu błędów w sytuacji, gdy sortowane słowa są różnej długości.
Linia 1. static void sortowanieBabelkowe otwórz nawias okrągły String otwórz nawias kwadratowy zamknij nawias kwadratowy slowa przecinek int indeksZnaku zamknij nawias okrągły otwórz nawias klamrowy.
Linia 3. zamknij nawias klamrowy.
static void sortowanieBabelkowe(String[] slowa, int indeksZnaku) {
}
Zapiszmy w zmiennej n długość tablicy slowa.
Linia 1. static void sortowanieBabelkowe otwórz nawias okrągły String otwórz nawias kwadratowy zamknij nawias kwadratowy slowa przecinek int indeksZnaku zamknij nawias okrągły otwórz nawias klamrowy.
Linia 2. int n znak równości slowa kropka length średnik.
Linia 3. zamknij nawias klamrowy.
static void sortowanieBabelkowe(String[] slowa, int indeksZnaku) {
int n = slowa.length;
}
Stwórzmy również dwie pętle. Pierwsza z nich w każdym swoim obiegu umieści na odpowiednim miejscu jeden z elementów. Druga pętla, wewnętrzna, będzie odpowiedzialna za porównywanie elementów i ich zamianę.
Linia 1. static void sortowanieBabelkowe otwórz nawias okrągły String otwórz nawias kwadratowy zamknij nawias kwadratowy slowa przecinek int indeksZnaku zamknij nawias okrągły otwórz nawias klamrowy.
Linia 2. int n znak równości slowa kropka length średnik.
Linia 3. for otwórz nawias okrągły int i znak równości 0 średnik i otwórz nawias ostrokątny n minus 1 średnik i plus plus zamknij nawias okrągły.
Linia 4. for otwórz nawias okrągły int j znak równości 0 średnik j otwórz nawias ostrokątny n minus i minus 1 średnik j plus plus zamknij nawias okrągły otwórz nawias klamrowy.
Linia 6. zamknij nawias klamrowy.
Linia 7. zamknij nawias klamrowy.
static void sortowanieBabelkowe(String[] slowa, int indeksZnaku) {
int n = slowa.length;
for (int i = 0; i < n - 1; i++)
for (int j = 0; j < n - i - 1; j++) {
}
}
Teraz wprowadzamy instrukcję warunkową, której nie ma w oryginalnym algorytmie. Sprawdzamy, czy słowa które porównujemy, mają na pozycji indeksZnaku jakikolwiek znak. Jeżeli nie mają (ponieważ np. są za krótkie), to porównywanie ich liter o danym indeksie jest bezcelowe.
Linia 1. static void sortowanieBabelkowe otwórz nawias okrągły String otwórz nawias kwadratowy zamknij nawias kwadratowy slowa przecinek int indeksZnaku zamknij nawias okrągły otwórz nawias klamrowy.
Linia 2. int n znak równości slowa kropka length średnik.
Linia 3. for otwórz nawias okrągły int i znak równości 0 średnik i otwórz nawias ostrokątny n minus 1 średnik i plus plus zamknij nawias okrągły.
Linia 4. for otwórz nawias okrągły int j znak równości 0 średnik j otwórz nawias ostrokątny n minus i minus 1 średnik j plus plus zamknij nawias okrągły otwórz nawias klamrowy.
Linia 5. if otwórz nawias okrągły slowa otwórz nawias kwadratowy j zamknij nawias kwadratowy kropka length otwórz nawias okrągły zamknij nawias okrągły zamknij nawias ostrokątny indeksZnaku ampersant ampersant slowa otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy kropka length otwórz nawias okrągły zamknij nawias okrągły zamknij nawias ostrokątny indeksZnaku zamknij nawias okrągły otwórz nawias klamrowy.
Linia 7. zamknij nawias klamrowy.
Linia 8. zamknij nawias klamrowy.
Linia 9. zamknij nawias klamrowy.
Linia 10. zamknij nawias klamrowy.
static void sortowanieBabelkowe(String[] slowa, int indeksZnaku) {
int n = slowa.length;
for (int i = 0; i < n - 1; i++)
for (int j = 0; j < n - i - 1; j++) {
if (slowa[j].length() > indeksZnaku && slowa[j + 1].length() > indeksZnaku) {
}
}
}
}
Zapisujemy instrukcje, które wykonają się, jeśli zostanie spełniony warunek zapisany w linii 5. Zadaniem tych instrukcji jest zamiana miejscami porównywanych elementów.
Linia 1. static void sortowanieBabelkowe otwórz nawias okrągły String otwórz nawias kwadratowy zamknij nawias kwadratowy slowa przecinek int indeksZnaku zamknij nawias okrągły otwórz nawias klamrowy.
Linia 2. int n znak równości slowa kropka length średnik.
Linia 3. for otwórz nawias okrągły int i znak równości 0 średnik i otwórz nawias ostrokątny n minus 1 średnik i plus plus zamknij nawias okrągły.
Linia 4. for otwórz nawias okrągły int j znak równości 0 średnik j otwórz nawias ostrokątny n minus i minus 1 średnik j plus plus zamknij nawias okrągły otwórz nawias klamrowy.
Linia 5. if otwórz nawias okrągły slowa otwórz nawias kwadratowy j zamknij nawias kwadratowy kropka length otwórz nawias okrągły zamknij nawias okrągły zamknij nawias ostrokątny indeksZnaku ampersant ampersant slowa otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy kropka length otwórz nawias okrągły zamknij nawias okrągły zamknij nawias ostrokątny indeksZnaku zamknij nawias okrągły otwórz nawias klamrowy.
Linia 6. if otwórz nawias okrągły slowa otwórz nawias kwadratowy j zamknij nawias kwadratowy kropka charAt otwórz nawias okrągły indeksZnaku zamknij nawias okrągły zamknij nawias ostrokątny slowa otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy kropka charAt otwórz nawias okrągły indeksZnaku zamknij nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy.
Linia 7. String pom znak równości slowa otwórz nawias kwadratowy j zamknij nawias kwadratowy średnik.
Linia 8. slowa otwórz nawias kwadratowy j zamknij nawias kwadratowy znak równości slowa otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy średnik.
Linia 9. slowa otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy znak równości pom średnik.
Linia 10. zamknij nawias klamrowy.
Linia 11. zamknij nawias klamrowy.
Linia 12. zamknij nawias klamrowy.
Linia 13. zamknij nawias klamrowy.
static void sortowanieBabelkowe(String[] slowa, int indeksZnaku) {
int n = slowa.length;
for (int i = 0; i < n - 1; i++)
for (int j = 0; j < n - i - 1; j++) {
if (slowa[j].length() > indeksZnaku && slowa[j + 1].length() > indeksZnaku) {
if (slowa[j].charAt(indeksZnaku) > slowa[j + 1].charAt(indeksZnaku)) {
String pom = slowa[j];
slowa[j] = slowa[j + 1];
slowa[j + 1] = pom;
}
}
}
}
Mamy gotowy stabilny algorytm sortowania oraz algorytm sortowania pozycyjnego. Możemy teraz wywołać program dla przykładowych danych:
Linia 1. public static void main otwórz nawias okrągły String otwórz nawias kwadratowy zamknij nawias kwadratowy args zamknij nawias okrągły otwórz nawias klamrowy.
Linia 2. String otwórz nawias kwadratowy zamknij nawias kwadratowy slowa znak równości otwórz nawias klamrowy.
Linia 3. cudzysłów ziemniak cudzysłów przecinek.
Linia 4. cudzysłów kartofel cudzysłów przecinek.
Linia 5. cudzysłów pyra cudzysłów przecinek.
Linia 6. cudzysłów pomidor cudzysłów przecinek.
Linia 7. cudzysłów melon cudzysłów przecinek.
Linia 8. cudzysłów marchewka cudzysłów przecinek.
Linia 9. cudzysłów papryka cudzysłów przecinek.
Linia 10. cudzysłów arbuz cudzysłów przecinek.
Linia 11. cudzysłów ananas cudzysłów przecinek.
Linia 12. cudzysłów cebula cudzysłów przecinek.
Linia 13. cudzysłów czosnek cudzysłów.
Linia 14. zamknij nawias klamrowy średnik.
Linia 16. sortowaniePozycyjneSlow otwórz nawias okrągły slowa zamknij nawias okrągły średnik.
Linia 17. for otwórz nawias okrągły int i znak równości 0 średnik i otwórz nawias ostrokątny slowa kropka length średnik i plus plus zamknij nawias okrągły.
Linia 18. System kropka out kropka println otwórz nawias okrągły slowa otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły średnik.
Linia 19. zamknij nawias klamrowy.
Linia 1. ananas.
Linia 2. arbuz.
Linia 3. cebula.
Linia 4. czosnek.
Linia 5. kartofel.
Linia 6. marchewka.
Linia 7. melon.
Linia 8. papryka.
Linia 9. pomidor.
Linia 10. pyra.
Linia 11. ziemniak.