158

Wstep Do Informatyki

Embed Size (px)

DESCRIPTION

Algorytmy, grafy, podstawy informatyki

Citation preview

  • Wykad ze Wstpu

    do Informatyki

    Rok 2004-2005

    Marek Zawadowski

    Wydzia Matematyki, Informatyki i Mechaniki

    Uniwersytet Warszawski

    3 stycznia 2005

    Spis treci

    1 Wstp (1/2) 4

    1.1 Literatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

    1.2 Zaliczenie i egzamin . . . . . . . . . . . . . . . . . . . . . . . 4

    1.3 Historia Informatyki . . . . . . . . . . . . . . . . . . . . . . . 4

    2 Wprowadzenie (2 1/2) 5

    2.1 Algorytm Euklidesa . . . . . . . . . . . . . . . . . . . . . . . 5

    2.2 Problem algorytmiczny . . . . . . . . . . . . . . . . . . . . . . 6

    2.3 Sortowanie liczb . . . . . . . . . . . . . . . . . . . . . . . . . . 6

    2.4 Analiza zoonoci algorytmu . . . . . . . . . . . . . . . . . . 7

    2.5 Wiee Hanoi . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

    2.6 Wyszukiwanie sowa w sowniku . . . . . . . . . . . . . . . . . 10

    2.7 Tablice rzeczywistego czasu dziaania algorytmw . . . . . . . 10

    2.8 Komputer od rodka . . . . . . . . . . . . . . . . . . . . . . . 12

    3 Jzyk Pascal (4) 14

    3.1 Jzyki programowania wysokiego poziomu . . . . . . . . . . . 14

    3.2 Diagramy skadniowe . . . . . . . . . . . . . . . . . . . . . . . 14

    3.3 Formalna denicja jzyka imperatywnego . . . . . . . . . . . 16

    3.4 Zmienne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

    3.5 Typy proste . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

    3.6 Typy strukturalne . . . . . . . . . . . . . . . . . . . . . . . . 20

    1

  • 3.7 Przegld instrukcji jzyka Pascal . . . . . . . . . . . . . . . . 21

    3.8 Procedury . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

    3.9 Procedury rekurencyjne . . . . . . . . . . . . . . . . . . . . . 34

    3.10 Poprawno programw . . . . . . . . . . . . . . . . . . . . . 40

    4 Podstawowe metody programowania (5) 43

    4.1 Metoda powrotw (prb i bdw) . . . . . . . . . . . . . . . 43

    4.2 Metoda 'dziel i rzd' . . . . . . . . . . . . . . . . . . . . . . 48

    4.3 Sortowanie przy pomocy porwna . . . . . . . . . . . . . . . 52

    4.4 Programowanie dynamiczne . . . . . . . . . . . . . . . . . . . 54

    4.5 Algorytmy zachanne . . . . . . . . . . . . . . . . . . . . . . . 59

    4.6 Algorytm sortowania przez kopcowanie (heapsort) . . . . . . . 63

    4.7 Podsumowanie . . . . . . . . . . . . . . . . . . . . . . . . . . 67

    5 Reprezentacja liczb na komputerze (2) 69

    5.1 Systemy liczbowe o rnych podstawach . . . . . . . . . . . . 69

    5.2 Reprezentacja staopozycyjna liczb cakowitych . . . . . . . . 71

    5.3 Operacje arytmetyczne staopozycyjne . . . . . . . . . . . . . 73

    5.4 Reprezentacja zmiennopozycyjna liczb rzeczywistych . . . . . 74

    5.5 Arytmetyka zmiennopozycyjna . . . . . . . . . . . . . . . . . 76

    5.6 Wybrane problemy numeryczne . . . . . . . . . . . . . . . . . 79

    6 Dynamiczne struktury danych (4) 82

    6.1 Podstawowe dynamiczne struktury danych . . . . . . . . . . . 82

    6.2 Typy wskanikowe . . . . . . . . . . . . . . . . . . . . . . . . 86

    6.3 Implementacja list . . . . . . . . . . . . . . . . . . . . . . . . 91

    6.4 Drzewa binarnych poszukiwa (BST) . . . . . . . . . . . . . . 95

    6.5 Struktury danych dla rodziny zbiorw rozcznych . . . . . . 101

    7 Algorytmy grafowe (5) 105

    7.1 Grafy i reprezentacje grafw . . . . . . . . . . . . . . . . . . . 105

    7.2 Skadowe spjne grafu niezorientowanego . . . . . . . . . . . 108

    7.3 Przeszukiwanie grafu wszerz (BFS) . . . . . . . . . . . . . . . 110

    7.4 Przeszukiwanie grafu w gb (DFS) . . . . . . . . . . . . . . . 117

    7.5 Sortowanie topologiczne . . . . . . . . . . . . . . . . . . . . . 122

    7.6 Silnie spjne skadowe grafu . . . . . . . . . . . . . . . . . . . 123

    7.7 Minimalne drzewo rozpinajce . . . . . . . . . . . . . . . . . . 129

    2

  • 8 Zoono algorytmw (3) 133

    8.1 Problemy decyzyjne . . . . . . . . . . . . . . . . . . . . . . . 133

    8.2 Algorytmy werykujce . . . . . . . . . . . . . . . . . . . . . 134

    8.3 Redukowalno problemw i problem P=NP . . . . . . . . . . 136

    8.4 Problemy nieobliczalne . . . . . . . . . . . . . . . . . . . . . . 138

    8.5 Metody przyblione . . . . . . . . . . . . . . . . . . . . . . . . 139

    9 Rozwizywanie ukadw rwna liniowych 146

    9.1 Mnoenie macierzy . . . . . . . . . . . . . . . . . . . . . . . . 146

    9.2 Rozwizywanie ukadw rwna liniowych niejednorodnych

    metod rozkadu LUP . . . . . . . . . . . . . . . . . . . . . . 146

    9.3 Obliczanie rozkadu LUP . . . . . . . . . . . . . . . . . . . . 150

    9.4 Macierze odwrotne . . . . . . . . . . . . . . . . . . . . . . . . 154

    9.5 Wyznacznik macierzy kwadratowej . . . . . . . . . . . . . . . 154

    3

  • 1 Wstp (1/2)

    1.1 Literatura

    1. Oglne wprowadzenie: D. Harel, Rzecz o istocie informatyki

    2. Algorytmy:

    T.H. Cormen, C.E. Leiserson, R.L. Rivest, Introduction to Algo-rithms (Wprowadzenie do Algorytmw)

    L. Banachowski, K. Diks, W. Rytter, Algorytmy i strukturydanych

    A.V. Aho, J.E. Hopcroft, J.D. Ulman, Projektowanie i analizaalgorytmow komputerowych

    3. Jzyk Pascal:

    M.Iglewski, J.Madey, S.Matwin, Pascal R.K. Kott, Programowanie w jzyku Pascal

    1.2 Zaliczenie i egzamin

    Zaliczenie: program i kolokwium. Egzamin: pisemny, po obu semestrach.

    1.3 Historia Informatyki

    IV w. p.n.e. Euklides: algorytm Euklidesa (pierwszy niebanalny algo-

    rytm).

    IX w n.e. Algorismus (Muhammad ibn Musa al-Kwarizmi =Muhammad

    syn Musy z Kworyzmu), algorytmy dodawania odejmowania, mnoe-

    nia, i dzielenia liczb dziesitnych.

    XIX w. n.e. Joseph Jaquard, maszyna tkacka sterowana algorytmem.

    Charls Babbage, maszyna rnicowa do obliczania wzorw matem-

    atycznych i projekt maszyny analitycznej, mechanicznego prototypu

    komputera.

    1920-30 r. Alan Turing, Emil Post, John von Neuman, Kurt Gdel, Alnzo

    Church, Stephen Kleene: badania pojcia funkcji obliczalnej.

    1945 r. J. von Neuman, pierwszy komputer (U Pensylvenia) (?)

    196- r. Informatyka staje sie now dziedzin wiedzy.

    4

  • 2 Wprowadzenie (2 1/2)

    2.1 Algorytm Euklidesa

    Dane wejciowe: dwie liczby naturalne m,n > 0. Wynik: NWD(m,n).Opis algorytmu. Odejmuj liczb wiksz od mniejszej a do wyrwnania

    liczb.

    Zapis algorytmu.

    a:=m; b:=n;

    dopki a b wykonuj {NWD(a,b)=NWD(m,n), a,b>=1}

    jeli a b to NWD(a, b) = NWD(ab, b).W tym celu wystarczy pokaza, e liczba k dzieli a i b wiw gdy dzieli (a b)i b.Ad 2. Oczywiste.

    Ad 3. Kade wykonanie instrukcji warunkowej zmniejsza sum a + b oco najmniej 1. Z drugiej strony mamy a 1, b 1. Zatem instrukcjawarunkowa moe by wykonana co najwyej m+ n 2 razy.

    5

  • 2.2 Problem algorytmiczny

    Problem (zadanie) algorytmiczny polega na

    scharakteryzowaniu wszystkich poprawnych danych wejciowych; scharakteryzowaniu oczekiwanych wynikw jako funkcji danych wej-ciowych.

    Rozwizanie algorytmiczne polega na podaniu algorytmu tzn. takiego

    opisu dziaa przy pomocy operacji elementarnych ktry zastosowany do

    poprawnych danych wejciowych daje oczekiwane wyniki.

    Rozrniamy wykonywanie algorytmw od dziaania twrczego.

    Problemy dotyczce algorytmw:

    1. Jzyk: zbir instrukcji elementarnych;

    2. Rozstrzygalno: czy istnieje algorytm rozwizujcy dany problem?

    3. Analiza poprawnoci: czy algorytm dziaa poprawnie, tzn. robi to co

    ma robi?

    4. Analiza zoonoci: czy algorytm dziaa szybko?

    5. Analiza numeryczna: czy algorytm dziaa dokadnie?

    2.3 Sortowanie liczb

    Dane wejciowe: liczba naturalna n i cig liczb a1, a2, . . . , an. Wynik: permutacja a1, a2, . . . , an cigu a1, a2, . . . , an taka, e a1 a2 . . . an.

    Przykad. Dane: 2, 7, 4, 5, 1. Wynik: 1, 2, 4, 5, 7.Jak do tego problemu podej systematycznie? Na przykad tak jak

    sortujemy rozdane karty w brydu.

    Zapis algorytmu (sortowanie przez wkadanie). (A[j] - j-ty element).

    dla j:=2 do n wykonuj

    k:=A[j];

    i:=j-1;

    dopki i>0 oraz A[i]>k wykonuj

    A[i+1]:=A[i];

    6

  • i:=i-1;

    A[i+1]:=k;

    Przykad.

    Dane : 2 7 4 5 12 4 7 5 12 4 5 7 1

    Wynik : 1 2 4 5 7

    2.4 Analiza zoonoci algorytmu

    Analiza zoonoci algorytmu jest to przewidywanie ile zasobw potrzeba do

    wykonania algorytmu.

    Zasoby:

    1. pami;

    2. poczenia komunikacyjne;

    3. czas dziaania (dla nas najwaniejszy).

    eby analizowa zoono algorytmu musimy co wiedzie o tym jak on

    bdzie wykonywany przez maszyn.

    My bdziemy zakada, e programy s wykonywane na maszynie o

    dostpie swobodnym (RAM): tzn. instrukcje s wykonywane jedna po drugiej

    (nigdy dwie na raz) i program nie moe si modykowa w trakcie dziaania.

    Czas dziaania zaley od rozmiaru danych wejciowych. 5 liczb nasz al-gorytm sortuje szybciej ni 1000. Take dla dwch cigw rwnej dugocialgorytm moe wykonywa rn liczb instrukcji w zalenoci od tego jak

    bardzo rni si one od cigu posortowanego. Na og, czas dziaania algo-

    rytmu wyraany jest jako funkcja rozmiaru danych wyjciowych.

    1. Rozmiar danych wejciowych jest to funkcja przyporzdkowujca

    poprawnym danym wejciowym algorytmu liczb naturaln.

    2. Czas dziaania algorytmu jest to funkcja przyporzdkowujca danym

    wejciowym liczb podstawowych operacji wykonywanych przez algo-

    rytm na tych danych.

    3. (Pesymistyczna, czasowa) zoono algorytmu jest to funkcja z N wN przyporzdkowujca liczbie naturalnej n najduszy czas dziaaniaalgorytmu na danych o rozmiarze n.

    7

  • Dla problemu sortowania rozmiar danych to dugo cigu.

    nr czas

    1 dla j:=2 do n wykonuj | n

    2 k:=A[j]; | n-1

    3 i:=j-1; | n-1

    4 dopki i>0 oraz A[i]>k wykonuj | t_2+...+t_n

    5 A[i+1]:=A[i]; | (t_2-1)+...+(t_n-1)

    6 i:=i-1; | (t_2-1)+...+(t_n-1)

    7 A[i+1]:=k; | n-1

    tj - liczba wykona linii 4 przy ustalonym j. tj - jest najwikszy gdy macierz jest uporzdkowana w porzdku male-jcym, wtedy tj = j.

    T (n) - zoono algorytmu.

    T (n) = 3(n 1) + n+ 2nj=2

    (j 1) +nj=2

    j 1 =

    = 3(n 1) + n+ 2n(n 1)2

    +n(n+ 1)

    2 1 = 3

    2n2 +

    72n 4To jest cigle 'za dokadnie', skadniki

    72n i 4 oraz staa 32 nie majwikszego znaczenia, przy duych n. To co jest wane to n2. Mwimy, e al-gorytm sortowania przez wkadanie ma zoono (pesymistyczn, czasow)

    O(n2).

    Notacja O(f(n)). Niech f : N N funkcja. Mwimy, e funkcja g :N N jest (klasy) O(f(n)) (piszemy g O(f(n)) lub wrcz g = O(f(n)))jeli istniej stae a, b R takie, e dla n > b g(n) a f(n) ('g przyjmujewartoci nie wiksze ni f z dokadnoci do staej').

    2.5 Wiee Hanoi

    A B C

    8

  • Problem wie Hanoi. Przenie pojedynczo n krkw z wiey Ana wiee B uywajc wiey C tak by nigdy krek wikszy nie lea na

    mniejszym.

    Opis algorytmu. Aby przenie n krkw z A na B przez C

    1. przenie n 1 krkw z A na C uywajc B;2. przenie krek z A na B;

    3. przenie n 1 krkw z C na B uywajc A.Zapis algorytmu.

    procedura przenies(m,X,Y,Z); {przenosi kraki z X na Y uywajc Z}

    jeli m=1 to przestaw(X,Y)

    w przeciwnym przypadku

    przenie(m-1,X,Z,Y);

    przestaw(X,Y)

    przenie(m-1,Z,Y,X);

    przenies(n,A,B,C) {wywoanie poczatkowe}

    Przykad. n = 3. ...

    Ile przestawie wykona algorytm by przestawi n krkw?

    an - liczba przestawie n krkw.

    Rwnanie rekurencyjne:{a1 = 1an+1 = an + 1 + an = 2an + 1

    Rozwizanie: an = 2n 1.Dowd indukcyjny. Dla n = 1, 211 = 1 = a1. Zamy, e an = 2n1.Wtedy

    an+1 = 2an + 1 = 2(2n 1) + 1 = 2n+1 2 + 1 = 2n+1 1

    Liczba przestawie jest proporcjonalna do iloci wszystkich operacji

    wykonywanych przez algorytm. Zatem cay algorytm dziaa w czasie O(2n).

    9

  • 2.6 Wyszukiwanie sowa w sowniku

    Problem wyszukiwania sowa w sowniku.

    Dane wejciowe: liczba naturalna n i cig sw w1, . . . , wn uporzd-kowany w porzdku leksykogracznym (alfabetycznym) oraz sowo w.

    Wynik: TAK, gdy dla pewnego 1 i n, w = wi; NIE, w przeciwnymprzypadku.

    Przykad. Dane: ~w = a, ala, b, bela, hela, w = bela. Wynik: TAK.

    Ponisza procedura mem sprawdza czy sowo wystpuje w sowniku

    pomidzy sowami wm1 i wm2.

    procedura mem(m1,m2);

    jeli m1=m2 to

    jeli w=w_m1 to wypisz('TAK')

    w przeciwnym przypadku wypisz('NIE')

    w przeciwnym przypadku

    m3:= (m1+m2) div 2;

    jeli w>w_m3 to mem(m3+1,m2)

    w przeciwnym przypadku mem(m1,m3)

    mem(1,n) (wywoanie pocztkowe)

    Rozmiar danych: dugo cigu.

    pn -liczba porwna sw dla sownika dugoci n.Rwnanie rekurencyjne: {

    p1 = 1p2n = pn + 1

    Rozwizanie: pn log n.Liczba porwna jest rzdu log n. Algorytm dziaa w czasie O(log n).

    2.7 Tablice rzeczywistego czasu dziaania algorytmw

    W poniszej tabeli przedstawiony jest rozmiar zada jakie mona rozwiza

    w cigu jednej sekundy, minuty, godziny.

    Zakadamy, e do wykonania operacji podstawowej potrzebna jest jedna

    milisekunda (= 103s).

    10

  • nr Algorytm Zoono Maksymalny rozmiar zadania

    1 sekunda 1 minuta 1 godzina

    A1 szukanie sowa O(log n) 21000 - -w sowniku

    A2 znajdowanie O(n) 1000 6 104 3.6 106maksimum

    w tablicy

    A3 sortowanie O(n log n) 140 4893 2 105przez 'scalanie',

    'kopcowanie'

    A4 sortowanie O(n2) 31 244 1897przez 'wkadanie',

    A5 n3 10 39 153A6 Wiee Hanoi O(2n) 9 15 21

    A teraz przypumy, e zwikszymy szybko komputera 10 razy.

    Ponisza tablica pokazuje o ile zwikszy si maksymalny rozmiar zadania

    ktry mona rozwiza po przyspieszeniu.

    nr Algorytm Zoono Maksymalny Maksymalny

    rozmiar rozmiar

    zadania przed zadania po

    przyspieszeniem. przyspieszeniu.

    A1 szukanie sowa O(log n) s1 s101w sowniku

    A2 znajdowanie O(n) s2 10 s2maksimum

    w tablicy

    A3 sortowanie O(n log n) s3 okoo 10 s3przez 'scalanie', dla duych n'kopcowanie'

    A4 sortowanie O(n2) s4 3.16 s4przez 'wkadanie',

    A5 n3 s5 2.15 s5A6 Wiee Hanoi O(2n) s76 s6 + 3.3

    11

  • 2.8 Komputer od rodka

    Schemat logiczny komputera

    Magistrale komunikacyjne

    Dyski

    Monitor

    Klawiatura

    Drukarka

    Sie

    Procesor:

    Arytmometr

    Jednostka

    sterujca

    Rejestry

    Pami

    wewntrzna:

    staa (ROM)

    operacyjna

    (RAM)

    Procesor przetwarza informacje i steruje pozostaymi elementami sys-temu.

    Pami suy do przechowywania informacji. Ukady wejcia-wyjcia (Dyski, Monitor, Klawiatura, Drukarka, Sie)umoliwiaj komunikacj komputera ze wiatem zewntrznym.

    Magistrale komunikacyjne cz moduy komputera.

    Komputer dziaa powtarzajc cykle rozkazowe. Na jeden cykl rozkazowy

    skada si wiele operacji. W pewnym przyblieniu mona je przedstawi

    nastpujco:

    1. pobranie kolejnego rozkazu z komrki pamici wskazywanej przez

    licznik rozkazw;

    2. sprawdzenie czy rozkaz wymaga pobrania danych, jeli tak, to wyz-

    naczenie miejsc w pamici z ktrych naley pobra dane i umieszczenie

    danych w rejestrach komputera;

    3. wykonanie rozkazu (arytmometr);

    12

  • 4. wysanie wyniku pod waciwy adres w pamici;

    5. zmiana zawartoci licznika rozkazw, tak by wskazywa kolejny rozkaz

    dla procesora;

    6. obsuga przerwa (o ile takie maj miejsce);

    7. przejcie do kroku 1. w celu wykonania nastpnego cyklu rozkazw.

    Od pomysu algorytmu do wykonania programu przez maszynie jest sz-

    ereg krokw do wykonania. Pierwsze kroki s wykonywane czowieka a

    nastpne przez maszyn. Mona wyszczeglni nastpujce etapy tego pro-

    cesu:

    1. Pomys algorytmu (czowiek);

    2. Algorytm (czowiek);

    3. Program w jzyku wysokiego poziomu (programista);

    4. Program w jzyku adresw symbolicznych, asemblerze, (kompilacja,

    maszyna);

    5. Kod maszynowy (dalsza kompilacja, maszyna);

    6. Wykonanie kodu na komputerze (maszyna).

    13

  • 3 Jzyk Pascal (4)

    3.1 Jzyki programowania wysokiego poziomu

    Jzyki programowania wysokiego poziomu s to sformalizowane jzyki suce

    do zapisu algorytmw.

    Typy jzykw programowania wysokiego poziomu:

    1. imperatywne: Pascal, C, Basic, Fortran, Cobol, APL, Algol, Forth, ...

    2. funkcyjne: ML, Miranda, Haskel, ...

    3. programowanie w logice: Prolog.

    4. programowanie zorientowane obiektowo: SmallTalk, C++...

    5. programowanie rwnolege: Occam, Concurrent Pascal, ...

    Na opis jzyka programowania skada si:

    1. Precyzyjna skadnia tzn. dokadne okrelenie co jest dopuszczalnym

    programem w tym jzyku.

    2. Jednoznaczna semantyka tzn. jednoznaczny opis kadego wyraenia

    dozwolonego skadniowo.

    (a) Semantyka operacyjna: opis stanu komputera przed i po wykona-

    niu instrukcji.

    (b) Semantyka denotacyjna: opis funkcji przeksztacajcej dane we-

    jciowe w dane wyjciowe.

    3.2 Diagramy skadniowe

    Skadni jzyka programowania mona opisywa gracznie przy pomocy dia-

    gramw skadniowych lub tekstowo przy pomocy notacji BNF. My opiszemy

    skadnie jzyka Pascal gracznie.

    W diagramie skadniowym obiekt deniowany wystpuje jako podpis do

    rysunku deniujcego. Symbole:

    1. Blok owalny

    14

  • obejmuje symbole oznaczajce same siebie.

    2. Blok prostoktny

    obejmuje pojcie zdeniowane gdzie indziej.

    3. Strzaka

    -

    wskazuje kolejno symboli w napisie zoonym.

    4. Rozgazienie

    -PPPPq

    oznacza alternatyw denicyjn - mona wybra dowoln ze strzaek.

    Przykady

    cyfra dziesitna

    01

    89

    -

    @@@R

    @@@R

    @@@R

    @@@R

    @@@

    @@@R

    @@@R

    @@@R

    . . .

    liczba bez znaku

    cyfra dziesitna

    - -6

    liczba

    liczba bez znaku

    +

    -

    @@R

    @@R

    -

    15

  • identykator

    litera

    litera

    cyfra dziesitna

    - *

    HHHj

    -

    6

    ?

    3.3 Formalna denicja jzyka imperatywnego

    Na tekst programu skadaj si

    1. opis struktur danych, tzn. opis obiektw na ktrych dziaa algorytm;

    w programie: denicje i deklaracje.

    2. opis procesu obliczeniowego; w programie: instrukcje.

    Czasem zawiera si to w nastpujcej 'rwnoci':

    program = algorytm + struktury danych

    Formaln denicja (fragmentu) jzyka Pascal mona przedstawi tak:

    program

    -

    program - identykator -

    ; - blok -

    . -

    16

  • blok

    -

    type - identykator -

    = - typ -

    ;

    6

    -

    var - identykator -

    : - typ -

    ;

    ;

    6

    6

    -deklaracja funkcji lub procedury

    -;

    6

    -

    begin - instrukcja -

    end -

    ;

    6

    W powyszym diagramie wystpuj kolejno sekcja denicji typw, sekcja

    deklaracji zmiennych, sekcja deklaracji funkcji i procedur oraz program

    gwny.

    typ

    *

    HHHj

    HHH -

    identykator typu

    opis typu

    Jednak dalszy opis jzyka Pascal przedstawimy mniej formalnie.

    3.4 Zmienne

    1. Zmienna i jej nazwa: zmiennmoemy utosamia z obszarem pamici,

    w ktrym przechowywana jest pewna warto (warto tej zmien-

    nej w postaci kodu dwjkowego). Nazwa zmiennej (identykator) to

    mnemotechniczny adres tego obszaru pamici.

    NB. Dla rnych zmiennych obszar pamici moe by rny.

    17

  • 2. Typ zmiennej wyznacza wielko obszaru pamici przeznaczonego na

    dan zmienn. Aby poprawnie skompilowa program musimy poinfor-

    mowa kompilator o zamiarze wykorzystania kadej zmiennej (wyjtki

    od tej reguy poznamy pniej). Taka informacja to deklaracja zmien-

    nej (lub staej).

    Deklaracje zmiennych w jzyku Pascal maj nastpujca posta:

    var nazwa1, nazwa2 : typ1;

    nazwa3 : typ3;

    ....

    Sowo 'var' jest sowem kluczowym rozpoczynajcym sekcj deklaracji

    zmiennych. Deklaracja zmiennych wprowadza identykatory zmiennych

    wymienione po lewej stronie deklaracji, i zapowiada, e bd one uywane

    dla oznaczania wartoci typu podanego po prawej stronie deklaracji.

    Denicje staych w jzyku Pascal maj nastpujc posta:

    const stala1='opis stalej';

    ....

    Sowo 'const' jest sowem kluczowym rozpoczynajcym sekcj denicji

    staych. Stae, podobnie jak zmienne, przechowuj wartoci rnych typw

    ale nie mog by modykowane podczas realizacji programu.

    Przykad

    const zakres=100;

    pi=3.14;

    liczba=17;

    znak='a';

    ciag_znakow='ala';

    3.5 Typy proste

    Podstawowymi typami jzyka Pascal s typy proste. Przy ich pomocy deni-

    uje si bardziej zoone typy strukturalne.

    Typy standardowe

    18

  • typ identykator przykadowe funkcje

    typu elementy typu i relacje

    logiczny boolean true, false and, or, not

    cakowity integer -2, 1, 1000 +,-,*, div, mod,0) to po jej wykonaniu zachodzi (n < k n > 0).1

    S tu pewne ograniczenia ktre nas w praktyce nie bd dotyczy. Gdy formua Pma kwantykatory to wyraenie w wstawiamy na tak zwane wolne wystpienia zmienneja. Ponadto, takie podstawienie nie moe wiza adnej ze zmiennych wystpujcych wwyraeniu w.

    22

  • Innymi sowy instrukcja podstawiania jest wykonywana w ten sposb, e

    najpierw wyliczamy warto wyraenia po prawej stronie a potem wstawiamy

    wyliczon warto na zmienn po lewej stronie.

    Do opisu znaczenia instrukcji przypisania uylimy zapisu logicznego.

    Oglnie zapis logiczny ma posta

    P{ I }Q

    gdzie P i Q s formuami a I instrukcj, i oznacza, e jeli przed wykonanieminstrukcji I prawdziwa jest formua P to po jej wykonaniu (o ile wykonywanieinstrukcji si zakoczy) prawdziwa jest formua Q. P nazywamy warunkiempocztkowym a Q warunkiem kocowym.Prawdziwa jest nastpujca regua wnioskowania

    P{ I }Q, Q{ J }RP{ I;J }R (2)

    Ta regua, jak i inne reguy wnioskowania, pozwala wywnioskowa formu

    pod kresk o ile ustalimy prawdziwo formu nad kresk. W tym przypadku

    regua (3) wyraa to, e ; czy dwie instrukcje nic w nich nie zmieniajc.

    Czsto uyteczna jest regua ktra nieznacznie uoglnia regu (2)

    P P , P { I }Q, Q Q, Q{ J }R, R RP{ I;J }S (3)

    Przykad. Zamian warto zmiennych x i y dowolnego typy T monawykona uywajc dodatkowej zmiennej z typu T w nastpujcy sposb:

    z:=x;

    x:=y;

    y:=z

    Mona to wykaza uywajc opisu znaczenia instrukcji podstawiania (1) oraz

    reguy (2) w nastpujcy sposb:

    (x = a y = b) {z := x} (z = a y = b)

    (z = a y = b) {x := y} (z = a x = b)(z = a x = b) {y := z} (y = a x = b)W praktyce takie rozumowania jest lepiej prowadzi od koca.

    23

  • Zatem, uywajc dwukrotnie reguy (2), otrzymujemy

    (x = a y = b) {z := x; x := y; y := z} (y = a x = b)

    Gdy T jest typem cakowitym lub rzeczywistym to moemy zamieniwartoci zmiennych x i y nie uywajc dodatkowej zmiennej, w nastpujcysposb:

    x:=x+y;

    x:=x-y;

    y:=x-y

    By pokaza, e powysze trzy instrukcje rzeczywicie wymieniaj wartoci

    zmiennych x i y znowu uyjemy aksjomatu (1) zaczynajc od koca (gdziewstawiamy formu ktr chcemy udowodni (y = a x = b)):

    ((x+y)((x+y)y)) = b(x+y)y = a {x := x+y} x(xy) = bxy = a

    x (x y) = b x y = a {y := x y} (x y) = b y = a)(x y) = b y = a) {x := x y} x = b y = a)Formua pierwsza ((x+y)((x+y)y)) = b(x+y)y = a (otrzymanana kocu) nie jest t o ktr nam chodzi. Ale zauwamy, e prawdziwa jest

    formua

    (x = a y = b) ((x+ y) ((x+ y) y)) = b (x+ y) y = a

    A teraz uywajc reguy (3) otrzymujemy dany wynik:

    (x = a y = b) {x := x+ y; y := x y; y := x y} (x = b y = a)

    Instrukcja pusta

    Instrukcja pusta to pusty cig znakw i znaczy 'nic nie rb'. Jej znaczenie

    opisuje si aksjomatem

    P{ }Pdla dowolnej formuy P . Jeli napiszemy cig instrukcji I1; ; I2 to jest tozoenie trzech instrukcji przy czym drug instrukcj jest instrukcja pusta.

    24

  • Instrukcja zoona

    Instrukcja zoona czy cig instrukcji w jedn instrukcj i ma posta

    begin I1; ... ; In end gdzie I1, ... , In s instrukcjami. Znaczenie tej

    instrukcji opisuje regua

    Pi { Ii } Pi+1 i = 1, . . . , nP1 { begin I1; . . . ; In end } Pn+1 (4)

    Przykad. Fragment programu

    begin

    x:=x+2;

    y:=2*x;

    end;

    jest zoeniem trzech instrukcji, z ktrych ostatnia jest instrukcj pust.

    Instrukcje warunkowe

    Mamy dwie instrukcje warunkowe. Pierwsza ma posta

    if w then I

    gdzie w jest wyraeniem typu boolowskiego a I jest instrukcj. Znaczenie tej

    instrukcji opisuje regua

    P w { I } Q P w QP {if w then I} Q (5)

    tzn. instrukcja oznacza 'jeli w to wykonaj I'. Druga instrukcja warunkowa

    jest rozszerzeniem pierwszej i ma posta

    if w then I1 else I2

    gdzie w jest wyraeniem typu boolowskiego a I1 i I2 s instrukcjami. Znacze-

    nie tej instrukcji opisuje regua

    P w { I1 } Q P w { I2 } QP {if w then I1else I2} Q (6)

    tzn. instrukcja oznacza 'jeli w to wykonaj I1 w przeciwnym wypadku

    wykonaj I2'.

    Przykad. Jeli x jest typu cakowitego to mamy

    T { if x < 0 then abs := x else abs := x } abs = |x| (7)

    25

  • gdzie T oznacza formu zawsze prawdziw. Z (1) i (3) mamy

    (T x < 0) (x = x x < 0), (abs = x x < 0) (abs = |x|)((x = x x < 0) { abs := x } (abs = x x < 0)

    (T x < 0) { abs := x } (abs = |x|)i podobnie mona pokaza, e

    (T (x < 0)) { abs := x } (abs := |x|).

    Zatem (7) wynika z powyszych dwch formu na mocy reguy (6).

    Iteracja warunkowa (ptla while)

    Instrukcja iteracji warunkowej ma posta

    while w do I

    gdzie w jest wyraeniem typu boolowskiego a I jest instrukcj.

    Przykad.

    while x

  • x:=0;

    while k

  • gdzie x jest zmienn typu porzdkowego, t1 i t2 s wyraeniami tego samego

    typu co zmienna x a I jest instrukcj.

    Przykad.

    for i:=1 to 10 do begin

    x:=x*i;

    y:=y+i

    end;

    Znaczenie tej instrukcji opisuje regua (zakadamy, e instrukcja I niezmienia wartoci zmiennej i oraz t1 succ(t2))

    P (t1), P (i) { I } P (succ(i)) i = t1, . . . , t2P (t1) { for i := t1 to t2 do I } P (succ(t2)) (9)

    Podobnie jak w przypadku ptli while formu P speniajc przesankitej reguy nazywamy niezmiennikiem ptli. Instrukcja ta powoduje, e in-

    strukcja I jest wykonywana kolejno dla wszystkich wartoci x of t1 do t2.

    Instrukcje wejcia-wyjcia

    Instrukcje wejcia-wyjcia su do komunikacji ze 'wiatem

    zewntrznym'. Instrukcja

    write(w)

    wypisuje na ekran warto wyraenia w typu standardowego. Instrukcja

    read(x)

    wczytuje warto z klawiatury na zmienn x typu standardowego.

    Przykady. Podajemy poniej dwa proste przykady programw. Pier-

    wszy nwd oblicza najwikszy wsplny dzielnik a drugi srednia redni aryt-

    metyczn n liczb.

    Program nwd;

    var n,m:integer;

    begin

    read(n);

    read(m);

    while nm do

    if n>m then n:=n-m

    else m:=m-n;

    write(n)

    end.

    28

  • Program srednia;

    var n,i:integer;

    x,s:real;

    begin

    read(n);

    s:=0;

    for i:=1 to n do begin

    read(x);

    s:=s+x;

    end;

    write(s/n)

    end.

    3.8 Procedury

    Programy nawet w jzyku wysokiego poziomu, jeli nie s podzielone na

    mniejsze moduy szybko staj si nieczytelne. By temu zapobiec moe je

    dzieli na mniejsze moduy ktre wykonuj poszczeglne fragmenty zadania

    i maj bardziej przejrzyst form. Do modularyzacji wikszych programw

    su procedury. Rozwamy nastpujce zadanie.

    Zadanie.

    Dane: tablica A liczb cakowitych. Wynik: Liczba wystpie liczby 1 po liczbie 0.Dla tablicy A = [1, 0, 0, 7, 1, 1, 0, 6, 7, 1, 1] wynik powinien by 2. Monato zadanie rozwiza tak:

    const m=100;

    var A : array[1..m] of integer;

    s,n,i : integer;

    begin

    for i:=1 to m do {wczytanie wartoci A}

    read(A[i]);

    s:=0; n:=1; {inicjalizacja zmiennych}

    while n

  • n:=n+1;

    if A[n]=1 then s:=s+1; {jeli znalazl 1 to zwikszamy s}

    end;

    end;

    write(s); {wypisanie wynikw}

    end.

    W nawiasach klamrowych zapisane s komentarze wyjaniajce co robi

    poszczeglne fragmenty programu. Mona jednak ten program zapisa, uy-

    wajc procedur, tak:

    const m=100;

    var A : array[1..m] of integer;

    s,n : integer;

    procedure dane;{wczytanie wartoci A}

    var i:integer;

    begin

    for i:=1 to m do

    read(A[i]);

    end;

    procedure szukaj(var j:integer;x:integer);

    {szukanie w tablicy A wartosci x od miejsca j}

    begin

    while (j

  • write(s); {wypisanie wynikw}

    end.

    Majc taki program mona go teraz atwo poprawi by szuka rnych kom-

    binacji liczb na przykad 0, 1 i 2, 3.

    const m=100;

    var A : array[1..m] of integer;

    s,n : integer;

    procedure dane;{wczytanie wartoci A}

    var i:integer;

    begin

    for i:=1 to m do

    read(A[i]);

    end;

    procedure szukaj(var j:integer;x:integer);

    {szukanie w tablicy A wartosci x od miejsca j}

    begin

    while (j

  • begin {program glowny}

    dane; {wywolanie procedury wczytujacej dane}

    write(kombinacja(0,1)); {wypisanie wynikw}

    write(kombinacja(2,3))

    end.

    W ten sposb pierwszy program zosta podzielony na mniejsze moduy, ktre

    wykonuj jasno okrelone podzadania. A sam program gwny zosta zre-

    dukowany do 'spisu treci'.

    Parametry i zmienne zwizane z procedurami

    Poniewa procedury mog zalee od parametrw rnego rodzaju i

    mona w nich deklarowa dodatkowe zmienne ktre istniej tylko w czasie

    wykonywania tej procedury, w poniszych tabelach zestawiamy i opisujemy

    te nowo napotkane 'twory'.

    Zmienne w procedurach

    Globalne Lokalne

    (zmienne uywane (zmienne zadeklarowane

    w procedurze ale w procedurze i istniejce

    nie zadeklarowane w tej tylko podczas dziaania

    procedurze i nie bdce tej procedury)

    parametrami formalnymi)

    Zmienne:

    Zmienne globalne s zadeklarowane w nagwku programu i istniej wczasie caego dziaania programu.

    Zmienne lokalne s deklarowane po nagwku procedury (i sowie var)i istniej tylko w czasie dziaania tej procedury.

    W ciele procedury dostpne s zarwno zmienne lokalne zadeklarowanew tej procedurze jaki i zmienne globalne. Wyjtek od tej reguy stanowi

    sytuacja, w ktrej zmienna globalna ma ten sam identykator co zmi-

    enna lokalna. Wtedy zmienna globalna nie jest dostpna w tej proce-

    durze

    2

    .

    2

    Takie zjawisko nazywa si zasanianiem zmiennych

    32

  • Parametry procedur

    Formalne Aktualne

    (wyliczone w nagwku (wyliczone przy kadym

    procedury i uywane woaniu procedury)

    w ciele procedury)

    woane przez warto wyraenia typw

    odpowiadajcych parametrom

    formalnym

    woane przez zmienn zmienne typw

    odpowiadajcych parametrom

    formalnym

    Parametry:

    Parametry formalne procedury to zmienne zadeklarowane w nagwkuprocedury ( w nawiasie, po identykatorze procedury).

    Parametry aktualne procedury to zmienne lub wyraenia, ktre sparametrami przy woaniach procedury.

    Parametry formalne woane przez warto zachowuj si w ciele pro-cedury jak zmienne lokalne z ta rnic, e s inicjalizowane przed

    rozpoczciem wykonywania procedury przez wartoci parametrw ak-

    tualnych.

    Parametry formalne woane przez zmienn (w nagwku procedury ichdeklaracj poprzedza sowo var) zachowuj si w procedurze podobnie

    do zmiennych globalnych. Dokadniej, parametr aktualny odpowiada-

    jcy parametrowi formalnemu woanemu przez zmienn musi by zmi-

    enn i wszystkie operacje dotyczce tego parametru formalnego w cza-

    sie wykonywania procedury s wykonywane na odpowiadajcym mu

    parametrze aktualnym.

    Uwaga. Z powyszego opisu wynika, e warto parametru aktualnego

    woanemu przez zmienn moe by aktualizowana w czasie dziaania pro-

    cedury. Moemy zatem, przy pomocy zmiennych woanych przez warto

    33

  • przekazywa szereg wartoci dowolnych typw obliczone w czasie dziaania

    procedury.

    Przykad.

    var t:array[1..100] of integer;

    a,b:integer;

    procedure cos (var x:integer;y:integer);

    var b,t:integer;

    begin

    x:=x+1; y:=y+1; a:=a+1; b:=y+1; t:=a+1;

    end;

    begin

    a:=20; b:=10;

    cos(a,b)

    writeln(a); writeln(b);

    end.

    W procedurze cos, x jest parametrem formalnym woanym przez zmienn,y jest parametrem formalnym woanym przez warto, b i t s zmiennymilokalnymi a zmienna a jest globalna. Zmienne globalne: tablicowa t icakowita b s niedostpne w procedurze cos, poniewa s zasonite przezzmienne lokalne o tym samym identykatorze i typie cakowitym. W in-

    strukcji woania procedury cos(a,b), a i b s parametrami aktualnymi. Wwyniku wykonania programu na ekranie zostan wypisane liczby:

    22

    10

    3.9 Procedury rekurencyjne

    Procedury rekurencyjne to takie, ktre woaj same siebie.

    Jedn z najprostszych funkcji, ktr wygodnie jest deniowa rekuren-

    cyjnie jest funkcja silnia. Mona j zdeniowa tak:

    n! =

    {1 gdy n = 0n (n 1)! gdy n > 0

    T matematyczn denicje mona atwo przetumaczy na funkcj w jzyku

    Pascal:

    34

  • function silnia(n:integer):integer;

    begin

    if n=0 then silnia:=1

    else silnia:=n*silnia(n-1)

    end;

    Do administrowania obliczeniami programu uywajcego procedur uywamy

    stosu odwoa. Stos

    3

    jest jedn z najprostszych dynamicznych struktury

    danych. Na stosie mona dokonywa trzech operacji:

    1. woy element na wierzch stosu;

    2. zdj element z wierzchu stosu;

    3. sprawdzi czy stos jest pusty.

    Stos liter mona sobie wyobraa tak:

    A

    B

    A

    C

    Wane jest, e liczba elementw na stosie jest w zasadzie nieograniczona, jego

    wielko moe si zmienia dynamicznie w trakcie wykonywania programu w

    zalenoci od biecych potrzeb.

    Sprbujmy teraz przeanalizowa jak jest wykonywana instrukcja

    silnia(5) umieszczona w pewnym miejscu programu gwnego, ktre oz-

    naczymy przez . By obliczy warto silnia(5)musimy przerwa wykony-wanie kolejnych instrukcji programu, wykona procedur silnia z parametrem

    o wartoci 5 a nastpnie powrci do wykonywania programu w miejscu wktrym je przerwalimy. By umoliwi taki powrt wkadamy na stos adres

    miejsca powrotu i aktualne wartoci zmiennych. Teraz stos wyglda tak:1

    , wart. zm.3

    Stos na przykad ksiek ma to do siebie, e mona wkada ksiki na wierzch i z

    wierzchu je zdejmowa, nie mona natomiast wyjmowa ich ze rodka, bez naruszania

    caej konstrukcji.

    35

  • Rozpoczynajc wykonywanie ciaa funkcji silnia zmienna n ma warto 5.Zatem n 6= 0 i pozostaje do wykonania instrukcja silnia:=n*silnia(n-1)przy wartoci zmiennej n rwnej 5. W tym celu naley obliczy wartowyraenia n*silnia(n-1). Warto n znamy ale by obliczy wartosilnia(n-1) musimy ponownie wywoa procedur silnia tym razem od

    parametru aktualnego n 1 = 5 1 = 4. Przed wywoaniem silnia(n-1)trzeba zapamita gdzie mamy wrci z tego woania i jakie wartoci maj

    mie wtedy zmienne. Oznaczmy miejsce silnia(n-1) w ciele procedury

    silnia jako . Zatem w tym przypadku musimy zapamita adres miejscapowrotu i warto zmiennej n rwn 5. Te dane wkadamy na stos, ktrywyglda teraz tak:

    , wart. zm., n = 5

    Majc tak zabezpieczony powrt rozpoczynamy obliczanie procedury silnia

    z wartoci pocztkow parametru n rwn 4. Poniewa 4 6= 0, znowumusimy wywoa procedur silnia, ale tym razem od parametru aktualnego

    n = 4 1 = 3. Przed wywoaniem silnia(n-1) znw trzeba zapamitagdzie mamy wrci z tego woania i jakie wartoci maj mie wtedy zmienne.

    Zatem wkadamy na stos adres miejsca powrotu i warto zmiennej n. Terazstos wyglda tak:

    , wart. zm., n = 5, n = 4

    ... i rozpoczynamy obliczanie silnia(3). W ten sposb dojdziemy w kocu

    do sytuacji w ktrej stos wyglda tak:

    36

  • , wart. zm., n = 5, n = 4, n = 3, n = 2, n = 1

    ... i rozpoczynamy obliczanie silnia(0). W tym przypadku warto funkcji

    silnia jest obliczana bezporednio w ciele procedury bez potrzeby dalszych

    odwoa. Po skoczeniu obliczenia silnia(0), na wierzchu stosu znajduje

    si informacja 'co dalej'. Zdejmujemy zatem z wierzchu stosu dane i n = 1,tak, e stos wyglda teraz tak:

    , wart. zm., n = 5, n = 4, n = 3, n = 2

    i kontynuujemy obliczenie w miejscu z wartoci n = 1, tzn. kontynuu-jemy obliczanie wartoci funkcji silnia z wartoci n = 1 i obliczan waniewartoci silnia(0) rwn 1. Teraz wyliczamy, e silnia(1) ma warto1 i koczymy wykonywanie tego woania funkcji silnia i ponownie wracamydo obliczania w miejscu i z wartoci zmiennych, ktre s zapamitane teraz

    na wierzchu stosu. Zdejmujemy zatem z wierzchu stosu dane i n = 2i kontynuujemy obliczenie funkcji silnia a do momentu gdy zakoczymy

    obliczanie wartoci silnia(5) rwnej 120. W tym momencie stos wygldatak:

    , wart. zm.

    Oprniamy teraz stos, wracamy do miejsca i wartoci zmiennych z przedwoania silnia(5) oraz wartoci silnia(5) rwn 120 i kontynuujemywykonywanie programu.

    Moemy drzewo odwoa dla woania silnia(5) przedstawia tak:

    37

  • silnia(5)

    silnia(4)

    silnia(3)

    silnia(2)

    silnia(1)

    silnia(0)

    tzn. silnia(5) woa silnia(4) a do silnia(0), a ta ostatnia jest wylicza-

    nia bez adnych dodatkowych woa.

    Za rekurencja. Rekurencyjne procedury s zwykle bardziej czytelne

    i atwiejsze do zaprogramowania jednak, poniewa ich implementacja uywa

    stosu, zwykle uywaj wikszej pamici i s nieco wolniejsze od procedur

    nierekurencyjnych, o ile takie istniej. Na przykad funkcj silnia mona

    obliczy iteracyjnie:

    function silnia1(n:integer):integer;

    var s,i:integer;

    begin

    s:=1;

    for i:= 1 to n do

    s:=s*i;

    silnia1:=s

    end;

    Tak zapisana funkcja jest nieco mniej czytelna ale obliczania przy jej uy-

    ciu bdzie nieco efektywniejsze. Natomiast w przypadku obliczania cigu

    Fibbonacciego zdeniowanego nastpujco:

    fn =

    0 gdy n = 01 gdy n = 1fn2 + fn1 gdy n > 1

    rnica szybko robi si o wiele istotniejsza. Jeli zapiszemy t funkcj

    rekurencyjnie:

    procedure Fibb(n:integer);

    begin

    if n=0 then Fibb:=0

    38

  • else if n=1 then Fibb:=1

    else Fibb:=Fibb(n-2)+Fibb(n-1)

    end;

    to wyglda ona elegancko ale jest bardzo nieefektywna, gdy wiele wartoci

    bdzie wyliczaa wielokrotnie. Drzewo odwoa dla woania Fibb(5) bdzie

    wygldao tak:

    Fibb(5)

    XXXXXXFibb(3) Fibb(4)

    @

    @ @

    @Fibb(1) Fibb(2) Fibb(2) Fibb(3)

    @

    @ @

    @ @

    @Fibb(0) Fibb(1) Fibb(0) Fibb(1) Fibb(1) Fibb(2)

    C

    CFibb(0) Fibb(1)

    A zatem Fibb(3) bdzie wywoany dwa razy Fibb(2) i Fibb(0) bdzie

    wywoany trzy razy, a Fibb(1) bdzie wywoany pi razy! Taka proce-

    dura nie tylko pochania wicej pamici ale i wielokrotnie wicej czasu od

    procedury iteracyjnej:

    procedure Fibb1(n:integer):integer;

    var x,y,i:integer;

    begin

    if n

  • 3.10 Poprawno programw

    Jak si przekona, e napisany przez nas program jest poprawny, tzn. dla

    poprawnych danych wejciowych daje poprawne wyniki? Testowanie jest

    pewn wskazwk ale trudno przetestowa program dla wszystkich danych

    wejciowych. Potrzebny jest dowd poprawnoci.

    Mwimy, e program jest poprawny jeli daje poprawne wyniki dla wszys-

    tkich moliwych danych wejciowych. Dowody poprawnoci zwykle skadaj

    si z dwch czci: dowodu czciowej poprawnoci i wasnoci stopu.

    Warunek pocztkowy okrela wasnoci jakie musz spenia poprawnedane wejciowe.

    Warunek kocowy okrela wasnoci jakie musz spenia poprawnedane wyjciowe, wyniki.

    Program, lub fragment programu S jest czciowo poprawny ze wzglduna warunek pocztkowy p i warunek kocowy q jeli o ile dane wejciowespeniaj warunek p i program si zatrzyma to dane wyjciowe speni-aj warunek q. Notacja: p{S}q.

    Program, lub fragment programu S jest poprawny ze wzgldu nawarunek pocztkowy p i warunek kocowy q jeli o ile dane wejciowespeniaj warunek p to program si zatrzyma i dane wyjciowe speni-aj warunek q.

    Przykad 1.

    Pokaemy, e fragment programu S1

    silnia:=1;

    k:=1;

    while k 0) i warunekkocowy q = (silnia = n!).Zauwamy, e jeli p jest speniony przed rozpoczciem wykonywania S1to r = (silnia = k!)(k n) jest speniony po wykonaniu pierwszych dwchinstrukcji z S1.Pokaemy, e formua r jest niezmiennikiem ptli while. Oznaczmy przez

    S par instrukcji k:=k+1;silnia:=silnia*k.

    40

  • Zamy, e warunki r i (k < n) s speniane. Oznaczmy przez silnia0oraz k0 wartoci zmiennych silnia i k przed wykonaniem S a przez silnia1 ik1 wartoci tych zmiennych po wykonaniu S. Pierwsza instrukcja zwikszawarto k o jeden, a std k1 = k0 + 1. Poniewa k0 < n to k1 = k0 + 1 n.Druga instrukcja mnoy warto zmiennej silnia przez (now) warto k.Zatem

    silnia1 = silnia0 k1 = k0! (k0 + 1) = (k0 + 1)! = k1!

    Czyli pokazalimy, e

    r (k < n){S}ri z reguy (8) otrzymujemy, e

    r{while k < n do S}(k n) r

    Zatem po wyjciu z ptli while (o ile to nastpi) mamy, e k = nsilnia = k!.Std q. Pokazalimy, e p{S1}q, tzn. e S1 jest czciowo poprawny zewzgldu na warunek pocztkowy p i warunek kocowy q.Ponadto ptla while zatrzyma si po n1 przejciach z wartoci k = n,gdy przed wejciem do ptli k = 1 oraz kade wykonanie ptli zwikszawarto zmiennej k o jeden. Zatem S1 jest poprawny ze wzgldu na warunekpocztkowy p i warunek kocowy q.

    Przykad 2. Pokaemy, e fragment programu S2

    z:=x; y:=1; m:=n;

    while m>0 do begin

    if (m mod 2) = 1 then y:=z*y;

    m:=m div 2;

    z:=z*z

    end

    jest poprawny ze wzgldu na warunek pocztkowy p = (n > 0) i warunekkocowy q = (y = xn).Niezmiennikiem ptli jest formua Q = (xn = y zm m 0). Jelioznaczymy przez z1, y1, m1, wartoci zmiennych z, y, m przed wykonaniemjednego obrotu ptli a przez z2, y2, m2, wartoci tych zmiennych po wyko-naniu jednego obrotu ptli to mamy:

    jeli m1 = 2 k to y2 = y1 oraz

    xn = y1 z1m1 = y1 (z1 z1)k = y2 z2m2 ;

    41

  • jeli m1 = 2 k + 1 to y2 = y1 z1 oraz

    xn = y1 z1m1 = (y1 z1) (z1 z1)k = y2 z2m2 .

    Oczywicie, przed wejciem do ptli niezmiennik jest speniony. Po wyjciu

    z ptli m = 0 i wtedy xn = y zm = y 1 = y. Std p{S2}q.Poniewa kady obrt ptli zmniejsza warto dodatni m o co najmniej

    1, ptla bdzie wykonana co najwyej n razy. Zatem S2 si zatrzyma dladowolnego n > 0.

    42

  • 4 Podstawowe metody programowania (5)

    4.1 Metoda powrotw (prb i bdw)

    Problem ustawienia n hetmanw.

    Dane: liczba naturalna n. Wynik: ustawienie n hetmanw na szachownicy n n tak by adnedwa hetmany si nie szachoway.

    Zastanwmy si jak taki problem mona rozwiza w miar efektywnie

    dla n = 8.

    Pomys 1 Przejrze wszystkie ustawienia hetmanw na szachownicy i

    sprawdza czy s poprawnie ustawione.

    Ustawie jest

    (648

    ) 4 109. To jest za duo!

    Pomys 2 Pomys pierwszy mona atwo poprawi ograniczajc nieco

    przestrze ktr mamy przeszukiwa. W kadym wierszu moe sta tylko

    jeden hetman. Wektor (i1, . . . , i8) dla 1 i1, . . . , i8 8 reprezentuje ustaw-ienie hetmanw na polach o wsprzdnych ((1, i1), . . . , (8, i8)). Takich wek-torw jest 88 107. Duo!

    program1

    for i1:=1 to 8 do

    for i2:=1 to 8 do

    ......

    for i8:=1 to 8 do

    sprawdz czy (i1,...,i8) reprezentuje poprawne ustawienie

    Pomys 3 Nietrudno zauway, e moemy i t przestrze ograniczy. W

    kadym wierszu i kadej kolumnie moe sta tylko jeden hetman. Wystarczy

    zatem przejrze wektory (i1, . . . , i8) bdce permutacjami zbioru {1, . . . , 8}.Permutacji jest 8! = 104. Sporo!

    program2

    proba:=pierwsza permutacja;

    while proba nie jest ostatni permutacj

    oraz nie jest rozwizaniem do

    proba:=nastpna_permutacja(proba);

    43

  • Pomys 4 (Metoda powrotw) Rozszerzamy czciowe poprawne

    rozwizanie a do uzyskania penego poprawnego rozwizania. Jeli si nie

    da rozszerzy czciowego rozwizania to wracamy i poprawiamy czciowe

    rozwizanie w pierwszym moliwym miejscu.

    Przykad n = 8.

    H

    H

    H

    H

    H *

    Na tej szachownicy hetmany zostay ustawione w kolejnych wierszach w

    pierwsze pole od lewej strony ktre nie jest szachowane przez poprzednio

    ustawione hetmany. W szstym wierszu wszystkie pola s szachowane, za-

    tem musimy pitym wierszu przestawi hetmana na nastpne nieszachowane

    pole w tym wierszu (sme zaznaczone ) i prbowa dalej...Szkic procedury realizujcej taki algorytm. (Konkretne algorytmy z

    powrotami, w tym ten rozwizujcy nasz problem, s 'ukonkretnieniem' tego

    schematy.)

    procedure probuj;

    begin

    zapocztkuj wybieranie kandydatw;

    repeat

    wybierz nastpnego kandydata;

    if kandydat jest dopuszczalny then begin

    dopisz kandydata do czciowego rozwizania;

    if rozwiazanie niepene then begin

    probuj wykona nastepny krok (rekursja);

    if proba nieudana then

    usun kandydata z czciowego rozwiazania

    end;

    end;

    until (prba udana) lub (nie ma wicej kandydatw)

    end;

    44

  • eby napisa szczegowo procedur musimy najpierw zastanowi si nad

    reprezentacj danych odpowiedni do naszych potrzeb. Powinnimy mie

    tablic het n liczb cakowitych reprezentujc obecnie rozwaane czciowerozwizanie, tzn

    het[i] = 0 gdy w i-tym wierszu nie ma hetmana,

    het[i] = j > 0 gdy i-tym wierszu na j-tym miejscu stoi hetman.

    Ponadto musimy pamita, ktre kolumny i lewe i prawe 'skosy',na ktrych ju stoi hetman. Bdziemy te informacje pamita w tablicach

    boolowskich kol, lewy, prawy, tak, e

    kol[i] =

    {true i-ta kolumna jest wolnafalse w i-tej kolumnie stoi hetman

    lewy[i] =

    {true gdy skos o sumie wsprzednych i jest wolnyfalse gdy na skosie o sumie wsprzednych i stoi hetman

    prawy[i] =

    {true gdy skos o rnicy wsprzednych i jest wolnyfalse gdy na skosie o rnicy wsprzednych i stoi hetman

    Oprcz tablic potrzebujemy jeszcze zmiennej OK ktra bdzie pamitaa czy

    ju znalelimy rozwizanie czy nie, tzn.

    OK =

    {true gdy znalelimy ju rozwiazaniefalse w przeciwnym przypadku.

    Zatem deklaracja istotnych zmiennych powinna wyglda tak:

    const n=8;

    var het : array[1..n] of integer;

    kol : array[1..n] of boolean;

    lewy : array[2..2*n] of boolean;

    prawy : array[1-n..n-1 of boolean;

    OK : boolean;

    procedury tak:

    procedure probuj(i:integer; var q : boolean);

    var k:integer;

    begin

    k:=0; {k - kolejna prbowana pozycja}

    45

  • repeat

    k:=k+1;

    if kol[k] and lewy[k+i] and prawy[k-i] then begin

    het[i]:=k; kol[k]:=false;

    lewy[k+i]:=false; prawy[k-i]:=false;

    if i

  • lewy[k+i]:=false; prawy[k-i]:=false;

    if i

  • 4.2 Metoda 'dziel i rzd'

    Metoda 'dziel i rzd' polega na rozwizaniu wikszego problemu poprzez

    podzielenie go na mniejsze podprogowy dla ktrych znajdujemy rozwizanie

    a nastpnie za ich pomoc znajdujemy rozwizanie caego problemu. Metod

    t zilustrujemy prezentujc algorytm sortowania przez scalanie.

    Problem sortowania.

    Dane wejciowe: liczba naturalna n i cig liczb a1, a2, . . . , an. Wynik: permutacja a1, a2, . . . , an cigu a1, a2, . . . , an taka, e a1 a2 . . . an.

    Zanim zaprezentujemy algorytm sortowania przez scalanie najpierw

    rozwamy problem scalania dwch cigw:

    Problem scalania.

    Dane wejciowe: dwa cig liczb a1, a2, . . . , an, b1, b2, . . . , bm. Wynik: permutacja c1, c2, . . . , cn+m cigu a1, a2, . . . , an, b1, b2, . . . , bmtaka, e c1 c2 . . . cn+m.

    Procedur scalania mona opisa tak.

    1. porwnujemy najmniejsze elementy dwch cigw, mniejszy z nich

    wpisujemy do cigu wynikowego i usuwamy z cigu scalanego,

    2. powtarzamy 1. a jeden z cigw scalanych bdzie pusty,

    3. dopisujemy pozostae elementy na koniec cigu wynikowego.

    Na przykad dla cigw scalanych

    a1, a2, . . . , an, b1, b2, . . . , bm

    jeli mamy

    a1 b1 a2 6 b1 a2 6 b2 a2 b3 . . .to wynikowy cig scalony wyglda tak:

    a1, b1, b2, a2 . . .

    Zauwamy, e scalanie wymaga co najwyej n+m 1 porwna.Teraz, przy denicji typu tablica=array[1..n] of integer, moemy

    tak napisa procedur sortujc przez scalanie.

    48

  • procedure sortowanie(var A:tablica;min,max:integer);

    var m:integer;

    begin

    if min

  • wykonywaniu procedury sortowanie dla tablicy o rozmiarze n. (Dla up-roszczenia zakadamy, e n = 2k.)

    T (n) =

    {0 gdy n = 12 T (n/2) + (n 1) gdy n > 1

    Notacja O(f(n)), (f(n)) i (f(n)) . Niech f : N N funkcja. Przy-pomnijmy, e funkcja g : N N jest (klasy) O(f(n)) jeli istniej stalea, b R takie, e dla n > a, g(n) b f(n). Jeli funkcja 'g(n) O(f(n))'mwimy czsto, e g(n) jest O(f(n)) i piszemy: g(n) = O(f(n)).Mwimy, e funkcja g : N N jest (klasy) (f(n)) jeli istniej stale

    a, b R takie, e dla n > a, b f(n) g(n). Podobnie jeli funkcja 'g(n) (f(n))' mwimy czsto, e g(n) jest (f(n)) i piszemy: g(n) = (f(n)).Mwimy, e funkcja g : N N jest (klasy) (f(n)) jeli g jest klasy

    O(f(n)) i (f(n)).

    Mamy

    Fakt 4.1 Niech a, b, c bd liczbami rzeczywistymi dodatnimi. Rozwizaniemrwnania rekurencyjnego

    T (n) =

    {b gdy n = 1a T (n/c) + b n gdy n > 1

    dla n postaci ck, (gdzie k N) jest funkcja

    T (n) =

    O(n) gdy a < cO(n lnn) gdy a = cO(nlogc a) gdy a > c

    Zauwamy, e jeli zinterpretujemy liczby a, b, c jako

    1.

    1c - rozmiar jednego podproblemu;

    2. a - liczba podproblemw;

    3. b n - czas budowania rozwizania problemu rozmiaru n z rozwizapodproblemw;

    to powyszy Fakt mona uy do obliczania zoonoci wielu algorytmw

    zbudowanych metod 'dziel i rzd', take algorytmu sortowania przez

    scalanie. W tym przypadku a = b = c = 2 a zatem T (n) = O(n ln(n)).Pniej pokaemy te, e T (n) = (n ln(n)).

    50

  • Dowd Faktu 4.1:

    Niech r = ac , n = cm. Wtedy

    T (n) = n b mi=0

    ri gdzie (m = logc n). (10)

    Rwno (10) udowodnimy przez indukcj po m.Dla m = 0, mamy n = c0 = 1 oraz

    T (n) = T (1) = b = n b 0i=0

    ri.

    Czyli (10) zachodzi dla m = 0.Zamy teraz, e (10) zachodzi dla n = cm. Wtedy uywajc denicjirekurencyjnej T i zaoenia indukcyjnego mamy

    T (cm+1)def T= a T (cm) + b cm+1 ind.=

    = a n b mi=0

    ri + b cm+1 =

    =a

    c cm+1 b

    mi=0

    ri + b cm+1 =

    = b cm+1(acmi=0

    ri + 1) =

    = b cm+1(m+1i=1

    ri + r0) =

    = b cm+1 m+1i=0

    ri

    Zamy, e a < c. Wtedy szereg

    i=0 rijest zbieny i jego suma jest

    rwna

    11r . Zatem

    T (n) = n b mi=0

    ri 11 ac

    b n = O(n).

    Jeeli a = c to ri = 1 dla dowolnego i N . Wtedy dla n = cm, mamymr=0 r

    i = logc n oraz

    T (n) = b n logc n = O(n lnn).

    51

  • Niech a > c. Mamy m = logc n oraz

    T (n) = n b logc ni=0

    ri = b n r1+logc n 1r 1 =

    =b

    r 1 (n (a

    c)1+logc n n) =

    =b

    r 1 (n (a1+logc n

    c n ) n) =

    =a b

    c (r 1) (alogc n c n

    a) =

    = const (nlogc a c na

    ) = O(nlogc a)

    gdzie const jest sta a przedostatnia rwno wynika z rwnoci alogc n =nlogc a. Poniewa a > c to logc a > 1.Q.E.D.

    4.3 Sortowanie przy pomocy porwna

    W poprzednim podrozdziale pokazalimy, e mona skonstruowa algorytm,

    ktry sortuje tablic n liczb w czasie O(n lnn), poprzez wskazanie konkret-nego algorytmu ktry ma te wasno ('sortowanie przez scalanie'). Czy

    mona zrobi to szybciej? Odpowied moe zalee od rnych szczegw.

    Na przykad, jeeli zaoymy, e w tablicy sortowanej jest stosunkowo

    niewiele rnych wartoci np. co najwyej 2 lub 3 lub 4 to mona posor-towa taka tablic w czasie O(n). Z drugiej strony jeli chcemy pokaza, enie ma adnego algorytmy, ktry sortuje w czasie mniejszym ni O(n lnn),to musimy dowie wicej (ni tylko wskaza algorytm i pokaza, e ma -

    dane wasnoci), musimy pokaza e 'kady algorytm robi 'co innego' (albo

    nie sortuje albo nie tak szybko jak bymy chcieli). By pokaza, e nie ma

    programu sortujcego szybciej ni O(n lnn) zaoymy, e sortowanie odbywasi metod porwna, tzn. porwnujemy elementy tablicy midzy sob i w

    zalenoci od wyniku porwnania co przestawiamy lub nie.

    Do abstrakcyjnej analizy algorytmw sortujcych przy pomocy porw-

    na uyjemy drzewa decyzyjnego. Wierzchoki wewntrzne drzewa s etyki-

    etowane decyzjami do podjcia. Podczas obliczenia, w zalenoci od ich

    wyniku przesuwamy si w lewo lub prawo. Licie drzewa s etykietowane

    poprawnymi rozwizaniami. Drzewo decyzyjne dla sortowania trzech ele-

    mentw a1, a2, a3 moe wyglda tak:

    52

  • a1 < a2

    XXXXXXT N

    a2 < a3 a3 < a2

    @

    @ @

    @a1 < a2 < a3 a1 < a3 a3 < a2 < a1 a1 < a3

    @

    @ @

    @a1 < a3 < a2 a3 < a1 < a2 a2 < a1 < a3 a2 < a1 < a3

    NT

    NT

    NT

    NT

    Jedno obliczenie w takim drzewie odpowiada jednej gazi drzewa. W li-

    ciach drzewa znajduj si wszystkie moliwe odpowiedzi, tzn. permutacje

    zbioru {a1, a2, a3} (kada co najmniej raz). Zatem wysoko drzewa - topesymistyczna zoono algorytmu. Mamy

    Lemat 4.2 Drzewo decyzyjne dla dowolnego algorytmu sortujcego n ele-mentw przy pomocy porwna ma wysoko (n lnn).

    Dowd: Niech H(n) bdzie wysokoci drzewa decyzyjnego dla pewnegoalgorytmu sortujcego przy pomocy porwna. Takie drzewo ma co najmniej

    n! lici. Poniewa pene drzewo binarne o wysokoci h ma 2h lici to dowolnedrzewo o wysokoci h ma co najwyej 2h lici. Std

    n! 2H(n)

    i

    log2(n!) H(n).Poniewa n! (n3 )n to

    H(n) log2(n!) log2(n

    3)n = n log2 n n log 3 = (n lnn).

    Q.E.D.

    Wniosek 4.3 Kady algorytm sortujcy tablic n elementw przy pomocyporwna ma pesymistyczn zoono czasow (n lnn).

    53

  • 4.4 Programowanie dynamiczne

    Programowanie dynamiczne (Pd) stosuje si do problemw optymaliza-

    cyjnych, w ktrych musimy dokonywa serii wyborw w celu znalezienia op-

    tymalnego rozwizania. Dokonujc wyborw, czsto musimy si wielokrotnie

    odwoywa do rozwizania tego samego podproblemu. Jeli wszystkich pod-

    problemw nie jest 'zbyt duo' to Pd jest metod efektywn. Algorytm Pd

    rozwizuje problem tylko raz i zapamituje do ponownego wykorzystania.

    Konstrukcja algorytmu:

    1. Charakteryzacja struktury optymalnego rozwizania.

    2. Rekurencyjna denicja optymalnego rozwizania.

    3. Obliczenie kosztu i sposobu konstrukcji optymalnego rozwizania

    metod 'od dou do gry' (bottom-up).

    4. Konstrukcja optymalnego rozwizania przy uyciu informacji oblic-

    zonej w punkcie 3.

    Niech ~x =< x1, . . . , xm >, ~y =< y1, . . . , yn > i ~z =< z1, . . . , zk > bdcigami. Wtedy

    1. ~z jest podcigiem cigu ~x, jeeli istnieje rosncy cig liczb naturalnych< i1, . . . , ik > taki, e zj = xij dla j = 1, . . . , k.

    2. ~z jest wsplnym podcigiem cigw ~x i ~y jeli jest podcigiem ~x i ~y.

    3. NWP (~x, ~y) oznacza zbir najduszych wsplnych podcigw cigw~x i ~y.

    Przykad.

    ~x =< A,B,C,B,D,A,B >, ~y =< B,B,D,C,B,A,A >

    ~z =< B,D,A >, ~z =< D,C > .

    Wtedy ~z jest podcigiem ~x i ~y a ~z jest podcigiem ~x ale nie ~y.

    Problem znajdowania najduszego wsplnego podcigu.

    Dane wejciowe: dwa cigi ~x i ~y. Wynik: ~z NWP (~x, ~y).

    54

  • Charakteryzacja najduszego wsplnego podcigu.

    Cig dugoci n ma 2n podcigw. Zatem sprawdzenie wszystkich pod-cigw jest kosztowne. Ale problem NWP ma wasno optymalnej pod-struktury.

    Niech ~x =< x1, . . . , xm > bdzie cigiem, i n. i-tym preksem cigu~x nazywamy cig ~xi =< x1, . . . , xi >.Przykad.

    ~x =< A,B,C,B,D,A,B >, ~x4 =< A,B,C,B >, ~x0 = Mamy

    Fakt 4.4 Niech ~x =< x1, . . . , xm > i ~y =< y1, . . . , yn > bd cigami oraz~z =< z1, . . . , zk > NWP (~x, ~y) . Wtedy1. Jeeli xm = yn to zk = xm = yn oraz ~zk1 NWP (~xm1, ~yn1).2. Jeeli xm 6= yn oraz zk 6= xm to ~z NWP (~xm1, ~y).3. Jeeli xm 6= yn oraz zk 6= yn to ~z NWP (~x, ~yn1).Dowd: Ad 1. Zamy, e xm = yn. Jeeli zk 6= xm to cig cigw ~xm1 i ~yn1. Wtedy cig < w1, . . . , wk, xm >jest wsplnym podcigiem ~x i ~y duszym od ~z. I znowu mamy sprzeczno.

    Ad 2. Jeli zk 6= xm to ~z jest podcigiem ~xm1. Jeli by istnia duszypodcig ~xm1 i ~y to byby on te podcigiem ~x i ~y. A to jest sprzeczne zzaoeniem.

    Ad 3. Ten przypadek jest podobny do 2.

    Q.E.D.

    Wniosek 4.5 Najduszy wsplny podcig dwch cigw zawiera najdusze

    wsplne podcigi preksw tych cigw.

    Rekurencyjna denicja rozwizania.

    Z podanego faktu wynika, e znalezienie ~z NWP (~x, ~y) sprowadza sido znalezienia

    ~z NWP (~xm1, ~yn1) gdy xm = yn

    55

  • oraz dwch podproblemw znalezienia

    ~z1 NWP (~xm1, ~y), ~z2 NWP (~x, ~yn1) gdy xm 6= ynTen ktry jest duszy naley do NWP (~x, ~y).Niech c(i, j) =dugo najduszego wsplnego podcigu cigw ~xi i ~yj .Wtedy

    c(i, j) =

    0 gdy i = 0 lub j = 0,c(i 1, j 1) + 1 gdy xi = yj ,max(c(i 1, j), c(i, j 1)) gdy xi 6= yj .

    T denicje mona atwo przetumaczy na funkcj rekurencyjnie obliczajc

    c ale zoono jej bdzie wykadnicza.

    Obliczanie kosztu i sposobu konstrukcji optymalnego rozwiza-

    nia.

    Moemy napisa funkcj, ktra oblicza koszt rozwizania optymalnego

    'od dou do gry'. To znaczy liczy dugo najduszego wsplnego podcigu

    preksw cigw ~x i ~y od najkrtszych a do caych cigw ~x i ~y. By po takimobliczeniu mc odtworzy najduszy wsplny podcig, przy okazji liczenia

    c(i, j) dla i, j > 0 musimy zapamita z ktrej klauzuli denicji funkcji ckorzystalimy i jeeli z trzeciej to ktra z wartoci c(i 1, j), c(i, j 1) byawiksza.

    Innymi sowy funkcja ta rozwizuje nastpujcy problem:

    Dane wejciowe: dwa cigi ~x i ~y. Wynik: dwie tablice; c jak wyej i b tak, e b(i, j) ='wskazwka' jakoblicza optymalne rozwizanie dla ~xi i ~yj .

    Tablice b i c (zwaszcza b) bd nam pomocne do znalezienia rozwizania.

    procedure dlugosc_NWP(x,y);

    begin

    m:=dlugosc(x);

    n:=dlugosc(y);

    for i:=1 to m do c[i,0]:=0;

    for i:=1 to n do c[0,i]:=0;

    for i:=1 to m do

    for j:=1 to n do

    if x[i]=y[j] then begin

    56

  • c[i,j]:=c[i-1,j-1]+1; {skracamy oba ciagi}

    b[i,j]:='xy'

    end else

    if c[i-1,j]>=c[i,j-1] then begin

    c[i,j]:=c[i-1,j]; {skracamy x}

    b[i,j]:='x'

    end else begin

    c[i,j]:=c[i,j-1]; {skracamy y}

    b[i,j]:='y'

    end;

    end;

    end;

    Przykad. Ponisza tablica opisuje wartoci tablic b i c obliczone dla cigw~x =< A,B,C,B,D,A,B > i ~y =< B,D,C,A,B,A > (m = 7, n = 6).

    j 0 1 2 3 4 5 6i ~y B D C A B A0 ~x 0 0 0 0 0 0 01 A 0 x, 0 x, 0 x, 0 xy, 1 y, 1 xy, 12 B 0 xy, 1 y, 1 y, 1 x, 1 xy, 2 y, 23 C 0 x, 1 x, 1 xy, 2 y, 2 x, 2 x, 24 B 0 xy, 1 x, 1 y, 2 y, 2 xy, 3 y, 35 D 0 x, 1 xy, 2 x, 2 x, 2 x, 3 x, 36 A 0 x, 1 x, 2 x, 2 xy, 3 x, 3 xy, 47 B 0 xy, 1 x, 2 x, 2 x, 3 xy, 4 x, 4

    W prawym dolnym rogu mamy c[7, 6] = 4. Zatem najduszy wsplnypodcig ~x i ~y ma dugo 4. Z tego rogu podrujc w gr gdy b[i, j] = x, wlewo gdy b[i, j] = y, oraz po skosie b[i, j] = xy, zbieramy kolejne elementynajduszego wsplnego podcigu ~x i ~y. W ten sposb znajdujemy, e NWP (~x, ~y).Konstrukcja optymalnego rozwizania.

    Majc tablic b moemy teraz wypisa cig ~z NWP (~x, ~y).procedure drukuj_NWP(i,j);

    begin

    if (i0) and (j0) then begin

    if b[i,j]='xy' then begin

    drukuj_NWP(i-1,j-1);

    57

  • write(x[i])

    end else

    if b[i,j]='x' then drukuj_NWP(i-1,j)

    else drukuj_NWP(i,j-1);

    end;

    end;

    Teraz instrukcja drukuj_NWP(dlugosc(x),dlugosc(y)) drukuje ~z NWP (~x, ~y).

    58

  • 4.5 Algorytmy zachanne

    Typowe algorytmy optymalizacyjne dokonuj szeregu wyborw w celu

    znalezienia optymalnego rozwizania. S jednak liczne problemy przy

    rozwizywaniu ktrych nie trzeba stosowa metody programowania dynam-

    icznego a wystarcz prostsze i bardziej efektywne algorytmy. Algorytmy

    zachanne wybieraj to co w danym momencie wyglda najlepiej w nadziei,

    e doprowadzi to do optymalnego globalnego rozwizania. Metod t zilus-

    trujemy rozwizujc nastpujcy problem.

    Problem wyboru zaj

    Mamy sal wykadow i zbir propozycji na jej wykorzystanie do

    prowadzenia rnych zaj w okrelonych godzinach. Chcemy wybra maksy-

    maln liczb zaj nie kolidujacych ze sob. Formalnie problem ten wyglda

    tak:

    Dane wejciowe: zbir n przedziaw P = {[si, fi) : 1 i n}, taki,e si, fi R si < fi dla i = 1, . . . , n.

    Wynik: podzbir A {1, . . . , n} o maksymalnej liczbie elementwtaki, e dla i, j A, i 6= j mamy [si, fi) [sj , fj) = .

    Opis algorytmu.

    1. Porzdkujemy przedziay wzgldem ich prawych kocw, tak by fi fj dla 1 i < j n.2. Wybieramy po kolei takie zajcia, ktre nie koliduj z ju wybranymi

    i si najwczeniej kocz:

    function wybor_zajec;

    begin

    A:={1};

    j:=1; {j - ostatnio wybrany element}

    for i:=2 to n do

    if s[i]>=f[j] then begin

    A:=A+{i};

    j:=i;

    end;

    zwroc(A);

    end;

    59

  • Fakt 4.6 Powyszy algorytm znajduje optymalne rozwizanie problemu

    zgodnego wyboru zaj.

    Dowd. Niech B {1, . . . , n} bdzie optymalnym rozwizaniem, |B| =k, oraz niechA {1, . . . , n} bdzie zbiorem skonstruowanym przez algorytm.Niech Al bdzie zbiorem pierwszych l elementw z A, B

    lzbiorem powstaym

    z B po usuniciu pierwszych l elementw.Zauwamy, e sposb konstrukcji zbioru A gwarantuje, e rne przedzi-ay o indeksach z A s rozczne.Pokaemy przez indukcj po l = 1, . . . , k, e

    Al jest okrelone i Al Bl jest optymalnym rozwizaniem. (11)Wtedy dla k = lmamyBk = i AkBk A jest optymalnym rozwizaniem,czyli Ak = A.Pozostaje pokaza (11). Dla l = 1 mamy pokaza, e A1 B1 =

    {1}B{min(B)} jest optymalnym rozwizaniem. Poniewa f1 fmin(B)(fi s uporzdkowane niemalejco) to przedzia [s1, f1) jest rozczny zprzedziaami [si, fi) dla i B{min(B)}. Zatem zbir A1B1 = {1}B1ma k elementw i jest optymalnym rozwizaniem.Zamy, e 1 l < k i AlBl jest optymalnym rozwizaniem. Poniewa

    l < k to 6= Bl {j : sj fmax(Al)} 6= .Niech i = min{j : sj fmax(Al)}. Wtedy Al+1 = Al {i}. Z denicji i,si fmax(Al), a to oznacza, e przedzia [si, fi) jest rozczny z przedziaamiw Al. Ponadto z minimalici i, fi fmin(Bl). Zatem [si, fi) jest rozczny zprzedziaami w Bl+1 = Bl {min(Bl)}. A to oznacza, e Al+1 Bl+1 jestoptymalnym rozwizaniem.

    Q.E.D.

    By mona byo stosowa algorytmy zachanne, podane jest by problem

    mia dwie cech:

    1. Wasno zachannego wyboru: globalne optymalne rozwizanie moe

    by otrzymane przez lokalne optymalne (zachanne) wybory.

    2. Optymalna podstruktury: (jak w Pd) optymalne rozwizanie problemu

    zawiera optymalne rozwizanie podproblemw.

    Uwaga. Nie kada moliwa strategia wyboru zachannego dla prob-

    lemu wyboru zaj daje optymalne rozwizanie. Na przykad wybr zaj

    niekolidujcych z ju wybranymi, ktre:

    60

  • 1. trwaj najkrcej,

    2. koliduj z najmniejsz liczb pozostaych zaj

    nie daje optymalnego rozwizania. Ponisze przykady wyjaniaj dlaczego.

    W tym przypadku

    wybierajc najkrtsze zajcia wybierzemy tylko dwa, gdy mona by wybra

    trzy, a w tym

    wybierajc zajcia kolidujce z najmniejsz liczb pozostaych zaj, za-

    czniemy od zaj oznaczonych i w efekcie wybierzemy trzy, gdy mona bywybra cztery.

    Problemy plecakowe.

    Problemy plecakowe dotycz pakowania do plecaka przedmiotw ktre

    maj w sumie najwiksz warto nie przekraczajc jednak dopuszczalnego

    obcienia plecaka. W jednej wersji musimy pakowa cae przedmioty a w

    drugiej moemy pakowa take tylko czci przedmiotw. Mimo, e prob-

    lemy wygldaj podobnie jeden moe by atwo rozwizany przy pomocy

    algorytmu zachannego a drugi nie ma efektywnego rozwizania. Formalnie

    problemy te mona sformuowa tak.

    Problem plecakowy 0-1.

    Dane wejciowe: n przedmiotw, i-ty przedmiot jest wart vi zotych iway wi kilogramw, w jest dopuszczalnym ciarem plecaka.

    Wynik: podzbir A {1, . . . , n} taki, e iAwi w oraz wartoiA vi jest maksymalna.

    Problem plecakowy uamkowy.

    Dane wejciowe: n przedmiotw, i-ty przedmiot jest wart vi zotych iway wi kilogramw, w jest dopuszczalnym ciarem plecaka.

    Wynik: podzbir A {1, . . . , n} oraz liczby ri R dla i A takie, eiA ri wi w oraz warto

    iA ri vi jest maksymalna.

    61

  • Dla problemu 01 nie jest znane istotnie lepsze rozwizanie ni przegl-danie wszystkich moliwych podzbiorw przedmiotw. Natomiast problem

    uamkowy mona rozwiza 'zachannie' w nastpujcy sposb:

    1. Porzdkujemy przedmioty wzgldem malejcej wartoci

    viwi.

    2. Wybieram pierwsze k przedmiotw tak, ek

    i=1wi w 4 102 = 45 103 u

    W szczeglnoci zmiennopozycyjne dziaania mnoenia i dodawania s

    przemienne ale nie s czne!

    78

  • 5.6 Wybrane problemy numeryczne

    W tej sekcji pokaemy kilka typowych problemw zwizanych obliczeniami

    zmiennopozycyjnymi.

    Obliczanie pierwiastkw rwnania kwadratowego

    Rwnanie kwadratowe

    x2 + px+ q = 0

    ma pierwiastki

    x1 =pp2 4q

    2i x1 =

    p+p2 4q2

    o ile wyrnik = p2 4q jest nieujemny. Obliczymy te pierwiastki warytmetyce 4-cyfrowej dla

    p = 6.433 i q = 0.009474.

    Obliczenie x1:

    1. = (6.433)2 = 41.38,

    2. = 4q = 0.03790,

    3. = = 41.34,4. =

    = 6.430,

    5. 1 = p = 6.433 6.430 = 0.003,6. x1 = 12 = 1.5 103.Poniewa przybliona warto pierwiastka x1 w arytmetyce 5-cyfrowejwynosi

    x1 1.4731 103

    to widzimy, e nasze obliczenie x1 dao nam tylko jedn dokadn cyfrznaczc i bd wzgldny wynosi

    x1 101.

    Korzystajc z poprzednich oblicze moemy obliczy x2:

    1. 2 = p+ = 6.433 + 6.430 = 12.86,

    79

  • 2. x2 = 22 = 6.43.

    Poniewa przybliona warto pierwiastka x2 w arytmetyce 5-cyfrowejwynosi

    x2 6.4313to widzimy, e nasze obliczenie x2 dao nam dokadne trzy cyfry znaczce.Przyczyna utraty dokadnoci w obliczeniu x1 tkwi w obliczeniu 1 wkroku 5. Obliczamy rnic liczb o bardzo bliskich wartociach. Natomiast

    problem ten nie istnieje przy obliczaniu 2 w kroku 2. obliczenia x2. Tamliczymy sum tych liczb nie tracc istotnie na dokadnoci.

    Majc dobre przyblienie x2, moemy te obliczy x1 ze wzoru Viete'ax1 x2 = q:

    x1 =(0.0094746.430

    )= 0.001473 = 1.473 103

    i wtedy mamy cztery cyfry dokadne oraz bd wzgldny

    x1 104.

    Mora z tych rozwaa jest taki, e jeeli p > 0 to x1 jest liczone dokad-niej a jeeli p < 0 to x2 jest liczone dokadniej.

    Schemat Hornera obliczania wielomianu

    Normalna procedura obliczenia wartoci wielomianu n-tego stopnia

    Wn(x) = anxn + an1xn1 + . . .+ a1x+ a0,

    sugerowana przez sposb zapisu wielomianu, polega na obliczeniu

    1. x2, x3, . . . , xn - n 1 mnoe,2. a1x, a2x

    2, . . . , anxn- n mnoe,

    3. a0 + a1x+ . . .+ an1xn1 + anxn n -dodawa.

    Zatem takie obliczenie wymaga 2n 1 mnoe i n dodawa.Natomiast istnieje inny sposb obliczania tej samej wartoci, zapro-

    ponowany przez Hornera. Liczymy:

    1. Pn(x) = anx+ an1 - 1 mnoenie i 1 dodawanie,

    2. Pn1(x) = (anx+ an1)x+ an2 - 1 mnoenie i 1 dodawanie,

    80

  • 3. . . .

    4. P1 = P2x+ a0 - 1 mnoenie i 1 dodawanie.

    Zatem takie obliczenie wymaga tylko n mnoe i n dodawa. Oprcz tego,e ta metoda obliczania wartoci wielomianu jest szybsza to jest te dokad-

    niejsza.

    81

  • 6 Dynamiczne struktury danych (4)

    'Zbiory matematyczne' nie zmieniaj si, natomiast 'zbiory informatyczne'

    mog si zwiksza, zmniejsza lub zmienia w inny sposb. S to 'zbiory

    dynamiczne'.

    Sposb w jaki reprezentujemy 'zbiory dynamiczne' zaley od tego jakie

    operacje chcemy na nich wykonywa. Mamy dwa rodzaje operacji: mody-

    kacje i pytania.

    Modykacje (przykady):

    1. dodaj(S,x) - dodaj element (wskazywany przez) x do zbioru S;

    2. usun(S,x) - usu element (wskazywany przez) x ze zbioru S.

    Pytania (przykady):

    1. szukaj(S,k) - sprawd czy element x naley do zbioru S; jeli tak towska ten element, jeli nie to wska Nil;

    2. minimum(S) - (pytanie na zbiorze liniowo uporzdkowanym) zwraca

    element najmniejszy zbioru S;

    3. maksimum(S) - (pytanie na zbiorze liniowo uporzdkowanym) zwraca

    element najwikszy zbioru S;

    4. nastepny(S,x) - (pytanie na zbiorze liniowo uporzdkowanym) zwraca

    element nastpny po x w zbioru S;

    5. poprzedni(S,x) - (pytanie na zbiorze liniowo uporzdkowanym)

    zwraca element poprzedni przed x w zbioru S.

    Zwykle potrzeba tylko czci spord tych operacji. Wane jest by oper-

    acje wykonywane byy szybko, tzn. w czasie staym lub co najwyej loga-

    rytmicznym w stosunku do rozmiaru zbioru S.

    6.1 Podstawowe dynamiczne struktury danych

    Stos

    Stos jest najprostsz struktur dynamiczn (LIFO - last in rst out).

    Mona wkada elementy tylko na wierzch stosu i zdejmowa elementy tylko

    z wierzchu stosu. Poza tym mona testowa czy stos jest pusty. Wszystkie

    operacje s wykonywane w czasie staym. Stos mona sobie wyobraa tak:

    82

  • AB

    C

    D

    Operacje na stosie:

    1. dodaj (na wierzch) Push(S,x);

    2. zdejmij (z wierzchu) Pop(S);

    3. test pustoci stosu

    empty(S) =

    {true gdy S jest pustyfalse w przeciwnym przypadku.

    Jak ju wczeniej pokazalimy, przy pomocy stosw mona implemen-

    towa procedury rekurencyjne. Stos S, jeli ma ograniczon wysoko,mona implementowa w tablicy:

    S : array[1..n] of typ;

    topS : integer;

    function empty :boolean;

    begin

    empty:=(topS=0)

    end;

    procedure push(x:typ);

    begin

    topS:=topS+1;

    S[topS]:=x;

    end;

    procedure pop(var x:typ);

    begin

    x:=S[topS];

    topS:=topS-1;

    end;

    83

  • Kolejka

    Kolejka jest struktur podobn do kolejki w sklepie (FIFO - rst in rst

    out). Mona wkada elementy tylko na koniec kolejki i zdejmowa elementy

    tylko z pocztku kolejki. Poza tym mona testowa czy kolejka jest pusta.

    Wszystkie operacje s wykonywane w czasie staym. Kolejk mona sobie

    wyobraa tak:

    E D C B A

    ?tail(ogon)

    ?head(glowa)

    Operacje na kolejce:

    1. dodaj (na koniec) dodaj(Q,x);

    2. zdejmij (z pocztku) usun(Q);

    3. test pustoci kolejki

    empty(Q) =

    {true gdy S jest pustyfalse w przeciwnym przypadku.

    Kolejk Q, jeli ma ograniczon dugo, mona implementowa w tabl-icy, ale w bardziej skomplikowany sposb ni stos.

    Q : array[0..n] of typ;

    headQ,tailQ : integer;

    * * * * * * * * *

    Q:

    ?tailQ

    ?headQ

    function empty :boolean;

    begin

    empty:=(headQ=tailQ)

    end;

    procedure wstaw(x:typ);

    begin

    Q[tailQ]:=x;

    if tailQ=n then tailQ:=0

    84

  • else tailQ:=tailQ+1;

    end;

    procedure usun(var x:typ);

    begin

    x:=Q[headQ];

    if headQ=n then headQ:=0

    else headQ:=headQ+1

    end;

    Listy.

    Lista to zbir elementw, z ktrych kady (z wyjtkiem ostatniego)

    wskazuje na nastpny i na kady element (z wyjtkiem pierwszego) wskazuje

    jaki element. List jednokierunkow mona sobie wyobraa tak:

    headHHHHHj

    x1

    -x2

    -x3

    -. . .

    xn

    NIL-

    Lista zajmuje proporcjonalnie wiele miejsca do liczby elementw na licie.

    List dwukierunkow mona sobie wyobraa tak:

    headHHHHHj

    x1

    NIL

    -

    x2

    -

    x3

    -

    . . .

    xn

    NIL

    -

    Drzewa binarne

    Drzewo binarne (o ile jest niepuste) ma korze i kady wierzchoek drzewa

    ma co najwyej dwa nastpniki, lewy i prawy. Ponadto z korzenia do kadego

    wierzchoka istnieje dokadnie jedna droga. Drzewo binarne mona sobie

    wyobraa tak:

    85

  • rootPPPPPqx1

    HHHHHHj

    x2

    HHHHHHj

    x3

    NIL HHHHHHjx4

    NIL NIL

    x5

    NIL NIL

    x6

    NIL NIL

    6.2 Typy wskanikowe

    Zmienne typw dotychczas poznanych istniej w istniej przez cay czas

    wykonywania tej czci programu (program gwny lub procedura), w ktrej

    s zadeklarowane. Maj one na stae przydzielon pami, do ktrej odwou-

    jemy si za pomoc identykatora zmiennej. S to zmienne statyczne. Takie

    zmienne nie nadaj si do reprezentowania 'struktur dynamicznych', na

    przykad tych, ktre zostay opisane powyej, (o ile nie naoymy z gry

    ogranicze dotyczcych rozmiaru tych struktur). Do reprezentowania ta-

    kich struktur su typy wskanikowe i wskazywane przez zmienne tych

    typw zmienne dynamiczne. Zmienne dynamiczne mona tworzy i usuwa

    w dowolnym miejscy programu a odwoujemy si do nich nie przez identy-

    kator zmiennej lecz przez zmienn wskanikow wskazujc t zmienn.

    Przykad deklaracji typu wskanikowego.

    type Tab=array[1..10] of integer; {typ tablicowy, przykladowy typ}

    Wskaznik=^Tab; {typ wskaznikow do elementow typu Tab}

    var A:Tab; {deklaracja zmiennej typu Tab}

    u,v,w:Wskaznik; {deklaracja zmiennych typu

    Wskaznik wskazujcego typ Tab}

    Zmienne typu wskaniki mog mie warto nieokrelon (np. zaraz

    po ich deklaracji) mog zawiera adres zmiennej dynamicznej typu Tab

    lub mog by rwne staej Nil, nie wskazujcej adnej zmiennej. Po ta-

    kich deklaracjach w pamici komputera mamy zarezerwowane takie obszary

    pamici (wartoci we wszystkich tablicach s losowe):

    86

  • A3 71 4 9

    u

    ?

    v

    ?

    Po wykonaniu kolejno instrukcji

    new(u); {1}

    v:=u; {2}

    new(v); {3}

    w:=u; u:=v; v:=w; {4}

    u^:=A {5}

    dispose(v); v:=Nil {6}

    new(u); {7}

    pami komputera bdzie wygldaa jak nastpuje. Po wykonaniu instrukcji

    1:

    A

    3 71 4 9

    u u

    - 10 1 0 7

    v

    ?

    Po wykonaniu instrukcji 2:

    A

    3 71 4 9

    u u

    - 10 1 0 7

    v

    87

  • Po wykonaniu instrukcji 3:

    A

    3 71 4 9

    u u

    - 10 1 0 7

    v v

    - 8 6 2 3

    Po wykonaniu linii 4:

    A

    3 71 4 9

    u v

    @@@@R

    10 1 0 7

    v u

    8 6 2 3

    Po wykonaniu instrukcji 5:

    A

    3 71 4 9

    u v

    @@@@R

    10 1 0 7

    v u

    3 71 4 9

    Po wykonaniu linii 6:

    88

  • A3 71 4 9

    u

    @@@@Rv u

    ? 3 71 4 9

    Po wykonaniu instrukcji 7:

    A

    3 71 4 9

    u u

    - 6 7 10 4

    v ?? 3 71 4 9

    A teraz dokadnie opiszemy procedury new, tworzc zmienn dynamiczn i

    dispose usuwajc zmienn dynamiczn.

    Zakadamy nastpujc deklaracj:

    var u,v : ^Typ

    Procedura new(v):

    1. tworzy now zmienn (dynamiczn) typu Typ cakowicie nieokrelon

    (rezerwuje miejsce w pamici komputera na zmienn typy Typ);

    2. tworzy nowy wskanik typu ^Typ i przypisuje go zmiennej v (adres

    nowo utworzonej zmiennej dynamicznej zostaje przypisany zmiennej

    v);

    3. Do utworzonej zmiennej mona si odwoa przez v^.

    Procedura dispose(v):

    1. usuwa zmienn (dynamiczn) typu Typ wskazywan przez v (zwalnia

    miejsce w pamici komputera zajmowane przez t zmienn); jeli v nie

    wskazuje zmiennej wystpi bd;

    89

  • 2. wszystkie zmienne wskazujce na v^ maj warto nieokrelon.

    Operacje na zmiennych i wartociach typw wskanikowych:

    1. do kadego typu wskanikowego naley staa Nil nie wskazujca na

    adn zmienn dynamiczn;

    2. instrukcje przypisania: v:=u oraz v:=Nil;

    3. relacje: v=u oraz vu;

    4. funkcje mog mie wartoci typw wskanikowych;

    5. parametry formalne i aktualne procedur mog by typu

    wskanikowego.

    W nastpnym paragrae poka jak mona implementowa listy uywa-

    jc typw wskanikowych. Ale typy wskanikowe mog si te przyda do

    innych celw, na przykad do deklaracji duych zmiennych. Deklaracja

    type Wektor = array[1..10000] of real;

    var A,B,C:Wektor;

    nie zostanie zaakceptowana przez kompilator Turbo Pascala poniewa ma on

    ograniczenie na czny rozmiar zmiennych deklarowanych w sekcji deklaracji

    zmiennych var a zmienne typu Wektor zajmuj duo pamici. Natomiast

    deklaracja

    type Wektor = array[1..10000] of real;

    Wsk=^Wektor

    var u,v,w:Wsk;

    zostanie zaakceptowana przez kompilator Turbo Pascala poniewa zmienne

    typu Wsk pamitaj tylko adresy i zajmuj mao pamici. Teraz na pocztku

    programu po instrukcjach

    new(u); new(v); new(w);

    mamy dostp do trzech zmiennych dynamicznych typu Wektor: u^, v^, w^.

    90

  • 6.3 Implementacja list

    Elementami listy s rekordy zawierajce warto (lub wartoci) i wskanik

    do nastpnego elementu na licie.

    Lista jednokierunkowa

    type lista=^element;

    element=record

    nazwisko : string;

    wiek : integer;

    next :lista

    end;

    Pokaemy jak wykona nastpujce operacje na licie:

    1. tworzenie pustej listy; (inicjalizacja)

    2. tworzenie nowej zmiennej typu element;

    3. wstawienie zmiennej wskazywanej przez zmienn wskanikow do listy;

    4. znajdowanie wskanika do elementu o szukanym polu;

    5. drukowanie wszystkich elementw listy;

    6. usuwanie wskazanego elementu z listy (tylko dla list dwukierunk-

    owych).

    procedure ini;

    begin head:=Nil end;

    function nowy: lista;

    var v:lista;

    begin

    new(v); v^.next:=Nil;

    read(v^.nazwisko);

    read(v^.wiek);

    nowy:=v

    end;

    procedure dodaj(v:lista);

    begin

    v^.next:=head;

    91

  • head:=v

    end;

    function szukaj(s:string):lista;

    var v:lista;

    begin

    v:=head; szukaj:=Nil;

    while (vNil) do

    if v^.nazwisko=s then begin

    szukaj:=v; v:=Nil

    end

    else v:=v^.next

    end;

    procedure druk;

    var v:lista;

    begin v:=head;

    while vNil do begin

    writeln(v^.Nazwisko,' ',v^.wiek);

    v:=v^.next

    end;

    end;

    Teraz fragment programu:

    ini;

    for i:=1 to 10 do dodaj(nowa);

    druk;

    tworzy list 10-elementow i j drukuje.

    Lista dwukierunkowa

    type lista2=^element2;

    element2=record

    nazwisko : string;

    wiek : integer;

    next,prev :lista

    end;

    92

  • Procedury ini, druk, szukaj dla listy dwukierunkowej s takie same

    jak dla listy jednokierunkowej. Natomiast procedury nowy, dodaj naley

    odpowiednio zmodykowa:

    function nowy2 : lista2;

    var v:lista2;

    begin

    new(v); v^.next:=Nil; v^.prev:=Nil;

    read(v^.nazwisko);

    read(v^.wiek);

    nowy2:=v

    end;

    procedure dodaj2(v:lista2);

    begin

    if headNil then head^.prev:=v;

    v^.next:=head;

    head:=v;

    v^.prev:=Nil;

    end;

    Ponadto na licie dwukierunkowej moemy atwo usuwa wskazany ele-

    ment.

    procedure usun2(x:lista2);

    begin

    if x^.prevNil then x^.prev^.next:=x^.next

    else head:=x^.next;

    if x^.nextNil then x^.next^.prev:=x^.prev

    end;

    Lista dwukierunkowa z wartownikiem Procedury dodaj2 i usun2

    s nieco skomplikowane, gdy musimy sprawdza czy lista jest pusta przy

    dodawaniu oraz czy s przed i za usuwanym elementem s inne elementy

    przy usuwaniu. Mona te procedury uproci dodajc do listy wartownika

    'sztuczny element', ktry powoduje, e lista nigdy nie jest pusta. W efekcie,

    na licie z wartownikiem, dodawanie i usuwanie odbywa si bez sprawdzania

    adnych warunkw.

    procedure ini3;

    93

  • begin new(head); head^.next:=head; head^.prev:=head

    end;

    procedure dodaj3(v:lista2);

    begin

    v^.next:=head^.next;

    v^.prev:=head;

    v^.next^.prev:=v;

    head^.next:=v;

    end;

    procedure usun3(x:lista2);

    begin

    x^.prev^.next:=x^.next;

    x^.next^.prev:=x^.prev

    end;

    function szukaj3(s:string):lista2;

    var v:lista2;

    begin

    v:=head^.next;

    while (vhead) and (v^.nazwas) do

    v:=v^.next;

    if vhead then szukaj3:=v

    else szukaj3:=Nil;

    end;

    procedure druk3;

    var v:lista2;

    begin v:=head^.next;

    while vhead do begin

    writeln(v^.Nazwisko,' 'v^.wiek);

    v:=v^.next

    end;

    end;

    Teraz, ponisza procedura czyci list:

    procedure empty;

    94

  • var v:lista2;

    begin

    while headhead^.next do begin

    v:=head^.next;

    usun3(v);

    dispose(v)

    end;

    end;

    Majc takie listy mona atwo implementowa stosy i kolejki.

    6.4 Drzewa binarnych poszukiwa (BST)

    Drzewo binarne jest to drzewo, w ktrym kady wierzchoek ma co najwyej

    dwa nastpniki, lewy i prawy. Ponadto, o ile jest niepuste, posiada ko-

    rze - jedyny wierzchoek, ktry nie jest nastpnikiem adnego wierzchoka.

    Bdziemy uywali poj: ojciec, lewy i prawy syn, lewe i prawe poddrzewo,

    potomek, przodek.

    Drzewo binarnych poszukiwa jest to drzewo binarne etykietowane, w

    ktrym kady wierzchoek ma etykiet wyrnion zwan kluczem. Klucze

    wierzchokw s typu, na ktrym okrelony jest porzdek liniowy. Pon-

    adto dla kadego wierzchoka v klucze w lewym poddrzewie s niewikszeod klucza wierzchoka v, a klucze w prawym poddrzewie s niemniejsze odklucza wierzchoka v.W Pascalu drzewa binarnych poszukiwa implementuje si uywajc

    typw wskanikowych.

    type wsk=^wierzcholek;

    wierzcholek=record

    klucz:integer;

    lewy,prawy,ojciec:wsk;

    Pokaemy procedury na drzewach:

    1. znajdowanie wierzchoka o danym kluczu;

    2. drukowanie rekordw wedug wzrastajcej wartoci kluczy;

    3. znajdowanie wierzchoka o kluczu minimalnym;

    4. znajdowanie wskanika do nastpnego wierzchoka;

    5. dodawanie nowego wierzchoka;

    95

  • 6. usuwanie wierzchoka z drzewa;

    7. inne przykadowe procedury rekurencyjne na drzewach.

    1. Znajdowanie wierzchoka o danym kluczu. Procedura rekuren-

    cyjna szukaj zwraca wskanik do wierzchoka o kluczu s w drzewie o

    korzeniu w lub Nil jeli nie ma takiego klucza. Procedura porusza si

    po drzewie, w lewo lub w prawo, z zalenoci od tego czy napotkane

    klucze na ciece s mniejsze czy wiksze od poszukiwanego. Jeli do-

    jdzie do koca cieki nie znajdujc po drodze szukanego wierzchoka

    to znaczy, e takiego wierzchoka w ogle nie ma w drzewie.

    function szukaj(w:wsk;s:integer):wsk;

    begin

    if w=Nil then szukaj:=Nil else

    if w^.klucz=s then szukaj:=w else

    if w^.klucz

  • function minimum(w:wsk):wsk;

    begin

    if wNil then

    while w^.lewyNil then w:=w^.lewy;

    minimum:=w

    end;

    4. Znajdowanie wskanika do nastpnego wierzchoka. Procedura

    next zwraca wskanik do wierzchoka o kluczu nastpnym po kluczu

    wierzchoka wskazywanego przez w lub Nil jeli nie ma takiego klucza.

    Procedura dziaa w ten sposb, e zwraca minimum poddrzewa o ko-

    rzeniu w^.prawy o ile jest ono niepuste, a jeli jest puste to wraca do

    gry po kolejnych przodkach a do momentu gdy znajdzie wierzchoek,

    dla ktrego poprzedni wierzchoek jest lewym synem.

    function next(w:wsk):wsk;

    var y:wsk;

    begin

    if w^.prawyNil then next:=minimum(w^.prawy)

    else begin

    y:=w^.ojciec; next:=Nil;

    while yNil do

    if wy^.lewy then begin

    w:=y; y:=y^.ojciec;

    end

    else begin

    next:=y; y:=Nil

    end;

    end;

    end;

    5. Dodawanie nowego wierzchoka. Procedura rekurencyjna dodaj

    dodaje nowy wierzchoek wskazywany przez w do drzewa binarnych

    poszukiwa o korzeniu wskazywanym przez r zachowujc struktur

    drzewa binarnego. Nowy wierzchoek jest zawsze dodawany jako nowy

    li w drzewie. Procedura woa parametr korzenia r przez zmienn

    poniewa, gdy drzewo jest puste, jest on modykowany.

    procedure dodaj(var r:wsk;w:wsk);

    begin

    97

  • w^.lewy:=Nil; w^.prawy:=Nil;

    if r=Nil then

    begin w^.ojciec:=Nil; r:=w end

    else

    if r^.klucz

  • kach. A gdy w ma dwch synw, B, C gdy w ma jednego syna, D gdy

    w nie ma synw.

    procedure usun(var r,w:wsk);

    var x,y:wsk;

    begin

    if (w^.lewy=Nil) or (w^.prawy=Nil) then y:=w

    else y:=next(w);

    {y wskazuje na wierzcholek ktory latwo usunac,

    bo ma co najwyzej jedno podrzewo}

    if y^.lewyNil then x:=y^.lewy

    else x:=y^.prawy;

    {x wskazuje na jedynego syna y, o ile taki istnieje}

    if xNil then x^.ojciec:=y^.ojciec;

    {o ile x istnieje, to modyfikujemy ojca x tak

    by teraz byl nim ojciec y}

    if y^.ojciec=Nil then r:=x

    {jesli y wskazuje korzen to modyfikujemy korzen}

    else

    if y=y^.ojciec^.lewy then y^.ojciec^.lewy:=x

    else y^.ojciec^.prawy:=x;

    {jesli y nie wskazuje korzenia to modyfikujemy ojca

    y tak by teraz jego synem (z wlasciwej strony) byl x}

    if yw then begin

    w^.klucz:=y^.klucz

    ....

    end;

    {jesli usuniety wierzcholek wskazywany przez y jest

    rozny od wierzcholka wskazywanego przez w to

    przepisujemy wszystkie dane z pola klucz (i innych

    pol przechowujacych dane o ile takie istnieja) ale

    nie z pol 'administrujacych drzewem': lewy, prawy,

    ojciec}

    w:=y;

    {zwracamy na w wskaznik usunietego wierzcholka}

    end;

    7. Inne przykadowe procedury rekurencyjne na drzewach. Jeli

    funkcj rekurencyjn mona obliczy znajc jej wartoci dla obu synw,

    to denicja takiej funkcji jest zwykle prosta, tak jak w pierwszych

    99

  • dwch przykadach. Natomiast gdy tak nie jest, jak w przypadku

    trzecim, to musimy skonstruowa now funkcje, ktra bdzie miaa t

    wasno. W praktyce taka funkcja oblicza wiele wartoci, z ktrych

    jedna jest przez nas poszukiwan a inne s tylko pomocnicze.

    (a) Obliczanie liczby wierzchokw drzewa.

    function rozmiar(w:wsk):integer;

    begin

    if w=Nil then rozmiar:=0

    else rozmiar:=1+rozmiar(w^.lewy)+rozmiar(w^.prawy)

    end;

    (b) Obliczanie wysokoci drzewa.

    function wysokosc(w:wsk):integer;

    var l,p:integer;

    begin

    if w=Nil then wysokosc:=0

    else begin

    l:=wysokosc(w^.lewy);

    p:=wysoksc(w^.prawy);

    if l

  • var u1,u2:wsk;

    d1,d2,h1,h2:integer;

    begin

    if r=Nil then begin u:=Nil; d:=0; h:=0 end

    else begin

    roznica1(r^.lewy,u1,d1,h1);

    roznica1(r^.prawy,u2,d2,h2);

    {obliczamy rekurencyjnie wartosci dla obu

    poddrzew}

    if h1>h2 then begin h:=h1+1; d:= h1-h2 end

    else begin h:=h2+1; d:=h2-h1 end;

    if (d>d1) and (d>d2) then u:=r

    {jestesmy w miejscu gdzie jest najwieksza

    roznica poddrzew}

    else if d1>d2 then begin d:=d1; u:=u1 end

    else begin d:=d2; u:=u2 end;

    {wstawiamy warosci poprzednie}

    end;

    end;

    begin{cialo funkcji roznica}

    roznica1(w,u,d,h);

    roznica:=u

    end;

    6.5 Struktury danych dla rodziny zbiorw rozcznych

    Rozwizywanie szeregu problemw wymaga grupowania elementw w zbiory

    rozczne. W takiej sytuacji potrzebna jest nam struktura, ktra pozwala

    na szybkie wykonywanie trzech operacji:

    1. make-set(k) - tworzenia zbioru, ktrego jedynym elementem jest k;

    2. union(k,l) - sumowania dwch zbiorw rozcznych, do ktrych

    nale elementy k i l;

    3. find(k) - znajdowania reprezentanta zbioru, do ktrego naley ele-

    ment k.

    Teraz opisz tak struktur. Zakadamy, e operacji make-set jest co

    najwyej n. Kady zbir jest reprezentowany przez list. Elementy listymaj wskaniki do nastpnego elementu i do elementu reprezentujcego dany

    101

  • zbir. Dodawanie bdzie polegao na czeniu list. By przyspieszy do-

    dawanie list bdziemy te pamitali w reprezentancie zbioru dugo listy

    (by dodawa krtsz list do duszej) i wskanik do ostatniego elementu

    listy. Wskaniki do elementw bdziemy pamitali w osobnej tablicy. Na

    obrazku mona to przedstawi tak:

    V:

    k3 :

    k2 :

    k1 :

    nazwa:dugo:

    next:

    rep:

    last:

    k23

    k3??

    k1?Nil?

    6