R1SV8OXUEADJ1
Obraz wygenerowany przez sztuczną inteligencję. Przedstawia szachownicę z ustawionymi figurami. Tło jest czarne, a figury w odcieniach koloru niebieskiego.

I_R_W14_M42_Java Ciekawe algorytmy rekurencyjne

Obraz wygenerowany przez sztuczną inteligencję Canva.ai
Źródło: domena publiczna.

Implementacja generatora permutacji w Java

Program rozpoczyna działanie w metodzie main(). Najpierw tworzy tablicę zawierającą liczby od 1 do 6.

Linia 1. public class Permutacje otwórz nawias klamrowy. Linia 2. 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 3. int otwórz nawias kwadratowy zamknij nawias kwadratowy dane znak równości otwórz nawias klamrowy 1 przecinek 2 przecinek 3 przecinek 4 przecinek 5 przecinek 6 zamknij nawias klamrowy średnik. Linia 4. zamknij nawias klamrowy. Linia 5. zamknij nawias klamrowy.

Następnie przekazuje tę tablicę do metody permutacje() i informuje ją, że układanie ma rozpocząć się od pierwszego miejsca, czyli od indeksu 0.

Linia 1. public class Permutacje otwórz nawias klamrowy. Linia 2. 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 3. int otwórz nawias kwadratowy zamknij nawias kwadratowy dane znak równości otwórz nawias klamrowy 1 przecinek 2 przecinek 3 przecinek 4 przecinek 5 przecinek 6 zamknij nawias klamrowy średnik. Linia 5. permutacje otwórz nawias okrągły dane przecinek 0 zamknij nawias okrągły średnik. Linia 6. zamknij nawias klamrowy. Linia 7. zamknij nawias klamrowy.

Metoda permutacje

Funkcja permutacje() tworzy wszystkie możliwe ustawienia liczb znajdujących się w tablicy.

Funkcja otrzymuje dwa argumenty:

Linia 1. public static void permutacje otwórz nawias okrągły int otwórz nawias kwadratowy zamknij nawias kwadratowy lista przecinek int indeks zamknij nawias okrągły otwórz nawias klamrowy. Linia 2. zamknij nawias klamrowy.
  • lista – tablicę zawierającą liczby,

  • indeks – numer miejsca w tablicy, które jest obecnie ustalane.

Na początku funkcja jest wywoływana z wartością indeks równą 0. Oznacza to, że program zaczyna od pierwszego miejsca w tablicy.

Funkcja najpierw sprawdza, czy ustalono już wszystkie miejsca w tablicy. Jeżeli indeks jest równy długości tablicy, oznacza to, że powstało kompletne ustawienie liczb.

Program wypisuje wtedy zawartość tablicy:

Linia 1. public static void permutacje otwórz nawias okrągły int otwórz nawias kwadratowy zamknij nawias kwadratowy lista przecinek int indeks zamknij nawias okrągły otwórz nawias klamrowy. Linia 2. if otwórz nawias okrągły indeks znak równości znak równości lista kropka length zamknij nawias okrągły otwórz nawias klamrowy. Linia 3. for otwórz nawias okrągły int liczba dwukropek lista zamknij nawias okrągły otwórz nawias klamrowy. Linia 4. System kropka out kropka print otwórz nawias okrągły liczba plus cudzysłów cudzysłów zamknij nawias okrągły średnik. Linia 5. zamknij nawias klamrowy. Linia 7. zamknij nawias klamrowy. Linia 9. zamknij nawias klamrowy.

Każda liczba zostaje wyświetlona w tym samym wierszu. Następnie instrukcja:

Linia 1. System kropka out kropka println otwórz nawias okrągły zamknij nawias okrągły średnik.

przenosi kursor do nowego wiersza, a polecenie:

Linia 1. return średnik.

kończy bieżące wykonanie funkcji.

Wybieranie elementu na dane miejsce

Jeżeli permutacja nie jest jeszcze gotowa, uruchamiana jest pętla:

Linia 1. public static void permutacje otwórz nawias okrągły int otwórz nawias kwadratowy zamknij nawias kwadratowy lista przecinek int indeks zamknij nawias okrągły otwórz nawias klamrowy. Linia 2. if otwórz nawias okrągły indeks znak równości znak równości lista kropka length zamknij nawias okrągły otwórz nawias klamrowy. Linia 3. for otwórz nawias okrągły int liczba dwukropek lista zamknij nawias okrągły otwórz nawias klamrowy. Linia 4. System kropka out kropka print otwórz nawias okrągły liczba plus cudzysłów cudzysłów zamknij nawias okrągły średnik. Linia 5. zamknij nawias klamrowy. Linia 7. System kropka out kropka println otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 8. return średnik. Linia 9. zamknij nawias klamrowy. Linia 11. for otwórz nawias okrągły int i znak równości indeks średnik i otwórz nawias ostrokątny lista kropka length średnik i plus plus zamknij nawias okrągły otwórz nawias klamrowy. Linia 12. prawy ukośnik prawy ukośnik Zamiana elementów. Linia 13. int temp znak równości lista otwórz nawias kwadratowy indeks zamknij nawias kwadratowy średnik. Linia 14. lista otwórz nawias kwadratowy indeks zamknij nawias kwadratowy znak równości lista otwórz nawias kwadratowy i zamknij nawias kwadratowy średnik. Linia 15. lista otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości temp średnik. Linia 16. zamknij nawias klamrowy. Linia 17. zamknij nawias klamrowy.

