Upload
dawid-dudek
View
42
Download
22
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