Permutacje
-- Sebastian Pawlak, 1999.
Permutacja jest to wzajemne jednoznaczne przekształcenie pewnego zbioru
na siebie.
Jeśli dany zbiór ma "n" elementów, to liczba permutacji (różnych
szeregów zbudowanych z elementów danego zbioru) wynosi n!.
Przedstawiony algorytm Dijkstry, dla zadanego zbioru liczb generuje "następnik
permutacyjny". Np. dla zbioru trzech liczb 1, 2, 3 na wyjściu pojawi się
1, 3, 2. Gdy otrzymany zbiór 1, 3, 2 podamy na wejście to otrzymamy
2, 1, 3 i następnie: 2, 3, 1; 3, 1, 2 i ostatni 3, 2, 1.
Algorytm postępowania przy wyznaczaniu permutacji danego szeregu liczb:
Załóżmy, że mamy dany szereg: 1 4 6 2 9 5 8 7 3.
Oto w jaki sposób wyznacza się jego następnik:
1. Poruszamy się od prawej strony do lewej, tak długo aż napotkamy element mniejszy od swojego prawego sąsiada. W tym przypadku elementem tym będzie 5 o ideksie i=5 (liczonym od zera); 2. Poruszając się ponownie od prawej strony szukamy pierwszego elementu większego niż ten znaleziony na pozycji "i", czyli 5. Elementem tym będzie 7 o indeksie j=7. 3. Zamieniamy miejscami elementy o indeksach "i" oraz "j". Otrzymamy szereg: 1 4 6 2 9 7 8 5 3. 4. Odbijamy lustrzanie szereg elementów od indeksu i+1 do końca szeregu. Otrzymamy szereg: 1 4 6 2 9 7 3 5 8. Wyznaczony szereg jest szukanym przez nas rozwiązaniem.
Oto jak zaimplementowałem powyższy algorytm:
Kod źródłowy pliku "permutacje.c":
/* Permutacje, algorytm Dijkstry * Sebastian Pawlak, 1999 */ #include <stdio.h> void permutacja(int t[], int max); void wypisz(int t[], int max); int main(void) { #define MAX 3 int t[MAX] = { 1, 2, 3 }; int i, j; wypisz(t, MAX); for (i = 0; i < 1 * 2 * 3 - 1; i++) { /* i < n! - 1 */ permutacja(t, MAX); wypisz(t, MAX); } return 0; } /* permutacja: generuje nastepnik permutacyjny dla zadanego szeregu liczb */ void permutacja(int t[], int max) { int i, j, k; if (max < 2) return; /* wyznaczanie pierwszego od prawej elementu * mniejszego niz jego sasiad z prawej strony */ i = max - 1; while ((i > 0) && (t[i - 1] >= t[i])) i--; /* wyznaczanie elementu wiekszego od znalezionego */ if (i > 0) { j = max; while ((j > 0) &&(t[j - 1] <= t[i - 1])) j--; } /* zamiana miejscami dwoch znalezionych wyzej elementow */ if ((i > 0) && (j > 0)) { k = t[i - 1]; t[i - 1] = t[j - 1]; t[j - 1] = k; } /* odbicie lustrzane szeregu elementow od indeksu i+1 do konca tablicy */ for (i++, j = max; i < j; i++, j--) { k = t[i - 1]; t[i - 1] = t[j - 1]; t[j - 1] = k; } } /* wypisz: wypisuje zawartosc tablicy */ void wypisz(int t[], int max) { int i; for (i = 0; i < max; i++) printf("%d%c", t[i], (i < max - 1) ? ' ' : '\n'); }