1 MATEMATYKA DYSKRETNA - wykÃlad 5
dr in˙z Krzysztof Bry´s
Algorytmy generuj¸ace podstawowe obiekty kombinatoryczne
Cz¸esto, w szczeg´olno´sci przy projektowaniu algorytm´ow peÃlnego przegl¸adu, potrzebna jest umiej¸etno´s´c wygenerowania wszystkich obiekt´ow kombinatorycznych danego rodzaju. Przed- stawimy teraz kilka algorytm´ow, kt´ore wypisuj¸a wszystkie permutacje, kombinacje i podziaÃly zbioru. Nale˙zy zaznaczy´c, ˙ze metod generowania wszystkich takich obiekt´ow jest wiele i ka˙zdy z czytelnik´ow jest z pewno´sci¸a w stanie zapropojektowa´c wÃlasn¸a metod¸e. Zaproponowane tu- taj metody s¸a efektywne a r´ownocze´snie charakteryzuj¸a si¸e prostot¸a budowy. Ich poprawno´s´c wydaje si¸e by´c oczywista.
Algorytm generuj¸acy list¸e wszystkich permutacji zbioru [n]
Przedstawiony poni˙zej algorytm jest algorytmem indukcyjnym, to znaczy w k-tym kroku zakÃladamy, ˙ze krok k − 1-szy algorytmu wygenerowaÃl poprawn¸a list¸e wszystkich pemrutacji zbioru [k − 1]. Zaczynamy oczywi´scie od wygenerowania listy wszystkich permutacji zbioru [1], kt´ora skÃlada si¸e z jedynej permutacji tego zbioru.
Krok 1.
L1 := (1)
Dla ka˙zdego k = 2, . . . , n wykonaj krok k:
Krok k. ZaÃl´o˙zmy, ˙ze mamy wygenerowan¸a list¸e wszystkich permutacji zbioru [k − 1]:
Lk−1= (p1, p2, . . . , p(k−1)!)
Niech pi,j b¸edzie permutacj¸a zbioru [k] powstaÃl¸a z permutacji pi zbioru [k − 1] przez dodanie k na j-tej pozycji. Wtedy
Lk := (p1,1, p1,2, . . . , p1,k, p2,1, p2,2, . . . , p2,k, . . . , p(k−1)!,1, p(k−1)!,2, . . . , p(k−1)!,k)
Poprawno´s´c algorytmu: Fakt, ˙ze dla ka˙zdego k = 2, . . . , n ka˙zda permutacja zbioru [k]
pojawia si¸e na li´scie Lk dokÃladnie raz wynika z dw´och dosy´c oczywistych fakt´ow:
1) Po dodaniu liczby k na pewnej pozycji w dowolnej permutacji zbioru [k−1] otrzymujmey permutacj¸e zbioru [k] (bo [k] = [k − 1] ∪ {k})
2) Po usuni¸eciu liczby k z dowolnej permutacji zbioru [k] otrzymujemy permutacj¸e zbioru [k − 1] (jest to wÃla´snie ta permutacja zbioru [k − 1], z kt´orej powstaÃla).
Zatem kazda permutacja zbioru [k] powstaje z dokÃladnie jednej permutacji zbioru [k − 1]
przez dodanie liczby k na pewnej pozycji.
PrzykÃlad Stworzymy list¸e L3 wszystkich permutacji zbioru [4]. Zach¸ecamy, w ramach pracy samodzielnej, do rozszerzenia jej do listy L4 lub nawet L5.
Najpierw tworzymy list¸e L1:
L1 = ((1))
333
2 Potem tworzymy L2 dodaj¸ac w jedynej permutacji z listy L1 liczb¸e 2 wpierw na pierwszej a potem na drugiej pozycji:
L2 = ((2, 1), (1, 2))
Nast¸epnie generujemy L3 bior¸ac wpierw pierwsz¸a permutacj¸e (2, 1) z listy L2 i dodaj¸ac liczb¸e 3 kolejno na pocz¸atku, w ´srodku i na ko´ncu a potem to samo robimy z drug¸a permutacj¸a (1, 2) z listy L2:
L3 = ((3, 2, 1), (2, 3, 1), (2, 1, 3), (3, 1, 2), (1, 3, 2), (1, 2, 3))
Algorytm generuj¸acy wszystkie k-elementowe podzbiory (kombinacje) zbioru [n]
Podamy tym razem algorytm rekurencyjny (to znaczy taki kt´ory odwoÃluje si¸e sam do siebie ale dla mniejszych warto´sci argument´ow). Algorytm ten mo˙ze zosta´c napisany jako algorytm programowania dynamicznego, to znaczy obliczenia mog¸a zosta´c wykonane w p¸etli pocz¸awszy od najmniejszych warto´s´ci parametr´ow a ko´ncz¸ac na docelowych.
Niech
G(n, k) b¸edzie list¸a wszystkich k-elementowych podzbior´ow (kombinacji) zbioru [n] oraz G(n − 1, k − 1) ∪ {n} b¸edzie list¸a powstaÃl¸a z G(n − 1, k − 1) przez dodanie liczby n do ka˙zdego zbioru na li´scie G(n − 1, k − 1).
Wtedy algorytm generuje list¸e G(n, k) nast¸epuj¸acy spos´ob:
G(i, 1) = ({1}, {2}, . . . , {i}) dla ka˙zdego i = 1, . . . , n
czyli dla k = 1 otrzymujemy list¸e 1-elementowych podzbior´ow zbioru [i], ka˙zdy element tego zbioru tworzy oddzielny 1-elementowy podzbi´or na tej li´scie.
G(i, i) = ([i]) dla ka˙zdego i = 1, . . . , n
czyli dla n = k otrzymujemy list¸e na kt´orej znajduje si¸e caÃly zbi´or (bo jest jedynym i- elementowym podzbiorem zbioru [i])
G(n, k) = (G(n − 1, k), G(n − 1, k − 1) ∪ {n}) je´sli 1 < k < n
czyli w tym ostatnim przypadku lista G(n, k) powstaje z poÃl¸aczenia (konkatenacji) list G(n − 1, k) i G(n − 1, k − 1) ∪ {n}.
Poprawno´s´c algorytmu Fakt, ˙ze ka˙zdy podzbi´or k-elementowy zbioru [n] wyst¸epuje dokÃladnie raz na li´scie G(n, k) wynika z tego, ˙ze ka˙zdy podzbi´or k-elementowy zbioru [n]
zawiera liczb¸e n i jest wtedy na li´scie G(n − 1, k − 1) ∪ {n} (bo powstaje z pewnego k − 1- elementowego podzbioru zbioru [n−1] praze dodanie liczby n) albo jej nie zawiera i jest wtedy na li´scie G(n − 1, k) (bo jest r´ownie˙z k-elementowym podzbiorem zbioru [n − 1])
PrzykÃlad Wygenerujmy list¸e G(4, 2) wszystkich 2-elementowych podzbior´ow (kombinacji) zbioru [4]. Jak wiemy, takich podzbior´ow (par nieuporz¸adkowanych) jest C42 =³42´= 6.
Poniewa˙z 2 < 4, to
G(4, 2) = G(3, 2), G(3, 1) ∪ {4}.
3 Teraz tworzymy potrzebne listy. Wpierw G(3, 2):
G(3, 2) = G(2, 2), G(2, 1) ∪ {3}
przy czym G(2, 2) i G(2, 1) s¸a listami ”trywialnymi”. Mianowicie:
G(2, 2) = ({1, 2}) oraz
G(2, 1) = ({1}, {2}) a st¸ad
G(2, 1) ∪ {3} = ({1, 3}, {2, 3}).
Wracaj¸ac do pocz¸atku:
G(3, 2) = ({1, 2}, {1, 3}, {2, 3})
Nast¸epnie tworzymy list¸e G(3, 1) ∪ {4}. Lista G(3, 1) skÃlada si¸e z wszystkich 1-elementowych podzbior´ow zbioru [3] czyli
G(3, 1) = ({1}, {2}, {3}) a zatem:
G(3, 1) ∪ {4} = ({1, 4}, {2, 4}, {3, 4}).
Ostatecznie otrzymujemy:
G(4, 2) = ({1, 2}, {1, 3}, {2, 3}, {1, 4}, {2, 4}, {3, 4})
Taka lista jest przykÃladowo list¸a wszystkich spotka´n jakie musz¸a ze sob¸a rozegra´c cztery zespoÃly piÃlkarskie (np. w jednej grupie na mistrzostwach ´swiata) graj¸ace systemem ka˙zdy z ka˙zdym (wersja dla kobiet: prosz¸e wyobrazi´c sobie, ˙ze chodzi o kobiece zespoÃly piÃlkarskie).
Zauwa˙zmy ze wszystkie k-elementowe wariacje zbioru [n] mo˙zna otrzyma´c przez wygen- erowanie wpierw wszystkich k-elementowych kombinacji zbioru [n] a potem wygenerowanie dla ka˙zdej z otrzymanych kombinacji wszystkich permutacji. Tak wi¸ec nie zachodzi potrzeba projektowania oddzielnego algorytmu generuj¸acego wszystkie k-elementowe wariacje zbioru [n].
Algorytm generuj¸acy wszystkie podziaÃly zbioru [n]
Padamy teraz algorytm kunstruuj¸acy list¸e Lnwszystkich podziaÃl´ow zbioru [n]. Pocz¸atkowa lista L1 skÃlada si¸e oczywi´scie z jedynego podziaÃlu zbioru [1]. W ka˙zdym kolejnym kroku, dla k = 2, . . . , n, jest konstruowana lista Lk wszystkich podziaÃl´ow zbioru [k] na podstawie listy Lk−1 wszytskich podziaÃl´ow zbioru [k − 1].
Krok 1.
L1 := (1)
Dla ka˙zdego k = 2, . . . , n wykonaj krok k:
Krok k. ZaÃl´o˙zmy, ˙ze mamy wygenerowan¸a list¸e Lk−1 wszystkich podziaÃl´ow zbioru [k − 1].
List¸e Lk tworzymy w nast¸epuj¸acy spos´ob:
Powered by TCPDF (www.tcpdf.org) Powered by TCPDF (www.tcpdf.org)