Pętla sprawdza kolejno wszystkie liczby, które można umieścić na aktualnej pozycji.

Na przykład, gdy indeks ma wartość 0, program wybiera liczbę na pierwsze miejsce. Następnie dla każdej możliwości ustala liczby na kolejnych pozycjach.

Następuje zamiana elementów

Linia 2. int temp znak równości lista otwórz nawias kwadratowy indeks zamknij nawias kwadratowy średnik. Linia 3. lista otwórz nawias kwadratowy indeks zamknij nawias kwadratowy znak równości lista otwórz nawias kwadratowy i zamknij nawias kwadratowy średnik. Linia 4. lista otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości temp średnik.

Aby umieścić wybraną liczbę na odpowiednim miejscu, program zamienia ze sobą dwa elementy tablicy.

Zmienna temp przechowuje chwilowo jedną wartość, aby nie została utracona podczas zamiany.

Przykładowo z tablicy: 1 2 3 po zamianie pierwszego i drugiego elementu może powstać 2 1 3. Następnie wywołana jest funkcja dla kolejnego miejsca

Linia 1. permutacje otwórz nawias okrągły lista przecinek indeks plus 1 zamknij nawias okrągły średnik.

Po wykonaniu zamiany funkcja wywołuje samą siebie. Tym razem wartość indeks jest większa o jeden, więc program zaczyna ustalać kolejne miejsce w tablicy.

Takie wywoływanie funkcji przez nią samą nazywamy rekurencją.

Program działa więc etapami: najpierw wybiera liczbę na pierwsze miejsce, potem na drugie, następnie na trzecie i kontynuuje, aż powstanie pełna permutacja.

Po sprawdzeniu jednej możliwości program przywraca wcześniejszy układ liczb. Dzięki temu może wybrać inną liczbę na tym samym miejscu i utworzyć kolejne permutacje.

Funkcja powtarza więc następujący schemat:

wybiera element → zamienia liczby → przechodzi do kolejnej pozycji → wypisuje gotową permutację → cofa zamianę → sprawdza następną możliwość.

W ten sposób tworzy wszystkie możliwe kolejności elementów tablicy.

Linia 1. public class Permutacje otwórz nawias klamrowy. Linia 3. public static void permutacje otwórz nawias okrągły int otwórz nawias kwadratowy zamknij nawias kwadratowy lista przecinek int indeks zamknij nawias okrągły otwórz nawias klamrowy. Linia 4. if otwórz nawias okrągły indeks znak równości znak równości lista kropka length zamknij nawias okrągły otwórz nawias klamrowy. Linia 5. for otwórz nawias okrągły int liczba dwukropek lista zamknij nawias okrągły otwórz nawias klamrowy. Linia 6. System kropka out kropka print otwórz nawias okrągły liczba plus cudzysłów cudzysłów zamknij nawias okrągły średnik. Linia 7. zamknij nawias klamrowy. Linia 9. System kropka out kropka println otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 10. return średnik. Linia 11. zamknij nawias klamrowy. Linia 13. for otwórz nawias okrągły int i znak równości indeks średnik i otwórz nawias ostrokątny lista kropka length średnik i plus plus zamknij nawias okrągły otwórz nawias klamrowy. Linia 14. prawy ukośnik prawy ukośnik Zamiana elementów. Linia 15. int temp znak równości lista otwórz nawias kwadratowy indeks zamknij nawias kwadratowy średnik. Linia 16. lista otwórz nawias kwadratowy indeks zamknij nawias kwadratowy znak równości lista otwórz nawias kwadratowy i zamknij nawias kwadratowy średnik. Linia 17. lista otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości temp średnik. Linia 19. permutacje otwórz nawias okrągły lista przecinek indeks plus 1 zamknij nawias okrągły średnik. Linia 21. prawy ukośnik prawy ukośnik Cofnięcie zamiany. Linia 22. temp znak równości lista otwórz nawias kwadratowy indeks zamknij nawias kwadratowy średnik. Linia 23. lista otwórz nawias kwadratowy indeks zamknij nawias kwadratowy znak równości lista otwórz nawias kwadratowy i zamknij nawias kwadratowy średnik. Linia 24. lista otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości temp średnik. Linia 25. zamknij nawias klamrowy. Linia 26. zamknij nawias klamrowy. Linia 28. 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 29. int otwórz nawias kwadratowy zamknij nawias kwadratowy dane znak równości otwórz nawias klamrowy 1 przecinek 2 przecinek 3 przecinek 4 przecinek 5 przecinek 6 zamknij nawias klamrowy średnik. Linia 31. permutacje otwórz nawias okrągły dane przecinek 0 zamknij nawias okrągły średnik. Linia 32. zamknij nawias klamrowy. Linia 33. zamknij nawias klamrowy.

Jak działa algorytm:

  • Na pierwszej pozycji próbujemy ustawiać kolejno wszystkie 6 elementów.

  • Dla każdej takiej decyzji rekurencyjnie ustawiamy element na kolejnej pozycji.

  • Proces trwa aż do momentu, gdy wszystkie pozycje są obsadzone.

  • Każda pełna konfiguracja jest jedną permutacją.

Podsumowanie:

  • Dla 6 elementów liczba permutacji jest bardzo duża, dlatego w praktyce często:

    • nie wypisuje się wszystkich permutacji,

    • lub przerywa algorytm po znalezieniu konkretnego rozwiązania.

  • Problem ten jest klasycznym przykładem rekurencji i cofania (backtrackingu) oraz doskonałym ćwiczeniem algorytmicznego myślenia.