21
Matematyka Dyskretna Andrzej Szepietowski 25 marca 2004 roku

rekurencja

Embed Size (px)

DESCRIPTION

Rekurencja

Citation preview

  • Matematyka Dyskretna

    Andrzej Szepietowski

    25 marca 2004 roku

  • Rozdzia 1

    Rekurencja

    1.1 Wieze HanoiRekurencja jest to zdolnosc podprogramu (procedury lub funkcji) do wywoywania sa-mego siebie. Zacznijmy od przykadu wiez Hanoi. Przypuscmy, ze mamy trzy wieze lubtrzy paliki: A, B i C. Na pierwszym paliku, A, znajduja sie trzy krazki rznej wielkosci,nanizane w porzadku od najwiekszego na dole do najmniejszego na grze. Paliki B i Csa na poczatku puste. Nalezy przeniesc wszystkie krazki z palika A na B, posugujac siew razie potrzeby palikiem C, wedug nastepujacych regu:

    mozna przenosic po jednym krazku z jednego palika na inny, nie mozna umieszczac wiekszego krazka na mniejszym.

    Rozwiazaniem tej amigwki dla trzech krazkw jest nastepujacy ciag siedmiu przeo-zen:

    A B, A C, B C, A B, C A, C B, A B,

    gdzie zapis X Y oznacza przeniesienie szczytowego krazka z palika X na palik Y .Chodzi nam teraz o algorytm, ktry dla dowolnej liczby N krazkw wypisze ciag

    operacji potrzebnych do przeozeniaN krazkw z palika A na palik B.Algorytm przekadania krazkw

    jezeli N = 1, to przekadamy ten jeden krazek A B, jezeli N > 1, to:

    przekadamyN 1 krazkw z A na pomocniczy palik C (posugujac sie wrazie potrzeby palikiem B),

    przekadamyN -ty krazek z A na B, przekadamyN 1 krazkw z C na A (za pomoca palika B).3

  • 4 Rozdzia 1. Rekurencja

    Nietrudno zauwazyc, ze jezeli proces przekadania N 1 krazkw jest prawidowy, tocay proces tez jest prawidowy, poniewaz obecnosc najwiekszego krazka na dole palikanie przeszkadza w przekadaniuN 1 mniejszych krazkw.

    Powyzszy algorytm opiszmy teraz za pomoca rekurencyjnej procedury przenies, kt-ra odwouje sie sama do siebie i wypisuje ciag instrukcji przeniesieniaN krazkw z palikaX na palik Y .

    procedura przenies(N krazkw z X na Y , za pomoca Z): jezeli N = 1, to wypisz X Y , jezeli N > 1, to

    przenies(N 1 krazkw z X na Z, za pomoca Y ), wypisz X Y , przenies(N 1 krazkw z Z na Y , za pomoca X).

    1.2 Drzewo rekursji

    Rysunek 1.1: Drzewo rekursji dla przekadania trzech krazkw w wiezach Hanoi

    3AB

    2AC

    1AB

    1BC

    2CB

    1CA

    1AB

    Dziaanie procedury rekurencyjnej dobrze ilustruje tak zwane drzewo rekursji. Rysu-nek 1.1 8.1 przedstawia drzewo rekursji dla algorytmu przekadania trzech krazkw nawiezach Hanoi. Wierzchoki odpowiadaja wywoaniom procedury. Skrt

    N

    X Yoznacza wywoanie procedury przenies(N krazkw z X na Y , za pomoca trzeciego pa-lika ). W korzeniu wywoujemy procedure do przeozenia 3 krazkw z palikaA na B. Towywoanie samo dwa razy wywouje przenies: raz dla przeniesiena 2 krazkw zA na C idrugi raz dla przeniesienia 2 krazkw z C na B, Tym wywoaniom odpowiadaja synowie

  • 1.3. Algorytm Euklidesa, wersja rekurencyjna 5

    korzenia drzewa i tak dalej. Wykonanie procedury rekurencyjnej nasladuje przeszukaniedrzewa rekursji metoda w gab. Uzywamy do tego celu stosu, na ktry wkadane sa wy-woania procedury. W kazdym momencie na stosie znajduja sie informacje o otwartych iciagle nie zamknietych wywoaniach. Jeezeli dane wywoanie sie wykona i zamknie, toodpowiedni element jest zdejmowany ze stosu. Stos taki nazwywany jest stosem rekursji.Ponizej wypisano zawartosc stosu po kolejnych wywoaniach i zamknieciach proceduryprzenies.

    [Przenies(3,A B)] [Przenies(3,A B)] [Przenies(2,A C)] [Przenies(3,A B)] [Przenies(2,A C)] [Przenies(1,A B)] [Przenies(3,A B)] [Przenies(2,A C)] [Przenies(3,A B)] [Przenies(2,A C)] [Przenies(1,B C)] [Przenies(3,A B)] [Przenies(2,A C)] [Przenies(3,A B)] [Przenies(3,A B)] [Przenies(2,C B)] [Przenies(3,A B)] [Przenies(2,C B)] [Przenies(1,C A)] [Przenies(3,A B)] [Przenies(2,C B)] [Przenies(3,A B)] [Przenies(2,C B)] [Przenies(1,A B)] [Przenies(3,A B)] [Przenies(2,C B)] [Przenies(3,A B)]

    1.3 Algorytm Euklidesa, wersja rekurencyjnaInnym przykadem algorytmu rekurencyjnego moze byc rekurencyjna wersja algorytmuEuklidesa, ktry oblicza najwiekszy wsplny dzielnik dwch dodatnich liczb naturalnycha i b: Oto uproszczona wersja definicji funkcji NWD

    if ab=0 then NWD(a,b):=a+belse if ab then NWD(a,b):=NWD(a mod b,b)

    else NWD(a,b):=NWD(a,b mod a)

    Jak widac definicja funkcji odwouje sie sama do siebie. Rysunek 1.2 przedstawiadrzewo rekursji dla obliczenia najwiekszego wsplnego dzielnika liczb 5 i 3. W tym przy-padku drzewo jest zredukowane do jednej sciezki. Ponizej przedstawiono zawartosci stosurekursji po kazdym wywoaniu i zamknieciu funkcji.

    [NWD(5, 3)] [NWD(5, 3)] [NWD(2, 3)] [NWD(5, 3)] [NWD(2, 3)] [NWD(2, 1)] [NWD(5, 3)] [NWD(2, 3)] [NWD(2, 1)] [NWD(0, 1)] [NWD(5, 3)] [NWD(2, 3)] [NWD(2, 1)] [NWD(5, 3)] [NWD(2, 3)] [NWD(5, 3)]

  • 6 Rozdzia 1. Rekurencja

    Rysunek 1.2: Drzewo reursji dla funkcji Euklidesa

    NWD(5, 3)

    NWD(2, 3)

    NWD(2, 1)

    NWD(0, 1)

    1.4 Rekurencyjne algorytmy przeszukiwania drzewIstnieje prosty i ciekawy sposb uzyskiwania postaci postfixowej wyrazenia arytmetycz-nego z drzewa tego wyrazenia. Aby uzyskac postac postfixowa wyrazenia, nalezy prze-szukac drzewo tego wyrazenia w pewien okreslony sposb, zwany przeszukiwaniem po-storder.

    Przeszukiwanie postorder. Aby przeszukac (pod)drzewo majace swj korzen w wierz-choku x:

    przeszukujemy jego lewe poddrzewo (z korzeniem w x0), przeszukujemy jego prawe poddrzewo (z korzeniem w x1), odwiedzamy wierzchoek x (korzen drzewa).

    Algorytm ten mozemy krtko przedstawic w schemacie:lewe poddrzewo prawe poddrzewo korzen.

    Przykad 1.1 Jezeli przeszukamy drzewo wyrazenia arytmetycznego z rysunku 1.3 i wy-piszemy po kolei etykiety odwiedzanych wierzchokw, to otrzymamy ciag:

    2a3d/+ ktry jest postacia postfixowa wyrazenia 2(a+ 3/d).

    Istnieja jeszcze dwie inne pokrewne metody przeszukiwania drzew binarnych: inorderi preorder:

  • 1.4. Rekurencyjne algorytmy przeszukiwania drzew 7

    Rysunek 1.3: Drzewo wyrazenia 2(a+ 3/d)

    2 +

    a /

    3 d

    Przeszukiwanie inorder. Aby przeszukac (pod)drzewo majace swj korzen w wierzcho-ku x:

    przeszukujemy jego lewe poddrzewo (z korzeniem w x0), odwiedzamy wierzchoek x (korzen drzewa), przeszukujemy jego prawe poddrzewo (z korzeniem w x1).

    Przeszukiwanie preorder. Aby przeszukac (pod)drzewo majace swj korzen w wierz-choku x:

    odwiedzamy wierzchoek x (korzen drzewa), przeszukujemy jego lewe poddrzewo (z korzeniem w x0), przeszukujemy jego prawe poddrzewo (z korzeniem w x1).

    Przykad 1.2 Jezeli przeszukamy drzewo z rysunku ?? metoda inorder, to etykiety utwo-rza ciag:

    2 a+ 3/dczyli wyrazenie w postaci infixowej, ale bez nawiasw. Przeszukanie tego samego drzewametoda preorder da ciag etykiet:

    2 + a/3dJest to tak zwana postac prefixowa wyrazenia. Znak operacji wystepuje w niej przed ar-gumentami. Podobne jak w postaci postfixowej, postac prefixowa da sie jednoznacznierozkadac i nie wymaga nawiasw.

  • 8 Rozdzia 1. Rekurencja

    1.5 Drzewa poszukiwan binarnychDrzewa sa podstawowa struktura przy budowie duzych baz danych. Jeda z najprostszychtakich struktur sa drzewa poszukiwan binarnych. Aby utworzyc drzewo poszukiwan bi-narnych, zaczynamy od pustego drzewa, a nastepnie wstawiamy po kolei elementy, ktremaja byc przechowywane w drzewie. Wstawiane elementy powinny byc z jakiegos upo-rzadkowanego zbioru. Ponizej przedstawiamy rekurencyjny algorytmu wstawiania ele-mentw do drzewa. W (x) oznacza wartosc przechowywana w wierzchoku x. Pamietaj-my, ze Tx oznacza poddrzewo o korzeniu w wierzchoku x.

    Algorytm wstawiania elementu do drzewa poszukiwan binarnych.Aby wstawic element e do drzewa Tx:

    jezeli drzewo Tx jest puste, toW (x) := e (wstaw e do korzenia x),

    w przeciwnym razieporwnaj e z zawartoscia korzenia W (x):jezeli e < W (x), to

    wstaw e do poddrzewa Tx0,jezeli e > W (x), to

    wstaw e do poddrzewa Tx1.

    Przykad 1.3 Przypuscmy, ze mamy ciag liczb naturalnych:

    128, 76, 106, 402, 100, 46, 354, 1018, 112, 28, 396, 35.

    Utworzymy dla tego ciagu drzewo poszukiwan binarnych.

    Rysunek 1.4: Drzewo poszukiwan po wstawieniu elementw: 128, 76, 106, 402

    128

    76

    106

    402

    Po wstawieniu pierwszych czterech elementw ciagu otrzymamy drzewo, ktre jestprzedstawione na rysunku 1.4, a po wstawieniu caego ciagu otrzymamy drzewo, ktrejest przedstawione na rysunku 1.5. Jezeli teraz przeszukamy to drzewo metoda inorder, tootrzymamy ten sam ciag, ale uporzadkowany:

    28, 35, 46, 76, 100, 106, 112, 128, 354, 396, 402, 1018.

  • 1.5. Drzewa poszukiwan binarnych 9

    Rysunek 1.5: Drzewo dla ciagu: 128,76,106,402,100,46,354,1018,112,28, 396,35

    128

    76

    46

    28

    35

    106

    100 112

    402

    354

    396

    1018

    Jezeli mamy juz drzewo poszukiwan binarnych T , to dla kazdego wierzchoka x Tzachodzi

    dla kazdego y Tx0, W (y) < W (x), dla kazdego y Tx1, W (y) > W (x).

    Czyli wszystkie wierzchoki w lewym poddrzewie Tx0 zawieraja wartosci mniejszeod wartosci w x, a wszystkie wierzchoki w prawym poddrzewie Tx1 zawieraja wartosciwieksze od wartosci w x.

    Aby stwierdzic, czy jakis element e znajduje sie na tym drzewie. Postepujemy podob-nie jak przy wstawianiu elementw. Zaczynamy od korzenia drzewa x = i szukamyelementu e za pomoca ponizszego rekurencyjnego algorytmu.

    Algorytm szukania elementu e na drzewie Tx.Aby stwierdzic, czy element e znajduje sie na drzewie Tx:

    jezeli Tx jest puste, tokoniec, elementu e nie ma na drzewie,

    jezeli Tx nie jest puste, toporwnujemy e z wartoscia W (x):jezeli e = W (x), to

    koniec, znalezlismy element e na drzewie,jezeli e < W (x), to

    szukamy e w lewym poddrzewie Tx0,

  • 10 Rozdzia 1. Rekurencja

    jezeli e > W (x), toszukamy e w prawym poddrzewie Tx1.

    W drzewie poszukiwan binarnych czas wyszukiwania lub wstawiania elementu jestO(h), gdzie h jest wysokoscia drzewa. W obu algorytmach tylko raz przechodzimy odkorzenia w d do liscia. Najlepiej by byo, gdyby wysokosc drzewa bya rzedu logarytmod liczby wierzchokw, ale nie w kazdym drzewie poszukiwan binarnych tak musi byc.

    1.6 Funkcje rekurencyjneCzasami wygodnie jest zdefiniowac funkcje za pomoca wzoru rekurencyjnego. Na przy-kad funkcje silnia definiuje sie zwykle za pomoca nastepujacych dwch rwnan:

    silnia(0) = 1,silnia(n) = n silnia(n 1), dla n 1.

    Podobnie mozna definiowac inne funkcje ze zbioru liczb naturalnych w zbir liczb natu-ralnych. Definicja taka zawiera przepis, jak policzyc wartosc funkcji dla wartosci poczat-kowych, oraz drugi przepis, jak wyliczyc wartosc dla argumentu n za pomoca wartoscifunkcji dla mniejszych argumentw.

    1.7 Funkcja (ciag) FibonacciegoNastepnym przykadem rekurencyjnego definiowania funkcji jest funkcja Fibonacciego,okreslona rwnaniami:

    F (0) = 0,F (1) = 1,F (n+ 2) = F (n+ 1) + F (n).

    Kolejne wartosci funkcji Fibonacciego to:0, 1, 1, 2, 3, 5, 8, 13, . . .

    Udowodnimy teraz przez indukcje, ze

    F (n) =n n

    5, (1.1)

    gdzie = 12 (1 +

    5) 1, 61803 oraz = 12 (1

    5) 0, 61803Rwnosc (1.1) zachodzi dla n = 0 i n = 1. Zazmy teraz, ze zachodzi dla wszystkich

    argumentw mniejszych od n. Zauwazmy, ze oraz sa rozwiazaniami rwnania x2 x 1 = 0, mamy wiec + 1 = 2 oraz + 1 = 2 a takze n1 + n2 = n orazn1 + n2 = n. atwo teraz mozna pokazac, ze F (n) = F (n 1) + F (n 2) =15(n n).Poniewaz || < 1, mamy 1

    5n < 1

    5< 12 , wiec wartosc F (n) jest rwna 15n po

    zaokragleniu do najblizszej liczby naturalnej i funkcja Fibonacciego rosnie wykadniczo.

  • 1.8. Algorytm sortowania przez scalanie 11

    1.8 Algorytm sortowania przez scalanieZajmijmy sie teraz pewnym prostym rekurencyjnym algorytem sortowania ciagu. Dlaprostoty zazmy, ze dugosc ciagu jest potega dwjki.Algorytm sortowania

    jezeli ciag ma dugosc jeden, to jest juz posortowany, jezeli ciag jest duzszy, to:

    dzielimy go na poowy, sortujemy te poowy, aczymy posortowane poowy w jeden posortowany ciag.

    Istota pomysu polega na tym, ze mozna szybko poaczyc dwa posortowane ciagi w jedenposortowany ciag. Algorytm aczenia wyjasnijmy na przykadzie. Przypuscmy, ze mamydwa ciagi:

    A = (1, 3, 6, 7), B = (2, 4, 8, 9),

    i ze chcemy je poaczyc w posortowany ciag C. Na poczatku ciag C jest pusty. Usta-wiamy dwa wskazniki po jednym na poczatku kazdego ciagu (wskazane elementy bedaoznaczone daszkiem):

    A = (1, 3, 6, 7), B = (2, 4, 8, 9), C = ().

    Porwnujemy wskazane elementy. Mniejszy z porwnanych elementw przepisujemy naciag C i przesuwamy wskaznik w tym ciagu, z ktrego by wziety element do ciagu C.W wyniku otrzymamy:

    A = (1, 3, 6, 7), B = (2, 4, 8, 9), C = (1).

    Powtarzamy ten proces tak dugo, az w jednym z ciagw ostatni element zostanie zabranydo ciagu C.

    A = (1, 3, 6, 7), B = (2, 4, 8, 9), C = (1, 2),

    A = (1, 3, 6, 7), B = (2, 4, 8, 9), C = (1, 2, 3),

    A = (1, 3, 6, 7), B = (2, 4, 8, 9), C = (1, 2, 3, 4),

    A = (1, 3, 6, 7), B = (2, 4, 8, 9), C = (1, 2, 3, 4, 6),

    A = (1, 3, 6, 7), B = (2, 4, 8, 9), C = (1, 2, 3, 4, 6, 7).

    W takiej sytuacje pozostae elementy tego drugiego ciagu przenosimy do ciagu C:A = (1, 3, 6, 7), B = (2, 4, 8, 9), C = (1, 2, 3, 4, 6, 7, 8, 9).

    Liczba porwnan potrzebna do scalenia ciagw nie jest wieksza od sumy dugosci tychciagw.

    Algorytm merge-sort (inaczej sortowanie przez scalanie), ktry sortuje ciag S,mozna rekurencyjnie opisac tak (rysunek 8.3):

  • 12 Rozdzia 1. Rekurencja

    merge-sort(S):

    jezeli S ma tylko jeden element, to koniec,

    jezeli S ma wiecej elementw, to: dzielimy ciag S na poowy S1 i S2, merge-sort(S1), merge-sort(S2), aczymy S1 i S2.

    Rysunek 1.6: Schemat dziaania algorytmu merge-sort dla ciagu 3, 7, 5, 2, 6, 1, 8, 4

    3752|6184

    37|52 61|84

    3|7 5|2 6|1 8|4

    3 7 5 2 6 1 8 4

    37 25 16 48

    2357 1468

    12345678

    Algorytm merge-sort jest przykadem algorytmu typu dziel i zwyciezaj, ktregooglny schemat wyglada tak:

    jezeli problem jest maego rozmiaru, to rozwiazujemy go bezposrednio,

    jezeli problem jest duzy, to: dzielimy problem na podproblemy, rozwiazujemy podproblemy, aczymy rozwiazania podproblemw w rozwiazanie caego problemu.

  • 1.9. Rozwiazywanie rwnan i nierwnosci rekurencyjnych 13

    1.9 Rozwiazywanie rwnan i nierwnosci rekurencyjnychOszacujmy teraz czas dziaania algorytmu sortowania przez scalanie. Niech T (n) oznaczaliczbe operacji porwnania potrzebna do posortowania ciagu dugosci n. Mamy nastepu-jace oszacowania:

    T (1) = 0, (1.2)T (n) 2T (n

    2) + n. (1.3)

    Druga zaleznosc wynika stad, ze aby posortowac ciag dugosci n, sortujemy dwa ciagidugosci n2 , a nastepnie potrzebujemy n porwnan, aby scalic te dwie powki. Dla pro-stoty rozwazan zakadamy tutaj, ze n jest potega dwjki, n = 2k dka jakiegos naturalnegok.

    Istnieje wiele sposobw wyliczania lub szacowania funkcji okreslonej rekurencyjnie.Przedstawimy teraz dwa najprostsze z nich: metode podstawiania i metode iteracji.

    1.10 Metoda podstawianiaW metodzie podstawiania odgadujemy rozwiazanie albo jego oszacowanie, a nstepniepokazujemy, ze jest ono poprawne. Pokazemy dziaanie tej metody szacujac zozonoscczasowa merge-sortu okreslona rekurencja (1.2)-(1.3). Zgadujemy, ze

    T (n) cn logn

    dla jakiejs staej c > 0 i udowodnimy przez indukcje, ze powyzsza nierwnosc zachodzidla kazdego potegi dwjki n 1. Zachodzi ona dla n = 1. Zakadamy teraz, ze T ( n2 ) c n2 log(n2 ) i podstawiamy do nierwnosci (1.3)

    T (n) 2c(n2) log(

    n

    2) + n

    cn logn cn+ n cn logn

    Ostatnia nierwnosc jest speniona, jezeli c 1.Metoda podstawiania zostaa zastosowana w podrozdziale o funkcji Fibonacciego do

    pokazania, ze

    F (n) =n n

    5, (1.4)

    ale tam odgadnieto dokadne rozwiazanie. Teraz pokazemy jak dojsc do rozwiaznia za-czynajac od oglniejszej postaci. Zacznijmy od rwnania

    F (n+ 2) = F (n+ 1) + F (n). (1.5)

  • 14 Rozdzia 1. Rekurencja

    Sprawdzmy, jakie funkcje postaci F (n) = cn speniaja to rwnanie. Po podstawieniu dorwnania (1.5) mamy

    cn+2 = cn+1 + cn

    Po podzieleniu stromnami przez cn, otrzymamy

    c2 = c+ 1.

    Jest to rwnanie kwadratowe z dwoma rozwiazaniami = 12 (1 +

    5)2 oraz =12 (1

    5)2, czyli dwie funkcje F1(n) = n oraz F2(n) = n speniaja rwnanie (1.5).

    Zauwazmy, ze takze kazda funkcja postaciF (n) = c1F1(n) + c2F2(n)

    gdzie c1 i c2 to stae, spenia rwnanie (1.5). Sprawdzmy teraz, dla jakich staych c1 i c2funkcja F spenia zaleznosci F (0) = 0 i F (1) = 1. Otrzymujemu ukad rwnosci

    0 = c1 + c2

    1 = c1+ c2

    Powyzszy ukad jest speniony dla

    c1 =1

    ( ) =15

    c2 = c1 = 15

    Tak wiec otrzymujemy wzr na funkcje Fibonacciego

    F (n) =n n

    5, (1.6)

    1.11 Metoda iteracyjnaMoteda iteracyjna polega na rozwijaniu rekursji. Przedstawimyja na trzech przykadachPrzykad 1.4 Jako pierwszy przykad rozwazmy zaleznosc.

    T (1) = 1

    T (n) = 3T (n

    4) + n

    Dla uproszczenia zakadamy, ze n jest potegan = 4k, dla jakiegos k naturalnego. FunkcjeT rozwijamy w nastepujacy sposb:

    T (n) = n+ 3T (n

    4)

    = n+ 3(n

    4+ 3T (

    n

    16))

  • 1.11. Metoda iteracyjna 15

    = n+ n3

    4+ 9T (

    n

    16)

    . . .

    = n+ n3

    4+ . . .+ n

    (3

    4

    )i1+ 3iT (

    n

    4i)

    Iteracje powtarzamy, az ostatni skadnik bedzie zawiera T (1), czyli gdy i = log4 n.Otrzymamy wtedy

    T (n) = n+ n3

    4+ . . .+ n

    (3

    4

    )i1+ 3iT (1)

    n

    i=0

    (3

    4

    )i+ 3log4 n = 4n+ o(n) = O(n)

    Skorzystalismy tu z rwnosci 3log4 n = nlog4 3 oraz z faktu, ze log4 3 < 1 i nlog4 3 = o(n).Przykad 1.5 Jako drugi przykad rozwazmy rekursje

    T (1) = 1

    T (n) = 2T (n

    2) + n

    Jak bedziemy ja rozwijac, to otrzymamyT (n) = n+ 2T (

    n

    2)

    = n+ n+ 4T (n

    4)

    . . .

    = n+ n+ . . .+ n+ 2iT (n

    2i)

    Dla i = log2 n. Otrzymamy wtedy

    T (n) = n

    log2 n1i=0

    1 + 2log2 n = n logn+ n = O(n log n)

    Przykad 1.6 Jako trzeci przykad rozwazmy rekursjeT (1) = 1

    T (n) = 4T (n

    2) + n

    Jak bedziemy ja rozwijac, to otrzymamy

    T (n) = n+ 4T (n

    2)

    = n+ n2 + 16T (n

    4)

    . . .

    = n+ n2 + . . .+ n2i1 + 4iT (n

    2i)

  • 16 Rozdzia 1. Rekurencja

    Dla i = log2 n. Otrzymamy wtedy

    T (n) = n

    log2 n1i=0

    2i + 4log2 n = n(2log n 1) + n2 = O(n2)

    1.12 Metoda rekurencji uniwersalnejPrzypuscmy, ze mamy rwnanie rekurencyjne

    T (n) = aT (n

    b) + f(n) (1.7)

    gdzie a 1 i b > 1. Rwnanie takie otrzymamy szacujac czas dziaania algorytmurekurencyjnego, ktry metoda "dziel i rzadz" dzieli problem na a podproblemw rozmiarunb

    . Funkcja f(n) opisuje czas potrzebny na podzielenie problemu na podproblemy i napoaczenie rozwiazan podproblemw w rozwiazanie caego problemu.

    Na koniec podamy bez dowodu twierdzenie mwiace jak mozna szacowac funkcjeT (n) okreslona rwnaniem (1.7).

    Twierdzenie 1.7 (o rekurencji uniwersalnej) Niech T (n) bedzie okreslone dla nieujem-nych liczb cakowitych rwnaniem rekurencyjnym

    T (n) = aT (n

    b) + f(n),

    gdzie a 1, b > 1 i nb

    oznacza dnbe lub bn

    bc. Wtedy

    (a) Jezeli f(n) = O(nlogb a) dla pewnej staej > 0, to T (n) = (nlogb a).

    (b) Jezeli f(n) = (nlogb a), to T (n) = (nlogb a logn).

    (c) Jezeli f(n) = (nlogb a+) dla pewnej staej > 0 oraz af(nb) cf(n) dla

    pewnej staej c < 1, to T (n) = (f(n)).

    Z pewnym uproszczeniem, powyzsze twierdzenie przedstawia rozwiazanie w zalez-nosci od wyniku porwnania funkcji f(n) i jednomianu nlogb a. W punkcie (a) funkcjaf(n) rosnie wolniej niz nlogb a, a scislej, iloraz f(n)

    nlogb a cn dla pewnych staych c i

    > 0. Taka sytuacja jest w przykadzie 1.6, w ktrym a = 4, b = 2 oraz f(n) = n, arozwiazaniem jest funkcja T (n) = O(n2).

    W punkcie (b) funkcje f(n) i nlogb a sa tego samego rzedu, tak jak w przykadzie 1.5,w ktrym a = 2, b = 2 oraz f(n) = n, a rozwiazaniem jest funkcja T (n) = O(n log n).

    W punkcie (c) funkcja f(n) rosnie szybciej niz nlogb a, a scislej, iloraz f(n)nlogb a

    cndla pewnych staych c i > 0. Taka sytuacja jest w przykadzie 1.4, w ktrym a = 3,b = 4 oraz f(n) = n, a rozwiazaniem jest funkcja T (n) = O(n).

  • 1.13. Funkcje tworzace 17

    1.13 Funkcje tworzaceRwnania rekurencyjne mozna rozwiazywac za pomoca funkcji tworzacych. Przesledzmyta metode na przykadzie funkcji Fibinacciego. Rozwazmy funkcje okreslona szeregiempotegowym.

    G(z) = F (0) + F (1)z + F (2)z2 + + F (n)zn + (1.8)Funkcje G(z) nazywamy funkcja tworzaca ciagu F (n). Nie przejmujemy sie teraz, czyszereg (1.8) jest zbiezny. Nasze rozumowanie bedzie mozna pzniej zweryfikowac zapomoca indukcji matematycznej. Mnozymy obie strony rwnania (1.8) przez z i przezz2.

    z G(z) = F (0)z + F (1)z2 + F (2)z3 + + F (n)zn+1 + (1.9)z2 G(z) = F (0)z2 + F (1)z3 + F (2)z4 + + F (n)zn+2 + (1.10)

    a nastepnie odejmujemy od rwnania (1.8) rwnania (1.9) oraz (1.10)G(z) zG(z) z2 G(z) = F (0) + (F (1) f(0))z + (F (2) F (1) F (0))z2 +

    + (F (n) F (n 1) F (n 2))zn + W tym szeregu wyraz wolny wynosi F (0) = 0, wspczynnik przy z rwna sie F (1) F (0) = 1, a wszystkie nastepne wspczynniki sa zerami poniewaz F (n) F (n 1)F (n 2) = 0 dla kazdego n 2. Mamy wiec

    G(z)(1 z z2) = zczyli

    G(z) =z

    (1 z z2) . (1.11)

    Jezeli rozwiniemy funkcje (1.11) w szereg, to wspczynniki tego rozwiniecia utwo-rza ciag Fibonacciego. Aby to zrobic, zauwazmy, ze funkcje G(z) mozna przedstawicjako

    G(z) =z

    (1 z z2) =15

    (1

    1 z 1

    1 z),

    gdzie oraz sa znanymi juz nam pierwiastkami wielomianu z2 z 1. Funkcja 11azposiada rozwiniecie

    1

    1 az =

    i=0

    aizi,

    Wiec funkcjaG(z) posiada rozwiniecie

    G(z) =

    i=0

    15(i i)zi,

    a z tego mamyF (n) =

    15(i i).

  • 18 Rozdzia 1. Rekurencja

    1.14 Zadania1. Wypisz ciag przeozen potrzebnych do przeniesienia czterech krazkw na wiezach

    Hanoi.

    2. Udowodnij, ze algorytm opisany w podrozdziale 8.1 wymaga 2n 1 przeozen doprzeniesienia n krazkw.

    3. Oblicz NWD(39, 24) wedug rekurencyjnego algorytmu Euklidesa.4. Napisz program, ktry rekurencyjnie oblicza: a) funkcje silnia, b) funkcje Fibonac-

    ciego,

    5. Napisz program, ktry oblicza symbol Newtona:a) wedug wzoru rekurencyjnego

    (n+ 1

    k

    )=

    (n

    k

    )+

    (n

    k 1),

    b) wedug wzoru (n

    k

    )=n(n 1) (n k + 1)

    k!.

    Porwnaj te programy.6. Funkcja h okreslona jest nastepujacymi rwnaniami:

    h(0) = 1,h(n+ 1) = 2 h(n) + 1.

    Oblicz wartosci h(1), h(2), h(3), h(4), h(5). Udowodnij, ze h(n) = 2n+1 1.7. Funkcja F okreslona jest nastepujacymi rwnaniami:

    F (0) = 0,F (1) = 1,F (n+ 2) = 3 F (n+ 1) F (n).

    Oblicz wartosci F (2), F (3), F (4), F (5). Rozwiaz ulad rwnosci metoda podsta-wiania.

    8. Wedug algorytmu aczenia poacz ciagi a = (2, 5, 10, 13, 16, 23)i b = (1, 3, 4, 7, 15, 20).

    9. Stosujac algorytm merge-sort posortuj ciag (2, 5, 10, 13, 16, 23, 1, 3, 4, 7, 15, 20).10. Stosujac algorytm merge-sort posortuj ciag sw: sowik, wrbel, kos, jaskka,

    kogut, dziecio, gil, kukuka, szczygie, sowa, kruk, czubatka.[Fragment wiersza Ptasie radio Juliana Tuwima]

  • 1.14. Zadania 19

    11. Dana jest funkcjaD : N N N :D(x, 0) = x,D(x, y + 1) = D(x, y) + 1.

    Oblicz D(2, 3). Co oblicza funkcja D?12. Dana jest funkcjaM : N N N :

    M(x, 0) = 0,M(x, y + 1) = D(x, y) + x.

    Oblicz M(4, 3). Co oblicza funkcja M?13. Przedstaw rekurencyjna definicje funkcji wykadniczej xy .14. Przedstaw rekurencyjna definicje odejmowania jedynki w liczbach n aturalnych,

    ktre okreslone jest wzorem M(x) = max{x 1, 0}.15. Przedstaw rekurencyjna definicje odejmowania w liczbach naturalnych, ktre okre-

    slone jest wzorem Minus(x, y) = max{x y, 0}.16. Rozwiaz metoda iteracyjna ukad rwnan

    T (1) = 1,T (n) = 2 T (n2 ) + n2, dla n 1.

    Porwnaj z twierdzeniem o rekurencji uniwersalnej.17. Rozwiaz metoda iteracyjna ukad rwnan

    T (1) = 1,T (n) = 4 T (n2 ) + n2, dla n 1.

    Porwnaj z twierdzeniem o rekurencji uniwersalnej.18. Rozwiaz metoda iteracyjna ukad rwnan

    T (1) = 1,T (n) = 8 T (n2 ) + n2, dla n 1.

    Porwnaj z twierdzeniem o rekurencji uniwersalnej.19. Za pomoca funkcji tworzacej rozwiaz ukad rwnan

    F (0) = 0,F (1) = 1,F (n+ 2) = F (n+ 1) + 2F (n).

    20. Wypisz w postaci infixowej, prefixowej i postfixowej wyrazenie przedstawione narysunku 7.

  • 20 Rozdzia 1. Rekurencja

    Rysunek 1.7: Drzewo wyrazenia

    +

    a +

    b c

    /

    d e

    21. Narysuj drzewo poszukiwan binarnych dla nastepujacego ciagu liczb: 30, 43, 13, 8,50, 40, 20, 19, 22.

    22. Narysuj drzewo poszukiwan binarnych dla nastepujacego ciagu sw: sowik, wr-bel, kos, jaskka, kogut, dziecio, gil, kukuka, szczygie, sowa, kruk, czubatka.[Fragment wiersza Ptasie radio Juliana Tuwima]

    23. Zaprojektuj algorytm wyszukiwania najmniejszego elementu w drzewie poszuki-wan binarnych.

    24. Zaprojektuj algorytm, ktry dla wierzchoka z wartoscia x wyszukuje w drzewieposzukiwan binarnych wierzchoka z nastepna wartoscia.

    1.15 Problemy

    1.15.1 Funkcja AckermannaFunkcja Ackermanna okreslona jest, dla liczb naturalnych i, j, k 1, nastepujacymi rw-naniami:

    A(1, j, k) = j + kA(i+ 1, j, 1) = jA(i+ 1, j, k + 1) = A(i, j, A(i+ 1, j, k))

    Funkcja Ackermanna jest przykadem funkcji majacej dosc prosta definicje, ale jestpraktycznie nieobliczalna z tego powodu, ze jej wartosci szybko rosna.

    1. Udowodnij, ze A(2, j, k) = j k oraz A(3, j, k) = jk.2. Oblicz A(3, j, 1), A(3, j, 2), A(3, j, 3), A(3, j, 4).

  • 1.15. Problemy 21

    3. Udowodnij, zeA(3, j, k) = j

    j}k razy.

    4. Oblicz A(4, 2, 1), A(4, 2, 2), A(4, 2, 3).

    1.15.2 Wieze Hanoi1. Udowodnij, ze kazdy algorytm przekadania krazkw w wiezach Hanoi wymaga co

    najmniej 2n 1 przeozen dla n krazkw.2. Rozwaz nastepujacy algorytm przekadania krazkw na wiezach Hanoi: Ustawiamy paliki w cykl A, B, C a za nim A. Powtarzamy dwa nastepujace ruchy, az do skutku:

    najpierw przekadamy najmniejszy krazek na nastepny cyklicznie palik,potem wykonujemy jedyny dopuszczalny ruch, ktry nie rusza najmniejszego

    krazka.

    Sprawdz ten algorytm dla n = 2, 3 i 4. Udowodnij, ze po 2n 1 ruchach algorytmprzeozy n krazkw na palik B, jezeli n jest nieparzyste, lub na palik C, jezeli n jestparzyste.