Beruflich Dokumente
Kultur Dokumente
PRZYKADOWY ROZDZIA
SPIS TRECI
KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG
TWJ KOSZYK
DODAJ DO KOSZYKA
CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK
CZYTELNIA
FRAGMENTY KSIEK ONLINE
Algorytmy i struktury
danych
Autorzy: Alfred V. Aho, John E. Hopcroft, Jeffrey D. Ullman
Tumaczenie: Andrzej Grayski
ISBN: 83-7361-177-0
Tytu oryginau: Data Structures and Algorithms
Format: B5, stron: 442
W niniejszej ksice przedstawiono struktury danych i algorytmy stanowice podstaw
wspczesnego programowania komputerw. Algorytmy s niczym przepis na
rozwizanie postawionego przed programist problemu. S one nierozerwalnie
zwizane ze strukturami danych listami, rekordami, tablicami, kolejkami, drzewami
podstawowymi elementami wiedzy kadego programisty.
Ksika obejmuje szeroki zakres materiau, a do jej lektury wystarczy znajomo
dowolnego jzyka programowania strukturalnego (np. Pascala). Opis klasycznych
algorytmw uzupeniono o algorytmy zwizane z zarzdzaniem pamici operacyjn
i pamiciami zewntrznymi.
Ksika przedstawia algorytmy i struktury danych w kontekcie rozwizywania
problemw za pomoc komputera. Z tematyk rozwizywania problemw powizano
zagadnienie zliczania krokw oraz zoonoci czasowej wynika to z gbokiego
przekonania autorw tej ksiki, i wraz z pojawianiem si coraz szybszych
komputerw, pojawia si bd take coraz bardziej zoone problemy
do rozwizywania i paradoksalnie zoono obliczeniowa uywanych
algorytmw zyskiwa bdzie na znaczeniu.
W ksice omwiono m.in.:
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
Spis treci
Od tumacza .............................................................................................................7
Wstp .....................................................................................................................11
1
Projektowanie i analiza algorytmw......................................................................15
1.1. Od problemu do programu ......................................................................................................................... 15
1.2. Abstrakcyjne typy danych.......................................................................................................................... 23
1.3. Typy danych, struktury danych i ADT ...................................................................................................... 25
1.4. Czas wykonywania programu .................................................................................................................... 28
1.5. Obliczanie czasu wykonywania programu................................................................................................. 33
1.6. Dobre praktyki programowania ................................................................................................................. 39
1.7. Super Pascal ............................................................................................................................................... 41
wiczenia .......................................................................................................................................................... 44
Uwagi bibliograficzne ....................................................................................................................................... 48
2
Podstawowe abstrakcyjne typy danych .................................................................49
2.1. Lista jako abstrakcyjny typ danych............................................................................................................ 49
2.2. Implementacje list ...................................................................................................................................... 52
2.3. Stosy ........................................................................................................................................................... 64
2.4. Kolejki........................................................................................................................................................ 68
2.5. Mapowania ................................................................................................................................................. 73
2.6. Stosy a procedury rekurencyjne ................................................................................................................. 75
wiczenia .......................................................................................................................................................... 80
Uwagi bibliograficzne ....................................................................................................................................... 84
3
Drzewa ...................................................................................................................85
3.1. Podstawowa terminologia .......................................................................................................................... 85
3.2. Drzewa jako abstrakcyjne obiekty danych................................................................................................. 92
SPIS TRECI
4
Podstawowe operacje na zbiorach .......................................................................117
4.1. Wprowadzenie do zbiorw....................................................................................................................... 117
4.2. Sowniki ................................................................................................................................................... 129
4.3. Tablice haszowane ................................................................................................................................... 132
4.4. Implementacja abstrakcyjnego typu danych MAPPING ......................................................................... 146
4.5. Kolejki priorytetowe ................................................................................................................................ 148
4.6. Przykady zoonych struktur zbiorowych............................................................................................... 156
wiczenia ........................................................................................................................................................ 163
Uwagi bibliograficzne ..................................................................................................................................... 165
5
Zaawansowane metody reprezentowania zbiorw ..............................................167
5.1. Binarne drzewa wyszukiwawcze ............................................................................................................. 167
5.2. Analiza zoonoci operacji wykonywanych na binarnym drzewie wyszukiwawczym.......................... 171
5.3. Drzewa trie ............................................................................................................................................... 175
5.4. Implementacja zbiorw w postaci drzew wywaonych 2-3-drzewa................................................... 181
5.5. Operacje MERGE i FIND ........................................................................................................................ 193
5.6. Abstrakcyjny typ danych z operacjami MERGE i SPLIT ....................................................................... 202
wiczenia ........................................................................................................................................................ 207
Uwagi bibliograficzne ..................................................................................................................................... 209
6
Grafy skierowane .................................................................................................211
6.1. Podstawowe pojcia ................................................................................................................................. 211
6.2. Reprezentacje grafw skierowanych........................................................................................................ 213
6.3. Graf skierowany jako abstrakcyjny typ danych ....................................................................................... 215
6.4. Znajdowanie najkrtszych cieek o wsplnym pocztku....................................................................... 217
6.5. Znajdowanie najkrtszych cieek midzy kad par wierzchokw .................................................... 221
6.6. Przechodzenie przez grafy skierowane przeszukiwanie zstpujce.................................................... 229
6.7. Silna spjno i silnie spjne skadowe digrafu....................................................................................... 237
wiczenia ........................................................................................................................................................ 240
Uwagi bibliograficzne ..................................................................................................................................... 242
7
Grafy nieskierowane ............................................................................................243
7.1. Definicje ................................................................................................................................................... 243
7.2. Metody reprezentowania grafw.............................................................................................................. 245
7.3. Drzewa rozpinajce o najmniejszym koszcie........................................................................................... 246
7.4. Przechodzenie przez graf ......................................................................................................................... 253
7.5. Wierzchoki rozdzielajce i skadowe dwuspjne grafu .......................................................................... 256
SPIS TRECI
8
Sortowanie ...........................................................................................................265
8.1. Model sortowania wewntrznego............................................................................................................. 265
8.2. Proste algorytmy sortowania wewntrznego............................................................................................ 266
8.3. Sortowanie szybkie (quicksort)................................................................................................................ 273
8.4. Sortowanie stogowe ................................................................................................................................. 283
8.5. Sortowanie rozrzutowe............................................................................................................................. 287
8.6. Dolne ograniczenie dla sortowania za pomoc porwna ....................................................................... 294
8.7. Szukanie k-tej wartoci (statystyki pozycyjne)........................................................................................ 298
wiczenia ........................................................................................................................................................ 302
Uwagi bibliograficzne ..................................................................................................................................... 304
9
Techniki analizy algorytmw ..............................................................................305
9.1. Efektywno algorytmw......................................................................................................................... 305
9.2. Analiza programw zawierajcych wywoania rekurencyjne.................................................................. 306
9.3. Rozwizywanie rwna rekurencyjnych ................................................................................................. 308
9.4. Rozwizanie oglne dla pewnej klasy rekurencji .................................................................................... 311
wiczenia ........................................................................................................................................................ 316
Uwagi bibliograficzne ..................................................................................................................................... 319
10
Techniki projektowania algorytmw ...................................................................321
10.1. Zasada dziel i zwyciaj ..................................................................................................................... 321
10.2. Programowanie dynamiczne .................................................................................................................. 327
10.3. Algorytmy zachanne ............................................................................................................................. 335
10.4. Algorytmy z nawrotami ......................................................................................................................... 339
10.5. Przeszukiwanie lokalne .......................................................................................................................... 349
wiczenia ........................................................................................................................................................ 355
Uwagi bibliograficzne ..................................................................................................................................... 358
11
Struktury danych i algorytmy obrbki danych zewntrznych .............................359
11.1. Model danych zewntrznych.................................................................................................................. 359
11.2. Sortowanie zewntrzne .......................................................................................................................... 362
11.3. Przechowywanie informacji w plikach pamici zewntrznych ............................................................. 373
11.4. Zewntrzne drzewa wyszukiwawcze ..................................................................................................... 381
wiczenia ........................................................................................................................................................ 387
Uwagi bibliograficzne ..................................................................................................................................... 390
SPIS TRECI
12
Zarzdzanie pamici ..........................................................................................391
12.1. Podstawowe aspekty zarzdzania pamici ........................................................................................... 391
12.2. Zarzdzanie blokami o ustalonej wielkoci ........................................................................................... 395
12.3. Algorytm odmiecania dla blokw o ustalonej wielkoci...................................................................... 397
12.4. Przydzia pamici dla obiektw o zrnicowanych rozmiarach ............................................................ 405
12.5. Systemy partnerskie ............................................................................................................................... 412
12.6. Upakowywanie pamici ......................................................................................................................... 416
wiczenia ........................................................................................................................................................ 419
Uwagi bibliograficzne ..................................................................................................................................... 421
Bibliografia ..........................................................................................................423
Skorowidz ............................................................................................................429
1
Projektowanie i analiza algorytmw
Stworzenie programu rozwizujcego konkretny problem jest procesem wieloetapowym. Proces ten
rozpoczyna si od sformuowania problemu i jego specyfikacji, po czym nastpuje projektowanie
rozwizania, ktre musi zosta nastpnie zapisane w postaci konkretnego programu, czyli zaimplementowane. Konieczne jest udokumentowanie oraz przetestowanie implementacji, a rozwizanie wyprodukowane przez dziaajcy program musi zosta ocenione i zinterpretowane. W niniejszym rozdziale zaprezentowalimy nasze podejcie do wymienionych krokw, nastpne rozdziay
powicone s natomiast algorytmom i strukturom danych, skadajcym si na wikszo programw komputerowych.
16
obfitym repertuarem procedur wykonujcych rne operacje na acuchach znakw (w taki sposb
dokonuje si przecie kompilacja programu w jzyku wysokiego poziomu, tak rwnie dokonuje
si wyszukiwania konkretnych fraz tekstowych w obszernych bibliotekach).
Algorytmy
Kiedy ju dysponujemy odpowiednim modelem matematycznym dla naszego problemu, moemy
sprbowa znale rozwizanie wyraajce si w kategoriach tego modelu. Naszym gwnym
celem jest poszukiwanie rozwizania w postaci algorytmu pod tym pojciem rozumiemy skoczon sekwencj instrukcji, z ktrych kada ma klarowne znaczenie i moe by wykonana w skoczonym czasie przy uyciu skoczonego wysiku. Dobrym przykadem klarownej instrukcji, wykonywalnej w skoczonym czasie i skoczonym wysikiem, jest instrukcja przypisania w rodzaju
. Oczywicie, poszczeglne instrukcje algorytmu mog by wykonywane wielokrotnie
i niekoniecznie w kolejnoci, w ktrej zostay zapisane. Wynika std kolejne wymaganie stawiane
algorytmowi musi si on zatrzymywa po wykonaniu skoczonej liczby instrukcji, niezalenie
od danych wejciowych. Nasz program zasuguje wic na miano algorytmu tylko wtedy, gdy jego
wykonywanie nigdy (czyli dla adnych danych wejciowych) nie prowadzi do ugrznicia sterowania w nieskoczonej ptli.
Co najmniej jeden aspekt powyszych rozwaa nie jest do koca oczywisty. Okrelenie
klarowne znaczenie ma mianowicie charakter na wskro relatywny, poniewa to, co jest oczywiste
dla jednej osoby, moe by wtpliwe dla innej. Ponadto wykonywanie si kadej z instrukcji w skoczonym czasie moe nie wystarczy do tego, by algorytm koczy swe dziaanie po wykonaniu
skoczonej liczby instrukcji. Za pomoc serii argumentw i kontrargumentw mona jednak w wikszoci przypadkw osign porozumienie odnonie tego, czy dana sekwencja instrukcji faktycznie
moe by uwaana za algorytm. Zazwyczaj ostateczne wyjanienie wtpliwoci w tym wzgldzie
jest powinnoci osoby, ktra uwaa si za autora algorytmu. W jednym z kolejnych punktw niniejszego rozdziau przedstawilimy sposb szacowania czasu wykonywania konstrukcji powszechnie
spotykanych w jzykach programowania, dowodzc tym samym ich skoczonoci czasowej.
Do zapisu algorytmw uywa bdziemy jzyka Pascal wzbogaconego jednake o nieformalne opisy w jzyku naturalnym programy zapisywane w powstaym w ten sposb pseudojzyku nie nadaj si co prawda do wykonania przez komputer, lecz powinny by intuicyjnie zrozumiae dla Czytelnika, a to jest przecie w tej ksice najwaniejsze. Takie podejcie umoliwia
rwnie ewentualne zastpienie Pascala innym jzykiem, bardziej wygodnym dla Czytelnika, na
etapie tworzenia prawdziwych programw. Pora teraz na pierwszy przykad, w ktrym zilustrowalimy wikszo etapw naszego podejcia do tworzenia programw komputerowych.
Przykad 1.1. Stworzymy model matematyczny, opisujcy funkcjonowanie sygnalizacji wietlnej
na skomplikowanym skrzyowaniu. Ruch na takim skrzyowaniu opisa mona przez rozoenie go
na poszczeglne zakrty z konkretnej ulicy w inn (dla przejrzystoci przejazd na wprost rwnie uwaany jest za zakrt). Jeden cykl obsugi takiego skrzyowania obejmuje pewn liczb
faz, w kadej fazie mog by rwnoczenie wykonywane te zakrty (i tylko te), ktre ze sob nie
koliduj. Problem polega wic na okreleniu poszczeglnych faz ruchu i przyporzdkowaniu kadego z moliwych zakrtw do konkretnej fazy w taki sposb, by w kadej fazie kada para zakrtw by par niekolidujc. Oczywicie, rozwizanie optymalne powinno wyznacza najmniejsz
moliw liczb faz.
Rozpatrzmy konkretne skrzyowanie, ktrego schemat przedstawiono na rysunku 1.1. Skrzyowanie to znajduje si niedaleko Uniwersytetu Princeton i znane jest z trudnoci manewrowania,
17
RYSUNEK 1.1.
Przykadowe
skrzyowanie
zwaszcza przy zawracaniu. Ulice C i E s jednokierunkowe, pozostae s ulicami dwukierunkowymi. Na skrzyowaniu tym mona wykona 13 rnych zakrtw; niektre z nich, jak AB
(czyli z ulicy A w ulic B) i EC, mog by wykonywane rwnoczenie, inne natomiast, jak AD i EB,
koliduj ze sob i mog by wykonane tylko w rnych fazach.
Opisany problem daje si atwo uj (modelowa) w postaci struktury zwanej grafem. Kady graf skada si ze zbioru wierzchokw i zbioru linii czcych wierzchoki w pary linie te
nazywane s krawdziami. W naszym grafie modelujcym sterowanie ruchem na skrzyowaniu
wierzchoki reprezentowa bd poszczeglne zakrty, a poczenie dwch wierzchokw krawdzi oznacza bdzie, e zakrty reprezentowane przez te wierzchoki koliduj ze sob. Graf odpowiadajcy skrzyowaniu pokazanemu na rysunku 1.1 przedstawiony jest na rysunku 1.2, natomiast w tabeli 1.1 widoczna jest jego reprezentacja macierzowa kady wiersz i kada kolumna
reprezentuje konkretny wierzchoek; jedynka na przeciciu danego wiersza i danej kolumny wskazuje, e odpowiednie wierzchoki poczone s krawdzi.
RYSUNEK 1.2.
Graf reprezentujcy
skrzyowanie pokazane
na rysunku 1.1
Rozwizanie naszego problemu bazuje na koncepcji zwanej kolorowaniem grafu. Polega ona
na przyporzdkowaniu kademu wierzchokowi konkretnego koloru w taki sposb, by wierzchoki
poczone krawdzi miay rne kolory. Nietrudno si domyli, e optymalne rozwizanie naszego
problemu sprowadza si do znalezienia takiego kolorowania grafu z rysunku 1.2, ktre wykorzystuje
jak najmniejsz liczb kolorw.
18
TABELA 1.1.
Macierzowa reprezentacja grafu z rysunku 1.2
AB
AC
AD
AB
BA
BC
BD
DA
DB
AC
AD
DC
EA
EB
EC
ED
BA
BC
BD
DA
DB
DC
EA
EB
EC
ED
Zagadnienie kolorowania grafu studiowane byo przez dziesiciolecia i obecna wiedza na temat
algorytmw zawiera wiele propozycji w tym wzgldzie. Niestety, problem kolorowania dowolnego
grafu przy uyciu najmniejszej moliwej liczby kolorw zalicza si do ogromnej klasy tzw. problemw NP-zupenych, dla ktrych jedynymi znanymi rozwizaniami s rozwizania typu sprawd
wszystkie moliwoci. W przeoeniu na kolorowanie grafu oznacza to sukcesywne prby wykorzystania jednego koloru, potem dwch, trzech itd. tak dugo, a w kocu liczba uytych kolorw
okae si wystarczajca (czego stwierdzenie rwnie wymaga sprawdzenia wszystkich moliwoci). Co prawda wykorzystanie specyfiki konkretnego grafu moe ten proces nieco przyspieszy,
jednake w oglnym wypadku nie istnieje alternatywa dla oczywistego sprawdzania wszystkich
moliwoci.
Okazuje si wic, e znalezienie optymalnego pokolorowania grafu jest w oglnym przypadku
procesem bardzo kosztownym i dla duych grafw moe okaza si zupenie nie do przyjcia, niezalenie od tego, jak efektywnie skonstruowany byby program rozwizujcy zagadnienie. Zastosujemy w zwizku z tym trzy moliwe podejcia. Po pierwsze, dla maych grafw duy koszt czasowy nie bdzie zbytni przeszkod i sprawdzenie wszystkich moliwoci bdzie zadaniem
wykonalnym w rozsdnym czasie. Drugie podejcie polega bdzie na wykorzystaniu specjalnych
wasnoci grafu, pozwalajcych na rezygnacj a priori z do duej liczby sprawdze. Trzecie podejcie odwoywa si bdzie natomiast do znanej prawdy, e rozwizanie problemu mona znacznie
przyspieszy, rezygnujc z poszukiwania rozwizania optymalnego i zadowalajc si rozwizaniem dobrym, moliwym do zaakceptowania w konkretnych warunkach i czsto niewiele gorszym
od optymalnego tym bardziej, e wiele rzeczywistych skrzyowa nie jest a tak skomplikowanych, jak pokazane na rysunku 1.1. Takie algorytmy, szybko dostarczajce dobrych, lecz niekoniecznie optymalnych rozwiza, nazywane s algorytmami heurystycznymi.
Jednym z heurystycznych algorytmw kolorowania grafu jest tzw. algorytm zachanny
(ang. greedy). Kolorujemy pierwszym kolorem tyle wierzchokw, ile tylko moemy. Nastpnie
wybieramy kolejny kolor i wykona naley kolejno nastpujce czynnoci:
(1) Wybierz dowolny niepokolorowany jeszcze wierzchoek i przyporzdkuj mu aktualnie uywany kolor.
19
(2) Przejrzyj list wszystkich niepokolorowanych jeszcze wierzchokw i dla kadego z nich
sprawd, czy jest poczony krawdzi z jakim wierzchokiem majcym aktualnie uywany
kolor. Jeeli nie jest, opatrz go tym kolorem.
Zachanno algorytmu wynika std, e w kadym kroku (tj. przy kadym z uywanych
kolorw) stara si on pokolorowa jak najwiksz liczb wierzchokw, niezalenie od ewentualnych
negatywnych konsekwencji tego faktu. Nietrudno wskaza przypadek, w ktrym mniejsza zachanno prowadzi do zastosowania mniejszej liczby kolorw. Graf przedstawiony na rysunku 1.3 mona
pokolorowa przy uyciu tylko dwch kolorw; jednego dla wierzchokw 1, 3 i 4, drugiego dla
pozostaych. Algorytm zachanny, analizujcy wierzchoki w kolejnoci wzrastajcej numeracji,
rozpoczby natomiast od przypisania pierwszego koloru wierzchokom 1 i 2, po czym wierzchoki
3 i 4 otrzymayby drugi kolor, a dla wierzchoka 5 konieczne byoby uycie trzeciego koloru.
RYSUNEK 1.3.
Przykadowy graf,
dla ktrego nie popaca
zachanno algorytmu
kolorowania
Zastosujmy teraz zachanne kolorowanie do grafu z rysunku 1.2. Rozpoczynamy od wierzchoka AB, nadajc mu pierwszy z kolorw niebieski; kolorem tym moemy take opatrzy1
wierzchoki AC, AD i BA, poniewa s one osamotnione. Nie moemy nada koloru niebieskiego
wierzchokowi BC, gdy jest on poczony z (niebieskim) wierzchokiem AB; z podobnych wzgldw nie moemy take pokolorowa na niebiesko wierzchokw BD, DA i DB, moemy to jednak
zrobi z wierzchokiem DC. Wierzchokom EA, EB i EC nie mona przyporzdkowa koloru niebieskiego w przeciwiestwie do osamotnionego wierzchoka ED.
Wemy kolejny kolor czerwony. Przyporzdkowujemy go wierzchokom BC i BD; wierzchoek DA czy si krawdzi z BD, wic nie moe mie koloru czerwonego, podobnie jak wierzchoek DB czcy si z BC. Spord niepokolorowanych jeszcze wierzchokw tylko EA mona
nada kolor czerwony.
Pozostay cztery niepokolorowane wierzchoki: DA, DB, EB i EC. Jeeli przypiszemy DA
kolor zielony, moemy go take przyporzdkowa DB, jednake dla EB i EC musimy wtedy uy
kolejnego (tego) koloru. Ostateczny wynik kolorowania przedstawiamy w tabeli 1.2. Dla kadego koloru w kolumnie Ekstra prezentujemy te wierzchoki, ktre nie s poczone z adnym
wierzchokiem w tym kolorze i przy innej kolejnoci przechodzenia zachannego algorytmu przez
wierzchoki mogyby ten wanie kolor uzyska.
Zgodnie z wczeniejszymi zaoeniami, wszystkie wierzchoki w danym kolorze (kolumna
Wierzchoki) odpowiadaj zakrtom uruchamianym w danej fazie. Oprcz nich mona take uruchomi inne zakrty, ktre z nimi nie koliduj (mimo e reprezentujce je wierzchoki maj inny
kolor), s one wyszczeglnione w kolumnie Ekstra.
Tak wic wedle otrzymanego rozwizania, sygnalizacja sterujca ruchem na skrzyowaniu
pokazanym na rysunku 1.1 powinna by sygnalizacj czterofazow. Po dowiadczeniach z grafem
przedstawionym na rysunku 1.3 nie mona nie zastanawia si, czy jest rozwizanie optymalne,
tzn. czy nie byoby moliwe rozwizanie problemu przy uyciu sygnalizacji trj- czy dwufazowej.
1
20
TABELA 1.2.
Jeden ze sposobw pokolorowania grafu z rysunku 1.2
za pomoc zachannego algorytmu
Kolor
Wierzchoki
Ekstra
niebieski
czerwony
zielony
ty
BA, DC, ED
AD, BA, DC, ED
BA, DC, EA, ED
21
Odrniamy tu abstrakcyjny typ danych od typu zbiorowego jzyka Pascal.
22
3-
-
Procedurze pokazanej na listingu 1.3 sporo jeszcze brakuje do tego, by zostaa zaakceptowana przez kompilator Pascala. Poprzestaniemy jednak na tym etapie jej precyzowania, gdy chodzi
nam raczej o prezentacj okrelonego sposobu postpowania ni ostateczny wynik.
23
Podsumowanie
Na rysunku 1.4 przedstawiamy schemat procesu tworzenia programu, zgodnie z ujciem w niniejszej ksice. Proces ten rozpoczyna si etapem modelowania, na ktrym wybrany zostaje odpowiedni model matematyczny dla danego problemu (np. graf). Na tym etapie opis algorytmu ma
zazwyczaj posta wybitnie nieformaln.
RYSUNEK 1.4.
Proces rozwizywania
problemu za pomoc
komputera
24
oprcz liczb dziesitnych honorowa take liczby w postaci szesnastkowej, niezbdne zmiany
trzeba bdzie wprowadzi jedynie w cile okrelonym fragmencie kodu, bez ingerowania w inne
fragmenty programu.
? @AB99
;
C:
;
AD
;
:A
#
);
od razu widoczna staaby si podstawowa zaleta abstrakcyjnych typw danych. Ot program korzystajcy z ADT ogranicza si tylko do wywoywania zwizanych z nim procedur ich implementacja jest dla niego obojtna. Dokonujc zmian w tej implementacji nie musimy ingerowa
w wywoania procedur.
25
Wymienione cztery operacje s co prawda wystarczajce w procedurze , lecz oczywicie zestaw
podstawowych operacji na grafie powinien by nieco bogatszy i powinien obejmowa na przykad:
dodanie krawdzi midzy podanymi wierzchokami, usunicie konkretnej krawdzi, usunicie kolorowania z wszystkich wierzchokw itp. Istnieje wiele struktur danych zdolnych do reprezentowania
grafu w tej postaci przedstawimy je dokadniej w rozdziaach 6. i 7.
Naley wyranie zaznaczy, e nie istnieje ograniczenie liczby operacji podstawowych zwizanych z danym modelem matematycznym. Kady zbir tych operacji definiuje odrbny ADT.
Przykadowo, zestaw operacji podstawowych dla abstrakcyjnego typu danych
mgby by nastpujcy:
(1) ? @AB99 procedura usuwajca wszystkie elementy ze zbioru A,
(2) BA:EA## procedura przypisujca zbiorowi C sum zbiorw A i B,
(3)
:F funkcja zwracajca liczb elementw w zbiorze A.
Implementacja abstrakcyjnego typu danych polega na zdefiniowaniu jego odpowiednika (jako
typu) w kategoriach konkretnego jzyka programowania oraz zapisaniu (rwnie w tym jzyku) procedur implementujcych jego podstawowe operacje. Typ w jzyku programowania stanowi zazwyczaj kombinacj typw elementarnych tego jzyka oraz obecnych w tym jzyku mechanizmw
agregujcych. Najwaniejszymi mechanizmami agregujcymi jzyka Pascal s tablice i rekordy.
Na przykad abstrakcyjny zbir
zawierajcy liczby cakowite moe by zaimplementowany
jako tablica liczb cakowitych.
Naley take podkreli jeden istotny fakt. Abstrakcyjny typ danych jest kombinacj modelu
matematycznego i zbioru operacji, jakie mona na tym modelu wykonywa, dlatego dwa identyczne modele, poczone z rnymi zbiorami operacji, okrelaj rne ADT. Wikszo materiau
zawartego w niniejszej ksice powicona jest badaniu podstawowych modeli matematycznych, jak
zbiory i grafy, i znajdowaniu najodpowiedniejszych (w konkretnych sytuacjach) zestaww operacji
dla tych modeli.
Byoby wspaniale, gdybymy mogli tworzy programy w jzykach, ktrych elementarne typy
danych i operacje s jak najblisze uywanym przez nas modelom i operacjom abstrakcyjnych typw
danych. Jzyk Pascal (pod wieloma wzgldami) nie jest najlepiej przystosowany do odzwierciedlania najczciej uywanych ADT, w dodatku nieliczne jzyki, w ktrych abstrakcyjne typy danych
deklarowa mona bezporednio, nie s powszechnie znane (o niektrych z nich wspominamy w notce
bibliograficznej).
26
G'+H$%I(($%
okrela czteroelementow tablic, ktrej komrka jest rekordem zawierajcym dwa pola: i
.
Trzecim mechanizmem agregujcym, dostpnym w Pascalu i niektrych innych jzykach, s
pliki. Plik, podobnie jak jednowymiarowa tablica, stanowi sekwencj elementw okrelonego typu.
W przeciwiestwie jednak do tablicy, plik nie podlega indeksowaniu; elementy dostpne s tylko
w takiej kolejnoci w jakiej fizycznie wystpuj w pliku. Poszczeglne elementy tablicy (i poszczeglne
27
pola rekordu) s natomiast dostpne w sposb bezporedni, czyli szybciej ni w pliku. Plik odrnia jednak od tablicy istotna zaleta jego wielko (liczba zawartych w nim elementw) moe
zmienia si w czasie i jest potencjalnie nieograniczona.
Wskaniki i kursory
Oprcz mechanizmw agregujcych istniej jeszcze inne sposoby ustanawiania relacji midzy komrkami su do tego wskaniki i kursory. Wskanik jest komrk, ktrej zawarto jednoznacznie
identyfikuje inn komrk. Fakt, e komrka A jest wskanikiem komrki B, zaznaczamy na schemacie struktury danych rysujc strzak od A do B.
W jzyku Pascal to, e zmienna moe wskazywa komrk o typie (($%, zaznaczamy
w nastpujcy sposb:
(($%
Strzaka poprzedzajca nazw typu bazowego oznacza typ wskanikowy (czyli zbir wartoci stanowicych wskazania na komrk o typie (($%). Odwoanie do komrki wskazywanej przez
zmienn (zwane take dereferencj wskanika) ma posta strzaka wystpuje za nazw zmiennej.
Kursor tym rni si od wskanika, e identyfikuje komrk w ramach konkretnej tablicy
wartoci kursora jest indeks odnonego elementu. W samym zamyle nie rni si on od wskanika jego zadaniem jest take identyfikowanie komrki jednak, w przeciwiestwie do niego,
nie mona za pomoc kursora identyfikowa komrek samodzielnych, ktre nie wchodz w skad
tablicy. W niektrych jzykach, jak np. Fortran i Algol, wskaniki po prostu nie istniej i jedyn
metod identyfikowania komrek s wanie kursory. Naley take zauway, e w Pascalu nie jest
moliwe utworzenie wskanika do konkretnej komrki tablicy, wic jedynie kursory umoliwiaj
identyfikowanie poszczeglnych komrek. Niektre jzyki, jak PL/I i C, s pod tym wzgldem
bardziej elastyczne i dopuszczaj wskazywanie elementw tablic przez prawdziwe wskaniki.
Na schemacie struktury danych kursory zaznaczane s podobnie jak wskaniki, czyli za pomoc strzaek, a dodatkowo w komrk bdc kursorem moe by wpisana jej zawarto4 dla zaznaczenia, i nie mamy do czynienia z typowym wskanikiem.
Przykad 1.3. Na rysunku 1.5 pokazano struktur danych skadajc si z dwch czci: tablicy
(zdefiniowanej wczeniej w tym rozdziale) i kursorw do elementw tej tablicy; kursory
te poczone s w list acuchow. Elementy tablicy
s rekordami. Pole
kadego z tych
rekordw jest kursorem do nastpnego rekordu i zgodnie z t konwencj, na rysunku 1.5 rekordy
tablicy uporzdkowane s w kolejnoci 4, 1, 3, 2. Zwr uwag, e pole
rekordu 2 zawiera
warto 0, oznaczajc kursor pusty, czyli nie identyfikujcy adnej komrki, konwencja taka ma
sens jedynie wtedy, gdy komrki tablicy indeksowane s poczwszy od 1, nie od zera.
4
Wynika to z jeszcze jednej, fundamentalnej rnicy midzy wskanikiem a kursorem. Ot implementacja wskanikw w Pascalu (i wszystkich niemal jzykach, w ktrych wskaniki s obecne) bazuje na adresie
komrki w przestrzeni adresowej procesu. Adres ten (a wic i konkretna warto wskanika) ma sens jedynie
w czasie wykonywania programu nie istnieje wic jakakolwiek warto wskanika, ktr mona by umieci na schemacie. Kursor natomiast jest wielkoci absolutn, pozostajc bez zwizku z konkretnymi adresami komrek przyp. tum.
28
RYSUNEK 1.5.
Przykadowa
struktura danych
Kada komrka acucha (w grnej czci rysunku) jest rekordem o nastpujcej definicji:
+$%
'$7
+$%
Pole tego rekordu jest kursorem do jakiego elementu tablicy
, pole zawiera
natomiast wskanik do nastpnej komrki w acuchu. Wszystkie rekordy acucha s rekordami
anonimowymi, nie maj nazw, gdy kady z nich utworzony zosta dynamicznie, w wyniku wywoania funkcji
. Pierwszy rekord acucha wskazywany jest natomiast przez zmienn :
+$%
Pole pierwszego rekordu w acuchu zawiera kursor do czwartego elementu tablicy
,
pole jest natomiast wskanikiem do drugiego rekordu. W drugim rekordzie pole data ma warto 2, co oznacza kursor do drugiego elementu tablicy
; pole jest natomiast pustym
wskanikiem oznaczajcym po prostu brak wskazania na cokolwiek. W jzyku Pascal puste
wskazanie oznaczane jest sowem kluczowym nil.
29
Jeeli tworzony program ma by uruchamiany tylko od czasu do czasu, wice bdzie z pewnoci pierwsze kryterium. Koszty zwizane z wytworzeniem programu s wwczas znacznie wysze
od kosztw wynikajcych z jego uruchamiania, naley wic dy do jak najefektywniejszego
wykorzystania czasu programistw, bez szczeglnej troski o obcienie zasobw systemu. Jeeli
jednak program ma by uruchamiany czsto, koszty zwizane z jego wykonywaniem szybko si
zwielokrotni. Wwczas gr bior wzgldy natury efektywnociowej, gdzie liczy si szybki algorytm, bez wzgldu na jego stopie komplikacji. Warto niekiedy wyprbowa kilka rnych algorytmw i wybra najbardziej opacalny w konkretnych warunkach. W przypadku duych zoonych systemw moe okaza si take celowe przeprowadzanie pewnych symulacji badajcych
zachowania konkretnych algorytmw. Wynika std, e programici powinni nie tylko wykaza si
umiejtnoci optymalizowania programw, lecz take powinni umie okreli, czy w danej sytuacji zabiegi optymalizacyjne s w ogle uzasadnione.
danych wejciowych,
jakoci kodu wynikowego generowanego przez kompilator,
architektury i szybkoci komputera, na ktrym program jest wykonywany,
zoonoci czasowej algorytmu uytego do konstrukcji programu.
To, e czas wykonywania programu zalee moe od danych wejciowych, prowadzi do wniosku, i czas ten powinien by moliwy do wyraenia w postaci pewnej funkcji wybranego aspektu
tych danych owym aspektem jest najczciej rozmiar danych. Znakomitym przykadem wpywu
danych wejciowych na czas wykonania programu jest proces sortowania danych w rozmaitych
odmianach, ktrymi zajmiemy si szczegowo w rozdziale 8. Jak wiadomo, dane wejciowe programu sortujcego maj posta listy elementw. Rezultatem wykonania programu jest lista zoona
z tych samych elementw, lecz uporzdkowana wedug okrelonego kryterium. Przykadowo, lista
2, 1, 3, 1, 5, 8 po uporzdkowaniu w kolejnoci rosncej bdzie mie posta 1, 1, 2, 3, 5, 8. Najbardziej intuicyjn miar rozmiaru danych wejciowych jest liczba elementw w licie, czyli dugo listy wejciowej. Kryterium dugoci listy wejciowej jako rozmiaru danych jest adekwatne
w przypadku wielu algorytmw, dlatego w niniejszej ksice bdziemy je stosowa domylnie
poza sytuacjami, w ktrych wyranie bdziemy sygnalizowa odstpstwo od tej zasady.
Przyjo si oznacza przez T(n) czas wykonywania programu, gdy rozmiar danych wejciowych wynosi n. Przykadowo, niektre programy wykonuj si w czasie T(n) = cn2, gdzie c jest
pewn sta. Nie precyzuje si jednostki, w ktrej wyraa si wielko T(n), wygodnie jest przyj,
e jest to liczba instrukcji wykonywanych przez hipotetyczny komputer.
Dla niektrych programw czas wykonania moe jednak zalee od szczeglnej postaci danych,
nie tylko od ich rozmiaru. W takiej sytuacji T(n) oznacza pesymistyczny czas wykonania (tzw. najgorszy przypadek ang. worst case), czyli maksymalny czas wykonania dla (statystycznie) wszystkich moliwych danych o rozmiarze n. Poniewa najgorszy przypadek stanowi sytuacj skrajn,
definiuje si take redni czas wykonania oznaczany przez Tavg(n) i stanowicy wynik (statystycznego)
urednienia czasu wykonania wszystkich moliwych danych rozmiaru n. To, e Tavg(n) stanowi miar
bardziej obiektywn ni czas pesymistyczny, staje si niekiedy rdem bdnego zaoenia, e
wszystkie moliwe postaci danych wejciowych s jednakowo prawdopodobne. W praktyce okrelenie
redniego czasu wykonania bywa znacznie trudniejsze, ni okrelenie czasu pesymistycznego zarwno
ze wzgldu na trudnoci zwizane z matematycznym podejciem do problemu, jak i z powodu
30
niezbyt precyzyjnego znaczenia okrelenia redni. Z tego wanie wzgldu przy szacowaniu zoonoci czasowej algorytmw bdziemy raczej bazowa na czasie pesymistycznym, ale bdziemy
uwzgldnia czas redni w sytuacjach, w ktrych da si to uczyni.
Zatrzymajmy si teraz nad punktami 2. i 3. przedstawionej listy, zgodnie z ktrymi czas wykonania programu zaleny jest zarwno od uytego kompilatora, jak i konkretnego komputera. Zaleno
ta uniemoliwia okrelenie czasu wykonania w sposb konwencjonalny, np. w sekundach, moemy
to uczyni jedynie w kategoriach proporcjonalnoci, mwic na przykad, e czas sortowania bbelkowego proporcjonalny jest do n2. Staa bdca wspczynnikiem tej proporcjonalnoci pozostaje
wielk niewiadom, zalen i od kompilatora, i od komputera oraz kilku innych czynnikw.
31
Przykad 1.6. Aby sprawdzi, czy funkcja T(n) = n3+2n2 jest (n3), zamy c = 1; wtedy T(n) cn3
dla n = 0, 1,
Zamy teraz, e T(n) = n dla n nieparzystych i T(n) = n2/100 dla n parzystych. Jeeli przyjmiemy c = 1/100, to dla wszystkich parzystych n (czyli dla nieskoczonej ich iloci) otrzymamy
T(n) = cn2, czyli T(n) cn2, wic T(n) jest (n2).
7
Okrelenie problem rozmiaru n jest tu wygodnym skrtem okrelajcym dane rozmiaru n przetwarzane przez program rozwizujcy problem przyp. tum.
32
RYSUNEK 1.6.
Zoono czasowa
czterech programw
Zestawienie widoczne w tabeli 1.3 nie pozostawia adnych wtpliwoci. Przewaga programu
o zoonoci O(n) jest wyranie widoczna, jego moliwoci wzrastaj dziesiciokrotnie. Pozostae
programy prezentuj si pod tym wzgldem mniej imponujco, poniewa wielko problemw
moliwych do rozwizywania przez nie wzrasta tylko nieznacznie. Szczeglnie program o zoonoci
O(2n) zdatny jest do rozwizywania jedynie problemw o niewielkich rozmiarach.
TABELA 1.3.
Wzrost maksymalnego rozmiaru moliwego do rozwizania problemu
w rezultacie dziesiciokrotnego przyspieszenia komputera
Zoono
czasowa T(n)
Komputer
oryginalny
Komputer
dziesiciokrotnie szybszy
Wzgldny przyrost
rozmiaru problemu
100n
5n2
n3/2
2n
10
14
12
10
100
45
27
13
10,0
3,2
2,3
1,3
Rozmiar problemu
Czas wykonania
programu (s)
Wzgldny przyrost
czasu wykonania
100n
5n2
n3/2
2n
100
140
120
100
10 000
100 000
1 000 000
1030 ( 31022 lat)
10
100
1000
1029
33
Szczypta soli
Mimo fundamentalnego znaczenia zoonoci czasowej, istniej przypadki, gdy nie jest ona jedynym
ani te najwaniejszym kryterium wyboru algorytmu. Oto kilka przykadowych sytuacji, w ktrych
gwn rol odgrywaj inne czynniki.
(1) Jeeli program ma by uyty tylko raz lub kilka razy bd ma by wykorzystywany sporadycznie,
koszty jego wytworzenia i przetestowania znacznie przewysza bd koszt zwizany z jego
uruchamianiem. O wiele waniejsze od efektywnoci algorytmu jest wwczas jego poprawne
zaimplementowanie w prosty sposb.
(2) Tempo wzrostu czasu wykonania programu, wyraone przez notacj duego O algorytmu
staje si czynnikiem krytycznym w przypadku asymptotycznym, czyli wtedy, gdy rozmiar problemu zaczyna zmierza do nieskoczonoci. Dla maych rozmiarw istotne staj si wspczynniki proporcjonalnoci (w funkcji zoonoci czasowej) duy wspczynnik proporcjonalnoci moe zrekompensowa szybko wynikajc z maego wykadnika potgi. Istnieje
wiele algorytmw, np. algorytm Schonhagego-Strassena mnoenia liczb cakowitych [1971],
ktre pod wzgldem zoonoci asymptotycznej s zdecydowanie lepsze od konkurentw, lecz
due wspczynniki proporcjonalnoci dyskwalifikuj je pod wzgldem przydatnoci do rozwizywania problemw pojawiajcych si w praktyce.
(3) Skomplikowane algorytmy nieatwo zrozumie, a tworzone na ich bazie programy s trudne
do konserwacji i rozwijania dla osb, ktre nie s ich autorami. Jeeli szczegy danego algorytmu s powszechnie znane w danym rodowisku programistw, mona bez obaw algorytm ten
wykorzystywa. W przeciwnym razie moe si okaza, e opnienia i straty wynike z niezrozumienia lub, co gorsza, z bdnego zrozumienia algorytmu mog zniweczy wszelkie korzyci
wynikajce z jego efektywnoci.
(4) Znane s sytuacje, w ktrych efektywne czasowo algorytmy wymagaj znacznych iloci pamici. Wica si z tym konieczno wykorzystania pamici zewntrznych (np. do implementacji pamici wirtualnej) moe drastycznie obniy szybko realizacji programu, niezalenie
od efektywnoci samego algorytmu.
(5) W algorytmach numerycznych wzgldy dokadnoci i stabilnoci s zwykle nieporwnywalnie
waniejsze od szybkoci oblicze.
34
Zamy, e T1(n) = O(f(n)) i T2(n) = O(g(n)) s czasami wykonania dwch fragmentw programu, odpowiednio, P1 i P2. czny czas wykonania obydwu fragmentw, kolejno P1 i P2, wynosi
wwczas T1(n)+T2(n) = O(max(f(n), g(n))). Aby przekona si, e jest tak istotnie, zdefiniujmy cztery
stae: c1, c2, n1, i n2 takie, e dla n n1 zachodzi T1(n) c1f(n) i, odpowiednio, dla n n2 zachodzi
T2(n) c2f(n). Niech n0 = max(n1, n2). Jeeli n n0, wtedy T1(n)+T2(n) c1f(n)+c2g(n) (c1+c2)
max(f(n), g(n)), czyli dla kadego n n0 zachodzi T1(n)+T2(n) c0max(f(n), g(n)), gdzie c0 = c1+c2.
Oznacza to (bezporednio na podstawie definicji), e T1(n)+T2(n) = O(max(f(n), g(n))).
Przykad 1.8. Opisan powyej regu sum wykorzysta mona do obliczenia zoonoci czasowej sekwencji fragmentw programu, zawierajcego ptle i rozgazienia. Zamy mianowicie,
e czasy wykonania trzech fragmentw wynosz, odpowiednio, O(n2), O(n3) i O(n log n). czny
czas wykonania dwch pierwszych krokw wyniesie wwczas O(max(n2, n3)) = O(n3), za czny
czas wykonania wszystkich trzech O(max(n3, n log n)) = O(n3).
W oglnym przypadku czas wykonania ustalonej sekwencji krokw rwny jest, z dokadnoci
do staego czynnika, czasowi kroku wykonywanego najduej. Niekiedy zdarza si, e dwa kroki programu (lub wiksza ich liczba) s w stosunku do siebie niewspmierne pod wzgldem czasu wykonania. Czas ten nie jest ani rwny, ani te systematycznie wikszy w przypadku ktrego z krokw.
Dla przykadu rozpatrzmy dwa kroki o czasie wykonania, odpowiednio, f(n) i g(n), gdzie:
n 4 dla n parzystych
f ( n) = 2
n dla n nieparzystych
n 2 dla n parzystych
f ( n) = 3
n dla n nieparzystych
Regu sum naley zastosowa w sposb bezporedni. czny czas wykonania wspomnianych krokw
rwny bdzie O(max(n4, n2)) = O(n4) dla n parzystych oraz O(max(n2, n3) = O(n3) dla n nieparzystych.
Innym poytecznym wnioskiem z reguy sum jest to, e w sytuacji, w ktrej g(n) f(n) dla
wszystkich n n0, O(f(n)+g(n)) jest tym samym, co O(f(n)). Na przykad O(n2+n) oznacza to samo, co O(n2).
W podobny sposb formuuje si regu iloczynw. Jeeli T1(n) = O(f(n)) i T2(n) = O(g(n)), to
T1(n) T2(n) rwne jest O(f(n)g(n)), co dociekliwy Czytelnik zweryfikowa moe samodzielnie w taki
sam sposb, jak zrobilimy to w przypadku reguy sum. W szczeglnoci O(cf(n)) jest tym samym,
co O(f(n)) (c jest tu dowoln sta dodatni).
Przed przystpieniem do omawiania oglnych regu analizy czasu wykonywania programw,
przyjrzyjmy si prostemu przykadowi ilustrujcemu wybrane elementy rzeczywistego procesu.
Przykad 1.9. Na listingu 1.4 widoczna jest procedura bubble sortujca tablic liczb rzeczywistych
w kolejnoci rosncej, metod sortowania bbelkowego (ang. bubblesort). Kade wykonanie ptli
wewntrznej powoduje przesunicie najmniejszych elementw w kierunku pocztku tablicy.
LISTING 1.4.
Procedura sortowania bbelkowego
G55
I'$7
$$(2" (' J '*
##'$7
-
.-
1-
G<I0GI
35
&K&&G<IGIG<I
3-G<IGI
4-GI
L-
-
Rozmiar sortowanej tablicy, czyli liczba elementw do posortowania, jest tu niewtpliwie wiarygodn miar rozmiaru problemu. Oczywicie, kada instrukcja przypisania wymaga pewnego staego
czasu, niezalenego od danych wejciowych; kada z instrukcji {4}, {5} i {6} wykonuje si wic
w czasie O(1), czyli O(0) (O(c) = O(0) dla dowolnej staej c). czny czas wykonania tych instrukcji
rwny jest na mocy reguy sum O(max(1, 1, 1)) = O(1) = O(0).
Przyjrzyjmy si teraz instrukcjom ptli i instrukcji warunkowej. Instrukcje te s zagniedone,
musimy wic zacz analiz od najbardziej wewntrznej z nich. Testowanie warunku instrukcji if
wymaga O(1) czasu. Jeeli chodzi o ciao tej instrukcji, czyli instrukcje uwarunkowane {4}, {5} i {6},
nie sposb z gry przewidzie, ile razy zostan wykonane. Zaoymy wic pesymistycznie, e bd
wykonywane zawsze, w czasie O(1). Zatem koszt wykonania caej instrukcji if wynosi O(1).
Przemieszczajc si na zewntrz, natrafiamy na wewntrzn ptl for (wiersze {2} {6}).
Oglnie rzecz ujmujc, czas wykonania ptli for jest sum czasu wykonania poszczeglnych jej
obrotw, przy czym musimy jeszcze doda O(1) czasu w kadym obrocie, potrzebnego na zwikszenie i testowanie zmiennej sterujcej oraz skok do pocztku ptli. Kady obrt wspomnianej ptli
wymaga wic O(1) czasu, liczba obrotw rwna jest natomiast O(ni) (i jest wartoci zmiennej
sterujcej ptli zewntrznej). Daje to czny czas wykonania ptli O((ni)1) = O(ni).
Dochodzimy wreszcie do ptli zewntrznej (wiersze {1} {6}). Wykonuje si ona n1 razy,
tak wic czny czas jej wykonania wynosi O(k), gdzie k rwne jest:
n 1
(n i) = n(n 1) / 2 = n
/2n/2
i =1
Procedura
wykonuje si w czasie O(n2). W rozdziale 8. przedstawimy inne algorytmy sortowania, dziaajce w czasie O(n log n), a zatem efektywniejsze8, gdy log n jest mniejsze od n.
Zanim przejdziemy do omawiania oglnych regu analizowania zoonoci obliczeniowej, przypomnijmy, e precyzyjne okrelenie grnego ograniczenia tej zoonoci, cho czasami bardzo atwe,
to w wielu wypadkach moe stanowi prawdziwe wyzwanie intelektualne.
Nie sposb zreszt poda jakiego kompletnego zbioru regu tego procesu. Ograniczymy si
tylko do wymienienia pewnych wskazwek i koncepcji ilustrowanych stosownymi przykadami.
Czas wykonania okrelonej instrukcji lub grupy instrukcji uzaleniony jest od rozmiaru danych wejciowych i opcjonalnie od wartoci jednej zmiennej lub wielu zmiennych. Natomiast jedynym dopuszczalnym parametrem wpywajcym na czas wykonania caego programu jest rozmiar danych
wejciowych.
(1) Czas wykonania instrukcji przypisania, wczytywania lub wypisywania danych przyjmuje si
jako O(1). Od tej zasady istnieje kilka wyjtkw. Po pierwsze, niektre jzyki, w tym Pascal,
dopuszczaj kopiowanie caych tablic (by moe do duych) za pomoc pojedynczej instrukcji
przypisania. Po drugie, prawa strona instrukcji przypisania zawiera moe wywoanie funkcji,
ktrej czasu wykonania nie mona pomin.
8
Wszystkie uywane w tej ksice logarytmy maj podstaw 2, chyba e wyranie zaznaczona zostaa inna.
Dla notacji duego o podstawa logarytmu i tak nie ma znaczenia, poniewa zmiana podstawy logarytmu
rwnoznaczna jest z pomnoeniem jego wartoci przez stay czynnik: logan = clogbn, gdzie c = logab.
36
(2) Czas wykonania sekwencji instrukcji okrelony jest przez regu sum z dokadnoci do staego
czynnika. Jest on rwny czasowi wykonania tej instrukcji, ktra wykonuje si najduej.
(3) Na czas wykonania instrukcji if skada si czas wykonania instrukcji uwarunkowanej i czas
wartociowania wyraenia warunkowego ten ostatni przyjmuje si zwykle jako O(1). Czas
wykonania instrukcji if-then-else oblicza si natomiast jako sum czasu wartociowania wyraenia warunkowego oraz czasu wykonania tej spord sekcji uwarunkowanych, ktra wykonuje si duej.
(4) Czas wykonania ptli jest sum wykonania wszystkich jej obrotw. Na czas wykonania jednego
obrotu skada si czas wykonania ciaa ptli oraz czas czynnoci pomocniczych zwizanych
z obsug zmiennej sterujcej i skokiem do pocztku ptli (zakada si, e owe czynnoci pomocnicze wykonywane s w czasie O(1)). Czsto czas wykonania ptli oblicza si, mnoc
liczb wykonywanych obrotw przez najwikszy moliwy czas wykonania pojedynczego obrotu,
ale czasami nie mona z gry ustali liczby wykonywanych obrotw, zwaszcza w przypadku
ptli nieskoczonej.
Wywoania procedur
Jeeli mamy do czynienia z programem, w ktrym adna z procedur nie jest rekurencyjna9, moemy
rozpocz analizowanie czasu wykonania od tych procedur, ktre nie wywouj adnych innych
procedur (oczywicie, wywoanie funkcji w wyraeniu rwnie uwaane jest tu za wywoanie
procedury), a co najmniej jedna taka procedura musi istnie, skoro wszystkie s nierekurencyjne10.
9
Wbrew pozorom nie mamy tutaj do czynienia z rekurencj, lecz nie ma procedury, ktra nie wywoywaaby
adnych innych. Autorzy piszc o rekurencji mieli zapewne na myli take jej pozory, jak powyszy przykad przyp. tum.
37
W kolejnych krokach analizujemy te procedury, ktre odwouj si wycznie do procedur o obliczonej ju zoonoci, i proces ten kontynuujemy a do przeanalizowania wszystkich procedur.
Kiedy niektre (lub wszystkie) procedury programu s rekurencyjne, nie jest moliwe ustawienie ich w opisanym powyej porzdku. Naley zatem uzna zoono czasow T(n) danej procedury za niewiadom funkcj zmiennej n, po czym sformuowa i rozwiza rwnanie rekurencyjne okrelajce t funkcj. Istnieje wiele sposobw analizowania rnego rodzaju zalenoci
rekurencyjnych. Niektrymi z nich zajmiemy si w rozdziale 9., natomiast w tym miejscu zaprezentujemy jedynie obliczanie zoonoci prostego programu rekurencyjnego.
Przykad 1.10. Widoczna na listingu 1.5 funkcja fact dokonuje rekursywnego obliczania funkcji
f(n) = n! (n! to iloczyn kolejnych liczb naturalnych od 1 do n).
LISTING 1.5.
Rekurencyjne obliczanie funkcji silnia
6$
'$7'$7
'$
M
-
/
.-
1-
=
<
-
Miar rozmiaru problemu dla tej funkcji jest oczywicie jej argument oznaczmy zatem
przez T(n) czas wykonywania si tej funkcji dla argumentu
. Instrukcje w wierszach {1} i {2}
wykonuj si oczywicie w czasie O(1), za instrukcja w wierszu {3} w czasie O(1)+T(n1). Dla
pewnych staych c i d mamy wic:
c + T (n 1) dla n > 1
T ( n) =
dla n 1
d
(1.1)
38
(1.2)
Zatem, zgodnie ze wzorem (1.2), T(n) = O(n). Zauwa, e dla celw naszej analizy przyjlimy, e mnoenie dwch liczb cakowitych realizuje si w czasie O(1). Zaoenie to moe nie by suszne, jeeli n
bdzie tak due, e bdziemy musieli uywa wielosowowej reprezentacji liczb cakowitych.
Zaprezentowana tutaj oglna metoda rozwizywania rwna rekurencyjnych polega na sukcesywnym zastpowaniu po prawej stronie rwnania wartoci T(k) wartociami T(k1) tak dugo, a
dla jakiego argumentu x warto T(x) wyraona zostanie nierekurencyjnie. Jeeli nie bdzie moliwe
dokadne oszacowanie poszczeglnych wartoci T(k), moemy posuy si ich grnymi ograniczeniami, a otrzymany wynik te bdzie wwczas grnym ograniczeniem na T(n).
11
Uwaga ta dotyczy wzorcowego jzyka Pascal. W 1992 roku ukazaa si wersja 7. Turbo Pascala, zawierajca wspomniane instrukcje. Niezalenie jednak od tego istniej sytuacje, w ktrych wyskok z gboko
zagniedonej ptli za pomoc instrukcji goto jest znacznie zgrabniejszy i czytelniejszy, ni mozolne przedzieranie si przez kilka poziomw wyrae warunkowych. Czytelnikw zainteresowanych problematyk
rozsdnego uywania instrukcji goto w Pascalu zachcam do przeczytania 2. rozdziau ksiki Delphi 7 dla
kadego, wyd. Helion 2003 przyp. tum.
39
Analizowanie pseudoprogramw
Techniki stosowane do analizy zoonoci czasowej prawdziwych programw daj si take zastosowa do podobnej analizy w stosunku do pseudoprogramw zawierajcych nieformalne opisy
w jzyku naturalnym oczywicie pod warunkiem, e zna si zoono czasow czynnoci opisywanych przez te nieformalne instrukcje. Kopot polega na tym, e jest ona na og silnie uzaleniona od implementacji, wic w przypadku procedur zaimplementowanych poowicznie lub
niezaimplementowanych w ogle, o ich zoonoci czasowej moemy powiedzie niewiele lub
zgoa nic. Paradoksalnie nieznajomo ta kryje w sobie pewn zalet. Decydujc si mianowicie
na uycie w programie pewnego abstrakcyjnego typu danych, nie determinujemy jeszcze zoonoci
czasowej tego programu ta bowiem zalena bdzie od (dokonanego pniej) wyboru konkretnej
implementacji procedur zwizanych z ADT. Ta wanie moliwo wyboru jest jednym z najwaniejszych argumentw przemawiajcych za uywaniem abstrakcyjnych typw danych.
Skoro czasy wykonania pewnych procedur wywoywanych w programie s jak na razie nieznane, sama zoono czasowa tego programu moe by traktowana jedynie jako funkcja, ktrej
parametrami s owe czasy wykonania, uzalenione z kolei od rozmiarw argumentw przekazywanych wspomnianym procedurom. Znaczenie sowa rozmiar jest zawsze spraw konkretnego
przypadku i interpretacji osoby dokonujcej analizy, chocia wybrany model matematyczny zazwyczaj wskazuje najbardziej trafne podejcie w tym wzgldzie. Jeeli na przykad argument przekazany
do procedury jest zbiorem danych (
), najbardziej odpowiedni miar jego rozmiaru jest liczba
zawartych w nim elementw. W kolejnych rozdziaach ksiki przedstawimy wiele podobnych przykadw zwizanych z analiz rozmaitych pseudoprogramw.
40
jest postpowaniem znacznie efektywniejszym, ni rozpoczynanie wszystkich dziaa od pocztku. Zasada ta dziaa take w drug stron, tworzc jaki program, we pod uwag, e by
moe kto zechce go wykorzysta w przyszoci do swych potrzeb.
(4) Bd kowalem swych narzdzi. W jzyku programistw narzdziami nazywane s programy
przeznaczone do wielokrotnego uytku, w rnych zastosowaniach. Piszc program, zastanw
si, czy nie naleaoby nada mu bardziej oglnej postaci i tym samym skonstruowa narzdzie
przydatne do rnych celw. Przykadowo, tworzc program ukadajcy harmonogram egzaminw, zastanw si, czy nie warto stworzy oglniejszego programu rozwizujcego problem
kolorowania grafu przy uyciu najmniejszej liczby kolorw. Znalezienie optymalnego harmonogramu sesji mogoby by wwczas tylko jednym z jego zastosowa, gdy wierzchoki grafu
reprezentowayby grupy studentw, rne kolory odzwierciedlayby rne terminy egzaminw,
za poczenie krawdzi dwch wierzchokw oznaczaoby, e w grupach reprezentowanych
przez te wierzchoki znajduj si wsplni studenci. Zastosowanie uniwersalnego programu
rozwizujcego problem optymalnego kolorowania grafu wykraczaoby natomiast daleko poza
problem organizacji sesji egzaminacyjnej, czego przykad pokazalimy na pocztku rozdziau, poszukujc optymalnego sposobu sterowania ruchem na skrzyowaniu.
(5) Wykorzystaj polecenia i programy systemu operacyjnego. Polecenia i programy systemw operacyjnych zdolne s wykona wiele poytecznych zada, dziaajc jednak w pojedynk, ograniczaj swe dziaanie do funkcji raczej elementarnych (do ktrych w kocu zostay stworzone).
Dobrze zaprojektowany system operacyjny udostpnia mechanizmy automatyzujce wspprac
poszczeglnych programw w taki sposb, by wyniki produkowane przez jeden z nich staway
si danymi wejciowymi drugiego. Zesp tak poczonych programw nazywamy potokiem, za poszczeglne programy nosz nazw filtrw. Jeeli repertuar polece i programw
danego systemu jest inteligentnie zaprojektowany, mona w nim tworzy potoki o zdumiewajcych moliwociach.
Przykad 1.11. Przykadem ciekawego potoku moe by program
, stworzony pierwotnie
przez S.C. Johnsona wycznie z polece systemu UNIX12. Program ten wczytuje z pliku tekst w jzyku
angielskim i wyprowadza wszystkie wystpujce w nim wyrazy, ktrych brakuje w doczonym
niewielkim sowniku. Program
przejawia co prawda tendencj do produkowania faszywych
alarmw w postaci sygnalizowania poprawnych sw jako sw bdnych13, lecz generowane
przez niego raporty s na tyle krtkie, e przy odrobinie inteligencji atwo zorientowa si, ktre
z wydrukowanych sw s rzeczywicie bdne (tre niniejszej ksiki zostaa zweryfikowana za
pomoc programu spell).
Pierwszym filtrem uytym w potoku (ktrym w kocu jest program
) jest polecenie
, ktre, dziki uyciu odpowiednich parametrw, suy do zamiany wielkich liter na ich
mae odpowiedniki oraz do zastpowania tzw. biaych znakw (blanks, czyli spacji i znakw
tabulacji) znakami nowego wiersza. W rezultacie otrzymujemy wykaz sw wystpujcych w tekcie, a wszystkie z nich pisane s wycznie maymi literami i kade znajduje si w osobnym wierszu.
Kolejne polecenie-filtr, , dokonuje posortowania tego wykazu w porzdku alfabetycznym. Kade
ze sw moe wystpowa w tekcie wiele razy, dlatego we wspomnianym wykazie mog si one
powtarza. Aby kade z nich wystpowao w wykazie tylko raz, wywoywane jest polecenie
"
dokonujce eliminacji duplikatw w posortowanej licie. Tak znormalizowany wykaz jest nastpnie konfrontowany ze sownikiem w celu wychwycenia tych jego pozycji, ktre nie wystpuj
12
41
w sowniku to zadanie wykonuje polecenie , ktrego parametrem jest nazwa wspomnianego
sownika. Oto wic kompletna tre programu-potoku
:
G <FIG<I('"'('
"
+$ '%
Programowanie na poziomie potokw wymaga od programistw dyscypliny, a raczej wsparcia polegajcego na tym, by jak najwicej tworzonych programw mogo w razie potrzeby peni
rol filtrw. W ostatecznym rozrachunku, mierzonym stosunkiem osignitych efektw do woonego wysiku, postpowanie takie na dusz met naprawd si opaca.
42
$
$
<$
<.
NNN
Przykad 1.12. Na listingu 1.6 widoczna jest funkcja zapisana z uyciem instrukcji return, na listingu 1.7 zawarta zostaa natomiast jej posta dostosowana do wymogw standardowego Pascala.
LISTING 1.6.
Funkcja fact korzystajca z instrukcji return
'$7'$7
/
=
<
-
15
przyp. tum.
43
LISTING 1.7.
i po transformacji do postaci wymaganej przez standardowy Pascal
'$7'$7
NNN
/
NNN
=
<
NNN
NNN
-
Trzecie z zastosowanych przez nas rozszerze wynika std, e jzyk Pascal w pewnych sytuacjach wymaga uycia identyfikatora typu, nie tolerujc jego definicji in extenso. Na przykad deklaracja:
G55;I'$7(($%
16
44
wiczenia
1.1.
Sze druyn: Szakale, Lwy, Ory, Bobry, Tygrysy i Skunksy, przygotowuje si do kolejnych
rozgrywek ligi pikarskiej. Szakale rozegray ju mecze z Lwami i Orami, Lwy take gray
ju z Bobrami i Skunksami, za Tygrysy gray z Orami i Skunksami. Kada druyna rozgrywa tylko jeden mecz w tygodniu. Znajd taki harmonogram rozgrywek, by kada druyna graa z kad i aby zajo to jak najmniej czasu. Wskazwka. Stwrz graf, ktrego
wierzchoki prezentowa bd te pary, ktre jeszcze nie rozegray meczu ze sob. Jeeli
poszczeglne kolory reprezentowa bd kolejne tygodnie rozgrywek, jakie bdzie znaczenie krawdzi w tym grafie?
*1.2. Rozpatrz rami robota zakotwiczone na jednym kocu. Rami to ma dwa przeguby, z ktrych kady pozwala na obrt o 90 w gr lub w d w paszczynie pionowej. Jak mgby
wyglda model matematyczny odzwierciedlajcy moliwe ruchy wolnego koca ramienia? Skonstruuj algorytm jego przesunicia z jednej dozwolonej pozycji do innej.
*1.3. Mamy obliczy iloczyn czterech macierzy liczb rzeczywistych: M1M2M3M4. Macierz
M1 ma rozmiar 1020, M2 2050, M3 501, a M4 1100. Zamy, e pomnoenie
dwch macierzy o wymiarach, odpowiednio, pq i qr wymaga pqr operacji elementarnych
(zgodnie z klasycznym schematem macierzy). Znajd tak kolejno mnoenia wspomnianych macierzy, ktra zminimalizuje cakowit liczb wykonanych operacji elementarnych.
Jak mona uoglni rozwizanie tego zadania na dowoln liczb macierzy?
**1.4. Dane jest 100 liczb rzeczywistych bdcych pierwiastkami kwadratowymi z kolejnych liczb
naturalnych od 1 do 100. Naley posegregowa te liczby na dwie grupy w taki sposb, by
ich sumy w obydwu grupach byy jak najbardziej zblione do siebie. Gdyby dysponowa
dwiema minutami czasu komputera, jakich oblicze dokonaby w tym czasie w celu uatwienia sobie rozwizania tego zadania?
1.5. Zaproponuj zachanny algorytm gry w szachy. Jakich wynikw spodziewaby si w przypadku jego zastosowania?
1.6. W punkcie Abstrakcyjne typy danych rozpatrywalimy abstrakcyjny typ
z operacjami
elementarnymi: ? @AB99, BA:EA i
:F. Zamy dla wygody, e ograniczamy si do zbiorw
stanowicych podzbiory zbioru ;##555#1-. Uwzgldniajc to ograniczenie, zaproponuj implementacje (w jzyku Pascal) wspomnianych operacji elementarnych.
1.7. Najwikszym wsplnym dzielnikiem dwch liczb cakowitych p i q nazywamy najwiksz
liczb cakowit d tak, e dzieli ona bez reszty zarwno p, jak i q. Zamierzamy zaimplementowa nastpujcy algorytm obliczania najwikszego wsplnego dzielnika p i q niech
r bdzie reszt z dzielenia p przez q; jeeli r rwne jest zero, to q jest szukanym najwikszym wsplnym dzielnikiem, w przeciwnym razie przypisujemy p:= q, q:= r i powtarzamy dzielenie17.
(a)
Udowodnij, e przedstawiony algorytm faktycznie znajduje najwikszy wsplny
dzielnik dwch liczb.
(b)
Zapisz ten algorytm w pseudojzyku.
(c)
Przekszta nieformalny program stworzony w punkcie (b) w poprawny program
w jzyku Pascal.
17
Algorytm ten wymylony zosta ponad 2300 lat temu przez Euklidesa i dzi jest powszechnie znany pod
jego nazwiskiem przyp. tum.
45
WICZENIA
1.8. Zamierzamy stworzy program formatujcy tekst, wyrwnujcy kady z wierszy do lewej
i prawej krawdzi. Program uywa dwch buforw: dla sw i dla wierszy. Pocztkowo
obydwa bufory s puste. Program wczytuje sowo do bufora sw i sprawdza, czy sowo
to zmieci si jeszcze w biecym wierszu (zapisanym tymczasowo w buforze wiersza).
Jeeli tak, sowo dopisywane jest do bufora wiersza i bufor sowa jest oprniany; jeeli
nie, w buforze wiersza midzy poszczeglne sowa zostaj rwnomiernie wstawione dodatkowe spacje, by wyrwna zawarto wiersza na obydwu krawdziach, po czym bufor
wiersza jest drukowany i oprniany.
(a)
Zapisz algorytm dziaania programu formatujcego w pseudojzyku.
(b)
Przekszta ten zapis w poprawny program w jzyku Pascal.
1.9. Jest n miast i dana jest tabela odlegoci midzy kad ich par. Napisz pseudoprogram,
ktry znajduje krtk ciek rozpoczynajc si i koczc w tym samym miecie, przechodzc przez kade z miast dokadnie jeden raz18. Poniewa jedyn znan metod znajdowania
najkrtszej cieki speniajcej podane warunki jest wyczerpujce poszukiwanie, zaproponuj
jaki algorytm heurystyczny znajdujcy ciek o dugoci moliwej do zaakceptowania.
1.10. Rozpatrzmy nastpujce funkcje zmiennej n:
f 1 ( n) = n 2
f 2 (n) = n 2 + 1000n
n dla n nieparzystych
f 3 ( n) = 3
n dla n parzystych
n dla n 100
f 4 ( n) = 3
n dla n > 100
Znajd wszystkie takie pary (i,j), e fi(n) = O(fj(n)) oraz takie, e fi(n) = (fj(n)).
1.11. Rozpatrzmy nastpujce funkcje zmiennej n:
n 2 dla parzystych n 0
g 1 ( n) = 3
n dla nieparzystych n 1
n dla 0 n 100
g 2 ( n) = 3
n dla n > 100
g 3 ( n) = n 2 , 5
Znajd wszystkie takie pary (i,j), e gi(n) = O(gj(n)) oraz takie, e gi(n) = (gj(n)).
1.12. Wyra w notacji duego O pesymistyczn zoono czasow (w funkcji ) nastpujcych procedur:
18
46
(a)
(b)
!"
(c)
(*d)
(d)
i
i =1
(e)
= O(n k +1 ) oraz
= (n k +1 ) dla cakowitych k.
i =1
Jeeli p(x) jest dowolnym wielomianem k-tego stopnia z dodatnim wspczynnikiem przy najwyszej potdze, to p(n) = O(nk) oraz p(n) = (nk).
47
WICZENIA
*1.14. Zamy, e T1(n) = (f(n)) oraz T2(n) = (g(n)). Ktre z poniszych stwierdze jest
prawdziwe?
(a)
T1(n)+T2(n) = (max(f(n), g(n))).
(b)
T1(n)T2(n) = (f(n)g(n)).
*1.15. Niektrzy autorzy definiuj wielko duej omegi w nastpujcy sposb: f(n) = (g(n)),
jeeli istniej takie stae dodatnie n0 i c, e dla wszystkich n n0 zachodzi f(n) cg(n).
(a)
Czy zgodnie z t definicj prawd jest, e f(n) = (g(n)) wtedy i tylko wtedy, gdy
g(n) = O(f(n))?
(b)
Czy stwierdzenie wyraone w punkcie a) jest prawdziwe w kontekcie definicji
(n) przedstawionej w podrozdziale Czas wykonywania programu?
(c)
Czy rozwizanie zadania 1.14 pozostaje niezmienne, jeeli przyj now definicj
duej omegi?
1.16. Uporzdkuj nastpujce funkcje pod wzgldem tempa wzrostu:
(a)
n
(b)
(c)
log n
(d)
log log n
(e)
log2n
(f)
n/log n
log2n
(g)
(h)
(1/3)n
(i)
(3/2)n
(j)
17
1.17. Zamy, e parametr poniszej procedury jest dodatni potg liczby 2. Znajd formu
wyraajc wypisywan warto zmiennej w funkcji .
$
#
$
48
$
$
$
#
(a)
(b)
Uwagi bibliograficzne
Koncepcja abstrakcyjnego typu danych ma sw genez w klasie (typie class) jzyka Simula 67
(Birtwistle i in., [1973]). Od tego czasu powstao wiele innych jzykw zawierajcych abstrakcyjne
typy danych, midzy innymi Alphard (Shaw, Wulf i London [1977]), C++ (Stroustrup [1982]), MESA
(Geschke, Morris i Satterthwaite [1977]) i Russel (Demers i Donahue [1979]). Koncepcja ADT jest
przedmiotem rozwaa prac Gotliebw [1978] oraz Wulfa i in. [1981].
Dzieo Knutha [1968] jest pierwsz ze znaczcych publikacji promujcych systematyczne studia
nad czasem wykonywania programw. Aho, Hopcroft i Ullman [1974] odnosz zoono czasow
i pamiciow algorytmw do rnorodnych modeli obliczeniowych, jak maszyny Turinga i maszyny
o dostpie swobodnym. Zobacz take uwagi bibliograficzne do rozdziau 9. zawierajce wicej
odsyaczy do rde traktujcych o analizie algorytmw i programw.
Jako lektur uzupeniajc na temat programowania strukturalnego poleci mona opracowania
Hoarego, Dahla i Dijkstry [1972], Wirtha [1973], Kernighana i Plaugera [1974] oraz Yourdona i Constantine [1975]. Organizacyjne i psychologiczne aspekty realizacji duych projektw programistycznych dyskutowane s przez Brooksa [1974] i Weinberga [1971]. Kernighan i Plauger [1981] demonstruj sposoby budowania uytecznych narzdzi programistycznych w Pascalu.