Download as pdf or txt
Download as pdf or txt
You are on page 1of 1118

Wydanie czwarte

Wydawnictwa Naukowo-Techniczne
Warszawa
Dane o oryginale:

Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest


Introductionto Algońthms
Copyright© 1990 by The Massachusetts Institute of Technology
Thirteenth printing, 1994

Redaktorzy Izabela Ewa Mika


Ewa Zdanowic.z

Okładkę i strony tytułowe projektował Paweł G. R.ubas:zewski


Opracowanie techniczne Ewa Eckhardt
Przygotowanie do druku Marta leczeń, Marianna Zadrożna

© Copyright for lhe Polish edition


by Wydawnictwa Naukowo-Techniczne
Warszawa 1997, 2001

All Rights Reserved


Printed in Poland

Utwór w całości ani we fragmentach nie może być powielany ani


rozpowszechniany za pomocą urządzeń elektronicznych, mechanicznych,
kopiujących, nagrywających i innych, w tym również nie może być umieszczany
ani rozpowszechniany w postaci cyfrowej zarówno w Internecie, jak i w sieciach
lokalnych bez pisemnej zgody posiadacza praw autorskich.

Adres poczty elektronicznej: wnt@pol.pl


Strona WWW: www.wnt.com.pl

ISBN 83-204-266~
Spistreści

Przedmowa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . • . . . . . . 13

1. Wstęp ....•..... .. .... ........ ........ .... ........ .. 21


1.l. Algorytm.y ......................................... ,,.,., . 21
1.2. Analiza algorytmów ......................................... . 26
l.3. Projektowanie algorytmów .................................... . 32
. . .
131 "·1· 1 zwyaęzaJ
e a ,,..zte
Mtod ..... . . . • . . . . . . . . . . . . . . . . . . . . . . . . . . . . .... . 32
l.3.2. Anali7.llalgorytmówtypu „dziel i zwyciężaj" ....................... . 34
1.4. Podsumowanie ............................................ . 36

Część I Podstawowy aparat matematyczny

2. Rzędy wielkości funkcji . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44


2.1. Notacja asymptotyczna . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
2.2. Standardowe notacje i typowe funkcje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

3. Sumy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
3.1. Wzory i dotyC"Z\(Zsum ...............................
własności . 64
3.2. Szacowanie wartości sum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . 68

4. Rekurencje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.1. Metoda podstawiania ........................................ . 78
4.2. Metoda iteracyjna .......................................... . 82
4.3. Metoda rekurencji uniwersalnej ................................ . 86
* 4.4. Dowód twierdzenia o rekurencji uniwersalnej . . . . . . . . . . . . . . . . . . . .... . 89
4.4.1. Dowód dla dokładnych potęg .................................. . 90
4.4.2. Części całkowite liczb ........................................ . 96

5
SPIS TRESCI

5. Zbiory i nie tylko ..................................... . 103


S.1. Zbiory .................................................. . 103
S.2. Relacje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
S.3. Funkcje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
S.4. Grafy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
S.S. Drzewa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
S.S.I. Drzewa wolne .............................................. 117
S.S.2. Drzewa ukorzenione i uporządkowane . . .......................... 120
S.S.3. Drzewa binarne i pozycyjne . . . . . . . . . . .......................... 121

6. Zliczanie i prawdopodobieństwo ......................... . 126


6.1. Zliczanie ................................................. . 126
6.2. Prawdopodobieństwo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
6.3. Dyskretne zmienne losowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
6.4. Rozkłady geometryczne i dwumianowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
* 6.S. Krańce rozkładu dwumianowego . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ISO
6.6. Ana1iza probabilistyczna . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . I S7
6.6.1. Paradoks dnia urodzin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
6.6.2. Kule i urny . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
6.6.3. Ciągi „dobrej passy'', czyli sukcesów.............................. 162

Część li Sortowanie i statystykipozycyjne


7. Heapsort - sortowanie przez kopcowanie .................. . 173
7.1. Kopce .............................•..•.................. 173
7.2. Przywracanie wla.sności kopca ................................. . 175
7.3. Budowanie kopca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
7.4. Algorytm sortowania przez kopcowanie (heapsort). . . . . . . . . . . . . . . . . . . . 180
1.S. Kolejki priorytetowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181

8. Ouicksort - sortowanie szybkie .................•......... 186


8.1. Opis algorytmu . . . . . . . . . . . . . . . . . . . . . . . . .. . . .. . . . .. .... •. . . . . 186
8.2. Czas działania algorytmu quicksort. . . . . . . . . . .. . . •. . . . •. .... .. . . . . 189
8.3. Probabilistyczne wersje algorytmu quicksort . . . .. . . .. . . . .. •. .. .. . . . . 194
8.4. Analiza algorytmu quicksort. . . . . . . . . . . . . . . .. . . .. . . . .. .... .. . . . . 196
8.4.1. Analiza przypadku pesymistycznego . . . . . . . . . .. . . .. . . . .. .... .. . . . . 196
8.4.2. Analiza przypadku średniego . . . . . . . . . . . . . . .. . . .. . . . .. .... .. . . . . 197

9. Sortowanie w czasie liniowym . . . . . . . . . . . . . . • . . . . . . . . . . . . 206


9.1. Dolne ograniczenia dla problemu sortowania.. . .. .. . . ... . . . . .. .. . . . . 206
92. Sortowanie przez zliczanie . . . . .. . .. .. •. . .. •. .. . . .•. . . . . .. •. . . . . 210
9.3. Sortowanie pozycyjne . . . . . . . .......... .. .. .. . . ... . . . . .. .. . . . . 212
9.4. Sortowanie kubełkowe . . . . . . . .......... .. .. •. . . •.. . . . . .. .. . . . . 215

1O. Mediany i statystyki pozycyjne . . . . • . . . . . . . • . . • . . . . . . . . . . . 220


IO.I. Minim.um i maksimum . . . . . . . . . . . . . . . . • . . . . . . • . . . . . . . . . . . . . . . . 221
10.2. Wybór w ocv:k:iwanym czasie liniowym . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
10.3. Wybór w pesymistycznym czasie liniowym. . . . . . . . . . . . . . . . . . . . . . . . . . 22S

6
SP1STRE$CI

Część 111Struktury danych


11. Elementarne struktury danych • • • • • • • • • • • • • • • • • • • • • • • • • • • • 236
11.1. Stosy i kolejki ............................................. . 236
11.2. Listy .................................................... 240
I 1.3. Reprezentowanie struktur wskaźnikowych za pomocą tablic . . . . . . . . . . . . . 245
l 1.4. Reprezentowanie drzew (ukorzenionych) . . . . . . . . . . . . . . . . . . . . . . . . . . . 249

12. Tablice z haszowaniem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256


12.l. Tablice z adresowaniem bezpośrednim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
12.2. Tablice z haszowaniem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
12.3. Funkcje haszujące . . . . . . . . . . . . . . . ............................ 264
12.3.1. Haszowanie modularne . . . . . . . . . . . .. . ...... .. . ... .. . . ..... .... 265
12.3.2. Haszowanie przez mnożenie . . . . . . . . .. . .... .. .. . ... .. . . ..... .... 266
12.3.3. Haszowanie uniwersalne . . . . . . . . . . . .. . ...... .. . ... .. . . ..... .... 268
12.4. Adresowanie otwarte . . . . . . . . . . . . . .. . ...... .. . ... .. . . ..... .... 271

13. Drzewa poszukiwań binarnych . . . . . . . . . . . . . . . . . . . . . . . . . . . 284


13.l. Co to jest dri.ewo poszukiwań binarnych?. . . . . . . . . . . ... .. . ... .. . .. . 285
13.2. Wyszukiwanie w drzewie poszukiwań binarnych . . . . . . . ... .. . ... .. . .. . 287
13.3. Operacje wstawiania i usuwania . . . . . . . . . . . . . . . . . . ... .. . ... .. . .. . 291
* 13.4. Losowo skonstruowane drzewa poszukiwań binarnych . . ... .. . ... .. . .. . 295

14. Drzewa czerwono-czarne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305


14.1. Własności drzew czerwono-czarnych . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
14.2. Operacje rotacji ............................................ . 308
14.3. Operacja wstawiania ........................................ . 310
14.4. Operacja usuwania ......................................... . 315

15. Wzbogacanie struktur danych . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324


IS.I. Dynamiczne statystyki pozycyjne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
15.2. Jak wzbogacać strukturę danych . . . . . . • . . . . . . . . . . . . . . . . . . . . . . . . . . 330
15.3. Drzewa przedziałowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334

Część IV Zaawansowane metody konstruowania


i analizowania algorytmów
16. Programowanie dynamiczne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
16.1. Mnożenie ciągu macierzy . . . . . . ............ ................ . . . . 347
16.2. Podstawy metody programowania dynamicznego . ................ . . . . 354
16.3. Najdłuższy wspólny podciąg . . . . ............ ................ . . . . 360
16.4. Optymalna triangulacja wielokąta ............ ................ . . . . 366

17. Algorytmy zachłanne ................................... 375


17.1. Problem wyboru zajęć........................................ 376
17.2. Podstawy strategii zachblnnej . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
17.3. Kody Huffmana . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . • . . . . . . . . . . . . . 383

7
SPIS TRE$CI

* 17.4. Teoretyczne podstawy strategii zachłannych......................... 391


17.4.1. Matroidy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
17.4.2. Algorytmy zachłanne na matroidzie ważonym....................... 393
* 17.5. Problem szeregowania zadań . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398

18. Analiza kosztu zamortyzowanego . . . . . . . . . . . . . . . . . . . . . . . . . 403


18.1. Metoda kosztu sumarycznego . . . . . . . . . . . . . . . . .. . . . . . . . . . .. . . . .. . 404
18.2. Metoda księgowania . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . .. . . . .. . 408
18.3. Metoda potencjału . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . .. . . . .. . 411
18.4. Tablice dynamiczne . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . .. . . . .. . 415
18.4.1. Powiększanie tablicy . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . .. . . . .. . 415
18.4.2. Powiększanie i zmniejszanie tablicy . . . . . . . . . . . . .. . . . . . . . . . .. . . . .. . 419

Część V Złożone struktury danych

19. B~drzewa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433


19.l. Definicja B-drzewa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
19.2. Podstąwowe operacje na B-drzewach.. ............................ 440
19.3. Usuwanie klucu z B-drzewa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447

20. Kopce dwumianowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454


20.1. Drzewa i kopce dwumianowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
20.1.1. Drzewa dwumianowe ......................................... 456
20.1.2. Kopce dwumianowe . . . . . . . . . . . . . . . • . . . . . . . . . . . . . . . . . . . . . . . . . 459
20.2. Operacje na kopcach dwumianowych . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460

21. Kopce Fibonacciego . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475


21.l. Struktura kopców Fibonacciego . . . . . ....... . . . . . . . . . . . . . . . . . . . . . 476
21.2. Operacje kopca złączalnego . . . . . . . . ....... . . . . . . . . . . . . . . . . . . . . . 479
21.3. Zmniejszanie wartości klucza i usuwanie węzła . . . . . . . . . . . . . . . . . . . . . . . 488
21.4. Oszacowanie maksymalnego stopnia . . ....... . . . . . . . . . . . . . . . . . . . . . 492

22. Struktury danych dla zbiorów rozłącznych . . . . . . . . . . . . . . . . . . . 498


22.1. Operacje na zbiorach rozłącznych ............................... . 498
22.2. Li st owa reprezentatja.. zb'1orow
. roz~czny
ł _ ..
............................ . SOI
22.3. Lasy zbiorów rozłącmych .................................... . sos
* 22.4. Analiza metody łączenia według rangi z kom.presją ścieżki ...........•.. 509

Część VI Algorytmy grafowe

23. Podstawowe algorytmy grafowe . . . . . . . . . . . . . . . . . . . . . . . . . . 526


23.1. Reprezentacje grafów . . .... . . . . . . . . .. . . . .. . . .. . .. . . . . ... . . . .. . 526
23.2. Przeszukiwanie wszerz . ... . . . . . . . . . •. . . . .. . . .. . .. . . . . ... . . . .. . 530
23.3. Przeszukiwanie w głąb . .... . . . . . . . . .. . . . •. . . .. . .. . . . . .•. . . . .. . 539
23.4. Sortowanie topologiczne ... . . . . . . . . .. . . . .. . . .. . .. . . . . ... . . . .. . S48

8
SPIS TRE$CI

23.5. Silnie spójne składowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 552


24. Minimalne drzewa rozpinające ........................... 562
24.1. Rozrastanie się minimalnego drzewa rozpinającego. . . . . . . . . . . . . . . . . . . . 563
24.2. Algorytmy Kruskala i Prima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 568
25. Najkrótsze ścieżki z jednym źródłem . . . . . . . . . . . . . . . . . . . . . . . 578
25.l. Najkrótsze ścieżki i relaksacja . . . . . . . . . . . . . . . . ...... .......... ... 583
25.2. Algorytm Dijkstry . . . . . . . . . . . . . . . . . . . . . . . . ...... .......... ... 593
25.3. Algorytm Bellmana-Forda . . . . . . . . . . . . . . . . . . ...... .......... ... 598
25.4. Najkrótsze ścieżki z jednym żródlem w acyklicznych grafach skierowanych .. 603
25.5. Ograniczenia różnicowe i najkrótsze ścieżki . . . . . . ...... .......... ... 606

26. Najkrótsze ścieżki między wszystkimi parami wierzchołków . . . . . . 618


26.1. Najkrótsze ścieżki i mnożenie macierzy . . . . . . . . . . . . . . . . . . . . . . . . . . . . 621
26.2. Algorytm Floyda-Warshalla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627
26.3. Algorytm Johnsona dJa grafów rzadkich . . . . . . . . . . . . . . . . . . . . . . . . . . . 634
* 26.4. Ogólny schemat rozwiązywania problemów ścieżkowych w grafach
skierowanych .............................................. 639
27. Maksymalny przepływ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649
27.1. Sieci przepływowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 650
27.2. Metoda Forda-Fulkersona . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 659
27.3. Maksymalne skojarzenia w grafach dwudzielnych . . . . . . . . . . . . . . . . . . . . . 673
* 27.4. Algorytmy przedprzepływowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 678
*27.5. Algorytm „podnieś i przesuń na początek" . . . . . . . . . . . . . . . . . . . . . . . . . 691

Część VII Wybrane zagadnienia



28. Sieci sortuJące ...................................... . 713
. . . .
28.1. S1eC1porownuJą.ce .......................................... . 714
28.2. Zasada zero-jedynkowa ...................................... . 718
28.3. Bitoniczna sieć sortują.ca. ..................................... . 721
28.4. . • se" aJąca
S1ec . ............................................. . 725
28.5. . • rt .
S1ec SO Ująca. , .....••.....••....•......•....•.....• , ....•.. 727

29. Układy arytmetyczne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 733


29.1. Układy kombinacyjne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 734
29.2. Układy sumują.ce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 739
29.2.l. Sumator szeregowy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 739
29.2.2. Sumator równoległy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 741
29.2.3. Sumator z zapamiętywaniem przenie&ień . . . . . . . . . . . . . . . . . . . . . . . . . . . 747
29.3. Układy mnożące . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 750
29.3.l. Tablicowy układ mnożący ........... : . . . . . . . . . . . . . . . . . . . . . . . . . 151
29.3.2. Drzewa Wallace'a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 755
29.4. Układy z taktowaną pamięcią. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 758
29.4.1. Bitowy sumator szeregowy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 758
29.4.2. Wektorowe układy mnożą.ce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 761

9
$PIS TREŚCI

30. Algorytmy równoległe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 769


30.1. Przeskakiwanie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ........... . 774
30.1.1. UsWanie porządku obiektów na liście ............................ . 774
30.1.2. Równoległe obliczenia prefiksowe na liście ......................... . 778
30.1.3. Metoda cyklu Eulera ........................................ . 780
30.2. Algorytmy typu CRCW a algorytmy typu EREW ................... . 784
30.3. Twierdzenie Brenta i sekwencyjna efektywność ...................... . 792
* 30.4. Sekwencyjnie efektywne równoległe obliczenia prefiksowe .............. . 797
30.5. Detenninistycme łamanie symetrii . . . . . . . . . . . . . . . . . . . . . . ........ . 804

31. Operacje na macierzach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 815


• . .
31.I. Wł w;noSCJ macierzy . . . . . . . . . . . . . . . . . . . . . . . . . . . . ............. . 826
31.2. Algorytm Strassena mnot.enia macierzy ........................... . 826
*31.3. Różne struktury algebraiczne i mnożenie macierzy boolowsk.ich ......... . 834
31.4. Rozwiązywanie układów równań liniowych ........................ . 839
31.S. Odwracanie macierzy ........................................ . 853
31.6. Symetryczne macierze dodatnio określone i metoda najmniejszych
kwadratów . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 858

32. Wielomiany i FFT ............................... , . . . . . 870


32.J. Reprezentacja wielomianów ................................... . 872
32.2. DFT i FFT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 879
32.3. Efektywne implementacje FFT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 887

33. Algorytmy teorioliczbowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 897


33.1. Podstawowe pojęcia teorii liczb . . . . . . . . . . . . . ..................... 898
33.2. Największy wspólny dzielnik . . . . . . . . . . . . . . ..................... 905
33.3. Arytmetyka modularna ....................................... 911
33.4. Rozwiązywanie liniowych równań modularnych. ..................... 918
33.5. Chińskie twierdzenie o resztach . . . . . . . . . . . . . ..................... 922
33.6. Potęgi elementu . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . 926
33.7. System kryptograficzny z kluC7.Cllljawnym RSA . . .. . . . . . . . . . . . . . . . . . 930
* 33.8. Sprawdzanie, czy liczba jest liczbą pierwszą . . . . . . .. . . . . . . . . . . . . . . . . . 937
* 33.9. Rozkład na czynniki . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . 946

Al- ...
34. Wyszukiwanie wzorca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 956
34.1. go „naiwny wyszu !ci'wania wzorca ......................... . 958
34.2. Algorytm Rabina-Karpa ..................................... . 960
34.3. Wyszukiwanie wzorca z wykorzystaniem automatów skończonych ........ . 965
34.4. Algorytm Knutha-Morri.sa-Pratta ............................... . 972
* 34.5. Algorytm Boyera-Moore'a .................................... . 980

35. Geometria obliczeniowa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 990


35.1. Własności odcinków . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 991
35.2. Sprawdzanie, czy jakakolwiek para odcinków się przecina . . . . . . . . . . . . . . . 996
35.3. Znajdowanie wypukłej otoczki . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1003
35.4. Znajdowanie pary najmniej odległych punktów ...................... 1013

10
SPIS TRE$CI

36. NP-zupełność ........................................ 1022


36.l. Czas wielomianowy .......................................... 1023
36.2. Weryfikacja w czasie wielomianowym ............................. 1031
36.3. NP-zupełność: i redukowalność .................................. 1036
36.4. Dowodzenie NP-zupełności .................................... 1046
36.S. Problemy NP-zupełne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10S4
36.S.L Problem kliki . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . IOS4
36.S.2. Problem pokrycia wienchołkowego ............................... IOS7
36.S.3. Problem sumy podzbioru ...................................... IOS9
36.S.4. Problem cyklu Hamiltona ..................................... 1062
36.5.S. Problem komiwojażera ........................................ 1068

37. Algorytmy aproksymacyjne .............................. 1013


37.1. Problem pokrycia wierzchołkowego ............................... 1076
37.2. Problem komiwojażera ........................................ 1078
37.2.L Problem komiwojażera z nierównością trójkąta ...................... 1079
37.2.2. Ogólny problem komiwojażera .................................. 1082
37.3. Problem pokrycia zbioru ...................................... 1084
37.4. Problem sumy podzbioru ...................................... 1089

Literatura ......................................•........ 1091

Skorowidz ..........•..•................................ 1101


Przedmowa

Książka jest wprowadzeniem do nowoczesnych metod badania algorytmów.


Przedstawiliśmy w niej dogłębną analizę wielu algorytmów, przy czym staraliś­
my się zrobić to w sposób zrozumiały dla każdego.
W poszczególnych rozdziałach omawiamy algorytmy, metody ich projek-
towania, dziedziny ich zastosowań lub inne pokrewne zagadnienia. Algorytmy
są zapisane w „pseudojęzyku" programowania, który jest zrozumiały dla każ­
dego, kto ma choć odrobinę praktyki programistyc-znej. Książka zawiera po-
nad 260 rysunków obrazujących działanie algorytmów. Ponieważ naszym kry-
terium optymalności algorytmów jest ich „złożoność", przedstawiamy szci.egó-
łową analizę czasu ich działania.
Książka ta jest przeznaczona dla słuchaczy wyk.ładów z algorytmów i struk-
tur danych, jak również dla osób, które ze względów zawodowych interesu-
ją się tą tematyką.

Do wykładowcy
Książka jest uniwersalna. Może być wykorzystana do wykładów z algorytmów
i struktur danych na różnym poziomie zaawansowania. Ponieważ zawarliśmy
w niej macznie więcej materiału niż to konieczne do semestralnego wykładu,
można ją traktować jak „worek", z którego wybiera się to, co akurat najbar-
dziej pasuje do danego wykładu.
Najlepiej przygotować zajęcia ze studentami według wcześniej wybranych
rozdziałów. Treść rozdziałów jest w dużym stopniu niezależna, a więc nie
powinno być z tym problemów. Złożoność materiału przedstawionego w każ­
dym rozdziale jest stopniowana - od problemów mało skomplikowanych do
bardziej skomplikowanych. Na wykładach dla początkujących można korzy-
stać jedynie z pierwszych podrozdziałów każdego rozdziału, a na zajęciach

13
PRZEDMOWA

ze studentami wprowadzonymi już w tę tematykę odwoływać się do pełnych


rozdziałów.
Książka zawiera ponad 900 zadań i ponad 120 problemów. Każdy pod-
rozdział kończy się zadaniami, a każdy rozdział zestawem problemów, Za-
dania to przeważnie krótkie pytania, które pomogą ugruntować wiedzę zdo-
bytą w danym rozdziale. Jedne z nich rozwiązuje się w mgnieniu oka, inne
wymagają dłuższego przemyślenia. Problemy są hardziej skomplikowane i czę­
sto obejmują nowy materiał; przeważnie zawierają kilka pytań o różnym sto-
pniu trudności.
Bardziej złożone części materiału są oznaczone gwiaz.dką (*). Nie zawsze
są trudniejsze, ale wymagają znajomości bardziej zaawansowanej matematyki,
lepszego przygotowania lub większej wyobraźni algorytmicznej.

Do studenta
Mamy nadzieję, że książka ta łagodnie wprowadzi Cię w problemy dotyczące
algorytmiki. Staraliśmy się, aby każdy algorytm był zrozumiały i interesujący.
Każdy krok algorytmu jest opisany tak, abyś nie miał kłopotów ze zgłębieniem
skomplikowanej strok.tury całego algorytmu. Przedstawiamy też aparat mate-
matyczny potrzebny do analizy algorytmów. Jeśli masz już pewne doświadcze­
nie w tej dziedzinie, możesz pominąć początkowe rozdziały.
Książka jest dosyć obszerna, a wykład będzie prawdopodobnie obejmował
tylko część zawartego w niej materiału. Chcieliśmy jednak., aby spełniała funk-
cję swego rodzaju encyklopedii przydatnej potem w pracy zawodowej.
Czego wymagamy od czytelnika?
• Powinien mieć pewne doświadczenie programistyczne. W szczególności po-
winien wiedzieć, na czym polega rekursja, i znać elementarne struktury da-
nych, takie jak. tablice i listy.
• Powinien umieć przeprowadzać dowody przez indukcję matematyczną. Nie-
które części książki wymagają elementarnej znajomości analizy matema-
tycznej. W części I zawarliśmy jednak. cały potrzebny tu materiał mate-
matyczny.

Do informatyka pracującego zawodowo


Książka ta jest doskonałym kompendium algorytmów. Ponieważ rozdziały są
niezależne, można się skoncentrować na problemach, które czytelnika w danej
chwili interesują. Większość prezentowanych algorytmów ma duże znaczenie
praktyczne; rozważamy zatem aspekty praktycznej ich realizacji. Dla niektó-
rych z niewielu algorytmów „teoretycznych" przedstawiamy alternatywny
algorytm „praktyczny". Jeśli chce się zaimplementować któryś z podanych

14
PRZEDMOWA

algorytmów, wystarczy przetłumaczyć go z naszego pseudojęzyka na wybrany


język programowania. Pseudojęzyk umożliwia zwartą i precyzyjną prezentację
algorytmu, Nie uwzględniamy w nim zatem obsługi błędów ani innych tech-
nicznych aspektów zwiąvinych z konkretnym środowiskiem programistycz-
nym. Poza tym, nie korzystając z rzeczywistego języka, pomijamy inne szcze-
góły techniczne dotyczące takiego języka, które mogłyby zaciemnić zrozumie-
nie algorytmu.

Błędy

W książce takiej objętości niewątpliwie nie da się uniknąć pewnych błędów


i braków. Będziemy wdzięczni za przekazanie nam wszelkich uwag. Szczegól-
nie mile będą widziane propozycje nowych ćwiczeń i problemów, ale prosimy
o dołączanie rozwiązań. Można je przesłać na adres
Introduction to Algorithms
MIT Laboratory for Computer Science
545 Technology Square
Cambridge, Massachusetts 02139
Można też użyć poczty elektronicznej, aby przekazać nam opisy błędów, po-
prosić o listę znanych błędów lub podzielić się konstruktywnymi uwagami. Oto
adres, na który należy się zwracać:

algorithms@theory .lcs.mit.edu,

pisząc w nagłówku listu Subject: help. Od razu zastrugamy się, że nie jesteśmy
w stanie odpowiedzieć na wszystkie listy osobiście.

Podziękowania

Wielu przyjaciół i kolegów znacznie się przyczyniło do poleps:renia jakości tej


książki. Dziękujemy im wszystkim za pomoc i konstruktywną krytykę.
MIT's Laboratory for Computer Science zapewniło idealne środowisko do
pracy. Nasi koledzy z grupy informatyki teoretycznej byli szc:rególnie toleran-
cyjni wobec naszych nieustających próśb o krytyczną ocenę rozdziałów. Na
szczególne podziękowania zasłużyli Baruch Awerbuch, Sbafi Goldwasser, Leo
Guibas, Tom Leighton, Albert Meyer, David Shmoys i Eva Tardos. Dziękuje­
my Williamowi Angowi, Sally Bem.us, Rayowi Hirschfeldowi oraz Markowi
Reinholdowi za dbałość o nas:ze komputery (DEC Microvax, Apple Macintosh
i Sun Sparcstation), jak również za rekompilację TEX-a, kiedy tylko przekra-
czaliśmy limit czasu kompilacji. Firma Thinking Machines Corporation częś­
ciowo sfinansowała pracę Charlesa Leisersona nad tą książką w czasie jego
nieobecności w MIT.

15
PRZEDMOWA

Wielu naszych kolegów użyło roboczych wersji tej książki na wykładach


na innych uczelniach. Wprowadzili wiele poprawek i zmian. Szczególnie dzię­
kujemy Richardowi Beigelowi (Yale), Andrew Goldbergowi (Stanford), Joan
Lucas (Rutgers), Markowi Overmarsowi (Utrecht), Alanowi Shermanowi
(fufts and Maryland) i Diane Souvaine (Rutgers).
Wielu naszych asystentów wniosło znaczący wkład w powstanie tej książ­
ki. Na naszą wdzięczność zasłużyli Alan Baratz, Bonnie Berger, Aditi Dhagat,
Burt Kaliski, Arthur Lent, Andrew Moulton, Marios Papaefthymiou, Cindy
Phillips, Mark Reinhold, Phil Rogaway, Flavio Rose, Arie Rudich, Alan Sher-
man, Qiff Stein, Snsroita Sur, Gregory Troxel i Margaret Tuttle.
Wiele osób służyło nam pomocą techniczną. Denise Sergent spędził wiele
godzin w bibliotekach MIT na przeglądaniu bibliografii. Maria Sensale, biblio-
tekarka naszej czytelni, zawsze była dla nas bardzo wyrozumiała. Z.ezwolenie
na korzystanie z prywatnej biblioteki Alberta Meyera zaoszczędziło nam wielu
godzin przeznaczonych na przygotowanie notatek do poszczególnych rozdzia-
łów. Shlomo Kipnis, Bill Niehaus i David Wilson sprawdzali stare zadania,
tworzyli nowe oraz robili notatki na temat ich rozwiązywania. Marios Papa-
efthymiou i Gregory Troxel pomagali przy robieniu skorowidza. Przez całe
lata nasze sekretarki Inna Radzihovsky, Denise Sergent, Gayle Sherman,
a przede wszystkim Be Hubbard pomagały nam w naszych pracach nad teks-
tem, za co serdecznie im dziękujemy.
Wiele błędów w roboczych wersjach książki zostało wykrytych przez stu-
dentów. N a naszą wdzięczność zasługują Bobby Blumofe, Bonnie Eisenberg,
Raymond Johnson, John Keen, Richard Lethln, Mark Llllibridge, John Peza-
ris, Steve Ponzio i Margaret Tuttle.
Dziękujemy naszym kolegom za krytyczne uwagi do niektórych rozdzia-
łów i na temat pewnych algorytmów. W szczególności jesteśmy wdzięczni Bil-
lowi Aiello, Alkowi Aggarwalowi, Erik.owi Bachowi, Vaikowi Chv3.talowi, Ri-
chardowi Cole'owi, Johanowi Hastadowi, Alexowi Ishiemu, Davidowi John-
sonowi, JOeJDu Kilianowi, Dinie Kravets, Bruce'owi Maggsowi, Jimowi Or-
linowi, Jamesowi Parkowi, Thane'owi Plambeckowi, Herschelowi Saferowi,
Jeffowi Shallitowi, Cliffowi Steinowi, Gilowi Strangowi, Bobowi Tarjanowi,
Paulowi Wangowi. Niektórzy z naszych kolegów zaproponowali nowe prob-
lemy do rozwiązania. Byli to Andrew Goldberg, Danny Sleator i Umesh Vazi-
rani. Bardzo im za to dziękujemy.
Książka ta została złożona t za pomocą systemu LATE)(. Rysunki zostały
wykonane na komputerze Apple Macintosh z użyciem MacDraw II; dziękuje­
my Joannie Terry z Qaris Corporation i Michaelowi Mahoneyowi z Advanced
Computer Graphics za wkład w te prace. Skorowidz został utworzony za po-
mocą programu Windex, napisanego w języku C. Bibliografia. została przygo-

' Dotyczy oryginahi (przyp. red.).

16
PRZEDMOWA

towana z użyciem systemu BIBTEX. Książka została złożona w American


Mathematical Society za pomocą systemu Autologic; dziękujemy za to Ralp-
howi Youngenowi z AMS. Okładka została zaprojektowana przez Jeannet Le-
endertse. Projekt typograficzny książki został opracowany przez Rebeckę
Daw. Amy Hendrickson zaimplementowała ten projekt w systemie LATEX.
Było dla nas prawdziwą przyjemnością pracować przy tworzeniu tego tek-
stu z MIT Press i McGraw-Hill. Szczególnie dziękujemy Frankowi Satlowowi,
Terry'emu Ehlingowi, Larry'emu Cohenowi i Lorrie Lejeune z MIT Press oraz
Davidowi Shapiro z wydawnictwa McGraw-Hill za podtrzymywanie nas na
duchu i cierpliwość. Jesteśmy S7.Czególniewdzięczni Larry'emu Cohenowi za
doskonałe zredagowanie książki.
Na koniec dziękujemy naszym żonom - Nicole Carmen, Lindzie Lue Lei-
serson i Gaił Rivest- oraz naszym dzieciom - Ricky'emu, WiJJiamowi i Debby
Leisersonom, Alexowi i Christopherowi Rivestom - za miłość i pomoc w czasie
pisania książki. (Alex Rivest pomógł również przy „paradoksie dnia urodzin
Marsjan").
Książka ta powstała dzięki miłości, cierpliwości i pomocy naszych rodzin.
To im dedykujemy tę książkę.

Cambridge, Massachusetts THOMAS H. CoRMEN


March 1990 CHARLES E. LEISERSON
RONALD L. RIVEST
Wprowadzen
do algorytmów
Rozdział 1

Wstęp

W tym ro7.dziale zaznajomimy czytelnika z podstawowymi narzędziami wyko-


rzystywanymi przy projektowaniu i analizie algorytmów. Nie jest tu wymaga-
na znajomość dodatkowych wiadomości, chociaż znajduje się kilka odwołań
do materiału, który będzie przedstawiony w części I.
Rozpoczniemy od ogólnego omówienia problemów oblicuniowych i al-
gorytmów służących do ich rozwiązywania. Naszym wiodącym przykładem
będzie sortowanie. Wprowadzimy „pseudojęzyk" (umowny językf) prograIDo-
wania służą.cy do specyfikowania algorytmów, który nie powinien sprawiać
trudności czytelnikom mającym jakąkolwiek praktykę programistyczną. Na
poc-zątku rozważymy prosty algorytm sortowania, a mianowicie sortowanie
przez wstawianie. Przeanalizujemy czas działania tego algorytmu i wprowadzi-
my notację określającą zależność czasu działania od liczby sortowanych ele-
mentów. Przedstawimy również metodę „dziel i zwyciężaj", użyteczną przy
projektowaniu pewnych algorytmów. Metody tej użyjemy w sortowaniu przez
scalanie. Zak:ońC'lymy porównaniem obu zaprezentowanych algorytmów.

1.1. Algorytmy
Nieformalnie, algorytm jest pewną. ściśle określoną procedurą. obliczeniową,
która dla właściwych danych wejściowych „produkuje" żądane dane wyjściowe
zwane wynikiem działania algorytmu. Algorytm jest więc ciągiem kroków obli-
czeniowych prowadzących do przekształcania danych wejściowych w wyjściowe.
Algorytm możemy również traktować jako sposób rozwiązania konkret-
nego problemu obliczeniowego. Postawienie problemu polega na sprecyzowaniu

t Będzie również stosowane zamiennie określenie „pseudokod" (przyp. red.).

21
ROZDZIAŁ 1. WSTĘP

wymagań dotyczących relacji między danymi wejściowymi i wyjściowymi, a al-


gorytm opisuje właściwą procedurę obliczeniową, która zapewnia, że ta relacja
zostanie osiągnięta.
Przegląd algorytmów rozpoczynamy od algorytmów sortowania. Sortowa-
nie polega na ustawieniu liczb z danego ciągu w porządku niemalejącym. Prob-
lem ten występuje często w praktyce i jest źródłem wielu standardowych metod
projektowania i narzędzi analizy algorytmów. Poniżej podajemy formalną de-
finicję problemu sortowania.

Dane wejściowe: Ciąg n liczb (a 1 , a2 , ... , an>·


Wynik: Permutacja (7miana uporządkowania) (a.1, a2,..., a;) ciągu wejścio-
., a .::s;;a ,~'""' ••• .:::;;On.
wego t aka , ze 1 2

Dla ciągu wejściowego (31, 41, 59, 26, 41, 58) wynikiem działania algorytmu
sortowania będzie ciąg wyjściowy (26, 31, 41, 41, 58, 59). Taki ciąg wejściowy
jest nazywany „egzemplarzem" problemu sortowania. Ogólnie, egzemplarz
problemu składa się z określonych danych wejściowych spełniających wszyst-
kie warunki podane w opisie problemu.
Sortowanie ma liczne zastosowania w informatyce (w wielu programach
jest wykorzystywane jako krok pośredni), czego rezultatem jest opracowanie
dużej liczby dobrych algorytmów sortujących. Optymalność algorytmu w da-
nym zastosowaniu zależy od liczby sortowanych elementów, stopnia posor-
towania elementów na wejściu oraz rodzaju użytej pamięci: RAM, dysk lub
taśma.
Algorytm jest poprawny, gdy dla każdego egumplam problemu algorytm
zatrzymuje się i daje dobry wynik. Mówimy wtedy, że poprawny algorytm
„rozwiązuje" zadany problem obliczeniowy. Algorytm niepoprawny może się
nigdy nie zatrzymać albo po zatrzymaniu dać zły wynik. Niepoprawne algoryt-
my mogą być jednakże użyteczne, jeśli ich błędne działanie może być kont-
rolowane. Zobaczymy to na przykładzie algorytmów znajdowania dużych liczb
pierwszych, w rozdz. 33. Z reguły jednak: nie będziemy się zajmować algoryt-
mami niepoprawnymi.
Algorytm można przedstawić w postaci programu komputerowego albo
zrealizować sprzętowo. Jedynym wymaganiem jest precyzja opisu wynikającej
z niego procedury obliczeniowej,
W tej książce będziemy przeważnie zapisywać algorytmy w pseudojęzyku
programowania, który jest bardzo podobny do C, Pascala lub Algolu. Jeśli
czytelnik zna któryś z tych języków, to nie powinien mieć trudności w rozumie-
niu nas2:egopseudojęzyka programowania. W takim pseudojęzylru (w odróż­
nieniu od „prawdziwych" języków programowania) będziemy używać większej
gamy sposobów do wyrażenia konkretnych kroków algorytmu. Czasami naj-
lepszym sposobem jest wyrażenie czegoś w języku naturalnym; czytelnik: nie

22
1.1. ALGORYTMY

powinien być zatem 7.dziwiony, gdy wewnątrz programu napotka zdania w ję­
zyku polskim. Pseudojęzyk różni się też tym od „prawdziwego" języka, że
nie uwzględnia się tu technik programowania. Problemy abstrakcji danych,
modularności i obsługi błędów są często ignorowane w celu uproszczenia opisu
algorytmu.

Sortowanie przez wstawianie


Rozpoczynamy od sortowania przez wstawianie, które jest efektywnym algoryt-
mem sortowania dla niewielkiej liczby elementów. Algorytm ten działa w taki
sposób, w jaki często ludzie porządkują talię kart. Zaczynamy od „pustej"
lewej ręki, po czym bierzemy ze stołu kolejne karty i wstawiamy je we właściwe
miejsca w talii kart, trzymanej w lewej ręce. Aby znaleźć właściwe miejsce dla
danej karty, porównujemy ją z kartami, które już mamy w ręce, przesuwając
się od strony prawej do lewej (patrz rys. 1.1).

. .
4
"' " ,o..

••
~
• •.....
•.o, ~

Rys. 1.1. Sortowanie talii kart za pomocą sortowania przez wstawianie

Sortowanie przez wstawianie (zapisane w naszym pseudojęzyku) jest przedsta-


wione jako procedura o nazwie INSERTION-SORT,której parametrem jest tabli-
ca A[l .. n] zawierająca ciąg długości n, który mamy posortować. (W pseudo-
języku liczba n elementów tablicy A jest oznaczona przez length[A]). Elementy
wejściowej tablicy są sortowane w miejscu, to znaczy, że są one przechowywane
cały czas w tej samej tablicy, z wyjątkiem stałej liczby elementów. Kiedy proce-
dura jest zakończona, tablica A zawiera posortowany ciąg wyjściowy.

INSERTION-SORT(A)
1 for j +- 2 to length{A]

23
ROZDZIAŁ 1. WSTĘP

2 do key - A[j]
3 t> Wstaw A[j] w posortowany ciąg A[l ..j - I].
4 i+-j-1
5 while i> O i A[i] > key
6 do A[i + I] - A[i]
7 i+-i-1
8 A[i+IJ-key

Na rysunku 1.2 widać działanie algorytmu dla tablicy A= (5, 2, 4, 6, 1, 3).


Indeks j wskazuje „kartę bieżącą", która jest właśnie wstawiana do talii kart
w ręce. Elementy tablicy A[l ..j - 1] reprezentują karty trzymane w ręce, a ele-
menty AU+ 1 .. n] odpowiadają stosowi kart na stole. Indeks j przesuwa się od
strony lewej do prawej. W każdej iteracji zewnętrznej pętli for element .A.[j]jest
pobierany z tablicy (wiersz 2). Następnie, począwszy od pozycjij - 1, elementy
są sukcesywnie przesuwane o jedną pozycję w prawo, aż zostanie znaleziona
właściwa pozycja dla .A.[j](wiersze 4-7) i wtedy ten element zostaje tam wsta-
wiony (wiersz 8).

5 2 4 6 I 3

2 5 4 6 1 3

~
2 4 5 I 3

~
2 4 5 6
9) 3

1 2
~
4 5 6
9)
I 2 3 4 5 6 Posortowane
Rys. 1.2. Działanie procedury INSl\RTION-SoRTdla. tablicy A= (S, 2, 4, 6, I, 3). Pozycja o indeksie
j jest oznaczona kółkiem

Konwencjeprzyjęte w stosowanym pseudojęzyku programowania


W naszym pseudojęzyku używamy następujących konwencji.

1. Wcięcia odpowiadają strukturze blokowej. Na przykład treść pętli for, któ-


ra zaczyna się w wierszu 1, zawiera się w wierszach 2-8, a treść pętli while,
która zaczyna się w wierszu 5, zawiera się w wierszach 6-7, ale nie obejmuje
wiersza 8. Nasz styl wcięć odnosi się również do instrukcji if-tben-else. Za-

24
stosowanie wcięć zamiast normalnych oznaczeń struktury blokowej, takich
jak begin i end, znacznie redukuje liczbę detali, zachowując (a nawet pod-
nosząc) klarowność prezentacji tJ.

2. Konstruktory iteracji while, for i repeat oraz warunkowe if, tb.en i else mają
tutaj tę samą interpretację co w Pascalu.
3. Symbol „t> '' oznacza, że reszta wiersza jest komentarzem.
4. Wielokrotne przypisywanie w formie i+- j +- e oznacza przypisanie zmien-
nym i oraz j wartości wyrażenia e; jest ono równoważne przypisaniu j +- e
łącznie z przypisaniem i+- j.
5. Zmienne (takie jak i,j oraz key) są lokalne w danej procedurze. Nie używa­
my zmiennych globalnych bez 2'.B7naczania tego explicite.
6, Dostęp do elementu tablicy odbywa się przez podanie jej nazwy i indeksu
żądanego elementu. Na przykład A[i] jest i-tym elementem tablicy A. Nota-
cja ,, .." służy do wyznaczania podtablicy. Tak więc A[l ..J] jest podtablicą
składającą się z elementów A[l], A[2], ... , A[j].
7. Dane złożone z kilku części są organizowane jako obiekty, składające się
z atrybutów lub pól. Konkretne pole jest podane przez nazwę pola, a następ­
nie identyfikator obiektu w nawiasach kwadratowych. Tablica może być na
przykład obiektem z atrybutem /ength mówiącym o liczbie jej elementów.
Aby określić liczbę elementów w tablicy A, piszemy /ength[A]. Sposób
użycia nawiasów kwadratowych będzie zawsze jednoznacznie wynikać
z kontekstu.
Zmienna odpowiadająca tablicy lub obiektowi jest traktowana jako
wskaźnik do danych reprezentujących tę tablicę lub ten obiekt. Dla wszyst-
kich pól/ obiektu x, przypisanie y +- x powoduje/[y) = / [x]. Ponadto jeśli
teraz wykonamy /[x] +- 3, to w następstwie nie tylko f[x] = 3, lecz także
/[y] = 3. Inaczej mówiąc, x i y wskazują na te same obiekty (są tymi samy-
mi obiektami) po przypisaniu y +- x.
Czasami wskaźnik na nic nie wskazuje; ma wtedy specjalną wartość
NIL.
8. Parametry są przekazywane do procedury przez wartość: wywoływana pro-
cedura otrzymuje swoją kopię parametrów, a zmiany wewnętrze tych kopii
nie są widoczne przez program wywołujący. Obiekty są przekazywane przez
wskaźniki do nich. Jeśli na przykład x jest parametrem procedury, to przy-
pisanie x +- y wewnątrz procedury jest niewidoczne na zewnątrz. Jednakże
przypisanie f[x] +- 3 jest widoczne.

1
> W prawdziwych językach programowania zazwyczaj nie używa się samych wcięć do za.
znaczenia struktury blokowej, ponieważ poziomy wcięc są trudne do określenia, kiedy tekst pro-
gramu jest dzielony na strony.

25
ROZDZIAŁ 1. WSTĘP

ZADANIA

1.1-1. Zilustruj (podobnie jak na rys. 1.2) działanie procedury INSERTION-


-SORT dla tablicy A= (31, 41, 59, 26, 41, 58).
1.1-2. Zmodyfikuj procedurę INSERTION-SORT tak, żeby sortowała w porzą­
dku nierosnącym.
1.1-3. Rozważmy następujący problem wyszukiwania:
Dane wejciowe: Ciąg n liczb A= (a 1 , a 2 , a 11) i wartość v.
••• ,
Wynik: Indeks i talci, że v = A[i] lub NIL, jeśli v nie jest zawarte w A.

Napisz algorytm wyszukiwania liniowego, który przegląda ciąg A od strony


lewej do prawej, szukając v.
1.1-4. Rozważmy problem dodawania dwóch n-bitowych liczb binarnych, pa-
miętanych jako n-elementowe tablice A i B. Wynik ma być w postaci
(n+ 1)-elementowej tablicy C. Sformułuj problem formalnie i napisz
w przyjętym tu pseudojęzyku procedurę sumownia dwóch liczb tego typu.

1.2. Analizaalgorytmów
Analiza algorytmu polega na określeniu zasobów, jalcie są potrzebne do jego
wykonania. Zasobem zasadniczym jest dla nas czas obliczeń, jednakże innymi
zasobami mogą być: pamięć, szerokość kanału komunikacyjnego lub układy
logiczne. Zwykle analizowanie kilku algorytmów dla tego samego problemu
prowadzi do wyboru najoptymalniejszego z nich.
Przed przeprowadzeniem analizy algorytmu musimy wybrać odpowiedni
model realizowania obliczeń, uwzględniając zasoby dostępne w przyjętej tech-
nologii i ich koszty. W większej części tej książki będziemy przyjmować, że
naszym podstawowym modelem obliczeń jest jednoprocesorowa maszyna o do-
stępie swobodnym do pamięci (w skrócie RAM od ang. Random Access Machi-
ne), a nasze algorytmy są realizowane jako programy komputerowe. W modelu
RAM instrukcje są wykonywane jedna po drugiej (sekwencyjnie). W dalszych
rozdziałach będziemy mieli sposobność badania modeli obliczeń równoległych
(dla komputerów równoległych) oraz modeli dla sprzętowych implementacji
algorytmów.
Czasami zanalizowanie nawet prostego algorytmu może być wyzwaniem.
Trzeba przy tym korzystać z kombinatoryki, rachunku prawdopodobieństwa,
wykazać się sprawnością w obliczeniach algebraicznych czy też umieć ziden-
tyfikować naistotniejsze człony pewnych wzorów. Ponieważ zachowanie się
algorytmu może być różne dla różnych możliwych danych wejściowych, po-
trzebujemy środków do wyrażania tego zachowania w postaci prostych, łat­
wych do zrozumienia formul.

26
1.2. ANALIZA ALGORYTMÓW

Chociaż do analizy danego algorytmu wybieramy z reguły tylko jeden


model obliczeń, mamy jednak wiele możliwości przedstawienia naszej analizy
algorytmu. Bezpośrednim celem jest znalezienie takiego sposobu analizy, aby
był on łatwy do zapisania i przekształcania, wyrażał najważniejsze właściwości
algorytmu i pomijał zbędne szczegóły.

Analiza sortowania przez wstawianie


Czas działania procedury INSERTION-SORT zależy od danych wejściowych:
sortowanie tysiąca elementów pochlania więcej czasu niż tr:rech elementów.
Ponadto czas ten zależy również od stopnia posortowania ciągów wejściowych.
W ogólności czas działania algorytmu rośnie razem z rozmiarem danych wej-
ściowych, tak więc tradycyjnie zapisujemy czas działania jako funkcję tego
rozmiaru. Musimy zatem precyzyjniej zdefiniować pojęcia: ,,czas działania"
i „rozmiar danych wejściowych".
Defmicja rozmiaru danych wejściowych zależy istotnie od rozważanego
problemu. W wielu problemach, takich jak sortowanie lub obliczanie dyskret-
nej transformaty Fouriera, najbardziej naturalną miarą jest liczba elementów
w ciągu wejściowym - na przykład liczba n elementów do posortowania. W in-
nych problemach, takich jak mnożenie dwóch liczb całkowitych, najlepszą
miarą rozmiaru danych wejściowych jest całkowita liczba bitów, potrzebnych
do reprezentowania tych danych w postaci binarnej. Czasami bardziej odpo-
wiednie do opisania rozmiaru jest użycie dwóch liczb. Jeśli na przykład dane
wejściowe stanowi graf, to ich rozmiar jest zadany liczbą wierzchołków i liczbą
krawędzi, występujących w tym grafie. Dla każdego rozważanego problemu
będziemy określać, co jest przyjęte za rozmiar danych wejściowych.
Czas działania algorytmu dla konkretnych danych wejściowych jest wyra-
żony liczbą wykonanych prostych (elementarnych) operacji lub „kroków". Jest
dogodne zrobienie założenia, że operacja elementarna jest maszynowo nieza-
leżna. Na razie przyjmujemy, że do wykonania jednego wiersza naszego pro-
gramu wymagamy stałego czasu. Wykonanie jednego wiersza programu nie
musi trwać tyle co wykonanie innego wiersza. My zakładamy, że każde wyko-
nanie i-tego wiersza wymaga czasu c1, przy czym c1 jest stalą. Taki punkt
widzenia jest zgodny z przyjętym modelem RAM i odzwierciedla sposób im-
plementacji naszego programu na nowoczesnych komputerach 1>.

ii Pojawiają. siętu pewne subtelności. Kroki obliczenia, które wyrażamy w języku natural-
nym, to często odwołania do procedur, których wykonanie może wymagać czasu dłuższego niż
stały. Możemy na przykład powiedzieć „posortuj punk.ty względem x", co, jak. się przekonamy,
zabiera czas dłuższy niż stały. 2'.a.uważmy też, że instrukcja polegające. na wywołaniu procedury
zajmuje czas stały, wykonanie zaś tej procedury może trwać dłużej, tzn. odróżniamy proces wywo-
łania procedury - przekazywania jej parametrów itd. - od procesu wykonywania tej procedury.

27
ROZDZIAŁ 1. WSTĘP

W prowadzonych poniżej rozważaniach wyrażenie opisujące czas działania


algorytmu INSERTION-SORT otrzymamy w wyniku uproszczenia skompliko-
wanej formuły, w której wykorzystuje się koszty c1, czyniąc go bardziej zwięz­
łym i łatwiejszym do przekształceń. Ta uproszczona notacja pozwala łatwo
rozstrzygać, które z algorytmów są bardziej efektywne.
Rozpoczynamy od prezentacji procedury INSERTION-SORT z podanym
.,kosztem" każdej instrukcji i liczbą jej wykonań. Dla każdego j = 2, 3, ... , n,
gdzie n = length[A],niech t1 będzie liczbą sprawdzeń warunku wejścia do pętli
wbile w wierszu 5 dla danej wartości j. Uwaga: nie liczymy kosztu wykonania
komentarzy.

INSERTION-SORT(A) koszt liczba wykonań


I for j +- 2 to length[A] c, n
2 do key -A[j] c, n-I
3 t> Wstaw A[j] do posortowanego ciągu o n-I
I> A[l ..j - I].
4 i*"'"j-1 c. n-I
5 while i> O i A[i] > key •
c, L ,,
J=2
6 do A[i + I] -A[i] •
c, L <1,-1J
i"" 2
7 i+-i-1 •
c, L <1,-1J
J=2
8 A[i+ I]-key c, n-I

Czas działania algorytmu jest sumą czasów wykonania poszcz.ególnych


instrukcji; jeśli instrukcja wykonuje się w czasie c1 i jest powtarzana n razy, to
mamy w sumie czas c;n''·Aby obliczyć czas działania T(n) procedury INSER-
TION-SORT, sumujemy iloczyny kosztów i liczby wykonań, otrzymując

• •
T(n) - c1 n + c2 (n - I)+ c4 (n - I)+ c, L ,,+ c, L (t, - I)
J=2 J=2

+ c, L (t, - I) + c,(n - I)
J=2

1
>Nie stosuje się to na przykład do pamięci; instrukcja potrzebująca. m słów pamięci wykony-
wana n razy niekoniecznie potrzebuje w sumie mn słów.

28
1.2. ANALIZA ALGORYTMÓW

Czas działania algorytmu może się jednak różnić nawet dla danych o tym
samym rozmiarze. W procedurze INSERTION-SORTna przykład najlepszy przy-
padek (optymistyczny) występuje wówczas, gdy wejściowa tablica jest już po-
sortowana. Dla każdego j = 2, 3, ... , n stwierdzamy, że A(i] ~ key w wierszu 5,
gdy i ma początkową wartość j - 1. Zatem tj = 1 dla j = 2, 3, ... , n, a minimal-
ny czas działania wynosi

T(n) = c 1n + c,(n - 1) + c4 (n - 1) + c,(n - 1) + c,(n - 1)

= (c 1 + c2 + c4 +Cs+ c8 )n-(c 2 + c4 +Cs+ c8 )


Ten czas działania można wyrazić jak.o an+ b dla stałych a, b zależnych od
kosztów c1 pojedynczych instrukcji; jest to zatem funkcja liniowa względem n.
Jeśli tablica jest posortowana w porządku odwrotnym - to znaczy w po-
rządku malejącym - mamy do czynienia z przypadkiem najgorszym (pesymis-
tycznym). Musimy porównać każdy element A[j] z każdym elementem pod-
tablicy A[l „j - 1], a więc tj= j dla j = 2, 3, ... , n. Zauważmy, że

Ij=n(n+ 1) _ 1
J=2 2
a

I (j _ l) = n(n ::- 1)
J.c2 2

(sumami takimi zajmiemy się w rozdz. 3), wnioskujemy zatem, że czas działa­
nia procedury INSERTION-SORTwynosi

+ c 6 ( n(n-
2
1))
+ - c7
(n(n -
2
1))
+ c 8 (n - 1)

Ten pesymistyczny czas działania można przedstawić jak.o an2 + bn + c dla


stałych a, b i c, które znowu zależą od kosztów c1; jest to zatem funkcja kwad~
ratowa względem n.

29
ROZDZIAŁ 1. WSTĘP

W typowych sytuacjach, takich jak sortowanie przez wstawianie, czas


działania algorytmu jest ustalony dla określonych danych wejściowych, nato-
miast w dalszych rozdziałach pokażemy algorytmy probabilistycznet, których
czasy działania mogą być różne dla tych samych danych wejściowych.

Analiza przypadków pesymistycznego i średniego


W analizie sortowania przez wstawianie rozważaliśmy zarówno przypadek opty-
mistyczny, w którym tablica z danymi wejściowymi była już posortowana, jak
i przypadek pesymistyczny, w którym tablica ta była posortowana w odwrotnym
porządku. Jednakże w dalszej części książki koncentrujemy się jedynie na przy-
padku pesymistycznym, a więc rozważamy najdłuższy czas działania dla każdych
danych wejściowych określonego rozmiaru. Są trzy powody takiego podejścia.
• Pesymistyczny czas działania jest górną granicą możliwego czasu działania
algorytmu dla każdych danych wejściowych. Znając ten czas, mamy gwa-
rancję, że algorytm nie będzie działał dłużej.
• Dla niektórych algorytmów pesymistyczny czas działania występuje dosyć
często. Zdarza się tak na przykład przy wyszukiwaniu w bazie danych infor-
macji, której w tej bazie nie ma.
• ,,Przypadek średni" jest często zbliżony do pesymistycznego. Załóżmy, że
wybieramy losowo n liczb i stosujemy sortowanie przez wstawianie. Jak
dużo czasu potrzeba na znalezienie miejsca w tablicy A[l ..j - 1], aby wsta-
wić element A[j]? Średnio połowa elementów w A[l ..j - l] jest mniejsza niż
A[j], natomiast polowa elementów jest większa. Sprawdzamy zatem średnio
połowę elementów pod.tablicy, tak więc t1 = j/2. Jeśli policzymy średni czas
działania, to otrzymamy, że jest to funkcja kwadratowa względem rozmiaru
danych, podobnie jak w przypadku pesymistycznym.
W niektórych sytuacjach będziemy zainteresowani przypadkiem średnim
lub oczekiwanym czasem działania algorytmu. Jednym z problemów przy ana-
lizowaniu przypadku średniego jest określenle „średnich" danych wejściowych.
Zakładamy często, że wszystkie dane wejściowe określonego rozmiaru są rów-
nie prawdopodobne. W praktyce nie zawsze musi tak być, ale algorytmy zran-
domizowane mogą czasami to zapewnić.

Rząd wielkości funkcji

Przy analizie procedury INSERTION-SORT korzystaliśmy z pewnych uprosz-


czeń. Najpierw zignorowaliśmy rzeczywisty koszt każdej instrukcji, używając

t Używane jest również określenie algorytmy randomizowane pochodzą.ce bezpośrednio od


term.inu angielskiego randomized algorithms (przyp. red.).

30
1 .2. ANALIZA ALGORYTMÓW

abstrakcyjnych stałych c1 do reprezentowania tych kosztów. Następnie abs-


trahowaliśmy jeszcze dalej, pomijając te stale i wprowadzając nowe stale a, b,
c w funkcji an 2 + bn + c, określającej czas działania algorytmu.
Przyjmijmy teraz jeszcze jedno uproszczenie. Dotyczy ono rzędu wielkości
funkcji. Rozważamy jedynie najbardziej znaczący składnik w formuli:::(tzn.
an 2 ), ponieważ inne składniki są nieistotne dla dużych n. Pomijamy również
stale czynniki, ponieważ nie są one istotne dla bardzo dużych danych. Piszemy
zatem na przykład, że sortowanie przez wstawianie ma pesymistyczny czas
działania 0(n 2 ). Notacji 0 używamy w tym rozdziale nieformalnie; będzie ona
zdefiniowana precyzyjniej w rozdz. 2.
Przeważnie uważamy, że dany algorytm jest lepszy od innego, jeśli jego
pesymistyczny czas działania jest funkcją niższego rzędu. Może to być niesłusz­
ne dla małych danych wejściowych, ale dla dostatecznie dużych danych na
przykład czas 0(n 2 ) jest zdecydowanie mniejszy niż 0(n 3 ).

ZADANIA
1.2-1. Rozważmy sortowanie n liczb z tablicy A następującą metodą. Znaj-
dujemy najmniejszy element tablicy A i wstawiamy na pierwsze miejsce
w pewnej tablicy B. Następnie znajdujemy drugi najmniejszy element
z A i wstawiamy na drugie miejsce w B. W ten sposób postępujemy dla
wszystkich n elementów tablicy A. Napisz dla tego algorytmu - który jest
znany jako sortowanie przez selekcję - program. Podaj pesymistyczny i op-
tymistyczny czas działania tego algorytmu, używając notacji 0.
1.2-2. Rozważmy znowu wyszukiwanie liniowe (patrz zad. 1.1-3). Ile elemen-
tów ciągu wejściowego trzeba średnio sprawdzić przy szukaniu losowego
elementu w tablicy? Jak to wygląda w przypadku pesymistycznym? Jaki
jest średni i pesymistyczny czas działania tego algorytmu wyrażony za
pomocą notacji 0? Odpowiedź uzasadnij.
1.2-3. Rozważmy problem wykrywania powtarzających się elementów w ciągu
n liczb (x 1, x 2 , ... , xn>·Pokaż, że można rozwiązać ten problem w czasie
0(nlgn), gdzie lgn oznacza log 2 n.
1.2-4. Rozważmy problem obliczania wartości wielomianów. Mamy danych
n współczynników a0 , a 1 , ... , 0 11_ 1 i liczbę rzeczywistą x, chcemy obliczyć
·-'
L a1x 1• Opisz bezpośredni algorytm rozwiązujący ten problem w czasie
j=O
0(n 2). Opisz algorytm działający w czasie @(n), w którym do obliczania
wielomianów jest zastosowana następująca metoda (zwana metodą Ho-
mera):
·-'
L a1x 1 = (...(a11_ 1x + a 11_ 2 )x + ...+ a 1)x + a0
i=O

1.2-5. Wyraż funkcję n 3 /1000 - 100n2 - lOOn+ 3, używając notacji 0.


31
ROZDZIAŁ 1. WSTĘP

1.2-6. Jak zmodyfikować (prawie każdy) algorytm, aby polepszyć jego czas
działania w przypadku optymistycznym?

1.3. Projektowanie
algorytmów
Jest wiele podejść do projektowania algorytmu. W sortowaniu przez wstawia-
nie stosuje się metodę przyrostową: mając posortowaną podtablicę A[l „j - 1],
wstawiamy pojedynczy element A[j] we właściwe miejsce, otrzymując większą
posortowaną podtablicę A[l „j].
W tym podrozdziale rozważamy inną metodę, zwaną „dziel i zwyciężaj"
(ang. divide-and-conquer).Użyjemy tej metody do zaprojektowania algorytmu
sortowania znacznie szybszego niż sortowanie przez wstawianie. Jedną z zalet
algorytmu zaprojektowanego w stylu „dziel i zwyciężaj" jest możliwość szaco-
wania czasu działania przy wykorzystaniu metod, które będą wprowadzone
w rozdz. 4.

1 .3.1. Metoda „dziel i zwyciężaj"


Wiele ważnych algorytmów ma stuk:turę rekurencyjną: W celu rozwiązania da-
nego problemu algorytm wywołuje sam siebie przy rozwiązywaniu podobnych
podproblemów. W algorytmach tych często stosuje się metodę „dziel i zwycię­
żaj": problem jest dzielony na kilka mniejszych podproblemów podobnych do
początkowego problemu, problemy te są rozwiązywane rekurencyjnie, a na-
stępnie rozwiązania wszystkich pod.problemów są łączone w celu utworzenia
rozwiązania całego problemu.
W podejściu „dziel i zwyciężaj" każdy poziom rekursji składa się z na-
stępujących trzech etapów:

Dziel: Dzielimy problem na podproblemy.


Zwyciężaj: Rozwiązujemy pod.problemy rekwencyjnie, chyba że są one małe­
go rozmiaru i już nie wymagają zastosowania rekursji - używamy wtedy
bezpośrednich metod.
Połącz: Łączymy rozwiązania podproblemów, aby otrzymać rozwiązanie ca-
łego problemu.

Algorytm sortowania przez scalanie otrzymujemy, stosując metodę „dziel i zwy-


ciężaj". Jego intuicyjny opis jest następujący.

Dziel: Dzielimy n-elementowy ciąg na dwa podciągi po n/2 elementów każdy.


Zwyciężaj: Sortujemy otrzymane podciągi, używając rekurencyjnie sortowa-
nia przez scalanie.
Połącz: Łączymy posortowane podciągi w jeden posortowany ciąg.

32
1.3. PROJEKTOWANIE ALGORYTMÓW

Zauważmy, że mechanizmu rekursji nie uruchamia się, gdy ciąg przezna-


czony do posortowania ma długość I, a więc jest automatycznie posortowany.
Podstawową operacją algorytmu sortowania przez scalanie jest scalanie
dwóch posortowanych ciągów dokonywane w kroku „połącz". W celu wyko-
nania scalania korzystamy z pomocniczej procedury MERGE(A, p, q, r), gdzie
A jest tablicą, ap, q, r są indeksami takimi, że p .:s;;q < r. W procedurze zakła­
da się, że podtablice A[p .. q], A[q + 1 .. r] są posortowane. Procedura MERGE
scala te tablice w jedną posortowaną tablicę A[p „ r].
Chociaż napisanie procedury scalania w naszym pseudojęzyku programo-
wania zostawiamy jak. zadanie (patrz zad. 1.3-2), łatwo skonstruować procedu-
rę MERGE działającą w czasie 0(n), gdzie n= r - p + 1. Odwołując się do
przykładu sortowania talii kart, można sobie wyobrazić następujące działanie:
załóżmy, że mamy dwa posortowane stosy kart ułożone awersem do góry,
z najmniejszymi co do wartości kartami na wierzchu. Chcemy połączyć te dwa
stosy w jeden posortowany stos wyjściowy, którego elementy (karty) leżą awer-
sem do dołu. Naszą podstawową operacją jest wybranie mniejszej z dwóch kart
na szczycie stosów kart leżących awersem do góry, zdjęcie jej ze stosu (na
szczycie którego jest teraz nowa karta) i umieszczenie tej karty awersem do
dołu na stosie wyjściowym. Powtammy tę operację, aż jeden ze stosów będzie
pusty. Wtedy resztę drugiego stosu przenosimy na stos wyjściowy, karta po
karcie. Podstawowa pojedyncza operacja jest wykonywana w czasie stałym,
wykonujemy n takich operacji, a więc scalanie odbywa się w czasie 0(n).
Z procedury MERGE korzystamy w algorytmie sortowania przez scalanie.
MERGE-SORT(A, p, r) sortuje elementy w podtablicy A[p .. r]. Jeśli p ~ r to
podtablica jest już posortowana. W przeciwnym razie znajdujemy q, które
dzieli A[p .. r] na dwie pod.tablice: A[p .. q], zawierającą Ln/2J elementów, oraz
A[q + 1 .. r], zawierającą rn/21 elementów 1>.

MERGE-SORT(A,p, r)
1 ifp<r
2 + r)/2J
tben q ~ L<P
3 MERGE-SoRT(A, p, q)
4 MERGE-SoRT(A, q + l, r)
5 MERGE(A, p, q, r)

Aby posortować cały ciąg A - (A[l], A[2], ... , A[n]), wywołujemy procedurę
MERGE-SORT(A, 1, length[A]), gdzie length[A] =n.Patrząc na drzewo wywo-
łań rekurencyjnych od dołu (gdy n jest potęgą dwójki), widzimy, że algorytm
najpierw sortuje pojedyncze ciągi w ciągi 2-elementowe, następnie 2-elemen-

n Zapis rxl oznacza najmniejszą liczbę całkowitą nie mniejszą niż x, natomiast LxJ oznacza
największą liczbę całkowitą nie większą niż x. Notacja ta jest zdefiniowana również w ro?.dz. 2.

33
ROZDZIAŁ 1. WSTĘP

Qąg posortowany
lt·.,:.'._,:.,,.,..:•:;,•,12:"···--k,'",.
., . . .. .
' i>,,
~
.. ',·.•. ' $ '
""' ,-. ,'
t'I
Scal

1:1 ',j'; ):;, 6]

/ '

Sca)
' '
/&,,,
12'..1 I I• 6j 11 .,al I2 •I
/s.v\ /Scal\ /Scal\ /Scal\
[il [1J 0 [!l [il [Il @ [il
Qąg początkowy

Rys. 1.3. Operacja sortowania przez roilanie tablicy A= (5, 2, 4, 6, I, 3, 2, 6). Długości posortowa~
nych ciągów wzrastają w miarę posuwania się algorytmu „w górę"

towe w 4-elementowe itd. Na końcu z ciągów n/2-elementowych otrzymujemy


ciąg długości n. Opisany proces jest przedstawiony na rys. 1.3.

1.3.2. Analiza algorytmów typu „dziel i zwyciężaj"


Kiedy algorytm zawiera rekurencyjne wywołania siebie samego, jego czas działa­
nia można często opisać zależnością rekurencyjną (rekurencją) wyrażającą czas
dla problemu rozmiaru n za pomocą czasu dla pod.problemów mniejszych roz-
miarów. Możemy potem skorzystać z aparatu matematycznego, aby rozwiązać
tę rekurencję i w ten sposób otrzymać oszacowania czasu działania algorytmu.
Rekurencja odpowiadająca czasowi działania algorytmu typu „dziel i zwy-
ciężaj" opiera się na podziale jednego poziomu rekursji na trzy etapy. Niech
Jtn) będzie czasem działania dla problemu rozmiaru n. Jeśli rozmiar problemu
jest wystarczająco mały, powiedzmy n .:e;;c dla pewnej stałej c, to jego rozwiąza­
nie zajmuje stały czas, co zapiszemy jako 9(1). Załóżmy, że dzielimy problem
na a podproblemów, każdy rozmiaru n/b. Jeśli D(n) jest czasem dzielenia prob-
lemu na podproblemy, a C(n) czasem scalania rozwią2.ań podproblemów
w pełne rozwią2.aoie dla oryginalnego problemu, to otrzymujemy rekurencję

T(n)={El(l), jeśli n ,:e;;C


aT(n/b)+D(n)+C(n) w przeciwnym razie
W rozdziale 4 pokażemy, jak rozwiązywać typowe rekurencje tego typu.
34
1.3. PROJEKTOWANIE ALGORYTMÓW

Analiza sortowania przezscalanie


Chociaż algorytm MERGE-SORTdziała poprawnie nawet wówczas, gdy n jest
nieparzyste, jednakże dla uproszczenia analizy załóżmy, że n jest potęgą dwój-
ki. Wtedy dzielimy problem na podproblemy ro7llliaru dokładnie n/2. W roz-
dziale 4 pokażemy, że nasze upraszczające założenie nie wpływa ną· rząd wiel-
kości funkcji będącej rozwiązaniem.
Rekurencję określającą czas T(n) sortowania przez scalanie otrzymujemy,
jak następuje. Sortowanie przez scalanie jednego elementu wykonuje się w cza-
sie stałym. Jeśli n > 1, to czas działania zależy od trzech etapów.

Dziel: Podczas tego etapu znajdujemy środek przedziału, co zajmuje czas sta-
ły. Zatem D(n) = 0(1).
Zwyciężaj: Rozwiązujemy rekurencyjnie dwa pod.problemy, każdy rozmiaru
n/2, co daje w sumie czas działania 2T{n/2).
Połącz: Jak to już poprzednio stwierdziliśmy, procedura MERGB działa
w czasie 0(n), a więc C(n) = 0(n).

Funkcje D(n) i C(n) dają po zsumowaniu funkcję rzędu 0(n). Dodając do


tego 2TC.n/2)z etapu „zwyciężaj", otrzymujemy następującą rekurencję na T(n):

jeśli n= I
T(n) = {®(!),
2T(n/2) + 0(n), jeśli n> 1

W rozdziale 4 pokażemy, że T{n) wynosi E>(nlgn), gdzie lgn oznacza log 2 n.


Dla dostatecznie dużych n sortowanie przez scalanie, w czasie E>(nlgn), jest
lepsze niż sortowanie pr;rez wstawianie, które działa w czasie pesymistycznym
0(n 2 ).
ZADANIA
1.3-1. Zilustruj (podobnie jak na rys. 1.3) działanie procedury MERGE-SORT
dla tablicy A= (3, 41, 52, 26, 38, 57, 9, 49).
1.3-2. Napisz program dla MERGE(A.,p, q, r).
1.3-3. Pokaż, stosując metodę indukcji matematycznej, że rozwiązaniem rów-
nania rekurencyjnego

2, jeśli n = 2,
T(n) ={
2T(n/2) + n, jeśli n=2k, k>l

jest T(n) = nlgn.


1.3-4. Sortowanie przez wstawianie może być wyrażone jako procedura reku-
rencyjna, jak następuje. Aby posortować A[l .. n], rekurencyjnie sortujemy

35
ROZDZIAŁ 1. WSTĘP

A[l .. n - !], po czym wstawiamy A[n] w posortowaną tablicę A[l .. n - !].


Napisz równanie rekurencyjne na czas sortowania przez wstawianie.
1.,3..5.Wróćmy jeszcze do problemu wyszukiwania {patrz zad. 1.1-3). Zauważ­
my, że jeśli ciąg A. jest posortowany, to możemy porównać środkowy ele-
ment z elementem v, pomijając dzięki temu przeszukiwanie polowy tablicy.
Wyszukiwanie hłoame polega na powtarzaniu tej operacji rekurencyjnie.
Napisz program, rekurencyjny lub nie, wyszukiwania binarnego. Uzasad-
nij, że jego czas działania wynosi 0(lg n).
1.3-6. Zauważmy, że w pętli winie w wierszach 5-7 procedury INSERTION-
-SORT w podrozdz. 1.1 jest zastosowane szukanie liniowe (do tyłu) w po-
sortowanej podtablicy A.[1..j - 1]. Czy można skorzystać z wyszukiwania
binarnego {patrz zad. 1.3-5), aby zmniejszyć czas działania do 0(nlgn)?
* 1.,3..7.Opisz algorytm działający w czasie 0(nlgn), który dla danego zbioru S
złożonego z n liczb rzeczywistych i liczby rzeczywistej x sprawdza, czy
istnieją dwa elementy w S, których suma jest równa dokładnie x.

1.4. Podsumowanie

Dobry algorytm jest jak „ostry nóż" - robi dokładnie to, co ma robić, z naj-
mniejszym wysiłkiem. Używanie złego algorytm.u to jak „krajanie stek.u kor-
kociągiem". Rezultat może nie być ani efektywny, ani „apetyczny".
Algorytmy służące do rozwiązania tego samego problemu mogą się zna-
cząco różnić efektywnością. Różnice te mogą być większe niż różnica między
komputerem osobistym i „superkomputerem". Dla przykładu rozważmy sytu-
ację, gdy na superkomputerze zastosowano algorytm sortowania przez wsta-
wianie, a na małym komputerze osobistym - algorytm sortowania przez scala-
nie. W obu wypadkach należy posortować tablicę zawierającą milion elemen-
tów. Załóżmy, że superkomputer wykonuje 100milionów operacji na sekundę,
podczas gdy komputer osobisty wykonuje w tym czasie tylko milion operacji.
Aby różnica była jeszcze bardziej widoczna, załóżmy, że sortowanie przez
wstawianie jest zaprogramowane przez niezwykle dobrego programistę i wyni-
kowy program wykonuje 2n2 operacji superkomputera, aby posortować
n liczb. Natomiast sortowanie przez scalanie jest zaprogramowane w ten spo-
sób, że wynikowy program wykonuje 50n lg n operacji. Aby posortować miHon
liczb, superkomputer potrzebuje czasu

2 · (106 ) 2 instrukcji .
, . uk .. -ek-d··· - 20000 sekund s; 5,56 godzin
10 mstr CJl1s un ę

podczas gdy komputer osobisty potrzebuje

36
PROBLEMY

50· 106 lg 106 instrukcji .


, . k .. k d ~ 1000 sekund~ 16,67 minut
I O 1nstru CJl1se un ę

Używając algorytmu, którego czas działania jest opisany funkcją niższego rzę­
du, napisanego nawet przez słabszego programistę, komputer osobisty działa
20 razy szybciej niż superkomputer!
Przykład ten świadczy o tym, że szybkość działania algorytmu jest co naj-
mniej równie istotna jak szybkość działania komputera. Całkowity czas za.leży
zarówno od wyboru dobrego algorytmu, jak i dobrego komputera. Dlatego
właśnie, podobnie do rozwoju nowych technologii, można za.obserwować
gwałtowny rozwój algorytmiki.

ZADANIA
1.4-1. Załóimy, że porównujemy implementację sortowania przez scalanie
i sortowania przez wstawianie na tym samym komputerze. Dla danych
wejściowych ro2'llliaru n sortowanie przez wstawianie działa w czasie 8n2 ,
podczas gdy sortowanie przez scalanie działa w czasie 64nlg n. Dla jak.ich
wartości n sortowanie przez scalanie jest lepsze niż sortowanie przez wsta-
wianie? Jak można 2'lllodyfikować program sortowania przez scalanie, aby
działał szybciej dla małych danych?
1.4-2. Jak.a jest najmniejsza wartość n, dla której algorytm wykonujący 100n2
operacji działa szybciej niż algorytm wykonujący 2n operacji na tym sa-
mym komputerze?

Problemy
1~1. Porównanie czasów działania
Dla funkcji/(n) i czasu t z poniższej tabeli wyznacz największy ro2'llliar n prob-
lemu, który może być rozwiązany w czasie t, zakładając, że algorytm działa
w ciąguf(n) mikrosekund.
t I I I I I 1 1
• . .
J sekunda rrnn. godz. dzień mtestąc rok wiek
lgn
.fi,
n
nlgn
+
_j.
n'
n'
2"
n! I I •
I I I
ROZDZIAŁ 1. WSTĘP

1-2. Sortowanie przez wstawianie dla małych tablic podczas sortowania przez
scalanie
Pomimo że sortowanie przez scalanie działa w czasie 0{nlgn), natomiast sor-
towanie przez wstawianie działa w czasie 0(n 2 ), stałe czynniki w sortowaniu
przez wstawianie czynią ten algorytm szybszym dla małych n. Zatem ma sens
korzystanie z sortowania przez wstawianie podczas sortowania przez scalanie,
kiedy rozmiar danych jest mały. Rozważmy modyfikację sortowania przez sca-
lanie, w której n/k podlist rozmiaru k sortujemy, używając sortowania przez
wstawianie, a następnie używamy mechanizmu scalania, gdzie k jest wartością,
którą należy wyznaczyć.

(a) Pokaż, że n/k pod.list, każda długości k, może być posortowanych za po-
mocą sortowania przez wstawianie w czasie E>(nk).
(b) Pokaż, że podlisty mogą być scalone w czasie E>(nlg(n/k)).
(c) Zakładając, rezmodyfikowany algorytm działa w czasie 6(nk + n lg(n/k)),
podaj, jaki jest maksymalny rząd wartości k jako funkcji zależnej od n, dla
którego zmodyfikowany algorytm ma ten sam rząd złożoności co normal-
ne sortowanie przez scalanie?
(d) Jakie k wybrać w praktyce?

1-3. Inwersje
Niech A[l .. n] będzie tablicą zawierającą n różnych liczb. Jeśli i <j oraz
A[i] > A[J], to para (i, 1) jest nazywana inwersją A.
(a) Wypisz pięć inwersji tablicy (2, 3, 8, 6, 1).
(b) Jaka tablica n-elementowa ma najwięcej inwersji? Ile ich jest?
(c) Jaka jest relacja między czasem działania sortowania przez wstawianie
i liczbą inwersji sortowanej tablicy? Opowiedź uzasadnij.
(d) Podaj algorytm wyznaczający liczbę inwersji permutacji n-elementowej
w czasie E>(nlgn) (Wskazówka: Zmodyfikuj sortowanie przez scalanie).

Uwagi do rozdziału
Jest wiele doskonałych książek o algorytmach, których autorami są między
innymi Aho, Hopcroft i Ullman [4, 5], Baase [14], Brassard i Bratley [33],
Horowitz i Sahni [105], Knuth [121, 122, 123], Manber [142], Mehlhorn [144,
145, 146], Purdom i Brown [164], Reingold, Nievergelt i Deo [167], Sedge-
wick [175] i Wilf [201].
Niektóre aspekty praktyczne są dyskutowane w książkach Bentleya [24,
25] i Gonneta [90].
W 1968 r. K.nuth opublikował pierwszy z trzech tomów książki The Art of
Computer Programming [121, 122, 123]. Pierwszy z nich był wstępem do al-

38
UWAGI DO ROZDZIAŁU

gorytmów, ze szczególnym uwzględnieniem analizy złożoności. Wszystkie trzy


tomy zawierają materiał związany z niniejszą książką. Cytując Knutha, słowo
„algorytm" pochodzi od nazwiska „al-Khowarizmi'', matematyka perskiego
z IX w.
Abo, Hopcroft i Ullman [4] zajmowali się asymptotyczną analizą algoryt-
mów jako narzędziem porównywania optymalności algorytmów. Spopularyzo-
wali oni również użycie rekurencji do analizy złożoności.
K.nuth [123] przedstawił encyklopedyczny przegląd podstawowych aloryt-
mów sortowania. Jego porównanie algorytmów sortujących zawiera dokładną
analizę czasu działania, podobną do tej jaką wykonaliśmy dla sortowania
przez scalanie. K.nuth, rozważając sortowanie przez wstawianie, przeanalizo-
wał również niektóre jego wersje. Najważniejszą spośród nich jest sortowanie
metodą Shella (wprowadzone przez D.L. Shella), w którym korzysta się z sor-
towania przez wstawianie na okresowych podciągach (co daje szybszy algo-
rytm sortujący).
Knuth opisał również sortowanie przez scalanie. Wspomina on, że
w 1938 r. skonstruowano mechaniczne urządzenie scalające dwa zbiory kart
perforowanych. J. von Neumann, jeden z pionierów informatyki, skonstruo-
wał program sortowania przez scalanie na komputerze EDVAC w 1945 r.
Część I

Podstawow
aparatmatematycz
Wprowadzenie
Analiza algorytmów wymaga często użycia aparatu matematycznego. Może
wystarczyć tylko znajomość algebry na poziomie szkoły średniej, ale może
zdarzyć się i tak, że trzeba będzie się wykazać umiejętnością rozwiązywania
równań rekurencyjnych. Ta część książki stanowi kompendium metod i narzę­
dzi, które będziemy stosować w analizie algorytmów. Jest pomyślana tak, aby
można się było do niej odwoływać w dalszych partiach książki. Niektóre tema-
ty są omówione dość szczegółowo.
Radzimy czytelnikowi, aby nie starał się zgłębić całego materiału matema-
tycznego od razu. Uważamy, że lepiej będzie, jeśli najpierw pobieżnie zapozna
się z zawartością rozdziałów tej części książki, po czym przejdzie do rozdziałów
poświęconych algorytmom. Po przeczytaniu ich może wrócić do tej części,
kiedy tylko dojdzie do wniosku, że powinien lepiej zrozumieć stosowane narzę­
dzia matematyczne.
Rozdział 2 zawiera dokładne definicje kilku notacji asymptotycznych
(przykładem jest notacja 0, o której była już mowa w rozdz. I). Naszym celem
jest tutaj nauczyć czytelnika posługiwania się notacją używaną w książce, a nie
rozumienia nowych koncepcji matematycznych.
Rozdział 3 dotyczy metod obliczania i szacowania sum, z czego często się
korzysta w analizie algorytmów. Wiele przedstawionych tu wzorów można
znaleźć w książkach z analizy matematycznej, ale wygodnie jest mieć je zgro-
madzone w jednym miejscu.
Metody rozwiązywania równań rekurencyjnych, które stosowaliśmy do
analizy sortowania przez scalanie w rozdz. 1, są tematem rozdz. 4. Jedną ze
skuteczniejszych metod jest tzw. ,,metoda rekurencji uniwersalnej", która mo-
że być użyta w rekurencjach powstających w algorytmach typu „dziel i zwycię­
żaj". Znaczna część rozdz. 4 jest poświęcona dowodowi poprawności tej meto-
dy, chociaż dowód można pominąć.

42
WPROWADZENIE

RoOOział 5 zawiera podstawowe definicje i notacje związane ze zbiorami,


relacjami, funkcjami, grafami i drzewami. Są w nim też opisane podstawowe
własności tych obiektów matematycznych. Materiał ten jest istotny do zro-
zumienia książki, ale może być pominięty, jeśli ma się pewne podstawy z mate-
matyki dyskretnej.
RoOOział 6 rozpoczyna się opisem podstawowych pojęć kombinatorycz-
nych: permutacji, kombinacji itp. Reszta rozdziału zawiera definicje i własności
związane z elementarnym rachunkiem prawdopodobieństwa. Do analizy wię­
kszości algorytmów w tej książce nie jest wymagana znajomość rachunku pra-
wdopodobieństwa; można zatem bezpiecznie pominąć ostatnie partie tego roz-
działu przy pierwszym czytaniu. RoOOzial ten jest jednak bardzo przydatny,
kiedy chce się lepiej zrozumieć omawianą dalej analizę probabilistyczną al-
gorytmów.
Rozdział 2

Rzędy wielkości
funkcji

Na podstawie rzędu wielkości funkcji, za pomocą której opisuje się czas działa­
nia algorytmu (o czym wspominaliśmy w rozdz. 1), można scharakteryzować
efektywność algorytmu i porównać złożoność dwóch różnych algorytmów.
Gdy na przykład rozmiar danych wejściowych n staje się bardzo duży sortowa-
nie przez scalanie, które działa w czasie pesymistycznym 9(nlgn), ,,wygrywa"
z sortowaniem przez wstawianie, którego pesymistyczny czas działania wynosi
9(n 2). Chociaż niekiedy możemy wyznllC"LyĆ dokładnie czas działania algoryt-
mu, jak na przykład w sortowaniu przez wstawianie w rozdz. I, jednak taka
dokładność często jest niepotrzebna, a jej osiągnięcie zbyt pracochłonne. Dla
dostatecznie dużych danych wejściowych stałe współczynniki i mniej znaczące
składniki we wzorze na czas działania są zdominowane przez rozmiar samych
tych danych.
Kiedy dla dostatecznie dużych danych wejściowych liczymy jedynie rząd
wielkości czasu działania algorytmu, wtedy zajmujemy się asymptotyczną zło­
żonością algorytmów. Oznacza to, że interesuje nas, jak szybko wzrasta czas
działania algorytmu, gdy rozmiar danych dąży do nieskończoności. Zazwyczaj
dla dostatecznie dużych danych najlepszy jest algorytm asymptotycznie bar-
dziej efektywny.
W tym ro:zdziale pokażemy kilka standardowych metod upraszczania ana-
lizy asymptotycznej algorytmów. Rozpoczniemy od podania definicji kilku ty-
pów „notacji asymptotycznej", której przykład zaprezentowaliśmy, wspomina-
jąc o notacji 0. Następnie pr7.edstawimy podstawowe notacje oraz zbadamy
zachowanie się funkcji często występujących w analizie algorytmów.

44
2.1. NOTACJA ASYMPTOTYCZNA

2.1. Notacjaasymptotyczna
W notacji używanej do opisu asymptotycznego czasu działania algorytmów
korzysta się z funkcji, których zbiorem argumentów jest zbiór liczb natural-
nych N= {O, 1, 2, ... }. Notacja taka jest użyteczna przy opisie pesymistycznego
czasu działania T(n), który zazwyczaj jest funkcją ro11Diaru danych wejścio­
wych, będąc.ego liczbą naturalną. Czasami jednak wygodna jest pewna modyfi-
kacja, na przykład rozszerzenie podobnej notacji na zbiór liczb rzeczywistych.
Niemniej jednak istotne jest, aby modyfikacja notacji nie prowadziła do straty
precyzji. W podrozdziale tym defmiujemy podstawowe notacje asymptotyczne,
a także wprowadzamy kilka ich modyfikacji.

Notacja 0
W rozdziale 1 stwierdziliśmy, że pesymistyczny czas działania algorytmu sor-
towania przez wstawianie wynosi T(n) = 0(n 2). Zdefmiujmy formalnie, co to
oznacza.
Dla danej funkcji g(n) oznaczamy przez 0(g(n)) zbiór funkcji

0(g(n)) = {/(n): istnieją dodatnie stale c 1 , c2 i n 0 takie, że


O ~ c 1g(n) ~/(n)~ c,.g(n)dla wszystkich n ;i, n 0 }

Funk:cja/(n) należy do zbioru 0(g(n)), jeśli istnieją dodatnie stałe c 1 oraz c2


takie, że funkcja może być „wstawiona między" c1 g(n) i c:zg(n)dla dostatecznie
dużych n. Chociaż 9(g(n)) jest zbio1fill, pisremy ,./(n)= 0(g(n))", żeby wyra-
zić, ż.e /(n) jest elementem El(g(n)), lub ,,/(n)E9(g(n))". Formalnie taka nota-
cja może wydawać się myląca, ale zobaczymy, że ma ona swoje zalety.
Na rysunku 2.la widać, dlaczego/(n) =
0(g(n)). Dla wszystkich wartości
n większych od n 0 wartość /(n) znajduje się między c1g(n) i czg{n). Inaczej
mówiąc, dla wszystkich n ;i, n 0 fnnkcja/(n) jest równa g(n) z dokładnością do
stałego współczynnika. Mówimy, że g(n) jest asymptotycznie dokładnym osza-
cowaniemdla/(n).
Definicja 0(g(n)) implikuje też, że każda funkcja, która jest rzędu 0(g(n)),
ma być asymptotycznie nieujemna,to znaczy, że /(n) ma być nieujemna dla
dostatecznie dużych n, Zatem funkcja g(n) musi być również asymptotycznie
nieujemna, w przeciwnym razie zbiór funkcji 0(g(n)) jest pusty. W związku
z tym zakładamy, że każda funkcja rzędu 0 jest asymptotycznie nieujemna.
Podobne założenie przyjmujemy dla innych asymptotycznych notacji wprowa-
dzonych w tym rozdziale.
W ro7.dziale 1 wprowadziliśmy niefonnalnie notację 0, dzięki której mo-
gliśmy pominąć składniki niższych rzędów i stały współczynnik przy składniku
o największym rzędzie. Uzasadnimy krótko, używając formalnych defmicji,

45
ROZDZIAŁ 2. RZĘDY WIELK0$CI FUNKCJI

cg(n)

/(n)
f(n)
/(n)

I cg(n)

c:__;______ ,
'o '------'-------
'o
'
,,,
/(n)= 8{g(n)) /(n)= O(g(n))
(b)
no /(n)""

(c)
O(g(n))

Rys. 2.1. Graficzne przykłady notacji 0, O i n. Poks:zana w lrażdej części wartość n0 jest minimalną.
możliwą. wartością; każda większa wartość jest również dobra. (a) Za pomocą notacji 0 szacuje się
funkcję z dokładnością do stałego współczynnika. Pisz.emy /(n) = 0(g(n)), jeśli istnieją dodatnie
stałe n0 , c1 i c1 talcie, że na prawo od n0 wartość/(n) leży zawsze między c 1g(n) i c1g(n). (b) Notacja
O daje górne ograniczenie funkcji z dokładnością do stałego współczynnika. Pisz.emy
f(n) .., O(g(n)), jeśli istnieją dodatnie stale n0 i c takie, że na prawo od n0 wartość /(n) jest nie
większa niż cg(n). (c) Notacja n
daje dolne ograniczenie funkcji z dokładnością do stałego współ­
czynnika. Piszemy /(n) = O(g(n)), jeili istnieją dodatnie stałe n0 i c takie, 2'il na prawo od n0
wartość /(n) jest nie mniejsza niż cg(n)

że -~ n2 - 3n = 0(n 2
). W tym celu musimy znaleźć dodatnie stale c 1 , c2 oraz
n0 takie, że

dla każdego n ;;i, n0 • Dzieląc powyższą zależność przez n2 , otrzymujemy

Prawa strona jest prawdziwa dla każdej wartości n ;;i, 1, gdy wybierzemy
c2 ;;i: 1/2. Podobnie, lewa strona jest prawdziwa dla każdej wartości n ;;i, 7, gdy
wybierzemy c 1 ~ 1/14. Wybierając c1 = 1/14, c2 = 1/2 oraz n 0 = 7, możemy
sprawdzić, że ~ n2 - 3n = 0(n 2
). Z pewnością istnieją inne możliwości wyboru
stałych, ale istotne jest głównie to, że istnieje jakakolwiek możliwość. Zauważ­

my, że wybór stałych zależy od konkretnej funkcji ~ tutaj ~ n2 - 3n; inne


funkcje rzędu 0(n 2
) będą wymagały użycia innych stałych współczynników.

46
2.1. NOTACJA ASYMPTOTYCZNA

Korzystając z formalnej definicji, możemy również stwierdzić, że


6n3 *-0(n 2 ). Załóżmy (przez zaprzeczenie), że istnieją stałe c2 i n0 talcie, że
6n3 ~ c 2n 2 dla wszystkich n ;;;;,n0 • Ale wtedy n ~ c2 /6, co nie może być prawdą
dla dowolnie dużych n, ponieważ c2 jest stałą.
Intuicyjnie, składniki niższego rzędu mogą być pominięte, gdyż są mało
istotne dla dużych n. Niewielka część składników wyższego rzędu jest w rzeczy-
wisto~ci dominująca. Zatem przypisując c 1 wartość odrobinę mniejszą niż
współczynnik przy składniku najwyższego rzędu oraz przypisując c2 wartość
odrobinę większą, powodujemy, że notacja 0 ma sens. Współczynnik przy
najbardziej znaczącym składniku może być pominięty, gdyż zmienia on c 1 i c2
tylko o stały współczynnik.
Jako przykład rozważmy funkcję kwadratową/(n) = an2 + bn + c, gdzie
a, b, c są stałymi i a> O. Odrzucając składniki niższego rzędu i stałe współ­
czynniki, otrzymujemy, że/(n) = E>(n2 ), Formalnie, dowodzimy tego samego,
biorąc stale c 1 ~ a/4, c, ~ 7a/4 i n0 ~ 2·max((lbl/a), ,/(lcl/a)). Czytelnik może
sprawdzić, że O~ c 1n 2 ~ an2 + bn + c ~ c2 n 2 dla wszystkich n;;;;,n 0 . Ogólnie,

dla każdego wielomianu p(n) = L' a;n\ gdzie a1 są stałymi i a,1> O, mamy
i"' o
p(n) ~ 0(n') (patrz problem 2-1).
Ponieważ każda stała jest wielomianem stopnia O, możemy wyrazić funk-
cję stałą jako 0(n°) lub 0(1). Ta ostatnia notacja formalnie nie jest całkiem
poprawna, gdyż nie bardzo wiemy, co tutaj dąży do nieskończoności 1 l. Będzie­
my często używać notacji E>(l) do oznaczenia albo wartości stałej lub funkcji
stałej względem pewnej zmiennej.

Notacja O
Notacja 0 asymptotycznie ogranicza funkcję od góry oraz od dołu. Kiedy
mamy tylko asymptotyczną granicę górną, używamy notacji O. Dla danej funk-
cji g(n) oznaczamy przez O(g(n)) zbiór funkcji

O(g(n)) = {f(n): istnieją dodatnie stałe ci n 0 takie, że O ~/(n)~ cg(n) dla


wszystkich n ;;;;,n 0 }

Z notacji O korzystamy po to, żeby oszacować funkcję z góry, z dokładnoś­


cią do stałego współczynnika. Rysunek 2.1 b ilustruje pewną intuicję związaną

ii Pewnym problemem jest to, że nasza notacja dla funkcji nie odróżnia funkcji od ich warto-
ści. W rachunku A.parametry funkcji są opisane bardziej fonna1nie: funkcja n 2 może być zapisana
jako Ml.n2 albo M'.r1 . Przyjmując bardziej rygorystycmą notację, skomplikowalibyśmy przekształ­
cenia algebraiczne, tak więc tolerujemy pewną niezgodność formalizmu.

47
ROZDZIAŁ 2. RZĘDY WIELKOŚCI FUNKCJI

z notacją O. Dla każdego n większego od n 0 wartość funkcji /(n) nie prze-


kracza g(n).
Piszemy f(n) = O(g(n)), gdy funktja f(n) jest elementem zbioru O(g(n)).
Zauważmy, że /(n)= 0(g(n)) implikuje /(n)= O(g(n)), ponieważ notacja
0 jest silniejsza niż notacja O. Korzystając z zapisu teoriomnogościowego,
mamy 0(g(n)) c: O(g(n)). Zatem z naszego dowodu na to, że każda kwadrato-
wa funkcja an2 + bn + c, gdzie a> O, należy do zbioru 8(n 2 ), wynika też. że
każda kwadratowa funkcja należy do zbioru O(n 2 ). Ciekawe jest to, że każda
liniowa funkcja an + b również należy do zbioru O(n 2 ), co łatwo zauważyć,
biorąc c= a+ ]hl i n0 = 1.
Czytelnikom, którzy się zetknęli wcześniej z notacją O, może się wydać
dziwne, że piszeo1y n = O(n 2 ). Często notacja O jest stosowana nieformalnie
do opisu asymptotycznie dokładnych oszacowań, dla których my używamy
notacji 0. Jednakt.e w tej książce, pisząc/(n) = O(g(n)), roZ11miemyjedynie, że
po przemnożeniu g(n) przez pewną stałą otrzymujemy asymptotyczną granicę
górną na /(n), nie mówiąc nic o tym, na ile jest ona dokładna. Rozróżnienie
górnego oszacowania od dokładnego oszacowania stało się standardem w lite-
raturze związ,anej z algorytmami.
Za pomocą notacji O opisujemy często czas dzjałania algorytmu, badając
jego ogólną strukturę. Na przykład struktura podwójnie zagnieżdżonej pętli
w algorytmie sortowania przez wstawianie z rozdz. 1 daje od razu górne osza-
cowanie O(n 2 ) na pesymistyczny czas działania: koszt wewnętrznej pętli jest
ograniczony z góry przez 0(1) (stałą), indeksy i oraz j są nie większe niż n,
wewnętrzna pętla jest wykonywana co najwyżej raz dla każdej spośród n 2 par
wartości i orazj.
Ponieważ notacja O odpowiada górnej granicy, szacując pesymistyczny
czas działania algorytmu, automatycznie szacujemy z góry czas działania tego
algorytmu dla wszystkich danych wejściowych. A więc oszacowanie O(n 2 ) na
pesymistyczny czas działania algorytmu sortowania przez wstawianie stosuje
się do czasu działania dla wszystkich danych. Jednakże oszacowanie 0(n 2) na
pesymistyczny czas działania algorytmu sortowania przez wstawianie nie im-
plikuje oszacowania 0(n 2 ) na czas działania tego algorytmu dla wszystkich
danych. Jak widzieliśmy na przykład w rozdz. 1, jeśli dane są. już posortowane,
to algorytm sortowania przez wstawianie działa w czasie 9(n).
Technicznie rzecz biorąc, pewnym nadużyciem jest powiedzenie, że czas
działania algorytmu sortowania przez wstawianie wynosi O(n 2 ), gdyż dla da-
nego n rzeczywisty czas działania zależy od konkretnych danych wejściowych
rozmiaru n. To znaczy, że czas działania nie jest jedynie funkcją zależną od n.
Mówiąc „c-zas działania wynosi O(n 2 }". rozwniemy, że pesymistyczny czas
działania (który rzeczywiście jest funkcją n) wynosi O(n 2 ), lub równoważnie, że
niezależnie od konkretnych danych wejściowych rozmiaru n czas działania al-
gorytmu dla tych danych wynosi O(n 2 ).

48
2.1. NOTACJA ASYMPTOTYCZNA

Notacja Q
Podobnie jak notacja O określa asymptotyczną granicę górną, notacja n okreś­
la asymptotyczną granicę dolną. Dla danej funkcji g(n) oznaczamy przez
O:(g(n))zbiór funkcji

O:(g(n))= {/(n): istnieją


dodatnie stałe ci n0 takie, że O~ cg(n) ~f(n) dla
wszystkich n ~ n0 }

Intuicja związana z notacją O jest pokazana na rys. 2.lc. Dla wszystkich war-
tości n większych od n0 wartość /(n) jest nie mniejsza niż cg(n).
Z definicji dotychczas wprowadzonych notacji asymptotycznych łatwo wy-
kazać słuszność następującego ważnego twierdzenia (patrz zad. 2.1-5).

l'WIERDZENIE2.1.
Dla każdych dwóch funkcji/(•) i g(n) zachodzi zależność/(•) - 0(g(n)) wtedy
i tylko wtedy, gdy f(n) - O(g(n)) if(n) - !l(g(n)).

Przykładem zastosowania tego twierdzenia jest fakt, że z dowodu na to, iż
an2 + bn + c = 0(n 2) (gdzie a, b, c są stałymi i a > O), wynika bezpośrednio,
że an 2 + bn + c = O:(n2) oraz an 2 + hn + c = O(n2 ). W praktyce, zamiast ko-
rzystać z twierdzenia 2.1 do uzyskania górnego i dolnego oszacowania z asym-
ptotycznie dokładnych oszacowań, jak to zrobiliśmy w tym przykładzie, za-
zwyczaj używamy go do wykaz.ania istnienia asymptotycznie dok.ładnych gra-
nic na podstawie istnienia asymptotycznej granicy górnej i asymptotycznej gra-
nicy dolnej.
Ponieważ notacja O opisuje granicę dolną, więc używając jej do oszacowa-
nia czasu działania algorytmu dla najlepszego przypadku, szacujemy również
czas działania algorytmu dla wszystkich danych wejściowych. Na przykład czas
działania algorytmu sortowania przez wstawianie dla najlepszego przypadku
wynosi O:(n),z czego wynika, że czas działania tego algorytmu wynosi O:(n).
Czas działania algorytmu sortowania przez wstawianie leży zatem między
.Q(n) a O(n2 ). Ponadto oszacowania te są asymptotycznie najlepsze z możli­
wych: na przykład czas działania algorytmu sortowania przez wstawianie nie
wynosi .Q(n2 ), gdyż algorytm ten działa w czasie ®(n), gdy dane są już posorto-
wane. Nie jest jednak sprzecznością powiedzenie, że pesymistyczny czas działa­
nia algorytmu sortowania przez wstawianie wynosi O:(n2), ponieważ dla pew-
nych danych wejściowych algorytm ten wymaga czasu O:(n2 ). Gdy mówimy, że
czas działania algorytmu wynosi .Q(g(n)),rozumiemy przez to, że niezależnie od
konkretnych danych wejściowych rozmiaru n czas działania algorytmu dla tych
danych wynosi co najmniej g(n) razy pewna stała, dla dostatecznie dużych n.

49
ROZDZIAŁ 2. RZĘDY WIELKOŚCI FUNKCJI

Notacja asymptotyczna w równaniach

Widzieliśmy już, jak notacja asymptotyczna może być użyta we wzorach mate-
matycznych. Wprowadzając na przykład notację O napisaliśmy „n = O(n 2 )".
Mogliśmy również napisać 2n 2 + 3n + 1 = 2n 2 + 0(n). Jak interpretujemy
wzory tego typu?
Gdy notacja asymptotyczna występuje po prawej stronie równania, tak jak
w n = O(n 2 ), oznacza to, że zdefmiowaliśmy znak równości jako oznaczenie
przynależności: neO(n 2 ). Jednak.że ogólnie, gdy notacja asymptotyczna poja-
wia się we wzorze, interpretujemy ją jako anonimową. funkcję o pomijalnej
nazwie. Na przykład wzór 2n2 + 3n + 1 = 2n2 + @(n) oznacza, że
2n2 + 3n + l = 2n 2 + f(n), gdzie f(n) jest pewną funkcją należącą do zbioru
0(n). W tym wypadku/(n) = 3n + I, co faktycznie należy do 0(n).
Używając notacji asymptotycznej w ten sposób, eliminujemy nieistotne
detale oraz upraszczamy równanie. W rozdziale 1 na przykład wyraziliśmy
pesymistyczny czas działania algorytmu sortowania przez scalanie jak.o reku-

renCJę

T(n) = 2T(n/2) + 0(n)


Jeśli jesteśmy zainteresowani tylko asymptotycznym :zachowaniem się T{n),
to nie ma sensu dokładne zajmowanie się nie znaczącymi składnikami; są one
w pewnym stopniu zawarte w anonimowej funkcji określonej przez składnik
0(n).
Liczba anonimowych funkcji w wyrażeniu jest rozumiana jak.o liczba sytu-
acji, w których notacja asymptotyczna występuje. Na przykład w wyrażeniu


LO(,)
I= 1

jest tylko jedna funkcja anonimowa (funkcja względem r). Wyrażenie to zatem
nie jest tym samym co 0(1) + 0(2) + ...+ O(n). To ostatnie nie ma jasnej
interpretacji.
W pewnych wypadkach notacja asymptotyczna pojawia się po lewej stro-
nie równania, na przykład

2n2 + 0(n) = 0(n 2 )


Równanie takie interpretujemy, korzystając z następującej reguły: Niezależnie
od tego, jak anonimowe funkcje są wybrane po lewej stronie znaku równości,
można wybrać anonbnowe funkcje po prawej stronie tak, że równanie będzie
zachodzić. Nasz przykład oznacza zatem, że dla każdej funkcjif(n)e0(n) ist-

50
2.1. NOTACJA ASYMPTOTYCZNA

nieje pewna funkcja g(n)e0(~ 2) tak.a, że 2n 2 +/(n)= g(n) dla wszystkich n.


Inaczej mówiąc, prawa stronR równania jest bardziej zgrubnym opisem lewej
strony.
Relacje takie mogą tworzyć łańcuch relacji, jak na przykład

2n2 + 3n + I = 2n 2 + 0(n)
- ®(n')
Każde z równań możemy zinterpretować, używając podanej wcześniej reguły.
Pierwsze z równań mówi, że istnieje pewna funkcja /(n)e0(n) tak.a, że
2
2n + 3n + 1 = 2n 2 + f(n) dla wszystkich n. Drugie z nich mówi, że dla każdej
funkcji g(n)e 0(n) (takiej jak wspomniana funkcja/(n)) istnieje pewna funkcja
h(n) e 0(n ) tak.a, że 2n 2 + g(n) = h(n) dla wszystkich n. Z interpretacji tej wy-
2

nika, że 2n + 3n + 1 = 0(n 2 ), co jest implikacją intuicyjnego rozumienia łań­


2

cuchów relacji.

Notacja o
Asymptotyczna granica górna określona przez notację O może być lub nie być
asymptotycznie dokładna. Granica 2n 2 = O(n 2) jest asymptotycznie dokładna,
ale granica 2n = O(n 2 ) nie jest. Notacja o służy do określenia granicy górnej,
która nie jest dokładna. Formalnie defmiujemy o(g(n)) (,,małe o od g w zależ­
ności od n") jako zbiór

o(g(n)) - {/(n): dla każdej dodatniej stałej c > Oistnieje stała n, > O taka,
że O .::;;J(n) < cg(n) dla wszystkich n~ n 0 }

Na przykład 2n = o(n 2 ), ale 2n 2 '=I-o(n2 ).


Definicje notacji O oraz notacji o są podobne. Główna różnica polega na
tym, że w przypadkuf(n) = O(g(n)) oszacowanie O .::;;f(n).::;;cg(n) zachodzi dla
pewnej stałej c > O, natomiast w przypadku f(n) = o(g(n)) oszacowanie
O ~f(n) < cg(n) zachodzi dla wszystkich stałych c >O.Intuicyjnie, w notacji o
funkcja f(n) staje się pomijalna w stosunku do g(n), gdy n dąży do nieskoń­
czoności; to znaczy

lim /(n)_ - O
(2.1)
•-• g(n)

Niektórzy autorzy używają tej granicy jak.o definicji notacji o. Definicja w tej
książce dotyczy jedynie anonimowych funkcji, które są asymptotycznie nie-

uJemne.

51
ROZDZIAŁ 2. RZĘDY WIELKOŚCI FUNKCJI

Notacja w

Notacja w ma się tak do notacji n


jak notacja o do notacji O. Notację w
stosujemy do oznaczania oszacowania, które nie musi być dokładne. Można to
zdefiniować przez

f(n)ew{g(n)) wtedy i tylko wtedy, gdy g(n)eo(f(n))

Jednakże formalnie definiujemy w(g(n)) jako zbiór

w(g(n)) = {/(n): dla każdej dodatniej stałej c > O istnieje stała n 0 > O
taka, że O~ cg(n) </(n) dla wszystkich n~ n 0 }

Na przykład n'/2 = w(n), ale n'/2 # w(n'). Relacjaf(n) = o,(g(n)) implikuje, że

. f(n)
hm--·--·-· = oo
"...."°g(n)
jeśli powyższa granica istnieje. To znaczy /(n) staje się dowolnie duże w stosun-
ku do g(n), gdy n dąży do nieskończoności.

Porównywanie funkcji
Wiele relacji dotyczących liczb rzeczywistych dotyczy też porównywania rzę­
dów wielkości funkcji. W dalszym tekście zakładamy, że/(n) i g(n) są asymp-
totycznie dodatnie.

Przechodniość:

f(n) = ®(g(n) i g(n) = ®(h(n)) implikuje f(n) = ®(h(n))


f(n) = O(g(n)) i g(n) = O(h(n)) implikuje f(n) = O(h(n))
f(n) = Q(g(n)) i g(n) = Q(h(n)) implikuje f(n) = Q(h(n))
f(n) = o(g(n)) i g(n) = o(h(n)) implikuje f(n) = o(h(n))
f(n) = w(g(n)) i g(n) = w(h(n)) implikuje f(n) = w(h(n))

Zwrotność:

f(n) = ®(f(n))
f(n) = O(f(n))
f(n) = Q(f(n))
Symetria:

f(n) = ®(g(n)) wtedy i tylko wtedy, gdy g(n) = ®(f(n))

52
2.1. NOTACJA ASYMPTOTYCZNA

Symetria transpozycyjna:

f(n) = O(g(n)) wtedy i tylko wtedy, gdy g(n) = O(f(n))


f(n) = o(g(n)) wtedy i tylko wtedy, gdy g(n) = w(f(n))

Ponieważ własności te zachodzą


dla notacji asymptotycznych, można się
doszukiwać analogii między porównywaniem dwóch funkcji fi g oraz porów-
nywaniem dwóch liczb rzeczywistych a i b:

f(n) = O(g(n)) "'a<; b


f(n) = O(g(n)) s; a;,, b
f(n) = El(g(n)) "'a= b
f(n) = o(g(n)) "' a < b
f(n) = w(g(n)) s; a>b

Jednak pewna własność liczb rzeczywistych nie przenosi się na funkcje:

Własność trichotomii:

Dla każdych dwóch liczb rzeczywistych a i b zachodzi dokładnie jeden


z następujących faktów: a< b, a = b lub a > b.

Chociaż można porównać każde dwie liczby, nie można tego zrobić dla funk-
cji w sensie asymptotycznym. Oznacza to, że dla dwóch funkcji /(n) i g(n)
może nie wystąpić żaden z dwóch faktów: f(n) = O(g(n)), f(n) = O(g(n)). Na
przykład funkcje n oraz n 1 +Ilion nie mogą być w tym sensie porównane, gdyż
wartość wykładnika w nt+lliDn waha się między O i 2, przyjmując wszystkie
pośrednie wartości.

ZADANIA

2.1-1. Niechf(n) i g(n) będą funkcjami asymptotycznie nieujemnymi. Korzys-


tając z podstawowych definicji notacji 0, udowodnij, że max(/(n),
g(n)) = El(f(n) + g(n)).
2.1-2. Pokaż że dla każdych dwóch stałych a i b, gdzie b > O, zachodzi

(n + a)' = El(n') (2.2)

2.1-3. Wyjaśnij, dlaczego prawdziwość stwierdzenia „Czas działania algoryt-


mu A wynosi co najmniej O(n 2 )", nie zależy od A.
2.1-4. Czy 2•+> = 0(2")? Czy 2 2 " = 0(2")?
2.1-5. Udowodnij twierdzenie 2.1.

53
ROZDZIAŁ 2. RZĘDY WłELKO$CI FUNKCJI

2.1-6. Pokaż, że czas działania algorytmu wynosi 0(g(n)) wtedy i tylko wtedy,
gdy jego pesymistyczny czas działania wynosi O(g(n)), a jego optymistycz-
ny czas działania wynosi O(g(n)).
2.1-7. Udowodnij, ;.., o(g(n)) "ru(g(n)) jest zbiorem pustym.
2.1-8. Możemy rozszerzyć naszą notację na przypadek dwóch parameterów
n i m, które dążą do nieskończoności z różnymi szybkościami. Dla danej
funkcji g(n, m) oznaczamy przez O(g(n, m)) zbiór funkcji

O(g(n, m)) = {f(n, m): istnieją dodatnie stałe c, n 0 i m 0 takie, że


O ~f(n, m) ~ cg(n, m) dla wszystkich n ~ n 0 oraz
m~m 0}

Podaj analogiczne defmicje dla O(g(n, m)) i @(g(n, m)).

2.2. Standardowenotacjei typowe funkcje


W tym podrozdziale przyjrzymy się pewnym standardowym funkcjom mate-
matycznym i notacjom oraz zbadamy zachodzące między nimi relacje. Pokaże­
my też pewne zastosowania notacji asymptotycznych.

Monotoniczność

Funkcja/(n) jest monotonicznie rosnąca, jeślim< n implikuje/(m) ~/(n). Po-


dobnie, jest ona monotonicznie malejąca, jeśli m < n implikuje f(m) ~ f(n).
Funkcja/(n) jest ściśle rosnąca, jeślim< n i:m.plikuje/(m) </(n), oraz ściśle
malejąca, jeślim < n implikuje f(m) > f(n).

Części całkowite liczb

Dla każdej liczby rzeczywistej x zapis LxJt oznacza największą liczbę całkowi­
tą, nie większą. niż X, a zapis Ixl ~ najmniejszą liczbę Całkowitą, nie mniejszą
niż x. Dla wszystkich liczb rzeczywistych x

x-1 < LxJ~x~ fxl<x+l


Dla każdej liczby całkowitej n

1n/2l+ Ln/2J= n

t W terminologii polskiej nie ma specjalnych nazw dla tych funkcji; dlatego też będziemy je
czasem nazywać zgodnie z terminologią angielską: L xJ- podłogą (ang.floor), a rxl- sufitem (ang.
ceiling) (przyp. tłum.).

54
2.2. STANDARDOWE NOTACJE I TYPOWE FUNKCJE

i dla każdej liczby całkowitej n oraz liczb całkowitych a '# O i b '# O

11n/al/bl= 1n/abl (2.3)


jak również

LLn/aJ/bJ
= Ln/abj (2.4)

Wprowadzone funkcje są monotonicznie rosnące.

Wielomiany
Dla danej dodatniej liczby całkowitej d wielomianem stopnia d zmiennej n jest
funkcja p(_n)postaci

p(n) = L' a,n'


l=O

gdzie stałe a0 , a 1 , ... , a„są współczynnik.ami wielomianu i a.,'# O.Wielomian jest


asymptotycznie dodatni wtedy i tylko wtedy, gdy a.,> O. Dla każdego asymp-
totycznie dodatniego wielomianu p(_n)stopnia d mamy p(n) = @(n"). Dla każ­
dej stałej rzeczywistej a ~ Ofunkcja n"jest monotonicznie rosnąca, a dla każdej
stałej rzeczywistej a~ O funkcja n" jest monotonicznie malejąca. Mówimy, że
funkcja/(n) jest ograniczona wielomianowo,jeśli/(n) = n°c1 >,inaczej mówiąc,
f(n) = O(,t') dla pewnej stałej k (patrz zad. 2.2-2).

Funkcje wykładnicze

Dla dowolnych liczb rzeczywistych a =I=-O,mi n mamy następujące tożsamości:

a0 = 1
a =a
1

a- 1 = l/a
(rl")" = a""
(rl")" = (a")"
d"d' = d" + li

Dla wszystkich n i a ~ l funkcja a' jest monotonicznie rosnąca względem n.


Przyjmijmy, że 0° = I.
Rzędy wielkości wielomianu i funkcji wykładniczej można wyrazić nastę~
pującą relacją dla wszystkich stałych rzeczywistych a i b takich, że a > 1:

. -n
Illil
•=O (2.5)
...... oo a•

55
ROZDZIAŁ 2. RZĘDY WIELKOSCI FUNKCJI

z czego wynika, że

n' - o(a")
A zatem każda dodatnia funkcja wykładnicza rośnie szybciej niż wielomian.
Oznaczając przez e liczbę 2,71828..., podstawę logarytmów naturalnych,
mamy dla wszystkich liczb rzeczywistych x

(2.6)

gdzie ,,!" oznacza „silnię" (którą zdefiniujemy później). Dla wszystkich liczb
rzeczywistych x mamy
e" ;> l + X (2.7)
przy czym równość zachodzi tylko wtedy, gdy x = D. Gdy Jxl~ I, mamy
przybliżenie

1+x~ć~1+x+x 2 (2.8)

Gdy x - D, przybliżenie ć przez 1 + x jest ca.łlciem dobre:


2
e"-l +x+6(x )

(:,N równaniu tym notacja asymptotyczna jest użyta do opisu zachowania się
funkcji w przypadku granicznym, ale raczej gdy x - D niż gdy x - co). Dla
kaid.ego x mamy

lim
n-> "'
(1+ 2)"-
n
e"

Logarytmy
Będ7iemy używali następujących notacji:

lg n = log 2 n (logarytm o podstawie 2)


Inn= log„n (logarytm naturalny)
lgkn = (lgn)k (potęgowanie)
lglgn - lg(lgn) (kompozycja)

Istotną konwencją notacyjną jest to, że logarytm funkcji odnosi się tylko do
składnika bezpośrednio występującego po symbolu logarytmu, a więc lg n + k
oznacza (lgn) + k, a nie lg(n + k). Dla n> O i b > l funkcja logbn jest ściśle
rosnąca.

56
2.2. STANDARDOWE NOTACJE I TYPOWE FUNKCJE

Dla wszystkich liczb rzeczywistych a > O, h > O, c > O (dla których od-
powiednie logarytmy są określone) i n zachodzą następujące zależności:

a= blog,a

log,(ab) - log, a+ log, b


lo&,d = nlogba
_ logca_
IO&,a- I b
og,
Iog,(1/a) - -log,a
I
logba= I b
og.
aloa,n = n'oa,a (2.9)

Ponieważ zmiana podstawy logarytmu z jednej stałej na inną zmienia jedy-


nie wartość logarytmu o stały współczynnik, często będziemy pisać „lg n", nie
dbając o stałe współczynniki, podobnie jak w notacji O. Informatycy uważają
liczbę 2 z.a najbardziej naturalną podstawę logarytmów, ponieważ wiele algo-
rytmów i struktur danych opiera się na dzieleniu problemu na dwie części.
Gdy lxl < 1, wtedy ln(l + x) ma proste rozwinięcie w szereg:

x2 xl x4 xs
In(! + x) - x - 2 + 3 - 4 + 5 - ...
Mamy również dwie nierówności dla x > -1:
X
-- ~ ln(l + X) ,s_;X (2.10)
I+ X

przy czym równość zachodzi tylko dla x = O.


Mówimy, że funkcja /(n) jest ograniC7.0napolilogarytmicznie, jeśli
f(n) = Jg°C1 >n. Rzędy wielkości wielomianów oraz polilogarytmów są w pewnej
relacji - podstawiając lgn w miejsce n oraz 2" w miejsce a w równaniu (2.5),
otrzymujemy

. Ig'n . Ig'n
Inn~- algn - = hm .....
___
a
=O
n--+o, 2 n-+o, n

Z granicy tej wynika, że

lg 6 n = o(n")

dla każdej stałej a> O. Tak więc każdy dodatni wielomian rośnie szybciej niż
każda funkcja polilogarytmiczna.

57
ROZDZIAŁ 2. RZĘDY WIELKOSCI FUNKCJI

Silnia
Symbol n! (czytaj „n silnia") jest określony dla n ~ Ow następujący sposób:

l, jeśli n=O
ni -
.- { n·(n-1)!, jeśli n> O
Zatem n!= l ·2·3 ...n.
Słabym ograniczeniem górnym na silnię jest n!::::;;n", gdyż każdy z n czyn-
ników w iloczynie jest nie większy ni.z n. Wzór Stirlinga

(2.11)

gdzie e jest podstawą logarytmu naturalnego, daje dokładniejsze górne ograni-


czenie, jak również ograniczenie dolne. Korzystając ze wzoru Stirlinga, można
udowodnić, że

n! - o(n")
n! = w(211)
lg(n!)- 0(nlgn)

Dla każdego n zachodzą również następujące oszacowania:

(2.12)

Logarytm iterowany
Używamy notacji lg·n (czytaj „log gwiazdka n") do oznaczenia logarytmu ite-
rowanego, który jest zdefniowany następująco. Niech funkcja lg<lln będzie
zdefiniowana rekurencyjnie dla nieujemnych liczb całkowitych i w poniższy
sposób:

n jeśli i= O
lg(lg<'-1ln), jeśli i> O i Igli-lln > O
nieokreślone, jeśli i> O i JgU- 1 >n::::;;
O lub JgU- 1 >n
jest nieokreślony

Pamiętajmy, aby odróżniać Ig(l)n (funkcję logarytmiczną zastosowaną


i razy
dla argumentu n) od Ig'n (logarytm n podniesiony do potęgi z). Logarytm
iterowany jest zdefiniowany jako

58
2.2. STANDARDOWE NOTACJE I TYPOWE FUNKCJE

0
lg n = min{ i~ O: Ig(l)n.,s;;1}

Logarytm iterowany jest funkcją bardzo wolno rosnącą:

Ig'2 - I
lg'4 - 2
lg'l6 - 3
lg'65536 - 4
lg.(265536)= 5

Ponieważ szacuje się, że liczba atomów we wszechświecie wynosi około 1080 ,


co jest dużo mniej niż 265536, rzadko spotkamy wartość n taką, że tg·n > 5.

Liczby Fibonacciego

Liczby Fibonacciego są zdefiniowane w sposób rekurencyjny:

F 0 =0
F1 = 1 (2.13)
F 1 =F 1_ 1 +F 1_ 2 dla i~ 2

Każda liczba Fibonacciego jest zatem sumą dwóch poprzednich, co daje


sekwencję

O, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...

Liczby Fibonacciego są związane z liczbą tj, wyznaczoną ze złotej proporcji oraz


"
z liczbą tj, z nią spr7.ężoną. Liczby te są określone wzorami:

(2.14)

- 1,61803...

~-1-Js
2

- - 0,61803...

W szczególności mamy

59
ROZDZIAŁ 2. RZĘDY WIELKOSCI FUNKCJI

(2.15)

co można wykazać indukcyjnie (zad. 2.2-7). Ponieważ !IPI<1, mamy


< t/.Js < 1/2, zatem i-ta liczba Fibonacciego F, jest równa ą,'/.Jś
l,P'I/.JS
zaokrąglone do najbliższej liczby całkowitej. Tak więc liczby Fibonacciego ros-
ną wykładniczo.

ZADANIA
2.2-1. Wykaż, że jeśli f(n) i g(n) są funkcjami monotonicznie rosnącymi, to
takimi są również funkcje f(n) + g(n) i f(g(_n)), oraz jeśli f(n) i g(n) są
dodatkowo nieujemne, to funkcjaf(n) · g(n) jest monotonicznie rosnąca.
2.2-2. Korzystając z definicji notacji O, pokaż, że Jtn) = n°ll) wtedy i tylko
wtedy, gdy istnieje stała k > O taka, że Jtn) = O(n~.
2.2-3. Udowodnij równanie (2.9).
2.2-4. Udowodnij, że lg(n!) = 0(nlgn) oraz że n!= o(n").
* 2.2-5. Czy funkcja rtg nl ! jest ograniczona wielomianowo? Czy funkcja
flglgnl ! jest ograniczona wielomianowo?
* 2.2-6. Co jest asymptotycznie większe: lg(lg"n) czy lg"Qgn)?
2.2-7. Udowodnij, stosując indukcję, że i-ta liczba Fibonacciego spełnia rów-
ność F1 = (<J, - (i,)/../-5,
gdzie liczba <J,wynika ze złotej proporcji, a (i,jest
1 1

liczbą z nią sprzężoną.


2.2-8. Udowodnij, że jeśli i~ O,to (i+ 2)-ga liczba Fibonacciego spełnia zale-
żność F;+z ~ <J, 1

Problemy
2-1. Asymptotyczne zachowanie się wielomianów
Niech

p(n) = L' a,n,


i=O

gdzie a,1> O, będzie wielomianem stopnia d zmiennej n i niech k będzie stałą.


Korzystając z defmicji notacji asymptotycznych, udowodnij następujące wła-
• •
snosc1:

(a) jeśli k ;,, d, to p(n) = O(n')


(b) jeśli k <; d, to p(n) = O(n')
(c) jeśli k = d, to p(n) = EJ(n')
(d) jeśli k > d, to p(n) = o(n')
(e) jeśli k < d, to p(n) = w(n')

60
PROBLEMY

2-2. Względny rząd asymptotyczny


Dla każdej pary wyrażeń (A, B) w poniższej tabeli napisz, cz.y A jest O, o, n,
ro lub E>od B. Załóżmy, że k ~ 1, e > O i c > 1 są stałymi. Twoja odpowiedź
powinna brzmieć „tak" lub „nie''.
A B o o n OJ (8)

(a) Ig'n n' ! •


!
(b) n• c' I
(c) .;--.. nsm" i
(d) 2" 2"'' •

(e) nlsm ni••


(!) lg(n!) lg(n")

2-3. Porządkowanie ze względu na rząd wielkości funkcji


(a) Uporządkuj następujące funkcje ze względu na ich rząd wielkości; to zna-
czy znajdź uporządkowanie g 1 , g 2 , ... , g 30 tych funkcji, spełniające zależno­
ści g 1 = .Q(g2 ), g 2 = O(g 3 ), ... , g 29 = .Q(g30 ). Podziel swoją listę na klasy
równoważności takie, że /(n) i g(n) należą do tej samej klasy wtedy i tylko
wtedy, gdy f(n) = E>(g(n)).

lg(lg'n) 2lg'n (,/2 )''" n' n! Qgn)!

(~)" n' lg 2n lg(n!) 2'" nl/li11

lnlnn lg'n n· 2" n11ti11 Inn I


2!B11 (lgn}1B" e" 41s11 (n+ I)! .jlgn
lg'Qgn) 2..J'1J111 n 2" nlgn 22·"

(b) Podaj przykładjednej nieujemnej funkcji f(n) takiej, że dla wszystkich


funkcji g 1(n) z części (a) fuokcja/(n) nie jest ani Olg,(n)), ani O(g,(n)).

2-4. Własności
notacji asymptotycznej
Niech /(n) i g(n) będą asymptotycznie dodatnimi funkcjami. Sprawdź praw-
dziwość następujących faktów (odpowiedź uzasadnij):

(a) f(n) = O(g(n)) implikuje g(n) = O(f(n))


(b) f(n) + g(n) = E>(min(f(n), g(n)))

61
ROZDZIAŁ 2. RZĘDY WIELKO$Cl FUNKCJI

(c) /(n)= O(g(n)) implikuje lg(/(n)) = O(lg(g(n))), gdzie lg(g(n)) > O if(n);;, I
dla wszystkich dostatecznie dużych n
(d) /(n) = O(g(n)) implikuje 2t•> = 0(2'"')
(e) f(n) = 0((/(n))')
(f) f(n) = O(g(n)) implikuje g(n) = 0.(/(n))
(g) /(n) = 0(/(n/2))
(h) /(n)+ o(/(n)) = 0(/(n))

2-S. Wariacje na temat notacji O i O:


Niektórzy autorzy definiują .Q w nieco inny sposób niż my; oznaczo,y przez
li (czyt;aj „omega nieskończoność") tę alternatywną notację. Mówimy, że
f(n) = 0(g(n)), jeśli istnieje dodatnia stała c taka, że/(n) ~ cg(n) ~Odlanie-
skończenie wielu liczb naturalnych n.

(a) Wykaż, że dla każdych dwóch fnnkcji/(n) i g0), które są asymptotycznie


nieujemne, zachndzi/(n) = O(g(n)) lubL(n) = il{g(n)), pcdczas gdy nie jest
to prawdziwe, jeśli użyjemy .Q ZJ1miastli.
(b) Opisz potencjalne wady i zalety używania notacji li zamiast ,Q przy okreś-
leniu czasu działania programów.
Niektórzy autorzy również definiują O w nieco m:iieniony sposób; oznacm:iy
przez O' alternatywną defmicję. Mówimy, że /(n)= O'(g(n)) wtedy i tylko
wtedy, gdy 1/(n)I = O(g(n)).
(c) Co się dzieje z obiema implikacjami zawartymi w sformułowaniu „wtedy
i tylko wtedy gdy" w twierdzeniu 2.1, kiedy przyjmie się tę nową definicję?
Niektórzy autorzy definiują iJ jak.o O z dokładnością do logarytmicznych
czynników:
ĆJ(g(n)) = {f(n): istnieją dodatnie stałe c, k i n 0 takie,
że O "'/(n) "' cg(n) lg'(n) dla wszystkich n ;;, n,}
(d) 2.defmiuj O oraz ~ w podobny sposób. Udowodnij odpowiednik twier-
dzenia 2.1.

2-6. Funkcje iterowane


Operator iteracji ,, .,. użyty w funkcji lg" może być zastosowany do monotonicz-
nie rosnących funkcji rzeczywistych. Dla funkcji/spełniającej zależnośćf(n) < n
definiujemy rekurencyjnie funkcję J<fl dla nieujemnych liczb całkowitych i:

f"'(n) = {f(f"- ''(n)), jeśli i> O


n, jeśli i= O

Dla danej stałej ce R definiujemy funkcję iterowaną/; jako

62
UWAGIDO ROZDZIAŁU

f;(n) = min{ i ;i:, O:f 1iJ(n) ~ c}


która czasami może być źle określona. Inaczej mówiąc, wielkość f;(n) jest
liczbą iterowanych zastosowań funkcji f potrzebnych do zredukowania argu-
mentu do c lub poniżej.
Dla każdej z następujących funkcjif(n) oraz stałej c podaj jak najbardziej
dokładne oszacowanie dlaf;(n).

f(n) C J;(n)
(a) lgn I
(b) n-I o
(c) n/2 I
(d) n/2 2
(e) Jn 2
(!) J-;; I
nlfl '
(g) 2
(h) n/lgn 2

Uwagido rozdziału
Knuth [121] podaje jako źródło notacji O teorioliczbową pracę P. Bachmanna
z 1892 r. Notacja o została wprowadzona przez E. Landaua w 1909 r. w jego
badaniach dotyczących liczb pierwszych. Notacje .O:i 0 były lansowane przez
K.nutha [124] w celu usprawnienia popularnych, ale technicznie niejasnych za-
stosowań notacji O zarówno do dolnych, jak i do górnych granic. Wiele osób
używa nadal notacji O tam, gdzie bardziej precyzyjna jest notacja 0. Dalszy
opis historii i rozwoju notacji asymptotycznych można znaleźć w książkach
Knutha [121, 124] oraz Brassarda i Bratleya [33].
Nie wszyscy autorzy definiują notacje asymptotyczne w ten sam sposób,
chociaż różne notacje są często zgodne w typowych sytuacjach. Niektóre alter-
natywne definicje uwzględniają też funkcje, które nie są asymptotycznie nie-
ujemne, tak długo jak ich bezwzględne wartości są odpowiednio ograniczone.
Wiele innych matematycznych własności funkcji można znaleźć na przy-
kład w książkach Abramowitza i Steguna [I] lub Beyera [27], a także w książ­
kach z analizy matematycznej autorstwa Apostoła [12] lub Thomasa i Finneya
[192]. Książka K.nutha [121] zawiera dużo materiału na temat matematyk.i
dyskretnej wykorzystywanej w informatyce.
Rozdział 3

Sumy

Kiedy algorytm zawiera iteracyjne konstrukcje sterujące, takie jak pętle wbile
lub for, jego czas działania możemy wyrazić jako sumę czasów potrzebnych na
każde wykonanie treści pętli. W podrozdziale 1.2 na przykład zauważyliśmy,
żej-ta iteracja w algorytmie sortowania przez wstawianie dla najgorszego przy-
padku wymaga czasu proporcjonalnego do j. Dodając czasy wykonania kolej-
nych iteracji, otrzymujemy sumę (lub szereg)

Obliczenie wartości tej sumy dało oszacowanie 0(n 2 ) na pesymistyczny


czas działania algorytmu. Przykład ten pokazuje, na ile ważne jest zrozwnienie
metod obliczania i szacowania wartości sum. (Jak zobaczymy w ro7.dz. 4, sumy
pojawiają się również przy obliczaniu rekurencji).
W podrozdziale 3.1 podamy kilka podstawowych wzorów, w których po~
jawiają się sumy, a w pod.rozdz. 3.2 pokażemy, jak szacować wartości sum.
Dowody dla kilku wwrów z podrozdz. 3.1 przedstawimy w pod.rozdz. 3.2 jako
ilustrację zastosowania podanego w nim materiału. Dowody pozostałych wzo-
rów można znaleźć w dowolnej książce z analizy matematycznej.

3.1. Wzory i własności dotyczące sum


Mając dany ciąg liczb a 1 , a 2 , ... , skończoną sumę wyrazów tego ciągu
a1 + a 2 + ...+ a 11
możemy zapisać w postaci

"
I"•
t= 1

64
3.1. WZORY I WŁASNO$CI DOTYCZĄCE SUM

Jeżeli n= O, to wartość sumy defmiuje się jak.o O. Jeśli n n.ie jest liczbą cał­
kowitą, to przyjmujemy, że górna granica sumowania wynosi LnJ. Podobnie,
jeżeli pierwsza wartość k = x nie jest liczbą całkowitą, to przyjmujemy, że
sumowanie zaczynamy od LxJ. Wartość sumy skończonej jest zawsze dobrze
określona i nie zależy od kolejności dodawania jej wyrazów.
Mając dany ciąg liczb a 1 , a 2 , ... , nieskończoną sumę wyrazów tego ciągu
. . '
a 1 + a 2 + ...mozemy zap1sac w postaci
.

co oznacza


lim I a,
n-coi=l

Jeśli ta granica n.ie istnieje, to szereg jest rozbieżny; jeśli granica istnieje, to
szereg jest zbieżny. Wyrazów szeregu zbieżnego nie można zawsze dodawać
w dowolnej kolejności. Można jednak tak dodawać wyrazy szeregu bezwzględ-
• 00

nie zbieżnego, to znaczy takiego szeregu L a1 , że szereg L la1 1jest zbieżny.


i;l k=l

Liniowość

Dla każdej liczby rzeczywistej ci każdej pary skończonych ciągów a 1 , a 2 , ... , an


i b1, b2, ..., bn

• • •
L (ca, + b,) - c L a,+ L b,
J:;l l:"'1 i=l

Liniowość tego typu zachodzi również dla nieskończonych szeregów zbież­


nych.
Własność liniowości może być wykorzystywana w przypadku sum zawie-
rających notację asymptotyczną. Na przykład

,t, ®(J(kll - e(,t,f<kl)


W tej równości notacja @ po lewej stronie odnosi się do zmiennej k, po prawej
zaś do zmiennej n. Tak.ie manipulacje możemy również stosować dla nieskoń­
czonych szeregów zbieżnych.

65
ROZDZIAŁ 3. SUMY

Szeregi arytmetyczne
Suma

"
I: k-1 +2+ ... +n
.t =, 1

z której korzystaliśmy przy analizie algorytmu sortowania przez wstawianie,


jest szeregiem arytmetycznym i wynosi

" I
.r, k- In(n + I) (3.1)

- 0 (n') (3.2)

Szeregi geometryczne
Dla liczby rzeczywistej x =F1 suma

"
[x'-l+x+x'+ ... +x"
.t=O

jest nazywana szeregiem geometrycznym lub wykładniczym i wynosi


n .x"+l_l
I:
.t=>o
x'----
x-1
(3.3)

Jeżeli suma ta jest nieskończona i lxl < I, to mamy nieskończony malejący


szereg geometryczny
• I
I:
.t=>o
x'--
1-x
(3.4)

Szeregi harmoniczne
Dla dodatniej liczby całkowitej n, n-tą liczbą harmoniczną nazywamy
I I I I
H-1+-+
" 2
--+-+
3 4
... + --
n
" I
-I:-
.t"'l k
- Inn+ 0(1) (3.5)

66
3.1. WZORY t WŁASNOŚCI DOTYCZĄCE SUM

Różniczkowanie i całkowanie szeregów


Wiele wzorów dla sum możemy uzyskać, całkując lub różniczkując poznane
już przez nas wzory. Różniczkując na przykład obie strony nieskończonego
szeregu geometrycznego (3.4) i mnożąc je przez x, otrzymujemy


Ikx'-
,. (1-x)
X 2 (3.6)
0

Szeregteleskopowy
Dla dowolnego ciągu a0 , a1 , ••• , a„

"
L (al - al-1) = a,, - ao (3.7)
l= 1

W tym szeregu każdy ze składników a 1 , a2 , ••• , an-t jest dodany i odjęty do-
kładnie raz. Mówimy, że szereg składa się teleskopowo. Podobnie

·-'
L (al- al+ 1) = a0 - a„
l=O

Jak.o przykład szeregu składającego się teleskopowo (szeregu teleskopowe-


go) rozwaimy szereg

n-1 1
I--
,.,k(k+1J

Jeśli zapiszemy każdy wyraz w postaci

I I I
···-~~
k(k + I) k k +I
to otrzymamy

,-, I •-'(I I )
,I,k(k+ 1)- ,;, k - k+1
I
- I --
n

67
ROZDZIAŁ 3. SUMY

Iloczyny

Skończony iloczyn a 1 a2 ••• a" możemy zapisać w postaci

Jeżeli n = O, to wartość
iloczynu definiujemy jako 1. Możemy przekształcić
wzór z iloczynem na wzór z sumą przy użyciu równości

ZADANIA

3.1-1. Znajdź prosty wzór na wartość sumy L" (2k - 1).


J:=1

* 3.1-2. Mnożąc szeregi harmoniczne, wykaż, że L 1/(2k - 1) -In(,.jn) +
J:=1
+ 0(1).

* 3.1-3. Wykaż, że L (k - 1)/2' - O.
J:: o

* 3.1-4. Oblicz wartość sumy L (2k + l)xn.
J:=1

3.1-5. Korzystając z własności liniowości, udowodnij, że L O(JJ:(n)) =
J:=1
- a(,I,f.(n))
3.1-6. Udowodnij, że ,t,Q(f(k))- n(,f,f(k)) .

3.1-7. Oblicz iloczyn CT2·4 1.
J:=l

* 3.1-8. Oblicz iloczyn n (1 -
ł= 2
1/k').

3.2. Szacowaniewartości sum


Istnieje wiele metod szacowania wartości sum, opisujących czas działania al·
gorytmów. Poniżej podajemy kilka najczęściej używanych.

68
3.2. SZACOWANIE WART0$CI SUM

Indukcja matematyczna

Podstawową metodą wyznaczania wartościsum jest zastosowanie indukcji ma-


tematycznej. Przykładowo wykażemy, że suma szeregu arytmetycznego

±
k"'l
k wynosi
1
2
n(n + 1). Możemy łatwo sprawdzić, że zachodzi to dla n= l,
indukcyjnie zakładamy więc, że zachodzi dla n i dowodzimy, że zachodzi rów-
nież dla n + 1. Otrzymujemy

n+ l n
L k - L k +(n+ I)
k"'l keol

I
- n(n+ l)+(n+ I)
2
I
- (n + l)(n + 2)
2

Indukcję matematyczną stosujemy nie tylko do wyznaczania dokładnej


wartości sumy. Możemy z niej również korzystać, gdy szacujemy tę wartość.
Przykładowo wykażemy, że suma szeregu geometrycznego L" 3 1
wynosi 0(3"),
1= o
a dokładniej, że L" 31 ,s;;c3ndla pewnej stałej c. Jeśli założymy, że c ~ 1, dla
1 "' o
o
n = Omamy L 31 = I ,s;;c · 1. Zakładając, że oszacowanie jest właściwe dla n,
1=0
udowodnimy, że jest również właściwe dla n+ l. Dla (1/3 + 1/c) ,s;;1 lub, rów-
noważnie, c ~ 3/2 mamy
n+ 1 n
I: 3' - I: 3' + 3•+,
1"'0 1=0

Więc L" 31 = O (3"), co było do okazania.


l=O
Należy bardzo ostrożnie używać notacji asymptotycznej, kiedy dowodzi
się prawdziwości oszacowań indukcyjnie. Przyjrzyjmy się przykładowo nastę-

69
ROZDZIAŁ 3. SUMY

pującemu mylnemu dowodowi równości L" k = O (n). Na pewno


t= 1

L' 1 k = 0(1).
t=
Zakładając, że to oszacowanie sumy zachodzi dla n, dowodzimy
teraz, że zachodzi dla n + 1:
11+ 1 n
L1 k= t=L1 k+(n+
ł=
I)

= O(n) +(n+ I) <= źle!!

=O(n+I)

Błąd polega na tym, że „stała" ukryta w notacji O rośnie razem ze wzrostem


n, więc w rzeczywistości nie jest stalą, czego nie uwzględniliśmy w naszym
dowodzie.

Ograniczanie wyrazów sumy


Czasami dobre ograniczenie górne s:zeregu można otrzymać, ograniczając każ­
dy z jego wyrazów. Często wystarcza ograniczenie wyrazów szeregu przez naj-
większy z nich. Na przykład łatwym do znalezienia ograniczeniem górnym
szeregu arytmetycznego (3.1) jest

" "
I k,; I n
t=l t=l

=n2

"
Zazwyczaj dla szeregów postaci Lat, jeżeli amax= max.1 ..,;t,snat, to
t= l

"

Metoda polegająca na ograniczaniu każdego wyrazu szeregu przez naj-


większy wyraz tego szeregu jest niedoskonała w porównaniu z metodą polega-
jącą na ograniczaniu szeregu przez szereg geometryczny. Przypuśćmy, że ma-
"
my dany szereg Lat, w którym at+ 1 /at ~ r dla każdego k ~ O, przy czym
.I:= o
r < 1 jest stałą. Jeśli at~ a0 r1',to suma może zostać ograniczona nieskończo­
nym malejącym szeregiem geometrycznym:
"
Lat~Laor1'
.
t=O ł=O

70
3.2. SZACOWANIE WARTOŚCI SUM

I
= ao
I- r

Możemy skorzystać z tej metody przy ograniczaniu sumy L (k/3ł). Pierw-
t=1
szy wyraz jest równy 1/3, a stosunek dwóch następujących po sobie wyrazów

wynosi

(k+l)/3'+' 1 k+l
··-= - .
k/3' 3 k
2
<:-
~ 3

dla każdego k ';?;-1. Każdy wyraz jest ograniczony z góry przez (1/3)(2/3).t,
z czego wynika, że

• k • I(2)'
I -'I--
t"'13t"""t„13 3

- 1
-·-·-·-·-
3 1-2/3
I

- 1
Podstawowym błędem przy stosowaniu tej metody jest pokaz.anie~ że
stosunek dwóch następujących po sobie wyrazów jest mniejszy od 1, a na-
stępnie założenie, że suma może zostać ograniczona przez szereg geometry-
czny. Przykładem może tu być nieskończony szereg harmoniczny, który jest
rozbieżny, gdyż

- lim (lg n)

Stosunek (k + 1)-szego i k-tego wyrazu tego szeregu wynosi k/(k + 1) < 1,


lecz szereg nie jest ograniczony malejącym szeregiem geometrycznym. W celu

71
ROZDZIAŁ 3. SUMY

ograniczenia danego szeregu szeregiem geometrycznym, należy pokazać, że


istnieje r < 1, które jest stale, tak że stosunek każdej pary następujących po
sobie wyrazów jest nie większy od r. W szeregu harmonicznym nie występuje
takie r, ponieważ stosunek ten staje się dowolnie bliski 1.

Rozdzielaniesum
Jednym ze sposobów oszacowania skomplikowanej sumy jest przedstawienie
jej w postaci sumy dwóch lub więcej szeregów powstałych przez rozdzielenie
indeksów owej sumy, a następnie ograniczenie tak powstałych szeregów. Przy-
puśćmy na przykład, że próbujemy znaleźć dolne ograniczenie szeregu aryt-

metycznego L' k, o którym wiemy, że jego górne ograniczenie wynosi n2 •


ł= 1
Możemy spróbować ograniczyć każdy z wyrazów sumy najmniejszym jej wyra-
zem, który wynosi 1. Otrzymamy dolne ograniczenie równe n - bardzo odległe
od naszej górnej granicy n2 .
Lepsze ograniczenie dolne otrzymamy, rozkładając ten szereg na sumę
szeregów. Dla wygody przyjmijmy, że n jest parzyste. Mamy wtedy
,12
' '
I
I;= 1
k- I k+ I k
.I:"' 1 k"'ll/2+1

,12
>IO+ '
.I:= 1
I
k=n/2+1
(n/2)

;, (n/2) 2

- O(n2 )

co jest asymptotycznie dokładnym ograniczeniem, ponieważ L' k = O(n 2).


k= 1
Sumę otrzymaną przy analizie algorytmu możemy rozdzielić, a następnie
pominąć stałą liczbę jej wyrazów początkowych. Tę metodę stosuje się, kiedy
'
wszystkie wyrazy a.1: sumy _Lak są niezależne od n. Jeżeli początkowe wyrazy
.I:= o
sumy są stałe i ich liczba jest stała, to dla dowolnej stałej k 0 > O, możemy
• •
nap1sac
n .1:
0 -1 n

I•,-I•,+I•,
k=O .1:=0 k=k 0

- E>(ll + I' a,
~=ko

72
3.2. SZACOWANIE WARTQ$CI SUM

Teraz możemy już użyć innych metod ograniczania sumy L" ak. Chcąc na
k=k,
przykład znaleźć asymptotyczne górne ograniczenie sumy
• k'
1:-2t
k=O

należy zauważyć, że dla k ~ 3 stosunek następujących po sobie wyrazów tej


sumy wynosi

(k+ 1)2 /2'+ 1


(k + 1)2
k 2 /2' 2k2

8
"'
~9 -

Więc

2 k2 oo k2
1: ·
k=o2"
· + 1: ··
teeJ 2t

,;;0(1J+ 91:• (S)'


·
8
-
k=O 9
- 0(1)
ponieważ druga suma jest malejącym szeregiem geometrycznym.
Metoda rozdzielania sum może być użyta do badania asymptotycznych
oszacowań w przypadkach dużo bardziej skomplikowanych niż ten rozważany
powyżej. Możliwe jest na przykład uzyskanie oszacowania O(lg n) dla szeregu
harmonicznego (3.5):

Idea polega na rozdzieleniu zakresu indeksów od 1 do n na Lig nJ części i ogra·


niczeniu każdej części przez 1. W ten sposób

LignJ 2'-l 1
,;;I;I;-,
J=O J=O 2

73
ROZDZIAŁ 3. SUMY

:s;;lgn+l (3.8)

Szacowaniecałkami

Jeżeli suma da się wyrazić w postaci L" f(k), gdzie f(k) jest funkcją mono-
k=m
tonicznie rosnącą, możemy oszacować ją przez całki

n n n+ 1
J f(x) dx <,, "i,f(k) <,, J /(x) dx (3.9)
•-1 •
Dowód tego oszacowania został zilustrowany na rys. 3.1. Suma jest tam przed-
stawiona jako pola prostokątów figury, a całka to szary obszar pod krzywą.
Jeżeli f(k) jest funkcją monotonicznie malejącą, to możemy użyć podobnej
metody do określenia ograniczeń

n+ l n n
J f(x) dx <,, "i,f(k) <,, J /(x) dx (3.10)
• •-1

Nierówności (3.10) dają dokładne oszacowanie n-tej liczby harmonicznej. Dol-


nym oszacowaniem jest

n 1 n+ 1 dx.
"[,--;;,j-
k= 1 k 1 X

-ln(n+l) (3.11)

Górnym oszacowaniem jest

= Inn
z c-zego

(3.12)

74
3.2. SZACOWANIE WARTO$CI SUM

f (x)

. •.·,
••
/: ..-,.
" '<
',; \;,;.·<':·
' •
• "-",p ·,. ··>

' ' '

•••

'
.·,.·<( " ,,,, ,:,.
;Is;• ' ' ..,,
'--- ~--~'--X
m-1 m m+l m+2 .- .- n-2 n-1 n n+I
<•)

f (x)

.... .... ~
n· " ..,

~ l
- - ~· '" ' I' ' ·; ......
..
..
..
••

__,
m-1 m m+l m+2 -· -· n-2 n-I n n+I
(b)

Rys. 3.1. Oszacowanie sumy L f(k) przez całki. Pole wszystkich prostokątów razem reprezentuje

wartość

·-·
sumy. Całka to szary obszar pod

krzywą. Jeżeli porównamy ze sobą obszary z części (a),

otrzymamy J /(x) dx ,i;,; L f(k), przesuwając prostokąty o jeden w prawo, dostaniemy


.. -1 r.~ ..
• n+ I
L /(k)
kwlO
,i;,; J„ /(x) dx, co zostało pokazane w części (b)

75
ROZDZIAŁ 3. SUMY

ZADANIA

3.2-1. Pokaż, że suma L" 1/k 2 jest ograniczona z góry przez stałą.
k=l
3.2-2. Znajdź asymptotyczne ograniczenie sumy

l!a nj

t
r
=o
1n12•1
3.2-3. Wykaż metodą rozdzielania sumy, że wartość n-tej liczby harmonicznej
wynosi OQg n).
3.2-4. Przybliż sumę L" k 3
całką.
t =1
3.2-S. Dlaczego, aby otrzymać górne oszacowanie n-tej liczby harmonicznej
L" 1/k, nie użyliśmy bezpośrednio nierówności (3.10)?
t= 1

Problemy
3-1. Szacowanie wartości smn
Podać asymptotycznie dokładne ograniczenia na wartości następujących sum
przy założeniu, że r ~ O i s ~ O są stałymi.

"
<•lL "'
t=l

(bJ r" tg'k


t= l

(cl r" k'tg'k


t= 1

Uwagido rozdziału
Książka Knutha [121] jest doskonałym odniesieniem do materiału prezentowa-
nego w tym rozdziale. Podstawowe wiadomości o sumach można znaleźć w ka-
żdej książce z analizy matematycznej, na przykład w pracach Apostoła [12] lub
Thomasa i Finneya [192],
Rozdział 4

Rekurencje

Jak już powiedzieliśmy w rozdz. 1, jeśli algorytm zawiera rekurencyjne wywo-


łanie samego siebie, to jego czas działania może być określony rekurencją.
Rekurencja jest równaniem lub nierównością opisującą funkcję złożoności
w zależności od jej wartości dla danych wejściowych o mniejszych rozmiarach.
W rozdziale 1 na przykład widzieliśmy, że pesymistyczny czas działania T(n)
procedury MERGE-SORT można przedstawić za pomocą rekurencji

jeśli n= 1
T(n) - {0(1), (4.1)
2T(n/2) + 0(n), jeśli n> I

Rozwiązaniem tej rekurencji jest T(n) = 0(nlgn).


W tym rozdziale prudstawimy trzy metody rozwiązywania rekurencji, tzn.
uzyskiwania asymptotycznych oszacowań rozwiązań przy zastosowaniu nota-
cji 0 lub O. W metodzie podstawiania zgadujemy oszacowanie, a następnie
dowodzimy przez indukcję, że odgadliśmy trafnie. W metodzie iteracyjnej prre-
kształcamy rekurencję w sumę, a następnie (aby ją rozwiązać) korzystamy
z technik. ograniczania sum. W metodzie rekurencji uniwersalnej stosujemy
oszacowania na rekurencje mające postać

T(n) - aT(n/b) + f(n)


gdzie a~ 1, b > 1, a f(n) jest daną funkcją; w metodzie tej rozważa się trzy
różne przypadki, które pozwalają na łatwe rozwiązywanie wielu prostych rów-
nań rekurencyjnych.

77
ROZDZIAŁ 4. REKURENCJE

Pomijanie szczegółów technicznych

W praktyce przy formułowaniu i rozwiązywaniu rekurencji pomijamy pewne


techniczne szczegóły. Dobrym przykładem takiego szczegółu, który często po-
mijamy, jest założenie, że argumentami funkcji są liczby całkowite. Z reguły
czas działania algorytmu T(n) nie jest zdefiniowany wtedy, gdy n nie jest cał­
kowite, gdyż w większości algorytmów romiiar danych wejściowych jest liczbą
całkowitą. Równanie rekurencyjne opisujące na przykład pesymistyczny czas
działania MERGB-SORT naprawdę wygląda następująco:

0(1), jeśli n=1


(4.2)
T(n) - { T(1n/1]) + T(Ln/2j) + 0(n), jeśli n> 1

Warunki brzegowe, jak.ie muszą być spełnione, aby można było rozwiązać
rekurencję, to następna klasa szczegółów, które z reguły pomijamy. Ponieważ
czas działania algorytmu dla danych wejściowych o stałym romiiarze jest sta-
ły, rekurencje opisujące czas działania algorytmu generalnie zawierają
T(n) - 0(1) dla wystarczająco małych n. Dla wygody będziemy zatem pomijać
dokładne ustalania warunków brzegowych rekurencji i założymy, że T(n) jest
stałe dla małych n. Rekurencję (4.1) na przykład zazwyczaj zapisujemy jak.o

T(n) - 2T(n/2) + 0(n) (4.3)

bez dok.ładnego
podawania wartości dla małych n. Powodem jest to, że zmiana
wartości T(l) zmienia rozwiązanie równania rekurencyjnego tylko o stalą,
więc rząd wielkości się nie zmienia.
Gdy rozwiązujemy równania rekurencyjne często pomijamy założenia
o całkowitości argumentów i warunki brzegowe; dopiero później okazuje się,
czy mają one jakiś znaczą.cy wpływ na rozwiązanie, czy też nie. Zazwyczaj
okazuje się, że nie mają one żadnego znaczenia, ale czasami trzeba wiedzieć,
kiedy należy je uwzględnić, a kiedy można pominąć. W określeniu ważności
wyżej wymienionych szczegółów pomaga zarówno doświadczenie w rozwiązy­
waniu równań rekurencyjnych, jak i pewne twierdzenia, które o tym trak.tują
(patrz tw. 4.1 i problem 4-5). W tym rozdziale rozważymy kilka z tych szczegó-
łów, aby pokazać subtelności metod rozwiązywania równań rekurencyjnych.

4.1. Metodapodstawiania
Metoda rozwiązywania równań rekurencyjnych przez podstawianie polega na
zgadnięciu postaci rozwiązania, a następnie wykazaniu przez indukcję, że jest
ono poprawne. Trzeba też znaleźć odpowiednie stale. Nazwa metody pochodzi

78
4.1. METODA PODSTAWIANIA

od tego, że
podstawiamy odgadnięty wzór funkcji dla mniejszych wartości,
korzystając z założenia indukcyjnego. Metoda ta jest bardzo skuteC'llla, ale
oczywiście może być zastosowana tylko w przypadkach, kiedy łatwo jest prze-
widzieć postać rozwiązania.
Metoda podstawiania może być użyta do określenia albo górnego, albo
dolnego oszacowania na wartości rozwiązania rekurencji. Jako przykład ob-
liczymy ograniczenie górne funkcji zadanej zależnością rekurencyjną

T(n) = 2T(Ln/2J) +n (4.4.)

która jest podobna do zależności (4.2) i (4.3). Zgadujemy, że rozwiązaniem jest


T(n) = O(nlgn). Naszym zadaniem jest teraz udowodnienie, że T(n) ~ cnlgn
dla dobrze wybranej stałej c > O. Zaczynamy od przyjęcia założenia, że ograni-
czenie zachodzi dla Ln/2J, tzn. T(i.n/2J),; c Ln/2Jlg (ln/2J ). Podstawienie tego
do naszego równania rekurencyjnego daje

T(n) <, 2(cln/2Jlg(Ln/2J)) +n


,; en lg(n/2) + n
= cnlgn - cnlg2 +n
=cnlgn-cn+n
.:::;;
cnlgn

gdzie ostatni krok jest spełniony, dopóki c ;;3!:1.


Indukcja matematyczna zmusza nas do pokazania, że nasze rozwiązanie
jest poprawne dla warunków brzegowych. To znaczy musimy pokazać, że mo-
żemy wybrać stałą c wystarczająco dużą i taką, że zależność T(n):::;;cnlgn
zachodzi tak.że dla warunków brzegowych. Wymóg ten często sprawia prob-
lem. Załóżmy, dla naszych rozważań, że T(l) = 1 jest jedynym (podstawo-
wym) warunkiem brzegowym równania rekurencyjnego. Wtedy jednak niemo-
żemy wybrać wystarczająco dużego c, ponieważ T(l).:::;; cl lg 1 = O.
Ta trudność w dowodzie indukcyjnym hipotezy dla konkretnego warunku
brzegowego może być łatwo przezwyciężona. Korzystamy z faktu, że notacja
asymptotyczna wymaga jedynie, abyśmy dowiedli, że T(n) ~ cnlgn dla n;;..:n 0 ,
gdzie n 0 jest stałą. W naszym dowodzie indukcyjnym, nie bierzmy pod uwagę
warunku T(l) = 1, przyjmijmy natomiast n= 2 i n= 3 jako część warunku
brzegowego. Możemy narzucić 7(2) i T(3) jako warunki brzegowe w dowodzie
indukcyjnym, ponieważ dla n> 3 rekurencja nie zależy bezpośrednio od 7(1).
Z rekurencji obliczamy, że T(2) = 4 i T(3) = 5. Dowód indukcyjny, że
en lg n dla dowolnego stałego c ;;..:2 możemy teraz przeprowadzić, wybie-
T(n) .:::;;
rając c wystarczająco duże, tak aby T(2).:::;;c2Ig2 oraz 7(3):::;; c3lg3. Okazuje

79
ROZDZIAŁ 4. REKURENCJE

się, że dowolnie wybrane c ~ 2 spełnia ten warunek. Dla większości równań


rekurencyjnych przekonyrny się, że możemy bezpośrednio rozszerzyć warunki
brzegowe tak, aby założenie indukcyjne było prawdziwe dla małych n.

Zgadywanie rozwiązania
Niestety, nie ma ogólnej zasady na zgadywanie poprawnych rozwiązań równań
rekurencyjnych. Odgadnięcie rozwiązania to kwestia doświadczenia i pomys-
łowości. Na szczęście jednak istnieją pewne „heurystyki", które mogą być po-
mocnicze przy zgadywaniu.
Jeżeli rekurencja jest podobna do innej, z którą spotkaliśmy się już wcześ­
niej, dobrze jest spróbować podstawić postać rozwiązania podobną do tej po-
przednio znanej. Jak.o przykład rozważmy rekurencję

T(n) = 2T(Ln/2J + 17) + n


która wydaje się trudna ze względu na dodane „17" w argumencie Tpo prawej
stronie zależności. Intuicyjnie, ten dodatkowy wyraz nie może jednak istotnie
wpłynąć na rozwiązanie rekurencji. Kiedy n jest duże, różnica między T(Ln/2J)
i T( Ln/2J + 17) nie jest aż tak duża: obydwie rekurencje dzielą n prawie równo
na polowy. Tak więc zgadujemy, że rozwiązanie wynosi T(n) = O(nlgn), co
można sprawdzić, używając metody podstawiania (patrz zad. 4.1-5).
Innym sposobem trafnego odgadnięcia postaci rozwiązania jest udowod-
nienie zgrubnego górnego oraz dolnego oszacowania na rekurencję, a następ­
nie stopniowe zmniejszanie błędu oszacowania. Możemy na przykład zacząć
od znalezienia dolnego ograniczenia T(n) = .Q(n)dla rekurencji (4.4), ponieważ
mamy składnik n w równaniu rekurencyjnym oraz możemy wykazać po-
czątkowe górne oszacowanie T(n) = O(n2 ). Następnie możemy stopniowo po-
prawiać dolne i górne oszacowanie, zwiększając dolne oszacowanie tak
długo, aż otrzymamy poprawne i asymptotycznie dokładne rozwiązanie
T(n) = El(nlgn).

Pewne subtelności
W pewnych wypadkach, gdy poprawnie się zgadnie asymptotyczne oszacowa-
nie na rozwiązanie rekurencji, mogą się pojawić kłopoty z przeprowadzeniem
dowodu indukcyjnego. Zazwyczaj problem polega na tym, że założenie nie jest
wystarczająco silne, aby udowodnić precyzyjne oszacowanie. Gdy natrafisz na
tak.i trudny przypadek, spróbuj pominąć składniki niższego rzędu.
Rozważmy rekurencję

T(n) = T(Ln/2J) + T(1n/1]) +I


80
4.1. METODA PODSTAWIANIA

Zgadujemy, że rozwią:,,anie wynosi O(n), oraz próbujemy wykazać, że


T(n) :s;,;en dla odpowiednio dobranej stałej c. Podstawiając zgadnięty wzór do
rekurencji, otrzymujemy

T(n).; cLn/2J+ c1n/2l+ I


=en+ I
z czego jednak nie musi wynikać, iż T(n) ~ en dla dowolnego c. Może nas skusić
wzięcie większych wartości, na przykład T(n) = O(n 2), co w istocie pomaga.
Faktycznie, zgadnięte początkowo rozwiązanie T(n) = O(n) jest poprawne.
W celu wykazania tego musimy jednakże przyjąć silniejsze założenie indukcyjne.
Intuicyjnie, zgadliśmy prawie dobrze, z dokładnością do stałej I. Niemniej
jednak indukcja nie działa, o ile nie sprecyzujemy dokładniej założenia induk-
cyjnego. Przezwyciężamy tę trudność przez odjęcie składnika niższego rzędu
w poprzednim wzorze. Przewidujemy teraz, że T(n) ~ en - b, gdzie b ~ Ojest
stalą. Mamy więc

T(n).; (cln/2J- b) + (c1n/2l- b) +1


=cn-2b+1
:s;.;en - b

gdy b ~ 1. Tak jak poprzednio, stała c musi być dostatecznie duża, aby za-
chodziły warunki brzegowe.
Większość ludzi uważa, że odejmowanie składnik.ów niższego rzędu jest
niezgodne z intuicją. Jeśli rachunki zawiodły, to czy nie powinniśmy zwiększać
odgadniętego wzoru. Aby zrozumieć ten krok, należy jednak pamiętać, że łat­
wiej jest udowodnić coś mocniejszego dla dużych wartości, zakładając coś mo-
cniejszego dla małych.

Unikanie pewnych pułapek


Korzystając z notacji asymptotycznej, można się łatwo pomylić. Na przykład
w rekurencji (4.4) możemy fałszywie wykazać, że T(n) = O(n), zgadując że
T(n) :s;.;en, a następnie udowadniając, iż

T(n) ", 2(cln/2J)+ n


~cn+n
- O(n) = źle!!
gdyż c jest stałą. Błąd polega na tym, że nie wykazaliśmy dokładnie tego co
trzeba, to znaczy, że T(n) ~ en.

81
ROZDZIAŁ 4. REKURENCJE

Zamiana zmiennych
Czasami drobny zabieg algebraiczny może zamienić daną rekurencję tak, aby
była podobna do takiej, którą już znamy. Jak.o przykład rozważmy rekurencję

T(n) - 2T(LJnj) + lgn


która wygląda na dosyć trudną. Możemy ją jednak uprościć przez zamianę
zmiennych. Dla wygody nie będziemy się przejmować zaokrąglaniem wartości
takich, jak Jn,aby były one liczbami całkowitymi. Podstawiając m = lgn,
otrzymujemy

T(2m) - 2T(2mfl) +m
Możemy teraz podstawić S(m) = T(2m), otrzymując rekurencję

S(m) - 2S(m/2) +m
podobną do rekurencji (4.4) i mającą takie samo rozwiązanie: S(m) =
= O(m lgm). Zamieniając odwrotnie S(m) na T(n), otrzymujemy T(n) =
- T(2·) - S(m) - O(mlgm) - O(lgnlglgn).

ZADANIA

4.1-1. Pokaż, że rozwiązaniem równania T(n) = T(fn/11) + I jest O(lgn).


4.1-2. Pokaż, że rozwiązaniem równania T(n)- 2T(Ln/2J) + n jest Cl(nlgn).
Wywnioskuj, że rozwiązaniem jest 0(nlgn).
4.1-3. Pokaż, że czyniąc różne założenia indukcyjne, możemy przezwyciężyć
kłopoty z warunkiem brzegowym T(l) = 1 dla rekurencji (4.4) bez modyfi-
kowania warunków brzegowych w dowodzie indukcyjnym.
4.1-4. Pokaż, że 0(nlgn) jest rozwiązaniem „dokładnej" rekurencji (4.2) dla
sortowania przez scalanie.
4.1-5. Pokaż, że rozwiązaniem równania T(n) = 2T(Ln/2J + 17) + n jest
O(nlgn).
4.1-6. Rozwiąż rekurencję T(n) = 2T(Jn) + 1, stosując zamianę zmiennych.
Nie przejmuj się tym, czy wartości są całkowite.

4.2. Metodaiteracyjna
Metoda iterowania rekurencji nie wymaga odgadywania odpowiedzi, ale może
wymagać zastosowania większego aparatu algebraicznego niż metoda podsta-
wiania. Główną ideą jest rozwijanie (iterowanie) rekurencji i wyrażanie jej jako

82
4.2. METODA ITERACYJNA

sumy składników zależnych tylko od n oraz od warunków brzegowych. Na-


stępnie mogą być użyte techniki sumowania do oszacowania rozwiązania.
Jako przykład rozważmy rekurencję

T(n) = 3T(Ln/4J) + n

Iterujemy ją następująco:

T(n) =n+ 3T(ln/4J)

=n+ 3(ln/4J + 3T(Ln/16J))


=n+ 3(ln/4J + 3{Ln/16J+ 3T(Ln/64j)))
=n+ 3Ln/4J + 9Ln/16J+ 27T(Ln/64j)

gdzie Lln/4J/4J = Ln/16J oraz LLn/16J/4J = Ln/64J wynikają z tożsamości


(2.4).
Jak długo musimy iterować zależność rekurencyjną, zanim osiągniemy wa-
runki brzegowe? Składnik i-ty w ciągu wynosi 3; Ln/4~. Iterowanie kończymy,
gdy n= 1, gdy Ln/4~ = 1 lub - równoważnie - gdy i przekracza log 4 n. Kon-
tynuując iterowanie do tego punktu oraz stosując oszacowania Ln/4~ ~ n/4;,
stwierdzamy, że suma odpowiada malejącemu szeregowi geometrycznemu:

T(n),;; n+ 3n/4 + 9n/16 + 27n/64 + ...+ 3'"""0(1)

= 4n + o(n)
= O(n)
Skorzystaliśmy tu z tożsamości (2.9), aby wywnioskować, że 310B•" = n10g,, 3 ,
i skorzystaliśmy też z faktu, że log 4 3 < I, otrzymując, że 0(n1°i•3 ) = o(n).
Metoda iteracyjna jest zazwyczaj związana z mnóstwem przekształceń al-
gebraicznych, więc zachowanie prostoty nie jest wcale tak łatwe. Punkt kluczo-
wy to skoncentrowanie się na dwóch parametrach: liczbie iteracji rekurencji
potrzebnych do osiągnięcia wan1nku brzegowego oraz sumie składników poja-
wiających się w kolejnych iteracjach. Czasami, w procesie iterowania rekuren-
cji, można przewidzieć rozwiązanie bez skomplikowanych przekształceń algeb-
raicznych. Wówczas iterowanie można poniechać na korzyść metody podsta-
wiania, która jest znacznie mniej algebraiczna.

83
ROZDZIAŁ 4. REKURENCJE

Gdy rekurencja zawiera funkcje dające część całkowitą liczby (funkcje


podłogi i sufitu), potrzebny aparat matematyczny może być szczególnie skom-
plikowany. Czasami pomocne jest założenie, że rekurencja jest zdefiniowana
tylko dla dokładnych potęg pewnej liczby. W naszym przykładzie, gdybyśmy
założyli, że n = 41 dla pewnej liczby całkowitej k, to można by pominąć branie
części całkowitych. Niestety, dowodzenie oszacowania T(n) = O(n) tylko dla
dokładnych potęg 4 jest nadużyciem notacji O. Definicje notacji asymptotycz-
nych wymagają, żeby nierówności były prawdziwe dla wszystkich dostatecznie
dużych liczb całkowitych, nie zaś tylko dla potęg liczby 4. W podrozdziale 4.3
zobaczymy, że dla dużej klasy rekurencji można w sposób czysto techniczny

T(n) 2
" "'
/~ /~
r(;) r(;) (;)' (;)'
I \ I \
r(:) r('.I)r(:) r(:)
(•) (b) (<)

2 ..................................... _, _______
..•..•,1~- 2
n
"
/ ~ 2
(;)' ( ; ) •••••••••••-••••••u••u•u11~• I 2
-,
2

lg"
I \ I \
(:)' (:)' (i)' (:)' .,,. -n I 2
4
I\I\I\I\
I \ I \ I \ I \
. •

2
W sumie: 0(11 )
(d)

Rys. 4.1. Konstrukcja drzewa rekursji dla równania rekurencyjnego T(n) = 2T(n/2) + n 1 . Część (a)
zawiera T(n), które jest stopniowo rozwijane w (b)-(d) do drzewa rekursji. W pełni rozwinięte
drzewo w części (d) ma wysokość Jgn (ma ono lgn + I poziomów)

84
4.2. METODA ITERACYJNA

sprowadzić je do potęg określonej liczby. Problem 4-5 zawiera również wa-


runki, przy których analiza dla dokładnych potęg pewnej liczby całkowitej
może być rozszerzona na wszystkie liczby całkowite.

Drzewa rekursji
Drzewo rekursji pozwala w dogodny sposób ilustrować rozwijanie rekurencji,
jak również ułatwia stosowanie aparatu algebraicznego służącego do rozwiąza­
nia tej rekurencji. Jest ono szczególnie użyteczne, gdy rekurencja opisuje al-
gorytm typu „dziel i zwyciężaj". Na rysunku 4.1 jest pokazane wyprowadzenie
drzewa rekursji dla równania rekurencyjnego

T(n) - 2T(n/2) + n'

Dla uproszczenia zakładamy, że n jest potęgą 2. Część (a) rysunku przedstawia


T(n), które w części (b) zostało rozwinięte w równoważne drzewo reprezentują­
ce rekurencję. Składnik n2 jest korzeniem (kosztem najwyższego poziomu re-
kursji), a dwa poddrzewa korzenia są dwiema „mniejszymi" rekurencjami
T(n/2). Część (c) ilustruje ten proces przy rozwijaniu T(n/2). Koszt każdego
z dwóch węzłów drugiego poziomu rekursji wynosi (n/2)2 • Kontynuujemy roz-
wijanie każdego węzła drzewa (przez rozbijanie go na części odpowiadające
rekurencji) tak długo, aż zostanie osiągnięty warunek brzegowy. W części (d)
rysunku widać drzewo wynikowe.
Szacujemy teraz koszt rekurencji, dodając wartości na każdym poziomie
drzewa. Najwyższy poziom ma sumaryczną wartość n2 , drugi poziom ma war-
tość (n/2)2 + (n/2) 2 = n 2 /2, trzeci poziom ma wartość (n/4)2 + (n/4)2 +
+ (n/4) 2 + (n/4) 2 = n2 /4 itd. Ponieważ wartości maleją geometrycznie, w su-
mie otrzymujemy co najwyżej tyle (z dokładnością do stałego czynnika), ile
wynosi największy (pierwszy) składnik, a zatem rozwiązaniem jest 0(n 2).
Inny, bardziej skomplikowany przykład drzewa rekursji widać na rys. 4.2
dla równania rekurencyjnego

T(n) - T(n/3) + T(2n/3) + n


(Znowu pomijamy dla uproszczenia branie części całkowitych). Gdy dodamy
wartości po poziomach drzewa rekursji, dla każdego poziomu otrzymamy n.
Najdłuższą ścieżką od korzenia do liścia jest n -+ (2/3)n -+ (2/3)2 n -+ ... -+ 1.
Ponieważ (2/3)"n = 1, gdy k = log 3 , 2 n, więc wysokość drzewa wynosi log 312 n.
Rozwiązanie rekurencji nie przekracza zatem nlog 3 , 2 n = O(nlgn).

ZADANIA
4.2-1. Wyznacz, używając metody iteracyjnej, asymptotyczne oszacowanie
górne dla rekurencji T(n) = 3T(Ln/2J) + n.

85
ROZDZIAŁ 4. REKURENCJE

n ·······························-·····-········-""··=••·

-" -2n .............................


:11~
3 3
.
"
/\ /\
2, 2, ··-············iii~
-" - - 4n n
9 9 9 9
I I I I I I I I
I I I I I I I I

• •
.

W sumie: O(n lg n)
Rys. 4.2. Drzewo rekursji dla równania rekurencyjnego T(n) = T(n/3) + T(2n/3) + n

4.2-2. Uzasadnij, korzystając z drzewa rekursji, że rozwiązaniem rekurencji


T(n) = T(n/3) + T(2n/3) + n jest !l(nlgn).
4.2-3. Narysuj drzewo rekursji dla T(n) = 4T(Ln/4J) + n i podaj dok:ladne
asymptotyczne oszacowanie rozwiązania tej rekurencji.
4.2-4. Skorzystaj z iterowania do rozwiązania rekurencji T(n) = T(n - a) +
+ T(a) + n, gdzie a ~ l jest stałą.
4.2-S. Skorzystaj z drzewa rekursji, aby rozwiązać rekurencję T(n) = T(o:n) +
+ T((l - o:)n) + n, gdzie o:jest stałą z przedziału O < o: < 1.

4.3. Metodarekurencji
uniwersalnej
Metoda rekurencji uniwersalnej podaje „uniwersalny przepis" rozwiązywania
równania rekurencyjnego postaci

T(n) = aT(n/b) + f(n) (4.5)

gdzie a ~ l i b > 1 są stałymi, a /(n) jest funkcją asymptotycznie dodatnią.


Metoda rekurencji uniwersalnej wymaga rozważenia trzech przypadków, ale
:zato rozwiązanie wielu równań rekurencyjnych może być wyznaczone całkiem
łatwo, czasami bez „papieru i ołówka".
Rekurencja (4.5) opisuje czas działania algorytmu, który dzieli problem
rozmiaru n na a podproblemów, każdy rozmiaru n/b, gdzie a i b są dodatnimi
stałymi. Każdy z a podproblemów jest rozwiązywany rekurencyjnie w czasie
T(n/b). Koszt dzielenia problemu oraz łąc.zenia rezultatów częściowych jest
opisany funkcją /(n). (Oznacza to, używając notacji z pod.rozdz. 1.3.2, że

86
4.3. METODA REKURENCJI UNIWERSALNEJ

/(n)= D(n) + C(n)). Na przykład rekurencja powstająca w procedurze


MERGE-SORTma a= 2, b = 2 if(n) = 0(n).
Technicznie rzecz biorąc, mamy tu nieścisłość polegającą na tym, że n/b nie
musi być liczbą całkowitą. Jednakże zastąpienie każdego z a składników
T(n/b) p=z T(ln/bj) lub T(1n/bl) nie wpływa istotnie na asymptotyczne za-
chowanie się rekurencji. (Udowodnimy to w następnym podrozdziale). PrzyjM
mujemy zatem jak.o coś normalnego nieuwzględnianie części całkowitych
(funkcji podłogi i sufitu) w rekurencjach tego typu.

Twierdzenie o rekurencji uniwersalnej


Metoda rekurencji uniwersalnej opiera się na następującym twierdzeniu.

TwIERDZENIE 4,1. (fwierdzenie o rekurencji uniwersalnej)


Niech a ;,i: I i b > 1 będą stałymi, niech/(n) będzie pewną funkcją i niech T(n)
będzie zdefiniowane dla nieujemnych liczb całkowitych przez rekurencję

T(n) = a'I\n/b) + f(n)


gdzie n/b oznacza Ln/bj lub In/bł, Wtedy funkcja T(n) może być ograniczona
asymptotycznie w następujący sposób.
I. Jeśli/(n) = O(n1o1,11-•) dla pewnej stałej Il> O, to T(n) = 0(n 101...).
2. Jeślif(n) = 0(n'"''), to T(n) = 0(n'""lgn).
3. Jeśli/(n) = O:(n1° 8"'+') dla pewnej stałej Il > O i jeśli af(n/b).:,.;;
cf(n) dla pewM
nej stałej c < 1 i wszystkich dostatecznie dużych n, to T(n) = 9(/(n)) .

Zanim zastosujemy twierdzenie o rekurencji uniwersalnej do konkretnych



przykładów, zastanówmy się przez chwilę, o co dokładnie w nim chodzi. W kaM
żdym z trzech przypadków porównujemy funkcję /(n) z funkcją n101,11. Intui·
cyjnie, rozwiązanie rekurencji zależy od większej z dwóch funkcji. Jeśli, tak
jak w przypadku 1, funkcja n10 '°" jest większa, to rozwiązaniem jest
T(n) = 0(n 1011"'). Jeśli, tak jak w przypadku 3, funkcja /(n) jest większa, to
rozwiązaniem jest T(n) = 9(/(n)). Jeśli, tak jak w przypadku 2, funkcje te są
tego samego rzędu, to prawą stronę mnożymy przez czynnik logarytmiczny,
a rozwiązaniem jest T(n) = 9(n 108"' lgn) = 0(/(n) lgn).
Oprócz tych intuicji trzeba jeszcze zrozumieć pewne aspekty techniczne.
W pierwszym przypadku funkcja /(n) nie tylko musi być mniejsza niż n1°"",ale
musi być wielomianowo mniejsza. Znaczy to, że /(n) musi być asymptotycznie
mniejsza niż n101,11 o czynnik n" dla pewnej stałej t > O. W trzecim przypadku
funkcja/(n) nie tylko musi być większa niż n1og"',ale musi być wielomianowa
większa oraz spełniać dodatkowo warunek „regularności", mówiący, 7.e

87
ROZDZIAŁ 4. REKURENCJE

af(n/b) ~ cf(n). Warunek ten jest spełniony przez większość wielomianowo


ograniczonych funkcji, z którymi się spotkamy.
Ważne jest uświadomienie sobie, że powyższe trzy przypadki nie wyczer-
pują możliwości na /(n). Jest pewna „luka" między przypadkami 1 i 2, gdy
funkcja/(n) jest mniejsza niż n-' 08 ..,, ale nie wielomianowo mniejsza. Podobnie,

jest pewna luka między przypadkami 2 i 3, gdy funkcja /(n) jest większa niż
n10H,II, ale nie wielomianowo większa. Jeśli funkcja/(n) ,,wpada" w jedną z tych
luk lub gdy warunek regularności w przypadku 3 nie zachodzi, to metoda
rekurencji uniwersalnej nie może być zastosowana do rozwiązania równania
rekurencyjnego.

Korzystanie z metody rekurencji uniwersalnej


Aby skorzystać z metody rekurencji uniwersalnej, po prostu stwierdzamy, któ-
ry Geśli jakikolwiek) przypadek z twierdzenia o rekurencji uniwersalnej można
zastosować i wypisujemy wtedy gotową odpowiedź.
Jako pierwszy przykład rozważmy

T(n) = 9T(n/3) +n

Dla tej rekurencji mamy a= 9, b = 3 i/(n) = n, a zatem n10L'I = n10&,9 = 0(n 2 ).


Ponieważ /(n)= O(n 108• 9 ----.), gdzie t = 1, możemy zastosować przypadek
1 z twierdzenia o rekurencji uniwersalnej i wywnioskować, że rozwiązaniem
jest T(n) = ®(n').
Rozważmy teraz

T(n) = T(2n/3) + I
gdzie a= l, b = 3/2,f(n) = l, a n1og,a = ,roa,,,1 =n°= 1. Stosujemy tutaj przy-
padek 2, gdyż /(n)= 0(n1°8 "') = 0(1), a zatem rozwiązaniem rekurencji jest
T(n) = ®Qgn).
Dla rekurencji

T(n) = 3T(n/4) + n lg n

mamy a= 3, b = 4, /(n)= nlgn oraz n1as.a = ft 01 • 3 = O(n°•793 ). Ponieważ


f(n) = .Q(n1oa.3 +•), gdzie e:::::0,2, więc stosuje się tutaj przypadek 3, jeśli może­
my pokazać, że dla/(n) zachodzi warunek regularności. Dla dostatecznie du-
żych n: af(n/b) = 3(n/4)lg(n/4) <, (3/4)nlgn = cf(n) dla c = 3/4. Korzystając
zatem z przypadku 3, możemy napisać, że rozwiązaniem rekurencji jest T(n) =
= ®(nlgn).
Metody rekurencji uniwersalnej nie można zastosować do rekurencji

88
* 4.4. DOWÓD TWIERDZENIA O REKURENCJI UNIWERSALNEJ

T(n) = 2T(n/2) + n lg n
chociaż ma ona poprawną formę: a= 2, b = 2,/(n) = nlgn i n101"'
=n.Wydaje
się, że powinien tu zachodzić przypadek 3, gdyż/(n) = n lg n jest asymptotycz-
nie większe niż n101"' = n, ale nie wielomianowo większe. Stosunek/(n)/n' 0 B"' =
= (nlg n)/n = lgn jest asymptotycznie mniejszy niż n• dla każ.dej dodatniej sta-
łej e. W konsekwencji rekurencja ta „ wpada" w lukę między przypadkiem
2 i przypadkiem 3. (Patrz zad. 4.4-2, gdzie znajdziesz jej rozwiązanie).
ZADANIA
4.3-1. Skorzystaj z metody rekurencji uniwersalnej i podaj dokładne asymp-
totyczne oszacowania dla następujących rekurencji:
(a) T(n) = 4T(n/2) + n
(b) T(n) = 4T(n/2) + n'
(c) T(n) = 4T(n/2) + n'
4.3-2. Czas działania algorytmu A jest opisany przez rekurencję T(n) =
= 1T(n/2) + n 2 • Algorytm konkurencyjny A' ma czas działania T'(n) =
= aT'(n/4) + n 2 • Jaka jest najwięksu liczba całkowita a, przy której A'
jest asymptotycznie szybszy niż A?
* 4.3-3. Skorzystaj z metody rekurencji uniwersalnej i pokaż, że rozwiązaniem
rekurencji T(n) = T(n/2) + 0(1) dla wyszukiwania binarnego (patrz zad.
1.3-5) jest T(n) = 0(Ign).
4.3-4. Rozważmy warunek regularności af(n/b) ~ cf(n) dla pewnej stałej
c < 1, który jest częścią przypadku 3 twierdzenia o rekurencji uniwersal-
nej. Podaj przykład prostej funkcji/(n), która spełnia wszystkie warunki
z przypadku 3 twierdzenia o rekurencji uniwersalnej z wyjątkiem warunku
regularności.

* 4.4. Dowód twierdzeniao rekurencjiuniwersalnej


Podrozdział ten zawiera dowód twierdzenia o rekurencji uniwersalnej (tw. 4.1)
- polecamy go uwadze czytelników bardziej zaawansowanych. Znajomość do-
wodu nie jest konieczna do stosowania twierdzenia.
Dowód jest dwuczęściowy. W pierwszej części analizuje się „uniwersalną"
rekurencję (4.5), przy upraszczającym założeniu, że T(n) jest zdefiniowane tyl-
ko dla dokładnych potęg b > l, tzn. dla liczb n= I, b, b2 , ••• Ta część zawiera
wyjaśnienie tego, co jest potrzebne do zrozumienia, dlaczego twierdzenie to jest
prawdziwe. W drugiej części rozszerza się analizę na wszystkie dodatnie liczby
całkowite n. Część ta jest dosyć techniczna i dotyczy operacji przeprowadza-
nych na częściach całkowitych (funkcjach podłogi i sufitu).

89
ROZDZIAŁ 4. REKURENCJE

W podrozdziale tym będziemy czasami używać notacji asymptotycznej


w sposób nie do końca formalny, rozważając zachowanie się się funkcji zdefi-
niowanych jedynie dla dokładnych potęg b. Przypominamy, że dokładne defi-
nicje notacji asymptotycznych wymagają, by oszacowania wykazać dla wszyst-
kich dostatecznie dużych liczb, nie zaś tylko tych, które są potęgami b. Ponie-
waż moglibyśmy wprowadzić zmodyfikowane notacje asymptotyczne objemu-
jące jedynie zbiór {b1: i = O, 1, ... }, nasza nieścisłość jest nieistotna.
Niemniej jednak używając notacji asymptotycznej w ograniczonym zbio-
rze argumentów, musimy być dość czujni, aby nie wyciągnąć żadnego fałszy­
wego wniosku. Dowodząc na przykład, że T(n) = O(n), gdy n jest dokładną
potęgą 2, nie gwarantuje się, że T(n) =
O(n). Funkcja T(n) może być zdefi-
niowana jako

n, jeśli n= 1, 2, 4, 8, ...
T(n) - { , • •
n , w przee1wnym razie

w którym to przypadku najlepszym górnym oszacowaniem, możliwym do


wykazania, jest T(n) =
O(n 2 ). Z tego typu powodów użycie asymptotycznej
notacji w ograniczonym zbiorze argumentów będzie zawsze jasno wynikać
z kontekstu.

4.4.1. Dowód dla dokładnych potęg

Pierwsza część dowodu twierdzenia o rekurencji uniwersalnej zawiera analizę


uniwersalnej rekurencji (4.5):

T(n) - aT(n/b) + f(n)


przy założeniu, że n jest dokładną potęgą b > l, gdzie b niekoniecznie jest
liczbą całkowitą. Analiza jest podzielona na trzy lematy. W pierwszym z nich
problem rozwiązywania uniwersalnej rekurencji jest redukowany do problemu
obliczania wyrażenia zawierającego sumy. W drugim są podane oszacowania
tych sum. W trzecim lemacie, wykorzystując dwa pierwsze lematy, dowodzimy
twierdzenie o rekwencji uniwersalnej dla dokładnych potęg b.

LEMAT 4.2.
Niech a~ 1 i b > 1 będą stałymi
oraz niech /(n) będzie nieujemną funkcją
zdefiniowaną dla dokładnych potęg b przez rekurencję

jeśli n=1
T(n) - {0(1),
aT (n/b) + f(n), jeśli n = bi

90
* 4.4. DOWÓD TWIERDZENIA O REKURENCJI UNIWERSALNEJ

gdzie i jest dodatnią liczbą całkowitą. Wtedy

loa.n-1
T(n) - 0(n 1''") + I alf(n/b') (4.6)
JoaO

DOWÓD
Iterując rekurencję, otrzymujemy

T(n) - f(n) + aT (n/b)


- f(n) + af(n/b) + a'T(n/b')
- f(n) + af(n/b) + a'f(n/b') + ...
+ a•or.n- 1f(n/bloa.n- 1) + al<>J,.11T(l)
Ponieważ a'° 1 -" = n101"', ostatnim składnikiem tego wyrażenia jest

ti"" T(ł) - 0(,r''')


co wynika z warunku brzegowego T(l) = 0(1 ). Pozostałą część można wyrazić
jako sumę
loa.,i- 1
IJ=O alf<nlb'J

zatem
Joa.n- 1
T(n) - 0(n 1"'") + L a1f(njb')
j"" o

co kończy dowód.

Drzewo rekursji
Spróbujmy najpierw dać pewną intuicję, używając drzewa rekursji. Na rysunku
4.3 widać drzewo odpowiadające iterowaniu rekurencji w lemacie 4.2. Korzeń
drzewa ma koszt/(n), a koszt każdego z jego a synów wynosif(n/b). (Wygod-
nie jest wyobrażać sobie, że a jest liczbą całkowitą, zwłaszcza gdy oglądamy
drzewo rekursji, ale takie założenie nie jest matematycznie niezbędne), Każdy
z synów korzenia ma a synów, przy czym koszt każdego z nich wynosi/(n/b 2);
mamy zatem a 2 węzłów, które są w odległości 2 od korzenia. Ogólnie, mamy a1
węzłów, które znajdują się w odległościj od korzenia, a każdy z nich ma koszt
f(n/bi). Koszt liścia wynosi T(l) = 8(1), a każdy liść znajduje się w odległości
log,,n od korzenia, gdyż n/b 101-" =I.Mamy a1°
1 >" = n 1oa.aliści w drzewie.

91
ROZDZIAŁ 4. REKURENCJE

/(n) -·-············································.............................
...........
;.,. /(n)

•••
f(n/b) f(n/b) f(n/b) "···iii• af(n/b)
..........................

' ' '


f(n b )f(n/b ) f(n/b ) ············iii•·

,, ..., ,, ..., ,, ...,


,,,,,,,,, ,, ....,, ..., ,, ....
,,,,,,,,.
·mm
,, ...,,,
,,,,,,,,. .... ,, ...,

••

••• '
' 8(1) 6(1) 8(1)
0(1) 0(1) 0(1) 6(1) 8(1) 8(1)
' ' '
8(1) 0(1) 0(1)----i..,.e n ( los•a)
log 1 a

' log•n-1
W sumie: e(nlog,
0
} + LJ
1~0
f(n!b 1)

Rys. 4.3. Drzewo rekursji generowane przez T(n) = aT(n/b) + f(n). Drzewo jest pełnym drzewem
rzędu a z n'°s.aliśćmi mającym wysokość logba. Koszt każdego poziomu jest pokazany po prawej
stronie rysunku, a ich suma jest dana w równaniu (4.6)

Możemy otrzymać równanie (4.6), sumując koszty poziomów drzewa, tak


jak to jest pokazane na rysunku. Koszt j-tego poziomu wynosi a'J(n/lY),a za-
tem całkowity koszt wynosi

loca,11-1
I <if(nli,;>
i"' o

W odpowiadającym rekurencji algorytmie typu „dziel i zwyciężaj" suma taka


reprezentuje koszty dzielenia problemów na podproblemy, a następnie ponow-
nego łączenia pod.problemów. Koszt wszystkich pod.problemów, będący ko-
sztem n10"" podproblemów rozmiaru 1 (liście w drzewie rekursji), wynosi
9(n'''').
Jeślirozpatrujemy drzewa rekursji, trzy przypadki twierdunia o rekurencji
uniwersalnej odpowiadają przypadkom, w których koszt drzewa jest: (1) zdo-
minowany przez koszty liści, (2) równomiernie rozłożony po poziomach drze-
wa, (3) 7.dominowany przez koszt korzenia.
Suma w równaniu (4.6) opisuje asymptotyczny koszt kroków dzielenia
i łączenia w odpowiadającym algorytmie typu „dziel i zwyciężaj". Następny
lemat podaje asymptotyczne oszacowania tej sumy.

92
* 4.4. DOWÓD TWIERDZENIA O REKURENCJI UNIWERSALNEJ

LEMAT4.3.
Niech a ~ 1 i b > 1 będą stałymi oraz niech /(n) będzie nieujemną funkcją
zdefiniowaną dla dokładnych potęg b. Funkcja g(n) zdefiniowana dla dokład­
nych potęg b przez

10, ... - 1
g(n) - L a;f(n/lJI) (4.7)
j=O

może być ograniczona asymptotycznie dla dokładnych potęg b w następujący


sposób.
1. Jeśli/(n) = O(lt 01 i.11-•)dla pewnej stałej c > O, to g(n) = O(n1011•a).
2. Jefili/(n) - E>(n'"''), to g(n) - E>(n'"''lgn).
3. Jeśli af(n/b) ::;;;cf(n) dla pewnej stałej c < l i wszystkich n ~ b, to
g(n) - 0(/(n)).

DOWÓD
Dla przypadku l mamy f(n) - O(n'0 ••-•), z czego wynika, ż, f(n/11)-
= O((n/b1)1°
8"'-"). Podstawiając to do równania (4.7), otrzymujemy

g(n) - 'a1(-"-)'""'-,)
o('"'f- j=O fy
(4.8)

Szacujemy sumę, używając notacji O i obliczając sumy odpowiednich szeregów


geometrycznych:

lo&.n-1. ( n )'osi.11-• log..,-1( ab' );


'°'
L,
a1 . . = nlogi.11-•
,,
'°' b"''
L,
i"'O er j=O

10, ... -1
- n' 0
••-· I
)"'O
(b'Y

-1)
-n'"·--·(b''""
b" - l

-n'"••-·(i
:)
Ponieważ O(n") =
b i 1, są stałymi, ostatnie wyrażenie redukuje się do n10,i.11-•
= O(lt 0
'"'). Podstawiając to wyrażenie do sumy w równaniu (4.8), otrzymujemy

g(n) - O(n'"'')
co kończy dowód dla przypadku 1.

93
ROZDZIAŁ 4. REKURENCJE

Przy założeniu, że /(n) = 0(n 1oa'") dla przypadku 2 mamy, że /(n/!Ji) =


= 0((n//})k>1olf).Podstawiając to do równania (4.7), mamy

g(n) =0 >o,a-•
( ,r, a' b' ·(")'""°) (4.9)

Szacujemy sumę, używając notacji 0, ale tym razem zamiast szeregów geomet-
rycznych, otrzymujemy ciąg takich samych wartości:

,....,-, (")'"''
'<C' a1 -.
L, <, = n'"'' >o,,-,(
'<C'
a
biot.a L,
)I
j=O U' j=O

lo1J1 -1
= n'o1.,, L 1
jaa O

Podstawiając to wyrażenie do sumy w równaniu (4.9), dostajemy

g(n) = 0(n' 0
'' log, n)

co kończy dowód dla przypadku 2.


Przypadek 3 można udowodnić w sposób podobny. Ponieważ/(n) pojawia
się w definicji (4.7) dotyczącej funkcji g(n), a wszystkie składnik.i w g(n) są
nieujemne, więc możemy wywnioskować, że g(_n)= D.(f(n)) dla dokładnych
potęg b. Przy założeniu, że af(n/b) :!(,,f(n) dla pewnej stałej c < 1 oraz wszyst-
kich n ~ b, mamy aif(n/bi) :!(,,df(n). Podstawiając to do równania (4. 7) i upra-
szczając, otrzymujemy szereg geometryczny, ale w przeciwieństwie do przypad-
ku 1 szereg ten ma malejące wyrazy:
logJI- 1
g(n) <; L a1f(njb')
J"" o
log.,.-1
,;; I: dJ<n>
j=O


,s;f(nl I: c1

94
* 4.4. DOWÓD TWIERDZENIA O REKURENCJI UNIWERSALNEJ

- O(f(n))
gdyż c jest stalą. Zatem g(n) - 0(f(n)) dla dokładnych potęg b. Przypadek
3 został przez nas w ten sposób uzasadniony; kończy to dowód całego lematu .

Możemy teraz udowodnić wersję twierdzenia o rekurencji uniwersalnej dla



przypadku, w którym n jest dokładną potęgą b.

LEMAT4.4.
Niech a ~ I i b > 1 będą stałymi oraz niech f(n) będzie nieujemną funkcją
zdefiniowaną dla dokładnych potęg b. Definiujemy T(n) dla dokładnych potęg
b za pomocą rekurencji

T(n) - {0(1), jeśli n=I


aT (n/b) + f(n), jeśli n = bi

gdzie i jest dodatnią liczbą całkowitą. Wtedy funkcja T(n) może być ograniczo-
na asymptotycznie dla dokładnych potęg b w następujący sposób.
1. Jeśli/(n) = O(n1"'"'-")dla
pewnej stałej e > O, to T(n) = 0(n 1011>").
2. Jeśli/(n) - 0(n'"'"), to T(n) - 0(n'"""lgn).
3. Jeśli f(n) = O(n 1og"'+")dla pewnej stałej e > O oraz jeśli af(n/b) ~ cf(n) dla
pewnej stałej c < 1 i wszystkich dostatecznie dużych n, to T(n) = 0(/(n)).

DOWÓD
Korzystamy z oszacowania w lemacie 4.3, aby obliczyć sumę (4.6) z lematu 4.2.
Dla przypadku 1 mamy

T(n) - 0(n'"'") + O(n'"'")

a dla przypadku 2

T(n) = 0(n 1011"') + 0(n 108""1gn)


- 0(n'"''lgn)

Dla przypadku 3 warunek af(n/b),:; cf(n) implikuje /(n) - Q(n'-••) (patrz


zad. 4.4-3). A zatem
T(n) - 0(n'"'') + 0(/(n))
- 0(f(n)) +

95
ROZDZIAŁ 4. REKURENCJE

4.4.2. Części całkowite liczb


Aby w pełni zakończyć
dowód twierdzenia o rekurencji uniwersalnej, musimy
rozszerzyć naszą analizę na sytuację, w której części całkowite (funkcje podłogi
i sufitu) pojawiają się w rekurencji uniwersalnej, a więc gdy rekurencja jest
zdefiniowana dla wszystkich liczb całkowitych, a nie tylko dla dokładnych
potęg b. Otrzymanie dolnego oszacowania dla

T(n) - aT(1 n/bł) + f(n) (4.10)

oraz górnego oszacowania dla

T(n) - aT(Ln/bJ) +f(n) (4.11)

jest trywialne, gdyż oszacowanie In/bł ~ n/b może być użyte w pierwszym
przypadku, aby otrzymać pożądany rezultat, a oszacowanie Ln/bj).:::;;
n/b mo-
że być użyte w drugim przypadku. Dolne oszacowanie rekurencji (4.11) wyma-
ga podobnej techniki co górne oszacowanie rekurencji (4.10), pokażemy więc
jedynie ostatnie z nich.
Chcemy iterować rekurencję (4.10), tak jak w lemacie 4.2. W czasie ite-
rowania rekurencji otrzymujemy sekwencję rekurencyjnych wywołań dla ar-
gumentów

n
1n/bł
11n/bł/bł
111n/bł /bł /bł

Oznaczmy i-ty element w tej sekwencji przez n;, gdzie

jeśli i= O
(4.12)
jeśli i> O

Naszym pierwszym celem jest wyznaczenie liczby iteracji k, dla której nk jest
x + 1, otrzymujemy
stałą. Korzystając z nierówności fxl .:::;;

96
* 4.4. DOWÓD TWIERDZENIA O REKURENCJI UNIWERSALNEJ

n I
ni"""'-+··
bi b..·+1

n I 1
bib+ · ·
"' - + ----
n3"""63 +1


Ogólnie

n i-1 1
n,~ b; + LI L
J=OV'

a zatem, gdy i= Liog,nJ, otrzymujemy n 1 ,;; b + b/(b - !) = 0(1).


Możemy teraz iterować rekurencję (4.10), otrzymując zależność

T(n) =f(n 0) + aT(n 1)

= f(n 0) + af(n,) + a2 T(n 2)


<;f(n 0) + af(n 1) + a'f(n 2) + ...

Llog..,J
-1
= El(n'"") + L a1f(n;) (4.13)
J=O

która jest podobna do równania (4.6) z tą różnicą, że n jest tu dowolną liczbą


całkowitą (a nie dokładną potęgą b).
Możemy teraz obliczyć sumę

Li"L"J- t
g(n) = L a1f(n;) (4.14)
J=O

z (4.13) w sposób analogiczny do dowodu lematu 4.3. Rozpoczynając od przy-


padku 3,jeśli af(fn/bl),;; cf(n) dla n> b + b/(b- !), gdzie c < I jest stalą, to
alf(n 1) ~ dj(n). Zatem suma w równaniu (4.14) może być obliczona tak jak
w lemacie 4.3. Dla przypadku 2 mamy /(n) = E>(n1° 11'1).Jeśli możemy pokazać,

że /(n 1) = O(n 10Bl'l/a1) = O((n/bi) 1011'1) to możemy przyjąć, że udowod-


niliśmy lemat 4.3 dla przypadku 2. Zauważmy, że j ~ Llo&nJ implikuje

97
ROZDZIAŁ 4. REKURENCJE

b1/n ,:::;;
1. Oszacowanie f (n) = O(n1"1>"}implikuje, że istnieje stała c > O taka,
że dla dostatecznie dużych ni

n b )1,...,
f(n;) ~ C ( i,;+ b _ )

-,(j;)(1+(~b~1))1,,,
~,(";Xi+ 1)1,..., bb

gdyż c(l + b/(b - 1))1oa.ajest stałą. Przypadek 2 został zatem udowodniony.


Dowód przypadku 1 jest prawie identyczny, Zasadniczy punkt, to wykazanie
oszacowania/(ni) = O(n 11>11.a~•),które jest podobne do odpowiadającego dowo-
du dla przypadku 2, chociaż aparat algebraiczny jest bardziej skomplikowany.
Udowodniliśmy zatem prawdziwość górnego oszacowania w twierdzeniu
o rekurencji uniwersalnej dla wszystkich liczb całkowitych n. Dowód dolnego
oszacowania jest podobny

ZADANIA
* 4.4-1. Podaj proste, ale dokładne wyrażenie dla n1 w równaniu (4.12) dla przy-
padku, w którym b jest dodatnią liczbą całkowitą, a nie dowolną liczbą
rzeczywistą.
* 4.4-2. Pokaż, że jeślif(n) = E>(n108"'Ig1 n), gdzie k ~ D,to rekurencja uniwersal-
na ma rozwiązanie T(n) = 8(n 1°"""lf+ 1 n). Dla uproszczenia ogranicz
swoją analizę do dokładnych potęg b.
* 4.4-3. Pokaż, że przypadek 3 w twierdzeniu o rekurencji uniwersalnej jest
„przesadzony", w tym sensie, że warunek regularności af(n/b),:::;;cf(n) dla
pewnej stałej c < 1 implikuje, że istnieje stała e > O taka, że
f(n) - !l(n1,..,+•).

Problemy
4.1. Przykłady rekurencji
Podaj asymptotyczne górne oraz dolne oszacowanie dla T(n) w każdej z da-
nych poniżej rekurencji. Załóż, że T(n) jest stałą dla n,:::;;2. Twoje oszacowania
powinny być tak dokładne, jak to możliwe. Odpowiedzi uzasadnij.

98
PROBLEMY

(a) T(n) = 2T(n/2) + n'


(b) T(n) = T(9n/10) + n
(c) T(n) = l6T(n/4) + n'
(d) T(n) = 7T(n/3) + n'
(e) T(n) = 7T(n/2) + n'
(f) T(n) = 2T(n/4) + ,/~
(g) T(n) = T(n - I)+ n
(b) T(n) = T(,/;) + I

4.2. Szukanie brakującej liczby całkowitej


Tablica A[l .. n] zawiera wszystkie liczby całkowite z przedziału O.. n oprócz
jednej. Można łatwo wyznaczyć brakującą liczbę całkowitą w czasie O(n), uży­
wając pomocniczej tablicy B[O .. n] w celu zapamiętania liczb występujących
w A. Jednakże w problemie tym nie mamy dostępu do całych liczb całkowitych
w A w stałym czasie. Elementy tablicy A są reprezentowane binarnie i moż.emy
jedynie korzystać z operacji typu „pobierzj-ty bit A[i]", która jest wykonywa-
na w stałym czasie.
Pokaż, że jeśli używamy jedynie tego typu operacji dostępu do danych, to
możemy jednak wyznaczyć brakującą liczbę w czasie O(n).

4.3. Koszty przekazywania parametrów


2.asadniczo w całej książre przyjmujemy, że przekazanie parametru w wywoła­
niu rekurencyjnym zajmuje stały czas, nawet jeśli przekazujemy N-elementową
tablicę. Założenie takie jest słuszne w większości systemów, ponieważ przeka-
zywany jest wskaźnik, a nie cała tablica. W tym problemie rozważamy konsek-
wencje trzech strategii przekazywania parametrów:
1. Tablica jest przekazywana przez wskaźnik. Czas= 0(1).
2. Tablica jest przekazywana przez kopiowanie. Czas = E>(N), gdzie N jest
rozmiarem tablicy.
3. Tablica jest przekazywana przez kopiowanie części tablicy potrzebnej w da-
nym wywołaniu. Czas = @(p - q + l ), jeśli jest przekazywana pod tablica
A[p .. q].
(a) Rozważmy rekurencyjny algorytm wyszukiwania binarnego zadanej liczby
w posortowanej tablicy (patrz zad. 1.3-5). Podaj rekurencję dla _pesymis-
tycznego czasu działania wyszukiwania binarnego, gdy tablice są przekazy-
wane przy użyciu każdej z trzech wymienionych powyżej strategii, oraz
podaj górne oszacowania na rozwiązanie rekurencji. Niech N będzie roz-
miarem oryginalnego problemu, a n - rozmiarem podproblemu.
(b) Wykonaj jeszcze raz to co w części (a) dla algorytmu MERGE-SORTz pod-
rozdz. 1.3.1.

99
ROZDZIAŁ 4. REKURENCJE

4.4. Więcej przykładów rekurencji


Podaj asymptotyczne górne oraz dolne oszacowanie dla T(n) w każdej z da-
nych poniżej rekurencji. Załóż, że T(n) jest stałą dla n:;;.;;2. Twoje oszacowania
powinny być tak dokładne, jak to możliwe. Odpowiedzi uzasadnij.

(a) T(n) = 3T(n/2) + nlgn


(b) T(n) = 3T(n/3 + 5) + n/2
(c) T(n) = 2T(n/2) + n/lgn
(d) T(n) = T(n - 1) + 1/n
(e) T(n) = T(n - 1) + lgn
(f) T(n) = ..jnT(..jn) + n

4.5. Warunki rozszenania


Często jesteśmy w stanie podać
oszacowanie rekurencji T(n) dla dokładnych
potęg stałej całkowitej b. W tym problemie podamy pewne dostateczne wa-
runki rozszerzenia oszacowania na wszystkie liczby rzeczywiste n> O.

(a) Niech T(n) i h(n) będą monotonicznie rosnącymi funkcjami i załóżmy, że


T(n) <; h(n), gdy n jest dokładną potęga stałej b > 1. Załóżmy ponadto, że
h(n) jest „wolno rosnąca" w tym sensie, że h(n) = O(h(n/b)). Wykaż, że
T(n) = O(h(n)).
(b) Załóżmy, że mamy rekurencję T(n) = aT(n/b) + f(n), gdzie a ?o 1, b > 1,
a f(n) jest monotonicznie rosnąca. Załóżmy jeszcze, że warunki brzegowe
rekurencji są dane przez T(n) = g(n) dla n :;;.;; n 0 , gdzie g(n) jest monoto-
nicznie rosnąca oraz g(n 0 ):;;.;; aT(n 0 /b) + f(n 0 ). Wykaż, że T(n) jest mono-
tonicznie rosnąca.
(c) Uprość dowód twierdzenia o rekurencji uniwersalnej dla przypadku,
w którym f(n) jest monotonicznie rosnąca i wolno rosnąca. Skorzystaj
z lematu 4.4.

4-6. Liczby Fibonacciego


W problemie tym badamy własności liczb Fibonacciego, które są 7.definiowne
rekurencją (2.13). W celu rozwiązania rekurencji dla liczb Fibonacciego sko-
rzystamy z metody funkcji tworzących. Definiujemy funkcję tworzącą (lub for-
malny szereg potęgowy) F jako


9'(z) = I F,z'
J=O

8
= O +z+ z2 + 2z3 + 3z4 + 5z 5 + 8z6 + 13z7 +21z + ...

(a) Pokaż, że 9'(z) =z+ z9'(z) + z 29'(z).

100
PROBLEMY

(b) Pokaż, że

z
91-(z)= 1-z-z 2

z
(1 - ,f,z)(l - ,/,z)

l ( l l )
- ,Is I:_-,t,z- l - ,t,z

gdzie

l +.js
,t, - .... - 1,61803 ...
2

oraz

-,t, - 1-../5- -0,61803 ...


2

(c) Pokaż, że


I
$F(z)- L ,,(,t, 1 - ,f,~z'
1=ov5

(d) Udowodnij, że F1 = qiJ,Y.5 dla i> O, zaokrąglone do najbliższej liczby cał~


kowitej. (Wskazówka: l</>I< I).
(e) Udowodnij, że F 1+ 2 ~ q,;dla i~ O.

4-7. Testowanie układów VLSI


Profesor Diogenes ma n przypuszczalnie identycznych układów VLSI 1>,które
w założeniu są zdolne testować się nawzajem. Urządzenie, którym dysponuje
profesor, może sprawdzić jednocześnie dwa układy: każdy z nich sprawdza,
czy drugi jest dobry. Dobry układ zawsze stwierdza poprawnie, czy drugi jest
dobry, natomiast zły układ może dać dowolną (być może niepoprawną) od~
powiedź. Są możliwe zatem cztery następujące wyniki testu:

Skrót VLSI pochodzi od pierwszych liter nazwy angielskiej „very-large.sca.le integration",


tJ
związanej z technologią nowoczesnych mikroprocesorów.

101
ROZDZIAŁ 4. REKURENCJE

Układ A stwierdza Układ B stwierdza Konkluzja


B jest dobry A jest dobry Oba są dobre lub oba są złe
B jest dobry A jest zły Co najmniej jeden jest zły
B jest zły A jest dobry Co najmniej jeden jest zły
B jest zły A jest zły Co najmniej jeden jest zły

(a) Wykaż, że jeśli mamy więcej niż n/2 układów złych, to profesor nie zawsze
może stwierdzić, które układy są dobre, opierając się na testach powyż­
szego typu. Załóżmy, że złe układy mogą w pewnym sensie współdziałać,
żeby nie można było wykryć, które z nich są dobre.
(b) Rozważmy problem znajdowania jakiegokolwiek dobrego układu spośród
n układów zakładając, że dobrych układów jest więcej niż n/2. Wykaż, że
Ln/2Jtestów wystarczy do zredukowania problemu do analogicznego prob-
lemu, którego rozmiar będzie mniej więcej połową rozmiaru wejściowego.
(c) Pokaż, że dobre układy mogą zostać zidentyfikowane przy użyciu E>(n)
testów zakładając, że mamy więcej niż n/2 dobrych układów. Sformułuj
i rozwiąż rekurencję, która opisuje liczbę testów.

Uwagido rozdziału
Rekurencje były badane już w 1202 r. pr:rez L. Fibonacciego, od którego na-
zwiska bierze się nazwa liczb Fibonacciego. A. De Moivre wprowadził metodę
funkcji tworzących (patrz problem 4-6) do rozwiązywania rekurencji. Metoda
rekurencji uniwersalnej jest wzięta (w zmodyfikowanej formie) od Bentleya,
Hakena oraz Saxe'a [26], którzy podają rozszerzoną metodę opisaną w zad.
4.4-2. K.nuth (121] oraz Liu [140] pokazują. jak rozwiązywać liniowe rekuren-
cje, korzystając z funkcji tworzących. Praca Purdoma i Browna [164] zawiera
rozszerzoną dyskusję na temat rozwiązywania rekurencji.
Rozdział 5

Zbiory i nie tylko

W poprzednich rozdziałach zetknęliśmy się już z elementami matematyki dys-


kretnej. W tym rozdziale dokładniej zajmiemy się elementarnymi własnościami
zbiorów, relacji, funkcji, grafów i drzew. Czytelnicy dobrze zaznajomieni z tym
materiałem mogą ten rozdział tylko przejrzeć.

5.1. Zbiory
Zbiór jest kolekcją oddzielnych obiektów, zwanych elementami zbioru. Jeżeli
obiekt x jest elementem zbioru S, to piszemy xeS (czytaj: ,,x jest elementem
zbioru S'' lub krócej ,.X należy do S"). Jeśli x nie jest elementem S, to piszemy
x,j; S. Możemy zdefiniować zbiór przez wypisanie jego elementów w nawia-
sach. Możemy na przykład zapisać zbiór S zawierający elementy 1, 2 i 3 w po-
staci S = {1, 2, 3}. Ponieważ 2 jest elementem zbioru S, a 4 nie jest, możemy
zapisać 2 e S i 4 ffS. Elementy zbioru nie są numerowane i zbiór nie może
zawierać dwóch takich samych elementów. Zbiory A i B są równe, co zapisuje~
my A = B, jeżeli zawierają te same elementy. Na przykład {1, 2, 3, I} = { 1, 2,
3) - {3, 2, l}.
Dla często spotykanych zbiorów używamy szczególnych oznaczeń.

• 0 oznacza zbiór pusty, tzn. zbiór nie zawierający żadnego elementu.


• Z oznacza zbiór liczb całkowitych, tzn. zbiór {... , - 2, -1, O, I, 2, ... }.
• R oznacza zbiór liczb rzeczywistych.
• N oznacza zbiór liczb naturalnych, tzn. zbiór {O, 1, 2, ... }o.

t) Niektórzy autorzy podają, że liczby naturalne mczynają się od I. Jednak obecnie przyjęło
się, że Ojest również liczbą naturalną.

103
ROZDZIAŁ 5. ZBIORYI NIE TYLKO

Jeśli wszystkie elementy zbioru A zawierają się w zbiorze B, tzn, jeżeli x e A


implikuje xeB, to piszemy As;. Bi mówimy, że A jest podzbiorem zbioru B.
Zbiór A jest podzbiorem właściwym zbioru B, co zapisujemy A c B, gdy A c B,
ale A #c B. (Niektórzy autorzy używają symbolu „ c " do oznaczenia zwyk-
łego zawierania zamiast zawierania właściwego). Dla każdego A zachodzi
A c A. Dla zbiorów A i B zachodzi A = B wtedy i tylko wtedy, gdy A c B
i B c A. Dla dowolnych zbiorów A, Bi C: jeżeli A s; Bi B c C, to A s; C. Dla
dowolnego zbioru A zachodzi 0 c A.
Często definiuje się zbiory, bazując na innych znanych już zbiorach.
Mając dany zbiór A, możemy zdefmiować zbiór B s; A przez podanie włas­
ności wyróźniającej elementy B z A. Możemy na przykład określić zbiór
liczb parzystych jako {x: x e Z i x/2 jest liczbą całkowitą}. Dwukropek w tym
zapisie oznacza „takie, że". (Niektórzy autorzy zamiast dwukropka używają
pionowej kreski).
Mając dane dwa zbiory A i B, możemy je również definiować, używając
operacji na zbiorach.
• Przecięciem zbiorów A i B nazywamy zbiór

AnB={x:xeAixeB}

• Sumą zbiorów A i B nazywamy zbiór

AuB={x:xeAłubxeB}

• Różnicą zbiorów A i B nazywamy zbiór

A- B= {x:xeA i x,tB}

Operacje na zbiorach podlegają podanym poniżej prawom.

Prawa zbiorów pustych:


An0=0
Au0=A

Prawa idempotentności:

AnA=A
AuA=A

Prawa przemienności:

AnB=BnA
AuB=BuA

104
5.1. ZBIORY

Prawa łączności:

A n(Br,C) = (AnB)r, C
A u(BuC) = (A uB)u C

Prawa rozdzielności:

Ar,(Bu C) = (AnB)u(Ar, C)
Au(Br,C) = (AuB)n(A u C) (5.1)

Prawa pochłaniania:
An(AuB)=A
Au(Ar,B)=A

Prawa De Morgana:

A-(Br,C) = (A-B)u(A- C)
A- (BuC) =(A -B)n(A - C) (5.2)

Pierwsze z praw De Morgana jest zilustrowane na rys. 5.1 przy użyciu diagra-
mu Venna, gdzie zbiory są przedstawione w postaci obszarów na płaszczyźnie.

• , . '
B .A B
. u
'
C C .
' C
A (B ri C) = A-(BriC) "' (A-8) u (A-C)
Rys. 5.1. Diagram Venna ilustrujący pierwsze prawo De Morgana (5.2). Każdy ze zbiorów A,
B i C jest reprezentowany prz.ez koło na płaszczyźnie

Często wszystkie z rozważanych zbiorów są podzbiorami jakiegoś więk­


szego zbioru U, zwanego uniwersum.Gdy rozważamy na przykład różne zbiory
składające się z liczb całkowitych, wtedy zbiór liczb całkowitych Z stanowi
uniwersum. Mając dane uniwersum U, defmiujemy dopełnienie zbioru A jako
A. = U - A. Dla dowolnego zbioru A c U, zachodzą następujące prawa:
A =A
Ar.A =0
Au A= U

105
ROZDZIAŁ 5. ZBIORY I NIE TYLKO

Prawa De Morgana (5.2) mogą zostać sformułowane przy użyciu dopeł-


nień zbiorów. Dla każdych dwóch zbiorów A, B c U zachodzi

Anll - A u o·
AuB=AnB
Zbiory A i B są rozłączne, jeżeli nie mają wspólnych elementów, tzn. jeżeli
A n B = 0. Zbiór fi' = {S;} niepustych zbiorów tworzy podział zbioru S, jeżeli

• zbiory w fi' są parami rozłączne, co znaczy, że jeśli S1, Si Ef/ i i =ftj, to


S 1 nS; = 0 oraz
• ich sumą jest S

s- us,
s,eY

Innymi słowy,[/ tworzy podział S, jeżeli każdy element S występuje w do-


kładnie jednym zbiorze S;Ef/.
Liczba elementów w zbiorze S oznaczana jako ]S]jest nazywana mocą (lub
rozmiarem) zbioru. Dwa zbiory mają tę samą moc, jeśli istnieje między nimi
odwzorowanie wzajemnie jednoznaczne. Moc zbioru pustego wynosi 101= O.
Jeśli moc zbioru jest liczbą naturalną, to mówimy, że zbiór jest skończony;
w przeciwnym wypadku - jest nieskończony. Zbiór nieskończony, który może
zostać odwzorowany wzajemnie jednoznacznie w zbiór liczb naturalnych N,
jest przeliczalny; w przeciwnym razie zbiór jest nieprzeliczalny. Zbiór liczb cał­
kowitych Z jest przeliczalny, ale zbiór liczb rzeczywistych R nie jest przelicz.al-
ny. Dla dwóch skończonych zbiorów A i B zachodzi

IAuBI - IAI+ IBI- IAnBI (5,3)

z czego wynika, że

IAu BI,; IAI+ IBI


Jeśli A i B są rozłączne, to IAn BI = Ooraz IAu BI = IAl+ IBI-Jeżeli A c B,
to IAI,; IBI,
Skończony zbiór o n elementach nazywa się czasami n-zbiorem; !-zbiór jest
nazywany singletonem. Podzbiór k-elementowy nazywamy k-podzbiore..n.
Zbiór wszystkich podzbiorów zbioru S, łącznie ze zbiorem pustym i zbio-
rem S, oznacza się przez 25 i nazywa zbiorem potęgowym S. Na przykład
2<•,•l - {0, {a}, {b}, {a, b}}. Zbiór potęgowy skończonego zbioru S ma
moc 21Si.

106
5.1. ZBIORY

Czasami zajmujemy się podobnymi do zbiorów strukturami, w których


elementy są ponumerowane. Parę uporządkowaną dwóch elementów
a i b oznacza się przez (a, b) i definiuje jak.o zbiór (a, b) = {a, {a, b}}. Para
uporządkowana (a, b) nie jest tą samą parą co para (b, a).
Iloczyn (produkt) kartezjański dwóch zbiorów A i B, oznaczany A x B, jest
zbiorem wszystkich tak.ich par uporządkowanych, że pierwszy element pary
jest elementem zbioru A, a drugi elementem zbioru B. Bardziej formalnie

A x B= {(a, b):aeA i beB}

Na przykład {a, b} x {a, b, c} = {(a, a), (a, b), (a, c), (b, a), (b, b), (b, c)}.Jeśli
A i B są zbiorami skończonymi, to moc ich iloczynu kartezjańskiego wynosi

IA x BI= IAl·IBI (5.4)

Iloczyn kartezjański n zbiorów A 1, A 2 , ... , A„ jest zbiorem n-tek

i jeżeli wszystkie zbiory są skończone, to moc iloczynu kartezjańskiego wynosi

Iloczyn kartezjański pojedynczego zbioru A złożonego ze sobą n razy ozna-


czamy przez
A"=AxAx ... xA
i jeśli A jest skończony, to moc iloczynu kartezjańskiego wynosi IA"I= !AJ".
Złożenie n-krotne może być również rozważane jak.o skończony ciąg długości
n (patrz str. 111).
ZADANlA

5.1-1. Narysuj diagramy Venna ilustrujące pierwsze prawo rozdzielności (5.1).


5.1-2. Udowodnij, że prawa De Morgana można zastosować do każdej skoń-
czonej rodziny zbiorów:

* 5.1-3. Udowodnij tak zwaną zasadę włączania i wyłączania, która jest uogól-
nieniem równości (5.3):

107
ROZDZIAŁ 5. ZBIORY I NIE TYLKO

IA1UA2U ... UA11l=


IA,I+ IA,I+ ...+ IA,I
-IA,,-,A,1- IA,r,A,1- ... (wszystkie pary)
+ !A1 nA 2 nA 31 + ...

(wszystkie trójki)

+<-1r- 1A,,-,A,,.,... ,-,A,I



1

S.1-4. Pokaź, że zbiór liczb nieparzystych jest przeliczalny.


S.1-S. Pokaź, że dla dowolnego skończonego zbioru S zbiór potęgowy 25 ma
21S1elementów (to znaczy istnieje 2151różnych podzbiorów S).
S.1-6. Podaj indukcyjną definicję n-krotnego iloczynu kartezjańskiego; skorzy-
staj z definicji pary uporządkowanej.

5.2. Relacje
Relacja binarna (dwuargumentowa) R dwóch zbiorów A i B jest podzbiorem
iloczynu kartezjańskiego A x B. Jeżeli (a, b)eR, to czasami piszemy: a Rb.
Kiedy mówimy, że R jest relacją binarną w zbiorze A, oznacza to, że R jest
podzbiorem A x A. Na przykład relacją „mniejsze niż" w zbiorze liczb natu-
ralnych jest zbiór {(a, b): a, be N i a< b}. Relacja n-arna (n-argumentowa)
w zbiorach A 1 , A 2 , •••, A11jest podzbiorem A 1 x A 2 x ... x A 11•
Relacja binarna R c A x A jest zwrotna, jeśli
aRa
dla każdego aeA. Na przykład.,=" i .. ~" są relacjami zwrotnymi w zbiorze
N, podczas gdy ,, <" nie jest. Relacja R jest symetryczna, jeżeli

a R b implikuje b R a
dla dowolnych a, b EA. Na przykład relacja ,, =" jest symetryczna, lecz ,, < "
i ,, ~ " już nie są. Relacja R jest pn:ecboclnia, jeżeli
aRb i bRc implikuje aRc

dla dowolnych a, b, c EA. Na przykład relacje ,. < ", ,, ~" i ,, =" są przechod-
nie, ale relacja R={(a, b):a, beN i a=b-1} nie jest, ponieważ
z 3 R 4 i 4 R 5 nie wynika, że 3 R 5.
Relacja, która jest zwrotna, symetryczna i przechodnia, nazywa się relacją
równoważności. Na przykład ,, =" jest relacją równoważności w zbiorze liczb
naturalnych, ale ,, <" nią nie jest. Jeśli R jest relacją równoważności w zbiorze
A, to dla dowolnego a e A klasa abstrakcji a jest zbiorem [a] = {b EA: a R b}
wszystkich elementów równoważnych a. Jeśli na przykład zdefiniujemy

108
5.2. RELACJE

R = {(a, b): a, b EN i a + b jest liczbą parzystą}, to R jest relacją równoważno­


ści, ponieważ a + a jest parzyste (zwrotność), a + b jest parzyste, z czego wy-
nika, że b + a jest parzyste (symetryczność), oraz a+ b i b + c są parzyste,
z czego wnioskujemy, że a+ c jest parzyste (przechodniość). Klasą abstrakcji
4 jest [4] - {O,2, 4, 6, ... }, a klasą abstrakcji 3 jest [3] - {I, 3, 5, 7, ... }.

TWIERDZENIE S.1. (Relacja równoważności jest podziałem)


Klasa abstrakcji relacji równoważności R w zbiorze A wyznacza podział A,
a każdy podział A wyznacza relację równoważności w A, dla której zbiory
podziału są klasami abstrakcji.

DOWÓD
W pierwszej części dowodu musimy pokazać, że klasy równoważności R są
niepustymi, parami rozłącznymi zbiorami, których suma wynosi A. Ponieważ
R jest zwrotna, aE [a], więc klasy równowa:7ności są niepuste; co więcej, ponie-
waż każdy element aEA należy do klasy abstrakcji [a], suma klas równoważ­
ności wynosi A. Pozostaje wykazać, że klasy abstrakcji są parami rozłączne,
tzn. jeśli dwie klasy abstrakcji [a] i [b] mają ten sam element c, to są tym samym
zbiorem. Tak więc jeśli a R c i b R c, to przez symetrię i przechodniość za-
chodzi a R b. Dla dowolnego elementu xE [a]:x R a, a więc x R b, z czego
wynika, że [a] c [b]. Podobnie, [b] c [a], a więc [a] - [b].
Co do drugiej części dowodu, niech d = {A1} będzie podziałem A, i zdefi-
niujmy R = {(a, b): istnieje i takie, że aEA 1 i beA 1}. Pokażemy, że R jest
relacją równoważ.ności w A. Zwrotność zachodzi, ponieważ aeA 1, z czego
wynika, że a Ra. Symetria zachodzi, ponieważ jeśli a Rb, to a i b znajdują się
w tym samym zbiorze A;, więc b R a. Jeżeli a R b i b R c, to wszystkie trzy
elementy należą do tego samego zbioru, więc zachodzi a R c, z czego wynika,
że zachodzi przechodniość. Widać, że zbiory podziału są klasami równoważno­
ści R, ponieważ aEA 1, skąd xE[a], z czego wynika, że XEA 1, oraz z xEA;
wynika, że xe[a]. +
Relacja binarna R w zbiorze A jest antysymetryczna, jeżeli

aRb i bRaimplikujea=b

Na przykład relacja ,, ~" w zbiorze liczb naturalnych jest antysymetrycz-


na, bo jeśli a ~ b i b ~ a, to a = b. Relacja, która jest zwrotna, antysymetrycz-
na i przechodnia, jest nazywana relacją częściowego porządku (częściowym po-
rządkiem), a zbiór, na którym jest ona zdefiniowana, nazywamy zbiorem częś­
ciowo uporządkowanym. Na przykład relacja ,jest potomkiem" jest relacją czę­
ściowego porządku w zbiorze wszystkich ludzi Geśli traktujemy każdego jako
własnego potomka).

109
ROZDZIAŁ 5. ZBIORY I NIE TYLKO

W częściowo uporządkowanym zbiorze A może nie być pojedynczego
„maksymalnego" elementu x takiego, że y R x dla wszystkich yeA. Zamiast
tego może istnieć wiele elementów maksymalnych, które nie są ze sobą w relacji
R. Na przykład wśród pewnej liczby pudelek różnych rozmiarów może być
kilka „największych" pudełek, których nie da się umieścić w żadnym innym
pudełku, lecz nie istnieje jedno pudełko „największe", do którego można 1lllie-
ścić każde inne pudełko. Częściowy porządek R w zbiorze A jest pełny lub
liniowy, jeśli dla dowolnych a, be A zachodzi a Rb lub b Ra. Na przykład
relacja ,, ~ " jest pełnym porządkiem liczb naturalnych, ale relacja ,jest po-
tomkiem" nie jest pełnym porządkiem zbioru wszystkich ludzi, ponieważ są
jednostki, które nie są ze sobą w ogóle spokrewnione.

ZADANIA
5.1-1. Udowodnij, że relacja bycia podzbiorem „c" określona we wszystkich
podzbiorach Z jest porządkiem częściowym, ale nie pełnym.
5.2-2. Wykaż, że dla dowolnej dodatniej liczby całkowitej n relacja „rów-
noważny modulo n" jest relacją równoważności w zbiorze liczb całko­
witych. (Mówimy, że a: b (mod n), jeśli istnieje liczba całkowita q taka,
że a - b = qn). Na jakie klasy abstrakcji ta relacja dzieli zbiór liczb cał­
kowitych?
5.2-3. Podaj przykłady relacji, które są
(a) zwrotne i symetryczne, ale nie przechodnie;
(b) zwrotne i przechodnie, ale nie symetryczne;
(c) symetryczne i przechodnie, ale nie zwrotne.
5.2-4. Niech S będzie skończonym zbiorem, a R relacją równoważności
w S x S. Pokaż, że jeśli dodatkowo R jest antysymetryczna, to klasy abs-
trakcji S relacji R są singletonami.
5.2-5. Profesor Narcissus twierdzi, że jeżeli relacja R jest symetryczna i prze-
chodnia, to jest również zwrotna. Podaje następujący dowód. Z symetrii
wynika: jeśli a Rb, to b Ra. Przechodniość implikuje a Ra. Czy profesor
ma rację?

5.3. Funkcje
Mając dane dwa zbiory A i B, funkcją / nazywamy relację binarną w A x B
taką, że dla każdego aeA istnieje dokładnie jedno beB takie, że (a, b)ef
.Zbiór A nazywa się dzieclriną funkcji f, a zbiór B - przeciwdziedziną funkcji f
Czasami zapisujemy/: A - B; jeśli (a, b) ef. to b = f(a), ponieważ b jest jedno-
znacznie określone przez wybór a.

110
5.3. FUNKCJE

Intuicyjnie, funkcja/ przyporządkowuje element z B każdemu elementowi


z A. żaden z elementów ze zbioru A nie może mieć przypisanych dwóch róż­
nych elementów z B, ale elementowi z B mogą być przypisane dwa różne
elementy zbioru A. Na przykład relacja binarna

f= {(a, b):aeN i b = a mod 2}


jest funkcją/: N-> {O, 1}, ponieważ każdej liczbie naturalnej a jest przypisana
dokładnie jedna wartość b z {O, 1} tak.a, że b = a mod 2. Na przykład O= /(O),
1 = /(1), O= /(2) itd. Natomiast relacja binarna

g= {(a, b):aeN i a+ bjest parzyste}

nie jest funkcją, ponieważ (1, 3) i (1, 5) spebtiają g, więc jeśli wybierzemy a = 1,
to nie ma dokładnie jednego b takiego, że (a, b)eg.
Mając daną funkcję/: A -i-B,jeśli b = /(a), to mówimy, że a jest argwnen-
tem f, a b jest wartością / w a. Możemy określić funkcję przez podanie jej
wartości dla każdego elementu z jej dziedziny. Na przykład/(n) = 2n dla neN,
co oznacza/= {(n, 2n): neN}. Dwie funkcje fig są sobie równe, jeśli mają tę
samą dziedzinę i przeciwdziedzinę i jeśli dla każdego a z dziedziny /(a) = g(a).
Oąg skończony o długości n jest funkcją f, której dziedzina jest zbiorem
{O, 1, ... , n - l}. Często określamy tak.i ciąg przez wypisanie jego wartości:
(f(O),f(l), ... ,f(n -1)).
Oąg nieskończony jest funkcją, której dziedziną jest zbiór liczb natural-
nych N. Na przykład ciąg Fibonacciego, zdefiniowany wzorem (2.13),jest cią­
giem nieskończonym (O, I, 1, 2, 3, 5, 8, 13, 21, .... ).
Kiedy dziedziną funkcji/ jest iloczyn kartezjański, często pomija się dodat-
kowe nawiasy otaczające argument funkcji f Jeżeli na przykład
f: A 1 x A 2 x ... x A11-> B, to napiszemy b = f(a 1 , a2 , ••• , 0 11) zamiast b = f((a 1 ,
a 2 , •••, a11)). Każde a1 nazywamy argwnentem funkcji/, pomimo że technicznie
(pojedynczy) argument/jest n-tką (a 1 , a2 , ••• , a11).
Jeśli/: A -> B jest funkcją i b = f(a), to mówimy, że b jest obrazem a wf
Obraz zbioru A' c A wf jest zdefiniowany jako

f(A1 = {beB:b =f(a) dla pewnego aeA'}

Zakres funkcji/jest obrazem jej dziedziny, to znaczy f(A). Na przykład za-


kresem funktji/:N-> N danej przez/(n) = 2n jest

f(N) = {m:m = 2n dla pewnego neN}

Funkcja jest surjekcją, jeślijej zbiór wartości jest jej przeciwdziedziną.


Na przykład funkcja /(n)= Ln/2J jest surjekcją z N w N, ponieważ każdy

111
ROZDZIAŁ 5. ZBIORY I NIE TYLKO

element ze zbioru N pojawia się jako wartość/ dla pewnego argumentu. Nato-
miast funkcja /(n) = 2n nie jest surjekcją ze zbioru N w N, ponieważ żaden
argument podstawiony do f nie daje 3. Funkcja/(n) = 2n jest jednakże surjek-
cją ze zbioru liczb naturalnych w zbiór liczb parzystych. Surjekcję /: A -+ B
nazywamy cza.sami odwzorowaniem zbioru A na zbiór B. Jeśli mówimy, że
funkcja/jest „na", oznacza to, że jest surjek.cją.
Funkcja/: A-+ B jest injekcją, jeśli różne argumenty/ dają różne wartości,
tzn. jeśli a -::/, /(a'). Na przykład funkcja/(n) = 2n jest injekcją ze
a', to /(a) -::/,
zbioru N w zbiór N, ponieważ każda liczba parzysta b jest obrazem wf co
najwyżej jednego elementu dziedziny, b/2. Funkcja/(n) = Ln/2J nie jest injek-
cją, ponieważ wartość 1 może powstać z dwóch argumentów: 2 i 3. Injekcjajest
czasami nazywana funkcją różnowartościową.
Funkcja/: A-+ B jest bijekcją, jeśli jest jednocześnie surjekcją i injekcją.
Na przykład funkcjaf(n) = (-1)' fn/21 jest bijekcją z N w Z:

o~ o
1~ -1
2~ 1
3~ -2
4~ 2

Powyższa funkcja jest injekcją, ponieważ żaden element ze zbioru Z nie jest
obrazem więcej niż jednego elementu ze zbioru N; jest surjekcją, ponieważ
każdy element zbioru Z pojawia się jak.o obraz jakiegoś elementu zbioru N,
a więc ta funkcja jest bijekcją. Bijekcja jest czasem nazywana odpowiedniością
wzajemnie jednoznaczną, ponieważ łączy parami elementy dziedziny i przeciw-
dziedziny. Bijekcja ze zbioru A w siebie jest nazywana pennutacją.
Kiedy funkcja/ jest bijekcją, jej odwrotność 1- 1 jest zdefiniowana jak.o

f-'(b) = a wtedy i tylko wtedy, gdy f(a) = b

Na przykład odwrotnością funkcjif(n) = (-1)' fn/21 jest

jeśli m ~ O
jeśli m <O
ZADANIA
5.3-1. Niech A i B będą zbiorami skończonymi i niech/: A-+ B będzie funkcją.
Wykaż, że

(a) jeśli/jest injekcją, to !Al,; IBI;


(b) jeśli/jest surjekcją, to !Al;,,IBI.

112
5.J...2. Czy funkcjaf(x) = x + 1 jest bijekcją, kiedy dziedziną i przeciwdziedzi-
ną jest N? Czy jest bijekcją w przypadku zbioru Z?
5.3-3. Podaj naturalną defmicję relacji odwrotnej do danej relacji binarnej ta-
ką, że jeśli ta relacja jest bijekcją, to relacja odwrotna jest jej funkcją
odwrotną.
* 5.3-4. Podaj bijekcję ze zbioru Z na zbiór Z x Z.

5.4. Grafy
W tej części książki przedstawimy dwa rodzaje grafów: skierowane (wrien-
towane) i nieskierowane (niewrientowane). Czytelnik powinien pamiętać
o tym, że pewne defmicje, z którymi spotykamy się w literaturze matematycz-
nej, mogą się różnić od podanych tutaj, lecz w większości różnice te są niewiel-
kie. W podrozdziale 23.l pokażemy, jak są reprezentowane grafy w pamięci
komputera.
Graf skierowany (lub digraf) G jest opisany parą (V, E), gdzie V jest
zbiorem skończonym, a E jest relacją. binarną w V. Zbiór V jest nazywany
zbiorem wierzchołków G, a jego elementy są nazywane wiencholkami. Zbiór
E jest nazywany zbiorem krawędzi G, a jego elementy nazywamy krawędziami.
Na rysunku 5.2a jest pokazany graf skierowany o zbiorze wierzchołków {l,
2, 3, 4, 5, 6}. Wierzchołki są przedstawione jak.o kółka, a krawędzie jak.o
strzałki. Zauważmy, że możliwe jest istnienie pętli od danego wierzchołka do

mego samego.
W grafie nieskierowanym G = (V, E), zbiór krawędzi Eto zbiór nieuporzą­
dkowanych par wierzchołków. Oznacza to, że krawędź jest zbiorem {u, v},
gdzie u, ve V i u "f' v. Do oznaczenia krawędzi będziemy używać zapisu (u, v)
zamiast oznaczenia w postaci zbioru {u, v}; zapisy (u, v) i (v, u) oznaczają tę
samą krawędź. W grafie nieskierowanym nie mogą występować pętle, więc

© 6
(,) (b) (c)

Rys. 5.2. Grafy skierowane i nieskierowane. (a) Graf skierowany G = (V, E), gdzie V= {I, 2, 3, 4, 5, 6}
i E = {(l, 2), (2, 2), (2, 4), (2, 5), (4, I), (4, 5), (5, 4), (6, 3)}. Krawędź (2, 2) jest pętlą. (b) Graf
nieskierowany G = (V, EJ,gdzie V"" {l, 2, 3, 4, 5, 6} i E = {(1, 2), (1, 5), (2, 5), (3, 6)}. Wierzchołek
4 jest izolowany. (c) Podgraf grafu z części (a) utworzony ze zbioru wierzchoHców{I, 2, 3, 6}

113
ROZDZIAŁ 5. ZBIORY I NIE TYLKO

każda krawędź zawiera dokładnie dwa różne wierzchołki. Na rysunku 5.2 (b)
jest pokazany graf nieskierowany o zbiorze wierzchołków {l, 2, 3, 4, 5, 6}.
Wiele definicji dotyczących grafów skierowanych i nieskierowanych jest
takich samych, chociaż niektóre terminy mają nieco inne znaczenie, Jeśli (u, v)
jest krawędzią grafu skierowanego G = (V, E), to mówimy, że krawędź (u, v)
jest wychodząca z wierzchołka u i jest wchodząca do wierzchołka v. Na przykład
krawędzie wychodzące z wierzchołka 2 na rys. 5.2a to (2, 2), (2, 4) i (2, 5).
Krawędzie wchodzące do wierzchołka 2 to (1, 2) i (2, 2). Jeśli (u, v) jest krawę­
dzią grafu nieskierowanego G = (V, E), to mówimy, że (u, v) jest incydentna
z wierzchołkami u i v. Na rysunku 5.2b krawędzie incydentne z wierzchołkiem
2 to (I, 2) i (2, 5).
Jeśli (u, v) jest krawędzią grafu G = (V, E), to mówimy, że wierzchołek
v jest sąsiedni do wierzchołka u. Kiedy graf jest nieskierowany, relacja sąsiedz­
twa jest symetryczna. Kiedy graf jest skierowany, relacja sąsiedztwa nie musi
być symetryczna. Jeśli w grafie skierowanym v jest wierzchołkiem sąsiadują­
cym z u, to czasem zapisujemy to jako u-+ v. Na rysunku 5.2a i b wierzchołek
2 sąsiaduje z wierzchołkiem I, ponieważ krawędź (1, 2) należy do obu grafów.
Wierzchołek 1 nie sąsiaduje z wierzchołkiem 2 na rys. 5.2a, ponieważ krawędż
(2, 1) nie należy do grafu.
Stopniem wierzchołka w grafie nieskierowanym jest liczba incydentnych
z nim krawędzi. Na przykład wierzchołek 2 na rys. 5.2b ma stopień 2. W grafie
skierowanym stopień wyjściowy wierzchołka jest liczbą krawędzi wychodzących
z niego, a stopień wejściowy wierzchołka jest liC'lbą krawędzi do niego wcho-
dzących. Stopniem wierzchołka w grafie skierowanym jest liczba będąca sumą
jego stopni: wejściowego i wyjściowego. Wierzchołek 2 na rys. 5.2a ma stopień
wejściowy 2, stopień wyjściowy 3 i stopień 5,
Ścieżka (droga) długości k z wierzchołka u do wierzchołka u' w grafie
G = (V, E) jest ciągiem wierzchołków (v 0, v1, v2 , ••• , vt) takich, że u= v0,
u' = V.1: i (v1_ 1, vJe E dla i= 1, 2, ..., k. Długość ścieżki jest liczbą krawędzi
ścieżki. Ścieżka zawiera wierzchołki v0 , v1 , ... , vt i krawędzie (v0 , v1 ), (v1 , v2 ), ... ,
(v.1:-i, vJ. Jeśli istnieje ścieżka p z u do u', to mówimy, że u' jest osiągalny
z u po ścieżce p, co zapisujemy: u 4 u', jeśli G jest grafem skierowanym. ścież­
ka jest nazywana ścieżką prostą, jeśli wszystkie jej wierzchołki są różne. Na
rysunku 5.2a ścieżka (I, 2, 5, 4) jest ścieżką prostą o długości 3. Ścieżka (2, 5,
4, 5) nie jest ścieżką prostą.
Podścieżka ścieżki p = (v 0, v1, ... , vl) jest ciągiem kolejnych wierzchoł­
ków. To znaczy, że dla dowolnych O ~ i~ j ~ k podciąg wierzchołków (v 1,
v1+ 1 , ••• , v1) jest podścieżką ścieżki p.
W grafie skierowanym ścieżka (v 0, v1, ... , vl) tworzy cykl, jeśli v0 = vt
oraz zawiera co najmniej jedną krawędź. Cykl nazywamy prostym, jeśli, dodat-
kowo, v1 , v2 , ... , v.1:są różne. Pętla jest cyklem o długości 1. Dwie ścieżki (v 0 ,
v1 , v2 , ••• , vt- 1 , v0 ) i (v(), v'1 , v2, ..., vl- 1 , v()) tworzą ten sam cykl, jeśli istnieje

114
5.4. GRAFY

liczba całkowitaj taka. że v/ = v{I+J)modk dla i= O, 1, ..., k - 1. Na rysunku 5.2a


ścieżka (1, 2, 4, 1) tworzy ten sam cykl co ścieżki (2, 4, I, 2) i (4, I, 2, 4). Jest
to cykl prosty. Cykl (1, 2, 4, 5, 4, 1) nie jest cyklem prostym. Cykl (2, 2)
złożony z krawędzi (2, 2) jest pętlą. Graf skierowany nie zawierający pętli
nazywamy prostym. W grafie nieskierowanym ścieżka (v 0 , v1 , ... , v1 ) tworzy
cyk.1,jeśli v0 = v.t i v1 , v2 , ... , v.t są różne i k ~ 2. Na przykład na rys. 5.2b ścieżka
(1, 2, 5, 1) tworzy cykl. Graf nie zawierający cykli nazywamy acyklicznym.
Graf nieskierowany jest spójny, jeśli każda para wierzchołków jest połą­
czona ścieżką. Spójne składowe grafu to klasy abstrakcji wierzchołków w rela-
cji ,,jest osiągalny z". Graf na rys. 5.2b ma trzy spójne składowe: {1, 2, 5}, {3,
6} i {4}. Wierzchołki ze zbioru {I, 2, 5} są wzajemnie osiągalne. Graf nie-
skierowany jest spójny, jeśli ma dokładnie jedną spójną składową, to znaczy,
jeśli każdy wierzchołek jest dostępny z każdego innego wierzchołka.
Graf skierowany jest silnie spójny, jeśli każde dwa wierzchołki są osiągalne
jeden z drugiego. Silnie spójne składowe grafu są klasami równoważności wie-
rzchołków w relacji „są wzajemnie osiągalne". Graf skierowany jest silnie spój-
ny, jeśli ma jedynie jedną silnie spójną składową. Graf na rys. 5.2a ma trzy
silnie spójne składowe: {l, 2, 4, 5}, {3} i {6}. Wszystkie pary wierzchołków
w {1, 2, 4, 5} są wzajemnie dostępne. Wierzchołki {3, 6} nie tworzą silnie
spójnej składowej, ponieważ wierzchołek 6 nie jest osiągalny z wierzchołka 3.
Dwa grafy G = (V, E) i G' = (V', E'") są izomorficzne,jeśli istnieje bijekcja
f: V - V' taka, że (u, v)eE wtedy i tylko wtedy, gdy (f(u), f(v))eE'. Innymi
słowy, możemy przenumerować wierzchołki G tak, aby były wierzchołkami G',
zachowując odpowiadające krawędzie w G i G'. Na rysunku 5.3a widać parę
izomorficznych grafów G i G' z odpowiadającymi zbiorami wierzchołków

G 3
3
5 4

G'

(a) (b)
Rys. 5.3. {a) Para izomorficmych grafów. Wierzchołki górnego grafu odpowiadają wierzchołkom
=
dolnego grafu w funkcji odwzorowującej/(1) u,/(2) = u,/(3) = w,/(4) = x,f(S).., y,/(6) = z.
(b) Dwa nieizomorficzne grafy: górny graf ma wiert.ehołek stopnia 4, natootiast dolny takiego nie ma

115
ROZDZIAŁ 5. ZBIORY I NIE TYLKO

V= {l, 2, 3,4, 5,6} i V'= {u, v, w,x,y,z}. Odwzorowanie Vw V'daneprzez


/(!)=u, /(2) = v, /(3) = w, /(4) = x, /(5) = y, /(6) = z jest wymaganą bije-
kcją. Grafy na rys. 5.3b nie są izomorficzne. Mimo że obydwa grafy mają po
5 wierzchołków i po 7 krawędzi, tylko górny graf ma wierzchołek stopnia 4.
Mówimy, re graf G' = (V', E') jest podgrafemgrafu G = (V, E), jeśli
V' c: V i E' c: E. Mając dany zbiór V' c: V, podgrafem grafu G utworzonym
z V' jest graf G' = (V', E'), w którym

E' = {(u, v)cE:u, vc V'}


Podgraf utworzony ze zbioru wierzchołków {1, 2, 3, 6} z rys. 5.2a jest pokaza-
ny na rys. 5.2c, a jego zbiór krawędzi to{(!, 2), (2, 2), (6, 3)}.
Mając dany graf nieskierowany G = (V, E), wersją skierowaną grafu Gna-
zywamy graf skierowany G' = (V, E'), w którym (u, v)eE' wtedy i tylko wte-
dy, gdy (u, v)eE, to znaczy, że każda krawędź nieskierowana (u, v) grafu
G zostaje w wersji skierowanej zastąpiona przez dwie krawędzie skierowane (u,
v) i (v, u). Mając dany graf skierowany G = (V, E), wersją nieskierowaną grafu
G nazywamy graf nieskierowany G' = (V, E'), w którym (u, v)e E' wtedy i tyl-
ko wtedy, gdy u =I-v i (u, v)eE, to znaczy, że wersja nieskierowana zawiera
krawędzie grafu G „z usuniętym skierowaniem" oraz usuniętymi pętlami. (Po-
nieważ (u, v) i (v, u) są w grafie nieskierowanym tą samą krawędzią, wersja
nieskierowana grafu skierowanego zawiera ją tylko raz, nawet jeśli graf skiero-
wany zawiera obie krawędzie (u, v) i (v, u)). W grafie skierowanym G = (V, E)
sąsiadem wierzchołka u jest dowolny wierzchołek sąsiadujący z u w nieskiero-
wanej wersji G. To znaczy, że v jest sąsiadem u, jeśli (u, v)eE lub (v, u)eE.
W grafie nieskierowanym u i v są sąsiadami, jeśli ze sobą sąsiadują.
Niektóre rodzaje grafów mają nadane specjalne nazwy. Graf pełny jest to
graf nieskierowany, w którym każda para wierzchołków jest połączona krawę­
dzią. Graf dwudzielny jest to graf nieskierowany G = (V, E), w którym zbiór
V może zostać podzielony na dwa zbiory V1 i V2 takie, że (u, v)e E implikuje
ue V1 i ve V2 lub ue V2 i ve V1 , to znaczy, że zbiór wszystkich wierzchołków
zostaje rozdzielony na dwa zbiory V1 i V2 • Acykliczny graf nieskierowany
nazywa się lasem, a spójny, acykliczny graf nieskierowany nazywa się (wolnym)
drzewem (patrz pod.rozdz. 5.5). Acykliczne grafy skierowane oznaczamy czasami
w skrócie jako dag - od pierwszych liter nazwy angielskiej directedacyclicgraph.
Istnieją dwie struktury podobne do grafów, z którymi możemy się cz.asem
spotkać. Multigraf jest podobny do grafu nieskierowanego, lecz może mieć
zarówno wielokrotne krawędzie między wierzchołkami, jak i pętle. Hipergraf
różni się od grafu nieskierowanego tym, że każda hiperkrawędź, zamiast łączyć
dwa wierzchołki, łączy pewien podzbiór wierzchołków. Wiele algorytmów na-
pisanych dla zwykłych grafów skierowanych i nieskierowanych może być za-
adaptowana dla tego typu struktur grafopodobnych.

116
5.5. DRZEWA

ZADANIA

5.4-1. Uczestnicy przyjęcia dla pracowników pewnej instytucji podają sobie


ręce na powitanie, przy czym każdy z nich zapamiętuje, ile razy podał
komuś rękę. Na koniec przyjęcia dyrektor tej instytucji sumuje, ile razy
każdy z jego pracowników podał komuś rękę. Wykaż, że wynik jest parzy-
sty, dowodząc lematu o podawaniu rąk: jeśli G = (V, E) jest grafem nie-
skierowanym, to

L stopień(v) - 2JEJ
5.4-2. Pokaż, że w grafie nieskierowanym długość cyklu musi wynosić co
najmniej 3.
5.4-3. Pokaż, że jeśli graf skierowany lub nieskierowany zawiera ścieżkę mię­
dzy dwoma wierzchołkami u i v, to zawiera ścieżkę prostą między tymi
wierzchołkami. Pokaż, że jeśli graf skierowany zawiera cykl, to zawiera
cykl prosty.
5.4-4. Pokaż, że dowolny spójny graf nieskierowany G = (V, E) spełnia zależ­
ność JEJ;,,JVJ- I.
5.4-5. Pokaż, że w grafie nieskierowanym relacja ,jest osiągalny z" jest relacją
równoważności w zbiorze wierzchołków grafu. Która z trzech własności
relacji równoważności zachodzi dla tej relacji w grafach skierowanych?
5.4-6. Co jest wersją nieskierowaną grafu skierowanego na rys. 5.2a? Co jest
wersją skierowaną grafu nieskierowanego na rys. 5.2b?
* 5.4-7. Pokaż, że hipergrafmoże być przedstawiony jako graf dwudzielny, jeśli
pozwolimy, aby relacja incydencji dla hipergrafu odpowiadała relacji sąsie­
dztwa w grafie dwudzielnym. (Wskazówka: Niech jeden zbiór wierzchoł­
ków w grafie dwudzielnym odpowiada wierzchołkom hipergrafu, a drugi
zbiór wierzchołków - hiperkrawędziom).

5.5. Drzewa
Podobnie jak dla grafów, tak.że dla drzew istnieje wiele oznaczeń (notacji).
W tej części książki podajemy definicje i własności kilku typów drzew. W pod-
rozdziałach 11.4 i 23.1 pokażemy,jak drzewa mogą być reprezentowane w pa-
mięci komputera.

5.5.1. Drzewa wolne


Zdefiniowane już w podrozdz. 5.4 drzewo wolne jest spójnym, acyklicznym
grafem nieskierowanym. Często mówimy, że dany graf jest drzewem, zamiast

117
ROZDZIAŁ 5. ZBIORY I NIE TYLKO

\
(o) (b) (c)

Rys, SA. (a) Drzewa wolne. (b) Las. (c) Graf, który zawiera cykl, a więc nie jest ani drzewem, ani lasem

powiedzieć, że graf ten jest drzewem wolnym. Graf nieskierowany, który jest
acykliczny, ale niekoniecznie spójny, nazywamy lasem. Wiele z algorytmów,
które stosujemy dla drzew, możemy również stosować w sposób podobny
w przypadku lasów.
Na rysunku 5.4a widać drzewo, a na rys. 5.4b - las. Graf na rys. 5.4c nie
jest ani drzewem, ani lasem, ponieważ zawiera cykl.
Następujące twierdzenie zawiera wiele ważnych faktów dotyczących drzew
wolnych.

TwIERDZENIE S.2. (Własności drzew wolnych)


Niech G = (V, E) będzie grafem nieskierowanym. Następujące fakty są rów-
noważne.
(1) G jest drzewem wolnym.
(2) Każde dwa wierzchołki G są połączone ze sobą dokładnie jedną ścieżką
prostą.

(3) G jest spójny, ale jeśli usuniemy którąś z krawędzi z E, to powstały graf jest
. '
n1esp0Jny.
.
(4) G jest spójny i !El- !VI- I.
(5) G jest acykliczny i !El- !VI-1.
(6) G jest acykliczny, lecz jeśli dodamy do Ejakąk.olwiek krawędź, to powstały
graf zawiera cykl.

DOWÓD
(1)=> (2): Ponieważ drzewo jest spójne, każde dwa wierzchołki G są połączone
co najmniej jedną ścieżką prostą. Niech u i v będą wierzchołkami połączonymi
dwiema różnymi ścieżkami prostymi p 1 i p 2 , jak to widać na rys. 5.5. Niech
w będzie wierzchołkiem, w którym ścieżki po raz pierwszy się rozchodzą; to
znaczy w jest pierwszym wierzchołkiem, przez który przechodzą ścieżki Pi i p 2
i którego następnikiem na p 1 jest x, a następnikiem na p 2 jest y, gdzie x 'F y.
Niech z będzie pierwszym wierzchołkiem, w którym ścieżki schodzą się ponow-
nie; a więc z jest pierwszym wierzchołkiem po w na Pi takim, że znajduje się on
na p 2 • Niech p' będzie podścieżką p 1 , która prowadzi z w przez x do z, i niech

118
5.5. DRZEWA

p'

,. '
• p"

Rys. 5.5. Jeden z kroków w dowodzie tw. 5.2: jeżeli (I) G jest drzewem wolnym, to (2) dowolne dwa
wierzchołki G są ze sobą połączone jedyną ścieżką prostą. Przypuśćmy (przez zaprzeczenie), że
wierzchołki u i v są połączone dwiema różnymi ścieżkami prostymi p 1 i p 1 • Ścieżki te pierwszy raz
łączą się w wierzchołku w i po raz pierwszy ro7.dzielają się w wierzchołku z. Ścieżka p' złożona
razem z odwrotnością ścieżki p" tworzy cykl, co prowadzi do sprzeczności

p" będzie pod.ścieżką p 2 , która prowadzi z w przez y do z. ścieżki p' i p" nie
mają wspólnych wierzchołków poza swoimi końcami. Tak. więc ścieżka otrzy-
mana przez złożenie p' i odwrotności ścieżki p" jest cyklem, co jest zaprze-
C'leniem acykliC'lności drzewa. Tak więc, jeśli G jest drzewem, może istnieć
najwyżej jedna ścieżka prosta między dwoma wierzchołkami.
(2)=-(3): Jeśli każde dwa wierzchołki G są połączone jedyną ścieżką pros-
tą, to G jest spójny. Niech (u, v) będzie jedną z krawęd.zi E. Ta krawędź jest
ścieżką z u do v, musi więc być jedyną ścieżką łączącą u i v. Jeśli usuniemy (u, v)
z G, przestanie istnieć ścieżka z u do v, więc operacja ta rozspójnia G.
(3) =- (4): Przyjmując, że graf G jest spójny i biorąc pod uwagę zad. 5.4-4,
mamy IE!~ IVI-1. Udowodnimy przez indukcję, że IEI~ JVI- 1. Graf spój-
ny o n= I lub n= 2 wierzchołkach ma n - l krawędzi. Przyjmijmy, że G ma
n~ 3 wierzchołków i wszystkie grafy spełniające (3) o mniej niż n wierzchoł­
kach spełniają również zależność IEI~ !VI- I. Usuwając dowolną krawędź
z G, rozdzielamy graf na k ~ 2 spójnych składowych (faktycznie k = 2).
Każda składowa spełnia (3), bo inaczej G nie spełniałby (3). Zatem,
przez indukcję, liC'lba krawędzi we wszystkich składowych razem wynosi co
najwyżej IVI - k ~ IVI - 2. Jeśli dodamy usuniętą krawędź, to otrzymamy
IEl<;IVl-1.
(4)=- (5): Przypuśćmy, że G jest spójny i IE)= IVI- l. Musimy wykazać,
że G jest acykliczny. Przypuśćmy, że G ma cykl zawierający k wierzchołków v1 ,
v2 , ••• , v1 • Niech G1 = (V 1 , E1) będzie właśnie tym cyklem. Zauważmy, że
IVkl= IE1 1 = k. Jeśli k < ]VI,to musi istnieć wierzchołek v1 + 1 eV- Vk, który
jest sąsiadem pewnego węzła v1e Vk, ponieważ G jest spójny. 2.defmiujmy
Gk+i = (V 1 + 1, Ek+i) jako podgraf G z Vk+t = V1 u {v1 + 1 } i Ek+l = E1 u {(v1,
vk+1 )}. Następnie zauważmy, że IVk+tl = jE1 + 1 1= k + 1. Jeżeli k + 1 < n, to
możemy w ten sam sposób zdefiniować Gk+i itd., aż otrzymamy Gn= (Vn,E,.),
gdzie n= IVI, vn
= v i IEnl= IVnl= 1v1.Ponieważ Gnjest podgrafem G,
Ens;. E, więc ]El~ IVI,co jest sprzeczne z założeniem IE)= ]VI - 1. Tak więc
G jest acykliczny.

119
ROZDZIAŁ 5. ZBIORY I NIE TYLKO

=
(5) (6): Przypuśćmy, że G jest acykliczny i IEI - IVI - 1. Niech k będzie
liczbą spójnych składowych G. Każda ze spójnych składowych jest z definicji
drzewem wolnym i skoro (1) implikuje (5), liczba wszystkich krawędzi we
wszystkich spójnych składowych G wynosi IV] - k. Tak więc k = 1 i G musi
być drzewem. Ponieważ (I) implikuje (2), każde dwa wierzchołki G są połączo­
ne jedyną ścieżką prostą. Dodanie do G krawędzi tworzy cykl.
(6)= (I): Załóżmy, że G jest acykliczny, ale jeśli dodamy do E krawędź,
utworzymy cykl. Musimy wykazać, że G jest spójny. Niech u i v będą dowol-
nymi wierzchołkami G. Jeśli u i v nie są sąsiadami, to przez dodanie krawędzi
(u, v) utworzymy cykl, którego wszystkie krawędzie poza (u, v) należą do G.
Istnieje zatem ścieżka od u do v, a ponieważ u i v zostały wybrane dowolnie,
więc G jest spójny.


5.5.2. Drzewa ukorzenione i uporządkowane
Dr:zewoz korzeniem (drzewo ukorzenione) jest drzewem wolnym, w którym jeden
z wierzchołków jest wyróżniony -wierzchołek ten nazywamy korzeniem drzewa.
Często wierzchołki drzew ukorzenionych nazywamy węzlami 1 l drzewa. Na rysun-
ku 5.6a widać drzewo ukorzenione mające 12 węzłów z korzeniem równym 7.

Głębokość O

..
li
Głębokość 1
:w
o Ił: Głębokość 2
t
~ Głębokość 3

Głębokość 4
(,) (b)

Rys. 5.6. Uporządkowane drzewa z korzeniami. (1.)Drzewo ukorzenione o wysokości 4 narysowane


w standardowy sposób: korzeń (węzeł 7) majduje się na szczycie,jego następnik.i (węzły o głęboko­
ści l) poniżej, ich następniki (węzły o głębokości 2) pod nimi itd. Jeśli drzewo jest uporządkowane,
to wzajemne uporządkowanie następników węzła od lewej do prawej ma maczenie; jeśli nie jest
- nie ma. (b) Inne drzewo ukorzenione. Jako drzewo ukorzenione, jest identyczne jak drzewo
w (a), lecz jak.o drzewo uporządkowane różni się od tamtego tym, że następniki węzła 3 występują
w innym porządku

l) Określenie „węzeł" jest często używane jak.o synonim wierz.chołka. My będziemy używać
terminu „węzeł" w znaczeniu wierzchołka drzewa ukorzenionego.

120
5.5. DRZEWA

Rozważmy węzeł x drzewa ukorzenionego T o korzeniu r. Każdy węzeł


y na ścieżce z r do x nazywamy przodkiem węzła x. Jeśli y jest przodkiem x, to
x jest potomkiem y. (Każdy węzeł jest jednocześnie swoim przodkiem i potom-
kiem). Jeżeli y jest przodkiem x i x #- y, to y jest właściwym przodkiem x,
a x jest właściwym potomkiem y. Poddrzewo o korzeniu x jest drzewem, utwo-
rzonym z potomków x, którego korzeniem jest x, Na przykład poddrzewo
o korzeniu w węźle 8 na rys. 5.6a zawiera węzły 8, 6, 5 i 9,
Jeśli ostatnią krawędzią drzewa T na ścieżce od korzenia r do węzła x jest
(y, x), to y jest poprzednikiem (ojcem) x, a x jest następnikiem (synem) y, Ko-
rzeń jest jedynym węzłem drzewa T, który nie ma poprzednika. Jeśli dwa węzły
mają ten sam poprzednik, to nazywamy je braćmi. Węzeł, który nie ma następ­
ników, jest węzłem zewnętrznym lub liściem. Węzeł, który nie jest liściem, jest
węzłem wewnętrznym.
Liczba następników węzła x drzewa ukorzenionego T nazywa się stopniem
x 1l. Długość ścieżki od korzenia r do węzła x nazywa się głębokością (pozio-
mem) węzła x w drzewie T. Największa głębokość węzła w drzewie T jest
wysokością drzewa T.
Drzewo uponądkowane jest drzewem ukorzenionym, w którym następniki
każdego z węzłów są uporządkowane. To znaczy, że jeśli węzeł mak następ­
ników, są to pierwszy następnik, drugi następnik:, ... i k-ty następnik. Dwa
drzewa widoczne na rys. 5.6 są różne jako drzewa uporządkowane, lecz takie
same jako drzewa ukorzenione.

5.5.3. Drzewa binarne i pozycyjne


Drzewa binarne najłatwiej opisać rekurencyjnie. Dnewo binarne T jest struk-
turą zdefiniowaną na skończonym zbiorze węzłów, które

• nie zawiera żadnych węzłów, lub


• składa się z trzech rozłącznych zbiorów węzłów: korzenia, drzewa binarnego
zwanego lewym poddrzewem i drzewa binarnego zwanego prawym poddrze-
wem.
Drzewo binarne, które nie ma żadnych węzłów, nazywa się drzewem pustym lub
drzewem zerowym i oznacza się czasami jako NIL. Jeśli lewe poddrzewo jest
niepuste, to jego korzeń nazywa się lewym następnikiem korzenia drzewa głów­
nego. Podobnie, korzeń niepustego prawego poddrzewa jest prawym następni­
kiemkorzenia drzewa głównego. Jeśli poddrzewo jest drzewem pustym NIL, to
mówimy, że brakuje następnika. Na rysunku 5.7a jest pokazane drzewo binarne,

Zauważmy, że stopień węzła za.leży od tego, czy Tjest drzewem ukorzenionym czy wolnym.
1
>
Stopień wierzchołka w drzewie wolnym jest, podobnie jak w grafie nieskierowanym, liczbą sąsied­
nich wierzchołków. Natomiast w drzewie ukorzenionym stopniem węzła jest liczba następników.

121
ROZDZIAŁ 5. ZBIORY I NIE TYLKO

,, 3

' 7
J
'4 l
~

'6
(•) (b) (,)

Rys. 5.7. Drzewa binarne. (a) Drzewo binarne naszkicowane w standardowy sposób. Następniki
węzła są narysowane pod nim: lewy po lewej, prawy po prawej stronie. (b) Inne drzewo binarne.
W (a) lewy następnik węzła 7 to 5, a prawy nie istnieje. W (b) lewy następnik 7 nie istnieje, a prawy
to 5. Drzewa te, jako drzewa uporządkowane, są takie same, lecz jako drzewa binarne różnią się
od siebie. (c) Drzewo binarne w (a) reprez.entowane przez węzły regularnego drzewa binarnego:
drzewa uporządkowanego, w którym stopień każdego węzła wewnętrmego wynosi 2. Liście są
umieszczone w kwadracikach

Drzewo binarne nie jest po prostu drzewem uporządkowanym, w którym


każdy z węzłów ma co najwyżej stopień 2. W drzewie binarnym na przykład,
jeśli węzeł ma tylko jeden następnik, to jego położenie - fakt C2yjest lewym
następnikiem czy prawym następnikiem - ma znaczenie. W drzewie uporząd­
kowanym nie ma rozróżnienia jednego następnik.a jako lewego lub prawego.
Na rysunku 5.7b widać drzewo binarne różniące się od tego z rys. 5.7a położe­
niem jednego z węzłów. Jeśli rozpatrzymy te drzewa jak.o drzewa uporząd­
kowane, to będą to identyczne drzewa.
Informacja o pozycjach węzłów w drzewie binarnym może być reprezen-
towana przez wewnętrzne węzły drzewa uporządkowanego, jak jest to pokaza-
ne na rys. 5.7c. Trik polega na wstawieniu w miejsce każdego z brak.ujących
następników drzewa binarnego węzła bez następników. Te liście są zaznaczane
jako kwadraty. Drzewo, które powstaje, jest regularnym drzewem binarnym:
każdy z węzłów jest bądź liściem, bądź ma stopień 2. Nie ma węzłów o stopniu
1. Porządek następników węzła odpowiada ich kolejności.
Reprezentacja pozycyjna może być rozszerzona na drzewa mające więcej
niż 2 następniki dla tego samego węzła. W drzewie pozycyjnym następniki tego
samego węzła są etykietowane różnymi liczbami całkowitymi. Mówimy, że
brakuje i-tego następnika, jeśli nie ma następnika etykietowanego przez i.
Drzewo rzędu k (k-ame) jest drzewem pozycyjnym, w którym każdy węzeł ma
następnik.i etykietowane wyłącznie liczbami nie przekraczającymi k. Tak. więc
drzewo binarne jest k-arnym drzewem z k = 2.
Pełne drzewo rzędu k jest drzewem rzędu k, w którym wszystkie liście mają
tę samą głębokość, a wszystkie węzły wewnętrzne mają stopień k. Na rysunku
5.8 widać pełne drzewo binarne o wysokości 3. Ile liści ma pełne drzewo rzędu

122
5.5. DRZEWA

Głębokość O

Głębokość 1

Gębokolć2

Gębokolć 3

Ry1. 5.8. Pełne drzewo binarne o wysokości 3 i 8 liściach oraz 7 węzłach wewnętrznych

ko wysokości h? Korzeń mak następników o głębokości 1, z których każdy


ma k następnik.ów o głębokości 2 itd. A więc liczba liści o głębokości h wynosi
k!'. Podobnie, wysokość pełnego drzewa rzędu k o n liściach wynosi logtn.
Liczba węzłów wewnętrznych pełnego drzewa rzędu k o wysokości h wynosi
,-1
] + k + k' + ...+ k'- l - L /c
l=O

k' - I
k-1
z równania (3.4). Tak więc pełne drzewo binarne o wysokości h ma 211- l
węzłów wewnętrznych.

ZADANIA
5.S-1. Narysuj wszystkie drzewa wolne utworzone z 3 wierzchołków A, Bi C.
Narysuj wszystkie drzewa ukorzenione o węzłach A, B i C, w których
A jest korzeniem.. Narysuj wszystkie drzewa uporządkowane, a następnie
binarne o węzłach A, B i C, w których A jest korzeniem.
S,5-2. Pokaż, że dla n~ 7 istnieje takie drzewo wolne o n węzłach, że wybiera-
jąc po kolei każdy z nich jako korzeń, za każdym razem otrzymujemy inne
drzewo z korzeniem.
S.S-3. Niech G = (V, E) będzie acyklicznym grafem skierowanym, który ma
wierzchołek v0 E V taki, że istnieje dokładnie jedna ścieżka z v0 do każdego
wierzchołka vE V. Udowodnij, że nieskierowana wersja grafu G tworzy
drzewo.
5.5-4. Wykaż, stosując indukcję, że w dowolnym regularnym drzewie binar-
nym liczba węzłów stopnia 2 jest o I mniejsza niż liczba liści.
5.S-5. Wykaż, stosując indukcję, że wysokość drzewa binarnego o n węzłach
wynosi co najmniej Lig nj.
* 5.5-6. Długość ścleW wewnębznej regularnego drzewa binarnego jest sumą, po
wszystkich węzłach wewnętrznych drzewa, głębokości każdego węzła. Po-

123
ROZDZIAŁ 5. ZBIORY I NIE TYLKO

dobnie, długość ścieżki zewnętrznej jest sumą, po wszystkich liściach drze-


wa, głębokości każdego liścia. Rozważmy regularne drzewo binarne
o n węzłach wewnętrmych, długości ścieżki wewnętrmej i oraz długości
ścieżki zewnętrznej e. Udowodnij, że e = i+ 2n.
* 5.5-7. Niech „waga" liścia x o głębokości d drzewa binarnego T będzie wyra-
żona wzorem w(x) = 2- 11• Udowodnij, że [w(x) :i::;;1, gdzie sumujemy po
"
wszystkich liściach x z T. (Nierówność ta nazywa się nierównością Krafta).
5.5--8. Pokaż, że każde drzewo binarne o L liściach (oprócz drzewajednowierz-
chołkowego) zawiera poddrzewo mające (włącznie) między L/3 i 2L/3 liści.

Problemy
5-1. Kolorowanie grafów
k-kolorowanie grafu nieskierowanego G = (V, E) jest funkcją c: V-+ {O, I,
... , k- l} taką, że c(u) ,' c(v) dla każdej krawędzi (u, v)eE. Innymi słowy,
liczby O, 1, ... , k - 1 reprezentują k kolorów i sąsiednie wierzchołki muszą
być innych kolorów.

(a) Pokaż, że każde drzewo jest 2-kolorowalne.


(b) Pokaż, że równoważne są następujące stwierdzenia:
I. G jest dwudzielny.
2. G jest 2-kolorowalny.
3. G nie ma cykli o długości będącej liczbą nieparzystą.
(c) Niech d będzie maksymalnym stopniem każdego wierzchołka grafu. Udo-
wodnij, że G może być pokolorowany d + 1 kolorami.
(d) Pokaż, że jeśli G ma 0(1 VI) krawędzi, to G może być pokolorowany
O(.j IVf)kolorami.

S.2. Grafy znajomości


Sformułuj każde z następujących stwierdzeń w postaci twierdzenia dotyczące­
go grafów nieskierowanych, a następnie udowodnij je. Przyjmij, że relacja zna-
jomości jest symetryczna, ale nie zwrotna.

(a) W dowolnej grupie ludzi n ~ 2 jest dwoje ludzi mających tę samą liczbę
znajomych w tej grupie.
(b) W każdej grupie złożonej z 6 ludzi znajdzie się troje wzajemnie sobie znajo-
mych lub trzech wzajemnie sobie nieznajomych.
(c) Dowolna grupa ludzi może być tak podzielona na dwie części, że co naj-
mniej połowa znajomych każdej z osób należy do grupy, do której ta osoba
nie należy.

124
UWAGI DO ROZDZIAŁU

(d) Jeśli każda osoba w danej grupie jest przyjacielem co najmniej polowy
osób w tej grupie, to można posadzić całą grupę przy stole tak, żeby każda
osoba siedziała pomiędzy dwoma znajomymi.

5-3. Podziały dnew


Wiele algorytmów typu „dziel i zwyciężaj", które operują na grafach, wymaga,
aby graf był podzielony na dwa prawie tej samej wielkości podgrafy przez
usunięcie niewielkiej liczby krawędzi. Rozważmy podziały drzew.

(a) Pokaż, że usuwając jedną krawędź, możemy podzielić wierzchołki dowol-


nego drzewa binarnego o n wierzchołkach na dwa zbiory A i B tak.ie, że
IAI .; 3n/4 i IBI.; 3n/4.
(b) Pokaż, że stała 3/4 w cr.ęści (a) jest optymalna, konstruując drzewo, w któ-
rym każdy zrównoważony podział powstający w wyniku usunięcia jednej
krawędzi dajeIAI- 3n/4.
(c) Pokaż, że przez usunięcie najwyżej O(lgn) krawędzi, możemy podzielić wie-
rzchołki dowolnego drzewa o n wierzchołkach na dwa zbiory A i B takie,
żelAI- L•/2Ji IBI- ,n/21.

Uwagido rozdziału
G. Boole zapoczątkował rozwój logiki symbolicznej i wprowadził wiele pod-
stawowych oznaczeń dla zbiorów w książce wydanej w 1854 r. Współczesna
teoria zbiorów została stworzona przez G. Cantora w latach 1874-1895. Can-
tor przede wszystkim skupił się na zbiorach o nieskończonej liczności. Termin
„funkcja" jest związany z nazwiskiem G. W. Leibnitza, który pierwszy użył go
w związku z pewnymi typami wzorów matematycznych. Teoria grafów po-
wstała w 1736 r., kiedy L. Euler dowiódł, że nie da się przejść każdego z sied-
miu mostów Królewca dokładnie jednokrotnie i wrócić do punktu wyjścia.
Użytecznym kompendium wielu definicji i zastosowań teorii grafów jest książ­
ka napisana przez Harary'ego [94].
Rozdział 6

Zliczanie
i prawdopodobieństwo

Rozdział ten jest przeglądem


podstawowych wiadomości z kombinatoryki i ra-
chunku prawdopodobieństwa. Jeśli jesteś zaznajomiony z tymi zagadnieniami,
to możesz pominąć początek rozdziału i skoncentrować się na dalsuj jego
części.Do zrozumienia materiału zawartego w większości rozdziałów nie jest
wymagana znajomość teorii rachunku prawdopodobieństwa, lecz w niektórych
miejscach jest ona bardzo ważna.
W podrozdziale 6.1 podamy elementarne wnioski z teorii zlicrania, włącza­
jąc standardowe wzory na zliC'lanie permutacji i kombinacji. Aksjomaty teorii
prawdopodobieństwa i podstawowe fakty związane z rozkładem prawdopodo-
bieństwa zaprezentujemy w pod.rozdz. 6.2, a zmienne losowe wraz z własno­
ściami wartości oczekiwanej i wariancji wprowadzimy w podrozdz. 6.3. Z kolei
w pod.rozdz. 6.4 zajmiemy się badaniem geometrycznych i dwumianowych roz-
kładów powstających z badania prób Bernoulliego. Studia rozkładu dwumia-
nowego będziemy kontynuować w pod.rozdz. 6.5, prowadząc zaawansowane
rozważania nad „krańcami" rozkładu. Na zakończenie w podroroz. 6.6 zilust-
rujemy analizę probabilistycmą, omawiając trzy przykłady: paradoks dnia
urodzin, losowe wrzucanie kul do urn oraz okresy dobrej passy.

6.1. Zliczanie
Teoria zliczania stara się odpowiedzieć na pytanie „Ile?" - bez faktycznego
zliczania. Możemy na przykład zapytać „Ile jest różnych liczb n-bitowych?"
lub „Ile jest podziałów na klasy n różnych elementów?". W tym podrozdziale
omawiamy elementy teorii zliczania. Zakładamy, że czytelnik. zna podstawowe
zagadnienia teorii zbiorów - jeśli nie, to powinien uprzednio zapoznać się
z materiałem zawartym w podrozdz. 5.1.

126
6.1. ZLICZANIE

Prawa sumy i iloczynu


Zbiór elementów, które chcemy policzyć, może być czasami wyrażony jako
suma zbiorów rozłącznych lub jako iloczyn (produkt) kartezjański.
Prawo sumy mówi, że liczba możliwości, na jakie możemy wybrać element
należący do jednego z dwóch zbiorów rozłącznych, jest równa sumie mocy tych
zbiorów. To znaczy, że jeśli A i B są zbiorami skończonymi nie mającymi
wspólnych elementów, to jA u BI= !Al+ IBJ, co wynik.a z równiania 5.3. Dla
przykładu, każdy znak na tablicy rejestracyjnej samochodu jest cyfrą lub literą.
Liczba możliwości dla każdej pozycji jest więc równa 26 + I O = 36, ponieważ
jest 26 możliwości, jeśli jest to litera, i 10 możliwości, jeśli jest to cyfra.
Prawo iloczynu mówi, że liczba możliwości, na jakie możemy wybrać upo-
rządkowaną parę elementów, jest równa liczbie możliwości, na jakie możemy
wybrać pierwszy element, pomnożonej przez liczbę możliwości, na jakie może­
my wybrać drugi element. Czyli, jeśli A i B są zbiorami skończonymi, to
JAx BI= IAI·IBI,co jest po prostu równością (5.4). Dla przykladu,jeśli cukier-
nia oferuje 28 smaków lodów i 4 rodzaje bakalii, to liczba możliwych zestawów
złożonych z jednej gałki lodów i jednej porcji bakalii wynosi 28 · 4 = 112.

Słowa

Słowo nad zbiorem skończonym (alfabetem) Sjest to ciąg elementów zbioru S.


Dla przykładu, istnieje 8 słów binarnych długości 3:
OOO,001, 010, Oli, 100, 101, 110, Ili
Czasami słowo długości k nazywamy k-slowem. Podslowo s' słowa s jest to
uporządkowany ciąg następujących po sobie elementów słowa s. Każde k-pod-
slowo słowa jest podslowem długości k. Na przykład 010 jest 3-podsłowem
słowa 01101001 (3-podslowo zaczynające się na pozycji 4), ale 111 nie jest
podsłowem 01101001.
Każde k-slowo nad zbiorem S może być traktowane jak.o element iloczynu
kartezjańskiego ~; w takim razie istnieje !S)t słów długości k. Dla przykładu,
liczba binarnych k-słów wynosi 2". Intuicyjnie, aby skonstruować k-słowo nad
n-zbiorem, mamy n sposobów na wybranie pierwszego elementu; dla każdego
z tych wyborów mamy n możliwości na wybranie drugiego elementu itd. kra-
zy. Konstrukcja ta prowadzi do k-krotnego iloczynu n· n ... n = nt, który jest
liczbą k-slów.

Permutacje
Pennutacją zbioru skończonego S nazywamy uporządkowany ciąg wszystkich
elementów zbioru S, przy czym każdy element występuje dokładnie raz. Jeśli
na przykład S = {a, b, c}, to mamy 6 permutacji zbioru S:

127
ROZDZIAŁ 6. ZLICZANIE I PRAWDOPODOBIEŃSTWO

abc, acb, bac, bca, cab, cba

Liczba permutacji zbioru n-elementowego wynosi n!, ponieważ pierwszy ele-


ment możemy wybrać na n sposobów, drugi na n - I sposobów, trzeci na
n - 2 sposoby itd.
Uporządkowany ciąg k elementów zbioru S, w którym zaden element nie
występuje więcej niż jeden raz, nazywamy k-permutacją zbioru S. (Czyli zwy-
czajna permutacja jest n-permutacją zbioru n-elementowego). Dwanaście
2-permutacji zbioru {a, b, c, d} to:

ab, ac, ad, ba, be, bd, ca, cb, cd, da, db, de

Liczba k-permutacji zbioru n-elementowego wynosi

n!
n(n - l)(n - 2) ...(n - k + 1) - (n_ k)! (6.1)

jako że istnieje n sposobów wyboru pierwszego elementu, n - 1 sposobów wy-


boru drugi.ego elementu itd., aż wybierzemy wszystkich k elementów, przy
czym ostatni będzie wybierany spośród n - k + l elementów.

Kombinacje
k-kombinacją zbioru n-elementowego S nazywamy po prostu k-elementowy
podzbiór zbioru S. Istnieje sześć 2-kombinacji zbioru 4-elementowego {a, b,
c, d}:
ab, ac, ad, be, bd, cd
(Używamy tutaj skrótu, zapisując
zbiór 2-elementowy {a, b} jako ab). Możemy
skonstruować k-kombinację zbioru n-elementowego, wybierając k różnych ele-
mentów z tego zbioru.
Liczba k-kombinacji zbioru n-elementowego może być wyrażona przez
liczbę k-permutacji tego zbioru. Dla każdej k-kombinacji istnieje dokładnie kl
permutacji jej elementów, gdzie każda z nieb jest inną k-permutacją zbioru
n-elementowego. Stąd liczba k-kombinacji zbioru n-elementowego jest równa
liczbie k-permutacji podzielonej przez k!; z równości (6.1) liczba ta wynosi

n!
(6.2)
k!(n - k)!

Dla k = Oze wzoru tego wynika, że możliwości wyboru Oelementów ze zbioru


n-elementowego jest 1 (nie O},bo O!= 1.

128
6.1. ZLICZANIE

Współczynniki dwumienne

Używamy zapisu(:) (czytaj „n nad k") do oznaczania liczby k-kombinacji


zbioru n-elementowego. Z równości (6.2) mamy

") n! (6.3)
( k - k!(n - k)!

Wzór ten jest symetryczny dla k i n - k:

(6.4)

Liczby te są także nazywane współczynnikami dwumiennymiQub dwumianowy-


mi), z powodu ich pojawienia się w rozwinięciu dwumianu:

(x + y)" = f (")x'y"-•
k"'Ok
(6.5)

Przypadek szczególny rozwinięcia dwumianu występuje, gdy x = y = 1:

2"=±(")
k"'O k
(6.6)

Wzór ten odpowiada zliczaniu 2n binarnych n-słów poprzez liczbę jedynek,


które one zawierają: jest (;) binarnych n-słów zawierających dokładnie k je-
dynek, jako że istnieje (;) sposobów wybrania k z n pozycji, na których
można umieścić jedynki.
Istnieje .wiele tożsamości związanych ze współczynnikami dwumiennymi.
2.adania zamieszczone na końcu tego podrozdziału dadzą czytelnikowi moż­
liwość udowodnienia kilku z nich.

Szacowanie współczynników dwumiennych


Czasami potrzebujemy oszacować wartość współczynnika dwumiennego. Dla
1 ~ k ~ n mamy dolne ograniczenie

") = n(n - l) ... (n ::-k+ l)


(k k(k-l) ... l

129
ROZDZIAŁ 6. ZLICZANIE I PRAWD0P0D0BIEl'.ISTW0

=(-")("-!)
k k-l ...(n-k+l) l

~(k")' (6.7)

Korzystając z nierówności k! ~ (k/e)1 wyprowadzonej ze wzoru Stirlinga


(2.12), otrzymujemy górne ograniczenie

n'
" k!
-.0.:
-- (6.8)

(6.9)

Dla każdych O~ k ~ n możemy skorzystać z indukcji (patrz zad. 6.1-12), aby


udowodnić ograniczenie

") n" (6.10)


( k "7,!'<n=k>""'
gdzie dla wygody przyjmujemy, że0° = 1. Dla k = hi, gdzie O~ l :E;1, ograni-
czenie to możemy zapisać jako

(6.11)

= 2nH(l) (6.12)

gdzie

H(l) = -llgl - (I - l)lg(l - l) (6.13)

jest (binarną) funkcją


entropii i gdzie, dla wygody, przyjmujemy, że Olg O = O,
zatem H(O) = H(l) = O.

130
6.1. ZLICZANIE

ZADANIA

6.1-1. Ile k-podsłów zawiera n-słowo? (Przyjmując identyczne k-podsłowa


zaczynające się na różnych pozycjach za różne). Ile pod.słów zawiera
w ogóle n-słowo?
6.1-2. Ftmkcja logiczna o n wejściach im wyjściach to funkcja ze zbioru {PRAW-
DA, FAŁSZ}" w zbiór {PRAWDA, FALSZ}m. Ile jest funkcji logicmych o n wej-
ściach i I wyjściu? Ile jest funkcji logicznych o n wejściach i m wyjściach?
6.1-3. Na ile sposobów można posadzić n osób przy okrągłym stole? Uznaje-
my dwa ustawienia za takie same, jeśli jedno powstaje z drugiego przez
obrót wokół stołu.
6.1-4. Na ile sposobów można wybrać trzy różne liczby ze zbioru {I, 2, ...,
100}, aby ich suma była parzysta?
6.1..S. Udowodnij tożsamość

(")--"-("-!)
k k k- I (6.14)

dlaO<k~n.
6.1-6. Udowodnij tożsamość

( ")-
k
n
n-k
(•-1) k
dlaO~k<n.
6.1-7. Aby wybrać k prreilmiotów z n, można jeden z nich wyróżnić i spraw-
dzić, czy ten wyróżniony przedmiot został wybrany. Użyj tej wskazówki
do udowodnienia, że

6.1-8. Korzystając z rozwiązania zad. 6,1-7, utwórz tabelę współczynników

dwumianu(;)dla n= O, 1, ..., 6i O~ k ~ nz( ~ )na górze, (~)i(~)


w następnym wierszu itd. Tabela taka nosi nazwę trójkąta Pascala,
6.1-9. Udowodnij, że

f;-(•+l)
l"-1 2

6.1-10. Pokaż, że dla dowolnych n~ O i O~ k ~ n maksymalna wartość (;)


jest osiągana dla k - Ln/2Jlub k - 1n/2l.

131
ROZDZIAŁ 6. ZLICZANIEI PRAWDOPODOBIEŃSTWO

*6.1-11. Udowodnij, że dla każdego n~ O,j~ O,k ~ O ij+ k :s;,;n

(6.15)

Podaj zarówno dowód algebraiczny, jak i argumentację opartą na meto-


dzie wybierania j + k przedmiotów spośród n. Podaj przykład, w którym
nie ma równości.
* 6.1-12. Użyj indukcji względem k :s;,;n/2, aby udowodnić nierówność (6.10),
a następnie użyj równości (6.4), aby rozszerzyć to na wszystkie k :s;,;n.
* 6.1-13. Użyj 'WZOruStirlinga, aby udowodnić, że
2 2
•)-
( n
'" (I + 0(1/n)) (6.16)
Jnn
* 6.1-14. Różniczkując funkcję entropii H(J..),pokaż, że osiąga ona maksimum
dla .l - 1/2. Ile wynosi H(l/2)?

6.2. Prawdopodobieństwo

Teoria prawdopodobieństwa jest zasadniczym narzędziem służącym do two-


rzenia i analizy algorytmów probabilistycznych. W podrozdziale tym wprowa-
dzamy podstawy tej teorii.
Prawdopodobieństwo definiujemy w odniesieniu do przestrzenizdarzeń S,
będącej zbiorem, którego elementy nazywamy zdarzeniami elementarnymi.Ka-
żde zdarzenie elementarne może być traktowane jako możliwy wynik ekspery-
mentu. W eksperymencie polegającym na rzucie dwiema rozróżnialnymi mone-
tami na przestrzeń zdarzeń możemy patrzeć jako na złożoną ze zbioru wszyst-
kich możliwych 2-slów nad zbiorem {o, R}:
S - {oo, OR, RO, RR)
Zdarzeniejest podzbiorem 1> przestrzeni zdarzeń S. Na przykład przy rzu-
cie dwiema monetami zdarzenie uzyskania jednego orła i jednej reszki to {OR,

l) W ogólnym rozkładzie prawdopodobieństwa mogą znajdować się podzbiory przestrzeni


zdarzeń S, które nie są uważane za zdarzenia. Sytuacja la występuje zwykle, gdy przestrzeń zda·
rzeń jest nieprzeliczalna. Głównym wymogiem jest, aby zbiór elementów przestneni zdarzeń był
zamknięty ze względu na operacje brania dopełnienia zdarzenia, tworząc zbiór skończonej lub
przeliczalnej liczby zdarzeń, oraz przecinanie skończonej lub przeliczalnej liczby zdarzeń. Więk­
szość rozkładów prawdopodobieństwa, którymi będziemy się zajmować, jest nad skończoną. lub
przelicz.alną przestrzenią zdarzeń i będziemy ogólnie przyjmować, że wszystkie podzbiory prze-
strzeni zdarzeń są zdarzeniami. Ważnym wyjątkiem jest ciągły rozkład jednostajny prawdopcxlo-
bień.stwa, który zostanie przedstawiony poniżej.

132
6.2. PRAWDOPODOBIEI\ISTWO

RO}. Zdarzenie Sjest nazywane zdarzeniem pewnym, a zdarzenie 0 jest nazy-


wane zdaneniem niemożliwym. Mówimy, że dwa zdarzenia A i B są wzajemnie
się wykluczające (rozłączne), jeśli A n B = 0. Czasami zdarzenie elementarne
se S traktujemy jako zdarzenie {s}. Z definicji, wszystkie zdarzenia elementar-
ne wzajemnie się wykluczają.

Aksjomaty teorii prawdopodobieństwa

Rozkład prawdopodobieństwa Pr{}t na przestrzeni zdarzeń Sjest to przypo-


rządkowanie zdarzeniom z S liczb rzeczywistych tak, że spełnione są następują­
ce aksjomaty prawdopodobieństwa:

1. Pr{A} ~ O dla każdego zdarzenia A.


2. Pr{S}=l.
3. Pr{A u B} = Pr{A) + Pr{B} dla każdych dwóch wmjemnie wykluczających
się zdarzeń A i B. Ogólniej, dla każdej (skończonej lub przeliczalnej) sek-
wencji zdarzeń A 1 , A 2 , ••• parami się wykluczających

Pr{A} nazywamy prawdopodobieństwem zdarzenia A. Zwracamy tutaj uwagę,


iż aksjomat 2 jest wymaganiem normalizacji: w rzeczywistości nie ma podstaw,
aby wybrać I jako prawdopodobieństwo zdarzenia pewnego, poza tym, że jest
to naturalne i wygodne.
Z tych aksjomatów i podstawowej teorii zbiorów (patrz podrozdz. 5.1)
wynika natychmiast kilka wniosków. Prawdopodobieństwo zdarzenia niemożli­
wego 0 wynosi Pr{0} =O.Jeśli Ac B, to prawdopodobieństwo Pr{A}.::::;;;Pr{B}.
Stosując zapis A. do oznaczenia zdarzenia S - A (dopełnienie zdarzenia A),
mamy Pr{A} = 1 - Pr{A}. Dla dowolnych dwóch zdarzeń A i B zachodzi

Pr{Au B} = Pr{A} + Pr{B}- Pr{An B) (6.17)

s; Pr{A) + Pr{B) (6.18)

Przypuśćmy, że w naszym przykładzie rzucania monetami każde z czterech


zdarzeń elementarnych ma prawdopodobieństwo 1/4. Wówczas prawdopodo-
bieństwo otrzymania co najmniej jednego orła wynosi

Pr{oo, OR,RO}= Pr{oo} + Pr{OR}+ Pr{Ro}


= 3/4
t Zostały przyjęte oznaczenia stosowane w oryginalnym wydaniu książki (przyp. red.).

133
ROZDZIAŁ 6. ZLICZANIE I PRAWDOPODOBIENSTWO

Alternatywnie, skoro prawdopodobieństwo otrzymania mniej niż jednego orła


wynosi Pr{RR} = 1/4, to prawdopodobieństwo otrzymania co najmniej jedne-
go orła wynosi 1 - 1/4 = 3/4.

Dyskretny rozkład prawdopodobieństwa


Rozkład prawdopodobieństwa jest dyskretny, jeśli jest zdefiniowany nad skoń­
czoną lub przeliczalną przestrzenią zdarzeń. Niech S będzie przestrzenią zda-
rzeń. Wówczas dla każdego zdarzenia A zachodzi

Pr{A}- I,,, Pr{s)


jako że zdarzenia elementarne, a w szczególności te w A, wzajmnie się wy-
kluczają. Jeśli przestrzeń S jest skończona i prawdopodobieństwo każdego
zdarzenia elementarnego se S wynosi

Pr{.,}- 1/ISJ

to wtedy mamy jednostajny rozkład prawdopodobieństwa na S. W tak.ich wypad-


kach eksperyment jest często opisywany jako „wybieranie elementu S losowo".
J ak:o przykład weźmy rzut mooetą symetryczną, w którym prawdopodo-
bieństwo uzyskania orła jest takie samo jak prawdopodobieństwo uzyskania
reszki, czyli 1/2. Jeśli rzucimy monetą n razy, to otrzymamy jednostajny roz-
kład prawdopodobieństwa zdefiniowany na przestrzeni zdarzeń S = {o, R}n
- zbiorze mocy 2n.Każde zdarzenie elementarne w S może być reprezentowane
jako słowo długości n nad zbiorem {o, R} i każde występuje z prawdopodo-
bieństwem I /2n.Zdarzenie

A= {wypadło dokładnie k orłów i dokładnie n - k reszek}

jest podzbiorem S wielkości IAI= (; ), jako że istnieje ( ~) słów długości


n nad {o, R}, które zawierają dokładnie k orłów. Prawdopodobieństwo zdarze-
nia A wynosi więc Pr{ A} = ( ~ )12n.

Ciągły rozkład jednostajny

Ciągły rozkład jednostajny jest przykładem rozkładu prawdopodobieństwa,


w którym nie wszystkie podzbiory przestrzeni zdarzeń są uważane za zdarze-
nia. Ciągły rozkład jednostajny jest zdefiniowany nad przedziałem domknię­
tym [a, b] liczb rzeC'lywistych, gdzie a < b. Intuicyjnie, chcielibyśmy, aby każdy

134
6.2. PRAWDOPODOBIEŃSTWO

punkt z pnedziału [a, b] był ,jednakowo prawdopodobny". Mamy tu nieprze-


liczalną liczbę punktów, więc jeśli przyporządkujemy każdemu punktowi to
samo skończone, dodatnie prawdopodobieństwo, nie możemy jednocześnie
spełnić aksjomatów 2 i 3. Z tego powodu chcielibyśmy przyporządkować pra-
wdopodobieństwo jedynie niektórym podzbiorom S w taki sposób, aby spełnić
aksjomaty dla tych zdarzeń.
Dla dowolnego przedziału domkniętego [c, dj, gdzie a~ c ~ d ~ b, ciągły
rozkład jednostajny prawdopodobieństwa definiuje prawdopodobieństwo zda-
rzenia [c, dJwzorem

d-c
Pr{[c, d]} - · --
b- a

Zwróćmy uwagę, że dla dowolnego punktu x = [x, x] prawdopodobieństwo


x wynosi O. Jeśli usuniemy końcowe punkty przedziału [c, d], to otrzymamy
przedział otwarty (c, d). Ponieważ [c, d] = [c, c] u (c, d) u [d, d], na podstawie
aksjomatu 3 możemy zapisać Pr{[c, d]} = Pr{(c, d)}. Ogólnie, zbiorem 7.darzeń
dla ciągłego rozkładu jednostajnego jest dowolny podzbiór [a, b], który może
być otrzymany jako skończona lub przelicz.alna suma przedziałów otwartych
i domkniętych.

Prawdopodobieństwo warunkowe i niezależność


Czasami dysponujemy już pewną wiedzą na temat wyniku danego doświadcze­
nia. Przypuśćmy na przykład, że kolega rzucił dwiema monetami i powiedział
nam, że co najmniej jedna z monet upadła orłem do góry. Jakie jest prawdopo-
dobieństwo, że na obu monetach wypadł orzeł? Informacja, którą otrzymali-
śmy, eliminuje możliwość pojawienia się dwóch reszek. Trzy pozostałe zdarze-
nia elementarne są jednakowo prawdopodobne, skąd wnioskujemy, że każde
występuje z prawdopodobieństwem 1/3. Ponieważ tylko w jednym ze zdarzeń
elementarnych wypadają dwa orły, odpowiedź na nasze pytanie brzmi 1/3.
Prawdopodobieństwo waninkowe określa w formalny sposób pojęcie po-
siadania a priori częściowej wiedzy na temat wyniku eksperymentu. Prawdopo-
dobieństwo warunkowe zdarzenia A danego tak, że jednocześnie zachodzi inne
zdarzenie B, jest zdefiniowane następująco:

Pr{AIB} - Pr{A n B) (6.19)


Pr{B}

kiedy Pr{B} "'O. (Zapis „Pr {AIB}" czytamy jako „prawdopodobieństwo


A pod warunkiem B"). Intuicyjnie, ponieważ wiemy, że B zachodzi, więc zda-
rzenie, Ze A również zachodzi, to A n B. Oznacza to, że A n B jest zbiorem

135
ROZDZIAŁ 6. ZLICZANIE I PRAWDOPODOBIErilSTWO

tak.ich wyników, że zachodzi zarówno A, jak i B. Skoro wynik jest jednym ze


zdarzeń elementarnych w B, normalizujemy prawdopodobieństwa wszystkich
zdarzeń elementarnych w B, dzieląc je przez Pr{B}, żeby ich suma wynosiła 1.
Prawdopodobieństwo warunkowe A pod wan1nkiem B jest zatem stosunkiem
prawdopodobieństwa zdarzenia A n B do prawdopodobieństwa zdarzenia B.
W powyższym przykładzie A jest zdarzeniem, w którym na obu monetach
wypadł orzeł, a B jest zdarzeniem, w którym co najmniej na jednej monecie
wypadł orzeł. Zatem Pr{AIB)= (1/4)/(3/4)= 1/3.
Dwa zdarzenia są niezależne, jeśli

Pr{An B) = Pr{A) Pr{B}

co jest równoważne, jeśli Pr{B} #::O, warunkowi

Pr{AIB}= Pr{A)

Przypuśćmy na przykład, że zostały rzucone dwie monety i wyniki rzutów są


niezależne. Wówczas prawdopodobieństwo pojawienia się dwóch orłów wy-
nosi (1/2)(1/2) = 1/4. Teraz przypuśćmy, że jedno zdarzenie polega na tym, że
pierwsza moneta upadła orłem do góry, a drugie na tym, że monety upadły
różnie. Każde z tych zdarzeń występuje z prawdopodobieństwem 1/2, a praw-
dopodobieństwo, że wystąpią oba zdarzenia, wynosi 1/4; zatem, na mocy defi-
nicji niezależności, zdarzenia te są niezależne - chociaż mogłoby się wydawać,
że oba zdarzenia zależą od wyniku dla pierwszej monety. Przypuśćmy wreszcie,
że monety są sklejone tak, że upadają obie orłem lub reszką do góry i że
obydwie te możliwości są jednakowo prawdopodobne. Wówczas prawdopodo-
bieństwo, że każda z monet upadnie orłem do góry wynosi 1/2, ale prawdopo-
dobieństwo, że obydwie upadną orłem do góry wynosi 1/2 #::(1/2)(1/2).Zatem
zdarzenie, że pierwsza moneta upadnie orłem do góry, i zdarzenie, że druga
moneta upadnie orłem do góry, nie są niezależne.
Zdarzenia należące do rodziny zdarzeń A 1 , A 2 , ... , A„ są parami nieza-
leżne, jeśli

Pr{A,n A 1) = Pr{A,}Pr{A;)
i <j:;;;,;n. Mówimy,
dla wszystkich 1 :;;;;: że zdarzenia te są (wzajemnie) niezależ­
ne, jeśli każdy k-podzbiór A;,, A 1,, ••• , A;,. rodziny, k:;;;,;n
gdzie 2 :;;;;:
i 1 < i 2 < ... < ik:;;;,;n, spełnia zależność
i l :;;;;:

Pr{A;,n A,, n ... n A,,)= Pr{A,,}Pr{A,,}... Pr{A4 )

Przypuśćmy na przykład, że rzucamy dwiema monetami. Niech A 1 będzie zda-


rzeniem polegającym na tym, że na pierwszej monecie wypadł orzeł, niech A 2

136
6.2. PRAWDOPODOBIENSTWO

będzie zdarzeniem polegającym na tym, że na drugiej monecie wypadł orzeł,


i niech A 3 będzie zdarzeniem polegającym na tym, że na każdej z monet wy-
padło co innego. Mamy

Pr{A1 } = 1/2
Pr{A,} = 1/2
Pr{A3 } = 1/2
Pr{A1 n A,}= 1/4
Pr{A1 n A3 } = 1/4
Pr{A,nA 3 } = l/4
Pr{A1 nA,nA 3 } =0

Ponieważ dla 1 :;;;; i <j ~ 3, mamy Pr{A 1 nA 1} = Pr{A 1}Pr{A1} = 1/4, zdarze-
nia A 1 , A 2 i A 3 są parami niezależne. Zdarzenia te jednakże nie są wzajemnie
niezależne, gdyż Pr{A1 n A, r, A,} = Oi Pr{A1 }Pr{A,}Pr{A 3
} = 1/8 ," O.

Twierdzenie Bayesa
Z definicji prawdopodobieństwa warunkowego (6.19) wynika, iż dla dwóch
zdarzeń A i B, każde o niezerowym prawdopodobieństwie, za.chodzi

Pr{A n B} = Pr{B}Pr{AIB} (6.20)


= Pr{A}Pr{BIA}
Rozwiązując to równanie ze względu na Pr{AIB}, otrzymujemy

Pr{AIB}= Pr{A}l'r{BIA}
(6.21)
Pr{B}

który to wzór jest znany jako wzór Bayesa. Mianownik Pr{B} jest stałą nor-
malizującą, którą inaczej można zapisać w następujący sposób. Ponieważ
B = (B n A) u (B n A) i B n A i B n A" są zdarzeniami wzajemnie się wyklu-
czającymi, więc

Pr{B}= Pr{BnA} + Pr{BnA}


+ Pr{A}Pr{B!A}
= Pr{A}Pr{BIA}
Podstawiając to do równości (6.21), uzyskujemy równoważną postać wzoru
Bayesa:

Pr{A}Pr{BIA}
T
Pr{AIB}= Pr{A}Pr{BIA}+ Pr{~A',c}P~,{=BIA

137
ROZDZIAŁ 6. ZLICZANIEł PRAWDOPOOOBIElilSTWO

WWr Bayesa może uprościć obliczanie prawdopodobieństw warunko-


wych. Przypuśćmy na przykład, że mamy monetę symetryczną i monetę fał­
szywą, która zawsze upada orłem do góry. Nasze doświadczenie składa się
z trzech niezależnych zdarzeń: jedną z dwóch monet wybieramy losowo, rzuca-
my raz tą monetą, a następnie rzucamy ponownie. Przypuśćmy, że na wybra-
nej monecie wypadł orzeł przy obydwu próbach. Jakie jest prawdopodobień­
stwo, że jest to ta fałszywa?
Rozwiążemy ten problem, posługując się wzorem Bayesa. Niech A będzie
zdarzeniem polegającym na tym, że została wybrana moneta fałszywa, i niech
B będzie zdarzeniem polegającym na tym, że moneta upadnie dwukrotnie or-
łem do góry. Chcemy znaleźć Pr{AIB}. Mamy Pr{A} = 1/2, Pr{BIA} = 1,
Pr{A} = 1/2 i Pr{BIA) = 1/4; tak więc
(1/2)· l
Pr{A IBJ= (1/2)·1 +(l/2)·(1/4)

=4/5

ZADANIA
6.2-1. Udowodnij nierówność Boole'a: dla każdej skończonej lub przeliczalnej
rodziny zdarzeń A 1 , A 2 , ••• zachodzi

Pr{A 1 v A, v ...).; Pr{A 1 } + Pr{A,} + ... (6.22)

6.2-2. Profesor Rosencrantz rzuca jedną monetą. Profesor Guildenstern rzuca


dwiema monetami. Jakie jest prawdopodobieństwo, że profesor Rosen-
crantz wyrzuci więcej orłów niż profesor Guildenstern?
6.2-3. Mamy 10 kart, każda z innym numerem od 1 do 10. Dokładnie tasuje-
my karty, po czym wyciągamy trzy (po kolei). Jalriejest prawdopodobień­
stwo, że te trzy karty będą miały coraz większe numery?
* 6.2-4. Mamy fałszywą monetę, która po rzuceniu upadła orłem do góry z (nie-
znanym) prawdopodobieństwem p, gdzie O <p < 1. Pokaż, w jaki sposób
rzut monetą symetryczną może być zasymulowany przez wielokrotny rzut
monetą fałszywą. (Wskazówka: Rzuć monetą dwukrotnie, a następnie
uznaj to za wynik symulowanego rzutu monetą symetryczną lub powtórz
eksperyment). Udowodnij, że odpowiedź jest poprawna.
* 6.2-S. Opisz procedurę, której danymi wejściowymi są dwie liczby całkowite
a i b takie, że O < a < b, a wynikiem może być orzeł z prawdopodobień­
stwem ajb i reszka z prawdopodobieństwem (b - a)/b. Podaj ograniczenie
oczekiwanej liczby rzutów monetą, które powinno być wielomianem ze
względu na 1gb.
6.2-6. Udowodnij, że

138
6.3. DYSKRETNEZMIENNE LOSOWE

Pr{AIB}+ Pr{A IBJ = I

6.:Z..7. Udowodnij, że dla dowolnej rodziny zdarzeń A 1, A 2 , ... , A„ zachodzi

Pr{A, r, A, r, ... r, A,) = Pr{A,}· Pr{A,IA,}· Pr{A,IA, c,A 2 } •••


Pr{A„IA1 n A 2 n ... n A"_ 1}

6.2-8. Pokaż, jak skonstruować zbiór n Marzeń, które są parami niezależne,


ale takie, że dowolny podzbiór k > 2 z nich nie jest wzajemnie niezależny.
6.:Z..9. Dwa Marzenia A i B są warunkowo niezależne od C, jeśli

Pr{Ar, BIC) = Pr{AIC}· Pr{BIC}

Podaj prosty, ale nie trywialny przykład dwóch zdarzeń, które nie są nieza-
leżne, ale są warunkowo niezależne od trzeciego zdarzenia.
* 6.:Z..10. Uczestniczysz w teleturnieju, w którym nagroda jest ukryta za jedną
z trzech zasłon. Otrzymasz nagrodę, jeśli wskażesz dobrą zasłonę. Po wy-
braniu przez Ciebie jednej z zasłon, ale przed jej podniesieniem, prowadzą­
cy podnosi jedną z pozostałych zasłon, odkrywając puste miejsce, i pyta,
czy chcesz zmienić swój wybór na pozostałą zasłonę. Jak zmienią się Twoje
szanse wygrania, jeśli 7.decydujesz się na zmianę?
* 6.:Z..11. Strażnik więzienny losowo wybrał spośród trzech więźniów jednego,
który wyjdzie na wolność. Dwóch pozostałych zostanie ściętych. Strażnik
wie, który z więźniów wyjdzie na wolność, lecz nie wolno mu udzielać
więźniom. informacji. Nazwijmy więźniów X, Y i Z. Więzień X pyta na
osobności strażnika, który z więźniów Y i Z będzie ścięty, argumentując,
że skoro i tak wie, że co najmniej jeden z nich zginie, strażnik nie poda mu
żadnej informacji o jego sytuacji. Strażnik powiedział X, że Y zostanie
ścięty. Więzień X czuje się teraz spokojniejszy, bo wie, że albo on, albo
więzień Z zostanie uwolniony, co oznacza, że prawdopodobieństwo wyj-
ścia wynosi teraz 1/2. Czy ma rację, czy też jego szanse nadal wynoszą 1/3?
Odpowiedź uzasadnij.

6.3. Dyskretnezmiennelosowe
Zmienna losowa (dyskretna) X jest funkcją ze skończonej lub przeliczalnej prze-
strzeni zdarzeń S w zbiór liczb rzeczywistych. Przyporządkowuje ona liczbę
rzeczywistą każdemu możliwemu wynikowi doświadczenia, co pozwala nam
operować indukowanym rozkładem prawdopodobieństwa na zbiorze liczb.
Dla zmiennej losowej X i liczby rzeczywistej x definiujemy zdarzenie X= x
jako {seS:X(s) = x); zatem

139
ROZDZIAŁ 6. ZLICZANIE I PRAWD0PODOB1Er;JSTWQ

Pr{X = x) = Pr{s}
{io,S:X(i)- x)

Funkcja

/(x) = Pr{X = x)

jest funkcją gęstości prawdopodobieństwa zmiennej losowej X. Z aksjomatów


prawdopodobieństwa mamy Pr{X = x} ~ O i L
Pr{X = x} = 1.

Jako przykład rozważmy rzut dwiema kostkami do gry. W przestrzeni
zdarzeń jest 36 możliwy-eh zdarzeń elementarnych. Przyjmujemy, że prawdopo-
dobieństwo rozkładu jest jednak.owe, więc każde zdarzenie elementarne seS
jest jednakowo prawdopodobne: Pr{s} = 1/36. Zdefiniujmy zmienną losową
X jak.o maksimum dwóch wartości widocznych na kostce. Mamy
Pr{X = 3} = 5/36, bo X przypisuje wartość 3 pięciu z 36-ciu możliwych zda-
rzeń elementarnych, a mianowicie (I, 3), (2, 3), (3, 3), (3, 2) i (3, I).
Często na tej samej przestrzeni zdarzeń definiuje się wiele zmiennych loso-
wych. Jeśli X i Y są zmiennymi losowym.i, to funkcja

f(x, y) = Pr{X =Xi Y = y)


jest funkcją gęstości łącznego prawdopodobieństwa zmiennych X i Y. Dla ustalo-
nej wartości y

Pr{Y=y)=Z:Pr{X=xi Y=y)

i podobnie, dla ustalonej wartości x

Pr{X = x) = 1:Pr{X = x i Y = y)
'
Korzystając z definicji (6.19) prawdopodobieństwa warunkowego, mamy

Pr{X=x i Y=y)
Pr{X=xlY=y)=~~~~~ -
Pr{Y = y)

Definiujemy dwie zmienne losowe X i Y jak.o niezależne, jeśli dla wszystkich


x i y zdarzenia X= x i Y = y są niezależne lub, równoważnie, jeśli dla wszyst-
kich x i y mamy Pr{X= x i Y= y) = Pr{X =x)Pr{Y= y).
Mając dany zbiór zmiennych losowych zdefmiowanych nad tą samą prze-
strzenią zdarzeń, możemy defmiować nowe zmienne losowe jak.o sumy, iloczy-
ny lub inne funkcje zmiennych początkowych.
·------------------------------
140
6.3. DYSKRETNEZMIENNE LOSOWE

Wartość oczekiwana zmiennej losowej

Najprostszą i najbardziej użyteczną charakterystyką rozkładu zmiennej loso-


wej jest „średnia" z wartości, jakie ona przyjmuje. Wartość oczekiwana (śred­
nia) dyskretnej zmiennej losowej X jest określona wzorem

E[XJ = Z:xPr{X= x) (6.23)

co jest dobrze określone, jeśli suma jest skończona lub zbieżna bezwględnie.
Czasami wartość oczekiwana X jest zapisywana jako µx lub, kiedy zmienna
losowa wynika z kontekstu, po prostu jak.o µ.
Wyobraźmy sobie grę, w której rzucamy dwiema monetami. Zarabiamy
3 zł za każdego orła, ale tracimy 2 zł za każdą reszkę. Wartość oczekiwana
zmiennej losowej X reprezentującej nasz zarobek wynosi

E[X] = 6· Pr{2 ORLY}+ I· Pr{! 0RZEL, I RESZKA}- 4· Pr{2 RESZKI}


= 6(1/4) + 1(1/2) - 4(1/4)
=I
Wartość oczekiwana sumy dwóch zmiennych losowych jest równa sumie
ich wartości oczekiwanych, czyli

E[X + YJ = E[X] + E[Y] (6.24)

kiedy tylko określone są


E[X] i E[Y]. Własność ta rozszerza się na skończone
i zbieżne bezwzględnie sumy wartości oczekiwanych.
Jeśli X jest dowolną zmienną losową, to dowolna funkcja g(x) defmiuje
nową zmienną losową g(...\:').
Jeśli wartość oczekiwana g(...\:')
jest określona, to

E[g(X)J = Z:g(x)Pr{X = x)

Niech g(x) = ax, wtedy dla dowolnej stałej a mamy

E[aXJ = aE[XJ (6.25)

Zatem, gdy wartości oczekiwane są liniowe, wtedy dla dowolnych dwóch


zmiennych losowych X i Y oraz dowolnej stałej a zachodzi

E[aX + YJ = aE[XJ + E[Y] (6.26)

Jeślidwie zmienne losowe X i Y są niezależne i każda z nich ma określoną


wartość oczekiwaną, to

141
ROZDZIAŁ 6. ZLICZANIE I PRAWDOPODOBIEŃS1WO

E[XYJ=IZ:xyPr{X=xi Y=y}
.'
= IIxyPr{X = x} Pr{Y = y}
.'

= E[X] E[Y]

Ogólnie, jeśli n zmiennych losowych X 1 , X 2 , ••• , X„ jest wzajemnie niezależ­


nych, to

E[X,X, ... XJ = E[X,J E[X,J ... E[X.J (6.27)

Kiedy zmienna losowa X przyjmuje wartości naturalne N= {O,I, 2, ... }, ist-


nieje dogodny wzór na jej wartość ocz.ekiwaną:


E[XJ = L iPr{X = i}
;"' o

= L i(Pr{X;, i} - Pr{X;, i+!})
i= o


= Z:Pr{X;, i} (6.28)
i= l

jako że każdy element Pr{ X ;;i: i}jest dodany i razy i odjęty i - I razy (oprócz
elementu Pr{X;:i: O}, który jest dodany O razy i nie odjęty w ogóle).

Wariancja i odchylenie standardowe


Wariancja zmiennej losowej X o wartości ocz.ekiwanej E[X] wynosi

Var[X] = E[(X - E[X])']


= E[X' - 2XE[X] + E'[XIl
= E[X'] - 2E[XE[Xll + E'[X]
= E[X'] - 2E 2 [X] + E 2 [X]
= E[X'] - E'[X] (6.29)

Powodem prawdziwości równości E[E 2 (XIl = E 2 [X] i E[X E[XIl = E'[X] jest
to, że E[X] nie jest zmienną losową, a po prostu liczbą rzeczywistą, co oznacza,

142
6.3. DYSKRETNEZMIENNE LOSOWE

że równość (6.25) ma tutaj zastosowanie (z a= E[X]). Równość (6.29) moźna


przekształcić, aby uzyskać wyrażenie podające wartość oczekiwaną kwadratu
zmiennej losowej:

E[X'J = Var[X] + E'[XJ {6.30)


Wariancja zmiennej losowej X i wariancja aX są związane zależnością

Var[aXJ = a'Var[XJ
Jeśli Xi Y są niezależnymi zmiennymi losowymi, to

Var[X + Y] = Var[X] + Var[Y]


W ogólności, jeśli n zmiennych losowych X 1 , X 2 , ••• , X„ jest parami nieza-
leżnych, to

Var[,±, x,J
= ,±, Var[XJ (6.31)

Odchylenie standardowe mtiennej losowej X jest to dodatni pierwiastek


kwadratowy z wariancji X. Odchylenie standardowe zmiennej losowej X jest
czasami zapisywane jako ux lub po prostu u, jeśli zmienna wynika z kontekstu.
Używając tej notacji, wariancję X można zapisać jako a 2 •

ZADANIA

6.3-1. Rzuciliśmy dwiema kostkami do gry. Jaka jest wartość oczekiwana su-
my liczb oczek widocznych na dwóch kostkach? Jaka jest wartość oczeki-
wana większej z liczb oczek widocznych na tych kostkach?
6.3-2. Macierz A[l ..n] zawiera n różnych liczb losowo uporządkowanych
z tym, że każda permutacja n liczb jest jednakowo prawdopodobna. Jaka
jest wartość oczekiwana indeksu największego z elementów macierzy? Jaka
jest wartość oczekiwana indeksu najmniejszego z elementów macierzy?
6.3-3. Gra polega na rzucaniu trzema kostkami. Gracz może postawić 1 zł na
jedną z liczb od t do 6. Zasady wypłacania wygranych po wykonaniu
rzutu są następujące: jeśli liczba obstawiona przez gracza nie pojawiła się
na żadnej z kostek, to traci on swoją złotówkę; jeśli liczba ta pojawiła się
dokładnie na k kostkach, dla k = 1, 2, 3, to zachowuje on swoją złotówkę
i dostaje dodatkowo k złotówek. Jaki jest oczekiwany zysk w jednej grze?
* 6.3-4. Niech X i Y będą niezależnymi zmiennymi losowymi. Udowodnij, że
f(X) i g(Y) są niezależne dla dowolnego wyboru funkcji/i g.
* 6.3-5. Niech X będzie nieujemną zmienną losową i przypuśćmy, że E[X] jest
dobrze określona. Udowodnij nierówność Markowa:

143
ROZDZIAŁ 6. ZLICZANIEI PRAWDOPODOBIEŃSTWO

Pr{X;, t) ,s;E[X)/t (6.32)

dla każdego t > O.


* 6.3-6. Niech S będzie przestrzenią zdarzeń i niech X i X' będą 2'llliennymi
losowymi takimi, że X(s) ~ X'(s) dla każdego se S. Udowodnij, że dla
dowolnej stałej t zachodzi zależność

Pr{X;, t);, Pr{X';, t)

6.3-7. Co jest większe: wartość oczekiwana kwadratu 2'llliennej losowej czy też
kwadrat jej wartości oczekiwanej?
6.3-8. Pokaż, że dla dowolnej zmiennej losowej X, która przyjmuje wyłącznie
wartości O i I, mamy Var[X) - E[X)E[l - X].
6.3-9. Udowodnij, że Yar[aX] = a 2 Yar[x] z defm.icji (6.29) wariancji.

6.4. Rozkłady geometrycznei dwumianowe


Rzut monetą jest przykładem próby Bemoulliego, która jest Wefmiowana jako
doświadczenie mogące zakończyć się jednym z dwóch mozliwych wynik.ów:
sukcesem, który występuje z prawdopodobieństwem p, lub poraiką, która wy-
stępuje z prawdopodobieństwem q = 1 - p. Kiedy mówimy o wielu próbach
Bemoulliego, mamy na myśli, że są one wzajemnie niezależne, i jeśli nie powie-
my wyraźnie, że jest inaczej, to każda z nich występuje z takim samym praw-
dopodobieństwem sukcesu p. Z próbami Bernoulliego są związane dwa ważne
rozkłady: rozkład geometryczny i dwumianowy.

Rozkład geometryczny
Przypuśćmy, że mamy ciąg prób Bemoulliego, każda
z prawdopodobieństwem
sukcesu p i prawdopodobieństwem porażki q = 1 - p. Ile nastąpi prób, zanim
odniesiemy sukces? Niech zmienna losowa X będzie liczbą prób potrzebnych
do osiągnięcia sukcesu. Wówczas X przyjmuje wartości z zakresu {1, 2, ...}
i dla k ~ 1 zachodzi równość

(6.33)

ponieważ mamy k - 1 porażek, zanim odniesiemy sukces. Rozkład prawdopo-


dobieństwa spełniający równanie (6.33) jest nazywany rozkładem geometrycz-
nym. Rysunek 6.1 ilustruje taki rozkład.
Przyjmując p < 1, wartość oczekiwana rozkładu geometrycznego może
być obliczana przy użyciu tożsamości (3.6):

144
6.4. ROZKŁADY GEOMETRYCZNE I DWUMIANOWE

0,35

0,30

0,25

0,20

0,15

0,10

0,05

,....,.,..,,,...,.,.~~ k
l 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Rys. 6.1. Rozkład geometryczny z prawdopodobieństwem sukcesu p = l/3 i prawdopodobieństwem
porażki q = l - p. Wartość oczekiwana rozkładu wynosi 1/p = 3

m
E[XJ - I kq•-•p
I; ea 1

p m
- ql=O
-I ką'

p q
- q. (1 - q)'

- 1/p (6.34)

Potrzeba więc średnio 1/p prób, aby odnieść sukces, czyli wynik intuicyjny.
Wariancja, która może być obliczona podobnie, wynosi

Var[XJ - q/p' (6.35)

Przypuśćmy na przykład, że powtarzamy rzuty dwiema kostkami aż do otrzy-


mania liczby siedem lub jedenaście. Na 36 możliwych wyników 6 daje nam
siódemkę i 2 - jedenastkę. Stąd prawdopodobieństwo sukcesu wynosi

145
ROZDZIAŁ 6. ZLICZANIE I PRAWDOPODOBIErilSTWO

p = 8/36 = 2/9 i musimy średnio rzucić l/p = 9/2 = 4,5 raza, aby otrzymać
w wyniku siedem lub jedenaście.

Rozkład dwumianowy
Ile sukcesów nastąpi podczas n prób Bemoulliego, jeżeli sukces następuje
z prawdopodobieństwem p, a porażka - z prawdopodobieństwem q = 1 - p?
Zdefiniujmy zmienną losową X jako liczbę sukcesów, jak.ie wystąpiły w n pró-
bach. Wówczas X przyjmuje wartości ze zbioru {O,1, ..., n} i dla k = O, ..., n
zachodzi równość

Pr{X-k)-(:)p'q•-• (6.36)

jako że istnieje ( ~) sposobów na wybranie k z n prób kończących się suk-


cesem, a prawdopodobieństwo właśnie
tych k sukcesów wynosi
otrzymania
p 1 q"- 1. Rozkład prawdopodobieństwa spełniający równanie (6.36) jest nazy-
wany rozkładem dwwnianowym.Dla wygody zdefmiujemy rodzinę rozkładów
dwumianowych, używając zapisu

b(k; n, p) -(:)p'(l
- p)•-• (6.37)

Rysunek 6.2 ilustruje rozkład dwumianowy. Nazwa „dwumianowy" wynika


z tego, że wzór (6.37) jest k-tym składnikiem rozwinięcia (p + q'f. Zatem, sko-
ro p + q = 1, to

L" b(k; n, p) - I (6.38)


J:=O

zgodnie z wymogami aksjomatu 2 prawdopodobieństwa.


Możemy obliczyć wartość oczekiwaną zmiennej losowej o rozkładzie dwu-
mianowym, korzystając ze wzorów (6.14) i (6.38). Niech X będzie zmienną
losową o rozkładzie b(k; n, p), i niech q = 1 - p. Z definicji wartości ocze-
kiwanej mamy

E[X] - L" kb(k; n, p)


l"' o

146
6.4. ROZKŁADY GEOMETRYCZNE I DWUMIANOWE

b(k; 15, 1/3)

0,25

0,20

0,15

0,10

0,05

Rys. 6.2. Rozkład dwumianowy b(k, 15, 1/3) pochodzący z n= 15 prób Bemou1liego, każda z praw-
dopodobieństwem sukcesu p = 1/3. Wartość oczekiwana rozkładu wynosi np= 5

= np L • ("-I)
ł:.=1 k-1
P1-1q"-1:.

= np ,-
L'( I)
ł.=O
n-
k
pt.qt11-1)-t.

,-,
-np I b(k; n-1,p)
ł:. =o
=np (6.39)
Korzystając z liniowości wartości oczekiwanej, możemy otrzymać ten sam
rezultat przy użyciu znaczniej mniej skomplikowanych obliczeń. Niech X bę­ 1
dzie zmienną losową oznaczającą liczbę sukcesów w i-tej próbie. Wówczas
E[XJ = p· l + q·O =pi z liniowości wartości oczekiwanej (6.26) oczekiwana
liczba sukcesów dla n prób wynosi


- I l E[XJ
i=

=np

147
ROZDZIAŁ 6. ZLICZANIE I PRAWDOPODOBIEŃSTWO

To samo podejście może byćzastosowane do obliczenia wariancji rozkła·


du. Używając równości (6.29), otrzymujemy Var[XJ = E[Xf] - E 2 [X;]. Ponie-
waż X; przyjmuje wyłącznie wartości O i 1, mamy E[Xf] = E 2 [XJ = p, zatem

Var[XJ - p - p' - pq (6.40)

Aby obliczyć wariancję zmiennej losowej X, skorzystamy z niezależności


n prób; stąd posługując się równaniem (6.31), mamy

Var[X] - Var[,±, x,]

= npq (6.41)

Jak można zobaczyćna rys. 6.2, rozkład dwumianowy b(k; n, p) rośnie,


w miarę jak k przebiega od O do np, a następnie się zmniejsza. Możemy udo·
wodnić, że rozkład ten zawsze zachowuje się w taki sposób, patrząc na stosu-
nek kolejnych prawdopodobieństw:

n!(k-l)!(n-k+ l)!p
- k!(n - k)! n!q

(n - k + l)p
(6.42)

(n+ l)p - k
-l+----------
kq

Stosunek ten jest większy niż 1, gdy (n+ l)p - k jest dodatnie. Zatem
b(k; n, p) > b(k - I; n, p) dla k <(n+ l)p (rozkład rośnie) i b(k;
n, p) < b(k - l; n, p) dla k >(n+ l)p (rozkład maleje). Jeżeli k - (n+ l)p jest

148
6.4. ROZKŁADY GEOMETRYCZNE I DWUMIANOWE

całkowite,to b(k; n, p) = b(k - 1; n, p), a więc rozkład ma dwa maksima: dla


k =(n+ l)p i k - I =(n+ I)p - 1 = np - q. W przeciwnym wypadku osiąga
on maksimum dla dokładnie jednego, całkowitego k, które leży w przedziale
np - q < k < (n + l)p.
Następujący lemat podaje górne ograniczenie rozkładu dwumianowego.

LEMAT 6.1.
Niech n ~ O, niech O < p < l, niech q = 1 - p i niech O ::::;;
k:::;;;n. Wówczas

b(k;n,p),c, (np)'(
-k·
nq
;;:..k
)"-•
DOWÓD
Korzystając ze wzoru (6.10), otrzymujemy

b(k; n, p) ~ (;)p' q"-•


ZADANIA
6.4-1. Sprawdź aksjomat 2 z aksjomatów prawdopodobieństwa dla rozkładu
geometrycznego.
6.4-2. Ile razy musimy średnio rzucić sześcioma monetami; zanim otrzymamy
3 orły i 3 reszki?
6.4-3. Pokaż, że b(k; n, p) ~ b(n - k; n, q), gdzie q ~ 1 - p.
6.4-4. Pokaż, że wartość maksymalna rozkładu dwumianowego b(k; n, p) wy-
t.J
nosi w przybliżeniu 1 2n np q , gdzie q = l - p.
* 6.4-5. Pokaż, że prawdopodobieństwo nieuzyskania sukcesu w n próbach Ber-
noulliego, każda z prawdopodobieństwem p = 1/n, wynosi w przybliżeniu
1/e.Pokaż, że prawdopodobieństwo uzyskania dokładnie jednego sukcesu
jest również w przybliżeniu równe 1/e.
* 6.4-6. Profesor Rosencrantz rzuca monetą n razy i to samo robi profesor Guil-
denstern. Pokaż, że prawdopodobieństwo, iż wyrzucą taką samą liczbę
orłów wynosi ( : 2
(W.vkazówka:Przyjmij, że dla profesora Rosencran-
)/4".
149
ROZDZIAŁ 6. ZLICZANIE I PRAWOOPODOBIENSTWO

tza sukcesem jest wyrzucenie orła, a dla profesora Guildensterna - wy-


rzucenie reszki). Opierając się na swoim dowodzie, wykaż, że

k=O k
- (2")
i: (")' n
* 6.4-7. Pokaż, że dla O~ k ~ n zachodzi zależność

b(_k;n, 1/2) ~ 2nH(t/


..)- ..

gdzie H(x) jest funkcją entropii (6.13).


* 6.4-8. Rozważmy n prób Bernoulliego, gdzie dla i= 1, 2, ... , n prawdopodo-
bieństwo sukcesu w i-tej próbie wynosi p 1 i niech X będzie zmienną losową
oznaczającą całkowitą liczbę sukcesów. Niech p ~ P; dla każdego i= 1,
2, ... , n. Udowodnij, że dla I ~ k ~ n zachodzi zależność

Pr{X < k},;


•-'
L b(i; n, p)
i= o

* 6.4-9. Niech X będzie zmienną losową określającą łączną liczbę sukcesów


w ciągu A n prób Bernoulliego, gdzie prawdopodobieństwo sukcesu w i-tej
próbie wynosi p 1, i niech X' będzie zmienną losową określającą łączną
liczbę sukcesów w ciągu A' n prób Bernoulliego, gdzie prawdopodobień­
stwo sukcesu w i-tej próbie wynosi pi~ P;· Udowodnij, że dla O ~ k ~ n
zachodzi zależność

Pr{X';, k};, Pr{X;, k}


(Wskazówka: Pokaż, jak uzyskać próby Bernoulliego w ciągu A' przez
doświadczenie związane z próbami w ciągu A, i wykorzystaj wynik
zad. 6.3-6).

* 6.5. Krańce rozkładu dwumianowego


Prawdopodobieństwo osiągnięcia co najmniej lub co najwyżej k sukcesów
w n próbach Bernoulliego, każda z prawdopodobieństwem sukcesu p, jest czę­
sto bardziej interesujące niż prawdopodobieństwo osiągnięcia dokładnie k suk-
cesów. W tym podrozdziale badamy krańce rozkładu dwumianowego: dwa
obszary rozkładu b(k; n, p), które są dalekie od średniej np. Udowodnimy kilka
ważnych oszacowań na sumy składników z obu krańców.
Na początku wyprowadzimy ograniczenie dotyczące prawego krańca roz-
kładu b(_k;n, p). Ograniczenia na lewym krańcu mogą być ustalone przez za-
mianę ról sukcesu i porażki.

150
* 6.5. KRAŃCE ROZKŁADU DWUMIANOWEGO
TwIERDZENIE6.2.
Rozważmy ciąg n prób Bemoulliego, gdzie sukces występuje z prawdopodo-
bieństwem p. Niech X będzie zmienną losową oznaczającą całkowitą liczbę
sukcesów. Wówczas dla O~ k ~ n prawdopodobieństwo uzyskania co naj-
mniej k sukcesów wynosi

" b(i; n, p)
Pr{X;, k} = L,
l=ł

DOWÓD
Korzystamy z nierówności (6.15)

Mamy

Pr{X;, k} = L" b(i; n, p)


l=ł

·-·
= L, b(k+
l=O
i; n,p)

,-,
()
= ~ P',I, b(i;n-k,p)
0

ponieważ ·-·
L
l=O
b(i; n - k, p) = 1 z równości (6.38).

151
ROZDZIAŁ 6. ZLICZANIE I PRAWDOP000BtErilSTWO

Następujący wniosek jest odpowiednikiem powyższego twierdzenia dla le-


wego krańca. W ogólności czytelnikowi pozostawiamy adaptację twierdzeń
zachodzących dla jednego z krańców na drugi).

WNIOSEK 6.3.
Rozważmy ciąg n prób Bernoulliego, gdzie sukces występuje
z prawdopodo-
bieństwem p. Jeśli X jest zmienną losową oznaczającą całkowitą liczbę suk-
k:;;;;n prawdopodobieństwo uzyskania co najwyżej k suk-
cesów, to dla O:;;;;:
, .
cesow wynosi

Pr{X,; k} -
•L b(i; n, p)
i=O

,; (
n-k
n )(1-py-•

Nasze kolejne ograniczenie jest związane z lewym krańcem rozkładu dwu-


mianowego. Daleko od wartości średniej, liczba sukcesów na lewym krańcu
zmniejsza się wykładniczo, o czym mówi następujące twierdzenie.

TwIERDZENIE 6.4.
Rozważmy ciąg n prób Bernoulliego, gdzie sukces występuje z prawdopodo-
bieństwem p, a porażka z prawdopodobieństwem q = 1 - p. Niech X będzie
zmienną losową oznaczającą całkowitą liczbę sukcesów. Wówczas dla
O < k < np prawdopodobieństwo uzyskania mniej niż k sukcesów wynosi
,_ I

Pr{X < k} - L b(i; n, p)


i=O

kq
< -······ ····b(k; n, p)
np-k

DOWÓD
,_,
Ograniczamy szereg L b(i; n, p) szeregami geometrycznymi, używając metody
i= o
z podrozdz. 3.2 (str. 70). Dla i= 1, 2, ... , k mamy ze wzoru (6.42)

b(i-1; n, p) iq
·-·-·- ~--
b(i; n, p) (n-i+ l)p

152
* 6.5. KRAŃCE ROZKŁADU DWUMIANOWEGO

<(ni;)({)
"(n:k)(!)
Jeśli przyjmiemy

to stąd wynika, że

b(i- I; n, p) < xb(i; n, p)

dla O < i~ k. Powtarzając to rozumowanie, otrzymujemy

b(i; n, p) < x"-' b(k; n, p)

dlaO~i<k,astąd

i-1 i·-1
I b(i; n, p) < I x"-' b(k; n, p)
i= o i=O

00

< b(k; n, p) I x'


I"' 1

X
- - - b(k; n, p)
1 -X


- b(k; n, p)
np- k

Jeśli k ~ np/2, to mamy kq/(np - k) ~ l, co oznacza, że



b(k; n,p) ograni-
cza sumę wszystkich składników o indeksach mniejszych od k. Dla przykładu
przypuśćmy, że rzucamy n monetami. Przyjmując p = 1/2 i k = n/4, z twier-
dzenia 6.4 wynika, że prawdopodobieństwo otrzymania mniej niż n/4 orłów
jest mniejsze od prawdopodobieństwa otrzymania dokładnie n/4 orłów. Po-
nadto dla dowolnego r ~ 4 prawdopodobieństwo otrzymania mniej niż n/r
orłów jest mniejsze od prawdopodobieństwa otrzymania dokładnie n/r orłów.
Twierdzenie 6.4 może również być całkiem użyteczne w połączeniu z górnymi
ograniczeniami rozkładu dwumianowego, których dotyczył lemat 6.1.

153
ROZDZIAŁ 6. ZLICZANIEI PRAWDOPODOBIE"'STWO

Ograniczenie na prawym krańcu może być znalezione podobnie.

WNIOSEK6.5.
Rozważmy ciąg n prób Bemoulliego, gdzie sukces występuje z prawdopodo-
bieństwem p. Niech X będzie zmienną losową oznaczającą całkowitą liczbę
sukcesów. Wówczas dla np< k < n prawdopodobieństwo uzyskania więcej niż
k sukcesów wynosi

Pr{X> k) - L' b(i; n,p)


l=k+ 1

(n - k)p
< · ·· b(k; n,p)
k-np

W następnym twierdzeniu bierze się pod uwagę n prób Bernoulliego, każ­
dą z prawdopodobieństwem p 1 uzyskania sukcesu, dla i= 1, 2, ... ,n.Jak wy-
nika z zamieszczonego dalej wniosku, możemy użyć tego twierdzenia do wy-
znaczenia ograniczenia na prawy kraniec rozkładu dwumianowego przyjmując
p 1 = p dla wszystkich prób.

TwIERDZENIE 6.6.
Rozważmy ciąg n prób Bernoulliego, gdzie w i-tej próbie, dla i= 1, 2, ... , n,
sukces występuje z prawdopodobieństwemp;, a porażka występuje z prawdopo-
dobieństwem ą 1 = 1 - P;· Niech X będzie 7mienną losową oznaczającą całkowitą
liczbę sukcesów i niech µ = E[X]. Wówczas dla r > µ zachodzi zależność

Pr{X-µ~r} ~ f (µe)'
DOWÓD
Ponieważ dla dowolnego a > O funkcja tfZX jest ściśle rosnąca względem x,
zatem mamy

Pr{X - µ;, r) - Pr{e"'x-,,;, e")


gdzie a będzie ustalona później. Korzystając z nierówności Markowa (6.32),
otrzymujemy

Pr{X - µ;, r),;; E[e"<•-,1,-~ (6.43)

Główny ciężar dowodu polega na ograniczeniu E[e"(X-"1i podstawieniu od-


powiedniej wartości dla or: w nierówności (6.43). Najpierw wyznaczymy

154
* 6.5. KRAŃCE ROZKŁADU DWUMIANOWEGO

Dla i= 1, 2, ... , n niech X 1 będzie zmienną losową, która przyjmuje


E[er:t(X-1'1.
wartość 1 - jeśli wynikiem i-tej próby Bernoulliego jest sukces, i O - jeśli
porażka, Wtedy

"
X= LX;
i= l

I

X-µ= L" (X;-p,)


i= l

Podstawiając za X - µ, otrzymujemy

E[e"''-'1= E[TI,•x,-,JJ
J= 1

" E[e"'x,-
= TI ''J
j =1
co wynika z (6.27), jako że wzajemna niezależność zmiennych losowych X
1
implikuje wzajemną niezależność zmiennych losowych ~x,-pJ (patrz zad. 6.3-
4). Z definicji wartości oczekiwanej mamy

(6.44)
~ exp(p 1ej

gdzie exp(x) oznacza funkcję wykładniczą: exp(x) = C. (Nierówność (6.44) wy-


nika z nierówności a:> O, q ~ 1, e"4 ~ e" i e-a.p =E;;1, a ostatni wiersz wynika
z nierówności (2.7)). Stąd otrzymujemy

"
E[e"''-•1<:;exp TI(p;e")
I= I

= exp(µe")
"
bo µ = L p 1• Dalej, z nierówności (6.43) wynika, że
i= l

Pr{X - µ ~ r} ~ exp(µe" - ar) (6.45)

155
ROZDZIAŁ 6. ZLICZANIE I PRAWDOPODOBIEŃSTWO

Wybierając l'.X = ln(r/µ) (patrz zad. 6.5-6). uzyskujemy

Pr{X - µ;.,, r}::::;;exp(µeln(r/µ)- rln(r/µ))


- exp(r - rln(r/µ))
e'
(r/µ)'


Twierdzenie 6.6 zastosowane do prób Bernoulliego, gdzie każda z prób ma
to samo prawdopodobieństwo zaistnienia sukcesu, daje nam następujący wnio-
sek dotyczący ograniczenia na prawym krańcu rozkładu dwumianowego.

WNIOSEK 6.7.
Rozważmy ciąg n prób Bernoulliego, gdzie w każdej próbie sukces występuje
z prawdopodobieństwem p, a porażka występuje z prawdopodobieństwem
q = 1 - p. Wtedy dla r > np zachodzi zależność

"
Pr{X - np;, r) - L b(k; n, p)
k=l11p+rl

DOWÓD
Dla rozkładu dwumianowego ze wzoru (6.30) wynika, że µ = E[X] = np.


ZADANIA
* 6.5-1. Co jest mniej prawdopodobne: nieuzyskanie żadnego orla w n rzutach
monetą, czy uzyskanie mniej niż n orłów w 4n rzutach monetą?
* 6.5-2. Pokaż, że
L
•-' ( n) a'<
i=o I
(a+ I)"
na-k(a+I)
k- --- b(k; n, a/(a + I))

dla każdego a > O i każdego k takiego, że O < k < n.


* 6.5-3. Udowodnij, że jeśli O < k < np, gdzie O < p < 1 i q = 1- p, to

156
6.6. ANALIZA PROBABILISTYCZNA

•-I'I,pą
i=O
1 "-i < kq
np - k
("P)'(
---
k n- k
nq )"-•

* 6.5-4. Pokaż, że przy założeniach jak w tw. 6.6 zachodzi zależność

Pr{µ - X ~
(n -
r} ~ ( ----
---,---
µ)e)'
Podobnie, pokaż, że przy założeniach jak we wniosku 6. 7 zachodzi zależność

Pr{np - X~ r} :::;;;· r (nqe)'


* 6.5-5. Rozważmy ciąg n prób Bernoulliego, gdzie w i-tej próbie, dla i= 1,
2, ... , n, sukces występuje z prawdopodobieństwem p 1, a porażka - z praw-
dopodobieństwem ą, = 1 - P;· Niech X będzie zmienną losową oznaczają­
cą całkowitą liczbę sukcesów i niech µ = E[X]. Pokaż, że dla r ~ O

Pr{X - µ ~ e-,•,z„
r} :::;;;

(W.vkazówka: Udowodnij, że + q,.e-a.p,:::;;;


p,e1""-• e-a.'12. Następnie popro-
wadź dowód jak w tw. 6.6, używając tej nierówności w miejsce nierówności
(6.44)).
* 6.5-6. Pokaż, że wybranie fl = ln(r/µ) minimalizuje prawą stronę nierówności
(6.45).

6.6. Analizaprobabilistyczna
W tym podrozdziale za pomocą trzech przykładów ilustrujemy na czym polega
analiza probabilistyczna. W pierwszym badamy prawdopodobieństwo tego, że
w pokoju, w którym znajduje się k osób, są pary osób, które urodziły się tego
samego dnia. W drugim badamy losowe wrzucanie kul do urn. W trzecim
zajmujemy się okresami „dobrej passy" uzyskiwania orłów w rzucaniu monetą.

6.6.1. Paradoks dnia urodzin


Dobrym przykładem na zilustrowanie rozumowania probabilistycznego jest
klasyczny paradoksdnia urodzin.Ile osób musi znajdować się w pokoju, aby
była duża szansa na to, że dwie z nich urodziły się tego samego dnia w roku?
Odpowiedź jest zaskakująca - kilka. Paradoksem jest, że w rzeczywistości
o wiele mniej niż jest dni w roku, co zaraz pokażemy.

157
ROZDZIAŁ 6. ZLICZANIE I PRAWDOPODOBIEŃSTWO

Aby odpowiedzieć na pytanie, ponumerujemy ludzi w pokoju liczbami


całkowitymi 1, 2, ... , k, gdzie k jest liczbą osób w pokoju. Ignorujemy lata
przestępne i zakładamy, że wszystkie lata mają n= 365 dni. Dla i= 1, 2, ... ,
k niech b1 będzie dniem roku, w którym przypadają urodziny osoby i, gdzie
I ~ b; ~ n. Przyjmujemy również, że urodziny są jednostajnie rozłożone na
n dni w roku, tak: że Pr{b 1 = r} = 1/n dla i= 1, 2, ... ,kir= 1, 2, ... , n.
Prawdopodobieństwo tego, że osoby i oraz j mają jednocześnie urodziny
zależy od tego, czy losowy wybór urodzin jest niezależny. Jeśli urodziny są
niezależne, to prawdopodobieństwo tego, że urodziny osób i orazj wypadają
dnia r wynosi

Pr{b, - r i b, - r) - Pr{b, - r}Pr{b, - r)


= 1/n2
Tak: więc prawdopodobieństwo, że urodziny te wypadają tego samego dnia,

wynosi

"
Pr{b, - b;) - L Pr{b, - r i b, - r)
r ee 1

- L"1 (l/n 2)
t ee

- I/n
Bardziej intuicyjnie, kiedy zostaje wybrane b1, prawdopodobieństwo tego, że b;
jest wybrane tak: samo, jest równe 1/n. Stąd prawdopodobieństwo, że i oraz
j mają razem urodziny, jest takie samo jak: prawdopodobieństwo tego, że uro-
dziny jednego z nich wypadają danego dnia. Zauważmy jednakże, że ten zbieg
okoliczności zależy od założenia, że urodziny są niezależne.
Możemy analizować prawdopodobieństwo, że co najmniej 2 z k osób ma
razem urodziny poprzez spojrzenie na zdarzenie dopełniające. Prawdopodo-
bieństwo, że co najmniej dwie daty urodzin się pokrywają, jest równe 1 minus
prawdopodobieństwo tego, że wszystkie daty urodzin są różne. Zdarzenie po-
legające na tym, że k osób ma różne urodziny to

B, -
•-'
(") A,
i= 1

gdzie A; jest zdarzeniem polegającym na tym, że osoba (i+ 1) ma urodziny


kiedy indziej niż osobaj dla wszystkicbj ~ i, czyli

A, - {b,., ,t,b,:J-1, 2..., i)

158
6.6. ANALIZA PROBABILISTYCZNA

Ponieważ możemy napisać B1;= A1;_1 n B1 _ 1, otrzymujemy u wzoru (6.20)


zależność rekurencyjną

Pr{B,} - Pr{B,_ 1 )Pr{A,_ 1 jB1 _ 1 ) (6.46)

gdzie bierzemy Pr{B 1 } = 1 jako warunek początkowy. Innymi słowy, pra-


wdopodobieństwo tego, że b 1 , ba, ... , b1 są różnymi dniami, jest prawdopo-
dobieństwem tego, że b 1 , ba, ... , bk.-i są różnymi dniami, razy prawdopo-
dobieństwo tego, że b1 '# b 1 dla i= 1, 2, ... , k - 1, danych tak, że b 1 , ba,
..., b1 _ 1 są różne.
Jeśli b 1 , b1 _ 1 są różne, to prawdopodobieństwo warunkowe tego, że
b2 , ••• ,
b1 # b1 dla i= l, 2, ... , k - 1, wynosi (n - k + 1)/n, ponieważ z n dni nie
zostało wybranych n - (k - 1) dni. Iterując rekurencję (6.46), otrzymujemy

Pr{B,} - Pr{B1 } Pr{A1 IB1 } Pr{A,IB,} ... Pr{A,_1 jB,_1 )

-!·(":I)(":2)...(n-:+I)
-1-(1-!)(1-!)···(1-k:l)
Nierówność (2.7), I +x ~ C, daje nam

= e-l{ł:.-1)/an

~ 1/2

dla - k(k - l)/2n ~ ln(l/2). Prawdopodobieństwo, że wszystkie k dni urodzin


są różne, jest co najwyżej 1/2 dla k(k - 1) ;i, 2nln 2 lub, rozwiązując równanie
kwadratowe, dla k ;i, (1 +J
1 + (Sifi2)n )/2. Dla n= 365 musimy mieć k ~ 23.
Tak więc, jeśli co najmniej 23 osoby są w pokoju, to z prawdopodobieństwem
co najmniej 1/2, co najmniej dwie osoby mają razem urodziny. Na Marsie
rok trwa 669 dni marsjańskich; potrzeba zatem 31 Marsjan, aby uzyskać ten
sam efekt.

159
ROZDZIAŁ 6. ZLICZANIE I PRAWDOPODOBIEŃSTWO

Inna metoda analizy

Możemy skorzystać z własności liniowości wartości


oczekiwanej (wzór (6.26)),
aby przeprowadzić prostszą, lecz przybliżoną tylko analizę paradoksu dnia
urodzin. Dla każdej pary (i,j) z k osób znajdujących się w pokoju zdefiniujmy
zmienną losową X 1i, dla I :s;;i <j :s;;
k, następująco:

X,;~ {I,
o,
jeśli osoby i oraz j

w przeciwnym •
razie
mają razem urodziny

Prawdopodobieństwo tego, że dwie osoby mają wspólne urodziny, wynosi 1/n,


a dalej z definicji wartości oczekiwanej (6.23)

E[X,;]~ I·(l/n)+O·(l -1/n)


~ 1/n
Oczekiwana liczba par osób mających razem urodziny jest, ze wzoru
(6.24), równa sumie osobnych wartości oczekiwanych dla każdej z par i wynosi

;t,'.i ~E[X;;] (~)~

k(k - 1)
2n
Kiedy zatem k(k - 1) ~ 2n, oczekiwana liczba par osób o takich samych
dniach urodzin wynosi co najmniej 1. Wobec tego, jeśli mamy co najmniej
J-2~ osób w pokoju, możemy oczekiwać, że co najmniej dwie z nich mają
wspólny dzień urodzin. Dla n = 365, jeśli k = 28, to oczekiwana liczba par
ludzi z tym samym dniem urodzin wynosi (28 · 27)/(2 · 365) ~ 1,0356. Tak więc
przy co najmniej 28 osobach oczekujemy, że co najmniej dwie z nich obchodzą
razem urodziny. N a Marsie, gdzie rok trwa 669 dni marsjańskich, potrzebuje-
my co najmniej 38 Marsjan.
Pierwsza analiza problemu wyznaczyła liczbę osób potrzebnych do tego,
aby prawdopodobieństwo istnienia pary zgadzających się dat urodzin przekra-
czało 1/2, a druga wyznaczyła liczbę taką, że oczekiwana liczba wspólnych
urodzin wynosi I. Pomimo że liczby osób są różne dla tych dwóch sytuacji, są
one równe asymptotycznie: 0(J-;_ ).

6.6.2. Kule i urny


Wyobraźmy sobie proces losowego wrzucania identycznych kul do b urn, po-
numerowanych 1, 2, ..., b. Kolejne rzuty są niezależne i każda kula może wpaść

160
6.6. ANALIZA PROBABILISTYCZNA

z równym prawdopodobieństwem do każdej z urn. Prawdopodobieństwo, że


kula trafi do dowolnej wybranej urny, wynosi 1/b. Tak więc wrzucanie kul jest
ciągiem prób Bernoulliego z prawdopodobieństwem sukcesu 1/b, gdzie przez
sukces rozwniemy, że kula wpadła do danej urny. Na temat procesu wrzucania
kul do urn można zadać mnóstwo interesujących pytań.
Ile kul wpadło do danej urny? Liczba kul, które wpadły do danej urny,
wynik.a z rozkładu dwumianowego b(k; n, l/b). Jeśli zostało rzuconych n kul,
to oczekiwana liczba kul, które wpadły do danej urny, wynosi n/b.
Ile średnio trzeba rzucić kul, aby dana urna zawierała kulę? Liczba rzutów,
które tneba wykonać, z.animdo danej urny wpadnie kula, wynika z rozkładu
geometrycznego z prawdopodobieństwem 1/b i stąd oczekiwana liczba rzutów
wynosi 1/(1/b) - b.
Ile kul trzeba rzucić, aby w każdej z urn była choć jedna kula? Nazwijmy
„trafieniem" rzut, w którym kula trafia do pustej urny. Chcemy wiedzieć, jaka
jest średnia liczba n rzutów potnebnych do uzyskania b trafień.
Trafienia te można wykorzystać do podzielenia n rzutów na etapy. Etap
i-ty składa się z rzutów po (i- 1)-szym trafieniu aż do i-tego trafienia. Pierw-
szy etap składa się z pierwszego rzutu, jako że wiemy, iż wszystkie urny są
puste. Dla każdego rzutu w czasie i-tego etapu mamy i - 1 urn zawierających
kule i b - i+ 1 pustych urn. Tak więc dla wszystkich rzutów w i-tym etapie
prawdopodobieństwo uzyskania trafienia jest równe (b- i+ 1)/b.
Niech n1 oznacza liczbę rzutów w i-tym etapie. Liczba rzutów potnebnych
do otrzymania b trafień wynosi zatem n = L• n;, Każda zmienna losowa n 1 ma
l=l
rozkład geometryczny z prawdopodobieństwem sukcesu (b - i+ l)/b, dlatego

b
E[n,] - b -,+. 1

Z własności liniowości wartości oczekiwanej mamy


- L E[n,]
i=l

• b
- i=L1 b-r+1.
• 1
-b[-c
I= 1 z

161
ROZDZIAŁ 6. ZLICZANIE I PRAWDOPODOBIEŃSTWO

.; bQn b + 0(1))
Ostatni wiersz wynika z ograniczenia (3.5) szeregu harmonicznego. Zatem po-
trzeba około bln b rzutów, aby oczekiwać, że w każdej z urn znajduje się kula.

6.6.3. Ciągi „dobrej passy", czyli sukcesów


Przypuśćmy, że rzucamy monetą n razy. Jaki jest najdłuższy ciąg kolejnych
orłów, który spodziewamy się uzyskać? Odpowiedź b12.uii0(1gn), jak wynik.a
z poniższej analizy.
Najpierw udowodnimy, że oczekiwana długość najdłuższego ciągu orłów
wynosi OQgn). Niech Alk będzie zdarzeniem polegającym na tym, że ciąg orłów
o długości co najmniej k rozpoczyna się od i-tego rzutu lub, bardziej precy-
zyjnie, z.darzeniem polegającym na tym, że w wyniku k kolejnych rzutów mo-
netą i, i+ 1, ..., i+ k - 1 otrzymujemy wyłącznie orły, gdzie 1 ~ k ~ n
i 1 ~ i ~ n - k + 1. Dla dowolnego zdarzenia Alk prawdopodobieństwo tego,
że w wyniku wszystkich k rzutów otrzymujemy orły, ma rozkład geometryczny
zp=q= 1/2:

Pr{A~}= 1/2' (6.47)

Dla k = 2 [lgnl
Pr{A,.2 rlinl}= 1/22 n11
nl
~ 1/22J11n
= 1/n2
i stąd prawdopodobieństwo, że ciąg orłów długości co najmniej 12lg nl rozpo-
czyna się od pozycji i jest dość niewielkie, zwłaszcza jeśli weźmiemy pod uwa-
gę, że jest co najwyżej n pozycji (a faktycznie n - 2 flgnl + 1), od których
może rozpocząć się ten ciąg. Prawdopodobieństwo, że ciąg orłów długości co
najmniej 12lg nl rozpoczyna się gdziekolwiek, wynosi więc

jako, że z nierówności Boole'a (6.22) prawdopodobieństwo sumy zdarzeń jest


równe co najwyżej sutriie prawdopodobieństw poszczególnych zdarzeń. (Za-
uważmy, iż nierówność Boole'a zachowuje ważność również dla zdarzeń takich
jak te, które nie są niezależne).

162
6.6. ANALIZAPROBABILISTYCZNA

Prawdopodobieństwo, że dowolny ciąg orłów ma długość co najmniej


2rlgnl wynosi więc co najwyżej 1/n; stąd prawdopodobieństwo, że najdłuższy
ciąg orłów ma długość mniejszą. od 2rJg nl, wynosi co najmniej 1 - 1/n, Ponie-
waż każdy taki ciąg ma długość co najwyżej n, oczekiwana długość najdłuż­
szego z nich jest ograniczona z góry przez

(2[lgnl)(l - 1/n) + n(l/n) = O(lgn)


Szanse, że ten ciąg orłów jest dłuższy niż rrJgnl rzutów, zmniejszają się
szybko wraz z r. Dla r ~ 1 prawdopodobieństwo, że ciąg rrtgnl orłów rozpo-
czyna się na pozycji i, wynosi

Pr{A,.,0,,1) = l/2'flgnl

Stąd prawdopodobieństwo, że najdłuższy taki ciąg ma długość co najmniej


r flgnl, jest równe co najwyżej n/n'= 1/n'- 1 lub, równoważnie, prawdopodo-
bieństwo, że najdłuższy ciąg ma długość mniejszą od rflgnl, jest równe co
najmniej I - 1/n'- 1 .
Na przykład dla n= 1000 rzutów monetą prawdopodobieństwo otrzyma-
nia ciągu co najmniej 2flgnl = 20 orłów wynosi co najwyżej 1/n = 1/1000.
Szanse otrzymania ciągu dłuższego niż 3 rtg nl = 30 orłów wynoszą co najwyżej
1/n2 = 1/1 OOO OOO.
Wyprowadzimy teraz dopełniające dolne ograniczenie: oczekiwana dłu­
gość najdłuższego ciągu orłów w n rzutach monetą wynosi O:(lgn). Aby udowo-
dnić to ograniczenie, zwrócimy uwagę na ciągi orłów o długości LignJ/2.
Z równości (6.47) otrzymujemy

= 1/2 L!rnJ/2
Pr{A;,LirnJ/2}

;;, 1/..;n
Prawdopodobieństwo, że ciąg orłów długości co najmniej Llgnj/2 nie rozpo-
czyna się na pozycji i, jest w takim razie równe co najwyżej I - 1/Jri.Może­
my podzielić n rzutów monetą na co najmniej L2n/llgnJJ grup po Llg nj/2
kolejnych rzutów. Ponieważ grupy te są złożone ze wzajemnie się wykluczają­
cych, niezależnych rzutów, prawdopodobieństwo, że każda z tych grup nie
będzie ciągiem orłów o długości LlgnJ/2, wynosi

163
ROZDZIAŁ 6. ZLICZANIE I PRAWDOPODOBIEr-.lSTWO

~ l/n

Skorzystaliśmy tutaj z nierówności (2.7), 1 + x ~ e", oraz faktu, który można


sprawdzić, iż (2n/lgn -1)/J--;;~ lgn dla n~ 2. (Dla n= 1 prawdopodobień­
stwo, że żadna grupa nie będzie ciągiem orłów, wynosi oczywiście co najwyżej
1/n - I).
Stąd prawdopodobieństwo tego, że najdłuższy ciąg orłów przekracza
LlgnJ/2, jest równe co najmniej 1 -1/n. Ponieważ najdłuższy tak.i ciąg ma
długość co najmniej O, oczekiwana jego długość jest równa co najmniej

(llgnJ /2) (I - 1/n) + O· (I/n) - ll(lgn)

ZADANIA
6.6-1. Przypuśćmy, że kule są wrzucane do b urn. Rzuty są. niezależne i każda
kula może trafić do każdej z urn z jednak.owym prawdopodobieństwem.
Jak.a jest oczekiwana liczba rzutów, zanim co najmniej jedna z urn będzie
zawierać dwie kule?
* 6.6-2. Czy przy analizie paradoksu dnia urodzin ważne jest, aby urodziny były
wzajemnie niezależne, czy też wystarczające jest, aby były parami niezależ­
ne? Odpowiedź uzasadnij.
* 6.6-3. Ile osób powinno zostać zaproszonych na przyjęcie, aby było prawdo-
podobne, iż troje z nich ma urodziny w tym samym dniu?
* 6.6-4. Jakie jest prawdopodobieństwo, że k-słowo nad zbiorem. licmości n jest
faktycznie k-permutacją? Jaki jest zwiąi.ek tego pytania z paradoksem
dnia urodzin?
* 6.6-5. Przypuśćmy, że n kul jest wrzucanych do n urn, przy czym każdy rzut
jest niezależny i każda z kul może wpaść do każdej urny z równym praw-
dopodobieństwem. Jak.a jest oczekiwana liczba pustych urn? Jak.a jest
oczekiwana liczba urn zawierających dokładnie jedną kulę?
* 6.6-6. Wzmocnij dolne ograniczenie długości ciągu kolejnych orłów pokazu-
jąc, że w n rzutach monetą prawdopodobieństwo tego, iż nie wystąpi ciąg
orłów dłuższy niż n-2lglgn, jest mniejsze od 1/n.

Problemy
6-1. Kule i 1B'DY
W tym problemie prześledzimy efekt różnych założeń dotyczących liczby spo-
sobów umieszczenia n kul w b różnych urnach.

164
PROBLEMY

(a) Przypuśćmy, że jest różnych n kul i że ich ułożenie w urnie nie ma znacze-
nia. Pokaż, że liczba sposobów 1m,ieszczenia kul w urnach wynosi b".
(b) Przypuśćmy, że kule są. różne i że kule w każdej z urn są uporządkowa­
ne. Udowodnij, że liczba sposobów umieszczenia kul w urnach wyno-
si (b + n - 1)!/(b - 1)!. (Wskazówka: Weź pod uwagę liczbę możliwości
ustawienia n różnych kul i b - 1 nierozróżnialnych kijów w jednym rzę­
dzie).
(c) Przypuśćmy, że kule są identyczne, a więc ich kolejność w urnie nie ma
maczenia. Pokaż, że liczba sposobów umieszczenia kul w urnach wynosi
(h+ :- 1
). (Wskazówka: Ile ustawień z punktu (b) powtarza się, jeśli
przyjmiemy, że
kule są identyczne?)
(d) Przypuśćmy, że kule są identyczne i że żadna z urn nie może zawierać więcej

niż jedną kulę. Pokaż, że liczba sposobów umieszczenia kul wynosi(!)·


(e) Przypuśćmy, że kule są identyczne i że żadna z urn nie może pozostać

pusta. Pokaż, że liczba sposobów umieszczenia kul wynosi (; =!)·


6-2. Analiza programu znajdującego maksimum
Następujący program znajduje maksymalną wartość w nieuporządkowanej ta-
blicy A[l .. n].

1 max+- -oo
2 fori+-1 ton
3 do t> Porównaj A[i] z max.
4 if A[i] > max
5 then max+- A[i]

Chcemy znaleźć średnią liczbę wykonań podstawienia w wierszu 5. Przyjmij-


my, iż wszystkie liczby w A są losowo wzięte z przedziału [O, 1].

(a) Jeśli
liczba x jest losowo wybrana ze zbioru n różnych liczb, to jak.ie jest
prawdopodobieństwo, że x jest największą liczbą z tego zbioru?
(b) Jaki jest związek między A[i] i A[j], dla 1 ~j ~ i, kiedy jest wykonywany
wiersz 5 programu?
(c) Jak.ie jest prawdopodobieństwo, dla każdego i z zakresu 1 ~ i~ n, że jest
wykonywany wiersz 5?
(d) Niech s 1 , s2 , ••• , s„ będą n zmiennymi losowymi, gdzie s1 reprezentuje
liczbę wykonań (O lub 1) wiersza 5 podczas i-tej iteracji pętli for. Ile
wynosi E[sJ?

165
ROZDZIAŁ 6. ZLICZANIE I PRAWDOPODOBIEKISTWO

(e) Niech s = s1 + s2 + ... + sn będzie całkowitą liczbą wykonań wiersza 5


podczas pewnego uruchomienia programu. Pokaż, że E[s] = 0(lgn).

6-3. Problem zatrudnienia


Pani profesor Dixon potrzebuje zatrudnić nowego asystenta. Zaaranżowała
spotkania z n kandydatami i chciałaby oprzeć swój wybór wyłącznie na ich
kwalifikacjach. Niestety, przepisy uniwersytetu wymagają, aby po każdym ze
spotkań natychmiast odrzuciła kandydata lub zaproponowała mu posadę.
Profesor Dixon zdecydowała się przyjąć strategię wybrania dodatniej licz-
by całkowitej k < n, po czym odrzucenia po rozmowie pierwszych k kandyda-
tów i zatrudnienia pierwszego następnego, który będzie miał kwalifikacje lep-
sze niż wszyscy poprzedni. Jeśli najlepiej wykwalifikowany kandydat jest
wśród pierwszych k, z którymi rozmawiała, zatrudni n~tego.Pokaż, że profesor
Dixon maksymalizuje swoje szanse na zatrudnienie najlepiej wykwaliflk:owa-
nego kandydata przez wybranie k w przybliżeniu równego n/e i że jej szanse
zatrudnienia najlepiej wykwalifikowanego kandydata są wtedy równe w przy-
bliżeniu 1/e.

6-4. Zliczanie probabilistyczne


Za pomocą t-bitowego licznika możemy normalnie zliczyć tylko do 2' - 1.
Korzystając ze zliczania probabilistycznego R. Morrisa, możemy zliczyć do
znacznie większej liczby kosztem pewnej utraty precyzji.
Niech wartość i na liczniku reprezentuje liczbę n1 dla i = O, 1, ..., 21 - 1,
gdzie n1 tworzą rosnący ciąg nieujemnych liczb. Przyjmujemy, że początkowa
wartość licznika wynosi O, reprezentując liczbę n0 = O. Operacja ZWIĘKSZ
działa na liczniku wskazującym wartość i w sposób probabilistyczny. Jeśli
i= 2' - 1, to zwracany jest błąd - przepełnienie. W przeciwnym wypadku licz-
nik jest zwiększany o 1 z prawdopodobieństwem 1/(n1+ 1 - n1) lub pozostaje
nie zmieniony z prawdopodobieństwem 1 - l/(n 1+ 1 - n1).
Jeśli wybierzemy n1 = i dla wszystkich i~ O, licznik nasz staje się zwyczaj-
nym licznikiem. Bardziej interesujące sytuacje występują. jeśli wybierzemy, po-
wio::lzmy,n1 = 21- 1 dla i> O lub n1 = F 1 (i-ta liczba Fibonacciego -patrz pod-
,ozdz, 2.2).
· W tym problemie przyjmujemy, iż n 2,_ 1 jest wystarczająco duże, aby pra-
wdopodobieństwo błędu przepełnienia można było pominąć.

(a) Pokaż, że wartośćoczekiwana reprezentowana na liczniku po wykonaniu


n operacji ZWIĘKSZ wynosi dokładnie n.
(b) Analiza wariancji wartości wskazywanej przez licznik zależy od ciągu n;.
Rozważmy prosty przypadek: n1 = lOOidla wszystkich i~ O. Oszacuj wa~
riancję wartości na licz.niku po wykonaniu n operacji ZWIĘKSZ.

166
UWAGI DO ROZDZIAŁU

Uwagi do rozdziału
Pierwsze ogólne metody rozwiązywania problemów prawdopodobieństwa zo-
stały przedyskutowane w sławnej korespondencji pomiędzy B. Pascalem i P. de
Fermatem, która rozpoczęła się w 1654 r., oraz w książce C. Huygensa
z 1657 r. Szczegółowa teoria prawdopodobieństwa rozpoczęła się od pracy J.
Bemoulliego z 1713 r. i A. De Moivre'a z 1730 r. Kolejne udoskonalenia teorii
wprowadzili P. S. de Laplace, S.-D. Poisson oraz C. F. Gauss.
Sumy :zmiennychlosowych były pierwotnie przedmiotem badań P. L. Cze-
byszewa i A. A. Markowa. Teoria prawdopodobieństwa została zak.sjomatyzo-
wana przez A. N. Kohnogorowa w 1933 r. Ograniczenia krańców rozkładu
zostały wprowadzone przez Czemoffa [40] i Hoeffdinga [99]. Podstawowe za-
gadnienia dotyczące losowych struktur kombinatorycznych opisał P. ErdOs.
Książki Knutha [121] oraz Liu [140]są dobrymi podręcznikami elementar-
nej kombinatoryki i zagadnień zliczania. Standardowe podręczniki, których
autorami są Billingsley [28], Chung [41], Drake [57], Feller [66] i Roz.anov
[171],dają wszechstronne wprowadzenie do probabilistyk.i. Bollobś.s [30], Hof-
ri [100] i Spencer [179] opisują w swoich pracach zaawansowane technik.ipro-
babilistyczne.
Część li

Sortowani
i statystykipozycyjn
Wprowadzenie
W tej części opiszemy algorytmy służące do rozwiązywania następującego pro,-
blemu sortowania:
Dane wejściowe: Ciąg n liczb (a 1, a2 , ••• , a,.).
Wynik: Permutacja (zmiana kolejności) (al, a2, ... , a~) ciągu wejściowego
. , , ,
t aka,zea 1 .::;;a2 ::::;; ... ~a ...
Ciąg wejściowy jest na ogół n-elementową tablicą, chociaż może też być re-
prezentowany inaczej, na przykład jako lista.

Struktura danych
W rzeczywistości liczby, które należy posortować, rzadko są wyodrębnionymi
wartościami. Każda z nich jest na og61 częścią zbioru danych, zwanych re-
kordem. Każdy rekord zawiera klucz, będący wartością, którą należy posor-
tować, a reszta rekordu składa się z dodatkowych danych, które na ogól są
przenoszone razem z kluczem. W praktyce, kiedy algorytm sortowania per-
mutuje klucze, musi również permutować dodatkowe dane. Jeśli każdy rekord
zawiera dużą liczbę dodatkowych danych, to cr.ęsto permutuje się tablicę
wskaźników do rekordów zamiast samych rekordów, żeby zminimalizować
przemieszczanie danych.
W pewnym sensie właśnie takie szczegóły implementacyjne odróżniają al-
gorytm od gotowego programu. To, czy sortujemy pojedyncze liczby, czy też
duże rekordy zawierające liczby, jest nieistotne pod względem wyboru metody,
za pomocą której procedura sortująca wyznacza kolejność elementów w posor-
towanym ciągu. Dlatego przy rozważaniu problemu sortowania na ogół za-
kładamy, że dane wejściowe składają się jedynie z liczb. Tłumaczenie algoryt-
mu sortowania liczb na program sortujący rekordy jest koncepcyjnie proste,

170
WPROWADZENIE

choć w danej sytuacji mogą zaistnieć subtelne trudności, które z zadania pro-
gramisty uczynią wyzwanie.

Algorytmy sortowania
W rozdziale 1 wprowadziliśmy już dwa algorytmy sortowania n liczb rzeczywi-
stych. Sortowanie przez wstawiane wymaga w najgorszym przypadku czasu
8(n ). Ponieważ jednak jego wewnętrzne pętle są krótkie, jest to szybki algo-
2

rytm sortowania w miejscu dla danych o małym ro7Jlliarze. (Przypominamy, że


algorytm sortowania sortuje w miejscu,jeśli tylko stała liczba elementów tabli-
cy wejściowej jest przechowywana poza tablicą podczas działania algorytmu).
Sortowanie przez scalanie ma lepszy asymptotyczny czas działania, E>(nlgn),
ale procedura MERGE, z której korzysta ten algorytm, nie działa w miejscu.
W tej części wprowadzimy dwa następne algorytmy sortowania dowolnych
liczb rzeczywistych. Algorytm heapsort (sortowanie przez kopcowanie - patrz
rozdz. 7) umożliwia posortowanie n liczb w miejscu w czasie O(nlgn). Używa
się tu ważnej struktury danych, zwanej kopcem, do implementacji kolejki prio-
rytetowej.
Algorytm quicksort (sortowanie szybkie - patrz rozdz. 8) także umożliwia
posortowanie n liczb w miejscut, ale jego pesymistyczny czas działania wynosi
0(n ). Jego średni czas działania wynosi jednak E>(nlgn) i w praktyce algorytm
2

ten jest znacznie lepszy niż algorytm heapsort. Tak.jak sortowanie przez wsta-
wianie, sortowanie szybkie ma zwięzły kod, dzięki czemu stała ukryta w notacji
0 jest mała. Jest to popularny algorytm sortowania dużych tablic danych.
Sortowanie przez wstawianie, przez scalanie, przez kopcowanie i sortowa-
nie szybkie są algorytmami porównującymi: ustalają kolejność sortowanego
ciągu przez porównywanie elementów. Rozdział 9 rozpoczniemy od wprowa-
dzenia modelu drzew decyzyjnych w celu zbadania ograniczeń czasu działania
algorytmów porównujących. Używając tego modelu, udowodnimy, że dolna
granica pesymistycznej złożoności działania każdego algorytmu porównujące­
go, służącego do sortowania n liczb wynosi O:(nlgn). Wykażemy w ten sposób,
że sortowanie przez kopcowanie i przez scalanie są asymptotycznie optymal-
nymi algorytmami porównującymi.
W rozdziale 9 pokażemy, że dolna granica !l(nlgn) może zostać przekro-
czona, jeżeli będziemy zbierali informacje o porządku posortowanych danych
wejściowych w inny sposób niż porównując elementy. W algorytmie sortowa-
nia przez zliczanie (counting sort), na przykład, zakłada się, że liczby wejścio­
we należą do zbioru {1, 2, ... , k}. Przez użycie indeksowania tablic,jak.o narzę­
dzia do ustaienia porządku elementów względem siebie, w algorytmie sortowa-
nia przez zliczanie można posortować n liczb w czasie O(k+n). Dlatego, kiedy

t O ile nie bierzemy pod uwagę pamięci potrzebnej na realizację rekursji (przyp. tłum.).

171
CZĘSC li. SORTOWANIE I STATYSTYKI P02YCYJNE

k=O(n), algorytm ten działa w czasie liniowym względem. rozmiaru tablicy


wejściowej. Podobny algorytm, a mianowicie algorytm sortowania pozycyjne-
go (radix sort) może być zastosowany do rozszerzenia zasięgu sortowania
przez zliczanie. Jeśli danych jest do posortowania n liczb calk.owitych, a każda
z nich mad cyfr, z których każda jest zawarta w zbior:ze {I, 2, ... , k}, to z.a
pomocą tego algorytmu można posortować te liczby w czasie O(d(n+k)). Kie-
dy d jest stałą, a k wynosi O(n). algorytm sortowania pozycyjnego działa w cza-
sie liniowym. Trzeci algorytm, sortowanie kubełkowe (bucket sort), wymaga
znajomości ro7kładu prawdopodobieństwa liczb w tablicy wejściowej. Można
za jego pomocą posortować n liczb rzeczywistych jednostajnie rozłożonych
w przedziale [O, 1) w średnim czasie O(n).

Statystyki pozycyjne
Mianem i-tej statystyk.i pozycyjnej zbioru n liczb określamy i-tą liczbę tego
zbioru posortowanego w kolejności rosnącej. Można oczywiście wybrać i-tą
statystykę pozycyjną zbioru przez posortowanie danych wejściowych i wybra-
nie i-tej liczby. Jeśli nie czyni się założeń o rozkładzie danych wejściowych, to
metoda ta działa w czasie O(nlgn), co wynika z rozważań przeprowadzonych
w rozdz. 9.
W raz.dziale 1O pokażemy, że można znaleźć i-ty najmniejszy element zbio-
ru w czasie O(n), nawet kiedy elementami są. dowolne liczby rzeczywiste. Za-
prezentujemy algorytm ze zwięzłym pseudokodem, którego czas działania
w najgorszym przypadku wynosi O(n 1 ), ale w średnim przypadku jest liniowy.
Podamy też bardziej skomplikowany algorytm, który działa w pesymistycznym
czasie O(n).

Wymagania matematyczne
Choć w tej części przeważnie nie używamy trudnej matematyki, jednak. przy
czytaniu niektórych podrozdziałów jest wymagane większe doświadczenie ma-
tematyczne. W szc:zególności przy analizie średniego czasu działania algoryt-
mów sortowania szybkiego, sortowania kubełkowego i wyznaczania statystyki
pozycyjnej wykorzystujemy rachunek prawdopodobieństwa, który jest omó-
wiony w rozdz. 6. Analiza pesymistycznego czasu działania liniowego algoryt-
mu wyznaczania statystyki pozycyjnej jest trochę bardziej złożona niż inne
analizy pesymistycznych przypadków omówione w tej części.
Rozdział 7

Heapsort- sortowanie
przezkopcowanie

W tym rozdziale wprowadzamy nowy algorytm sortowania. Podobnie jak dla


algorytmu sortowania przez scalanie, ale nie jak dla sortowania przez wstawia-
nie, czas działania algorytmu sortowania przez kopcowanie (heapsort) wynosi
O(nlgn). Tak jak sortowanie przez wstawianie, ale inaczej niż sortowanie przez
scalanie, algorytm beapsort sortuje w miejscu: tylko stała liczba elementów
tablicy jest w czasie działania algorytmu przechowywana poza tablicą wejścio­
wą. Dlatego algorytm ten łąc:zy dobre cechy opisanych wcześniej algorytmów.
W algorytmie heapsort wprowadza się także nowy sposób konstrukcji al-
gorytmów: używa się tu struktury danych, zwanej „kopcem", do przetwarza-
nia danych w czasie działania algorytmu. Kopiec jest nie tylko użyteczny dla
algorytmu heapsort, ale działa również jako wydajna kolejka priorytetowa.
Kopce pojawią się znowu w algorytmach opisanych w dalszych rozdziałach.

7.1. Kopce
Kopiec(binarny)jest to tablicowa struktura danych, którą można rozpatrywać
jako pełne drzewo binarne (patrz podro7.dz.5.5.3),jak to widać na rys. 7.1. Każdy
węzeł drzewa odpowiada elementowi tablicy, w którym jest podana wartość
węzła. Drzewo jest pełne na wszystkichpoziomach z wyjątkiem być może najniż­
szego, który jest wypełniony od strony lewej do pewnego miejsca. Tablica
A reprezentująca kopiec ma dwa atrybuty: length(A],określający liczbę elemen-
tów tablicy, i heap-size[A],określający liczbę elementówkopcaprzechowywanych
w tablicy. To znaczy, że żaden element tablicy A[l .. length[A]]występujący po
A(heap-size[A]],gdzie heap-size(A]~ length[A],nie jest elementem kopca. Korze-
niem drzewa jest A[l], a mając dany indeks i węzła, można łatwo obliczyć indeksy
jego ojca PARENT(i),lewego syna LEFr(i) i prawego syna R.IGHT(i).

173
ROZDZIAŁ 7. HEAPSORT - SORTOWANIE PRZEZ KOPCOWANIE

\,\-i!, ' ') :o

0)
i :J ) I II I

Rys. 7.1. Kopiec można rozpatrywać jako (a) drzewo binarne i {b) jako tablicę. Liczba w kółku
w każdym wężle drzewa jest wartością przechowywaną w tym wężle. Liczba obok węzła jest
odpowiadającym mu indeksem tablicy

PARENT(i)
return i/2
LEFf(i)
return2i
RIGHT(i)
return2i + 1

Na większości komputerów procedura LEFT może policzyć 2i z.a pomocą jed-


nej instrukcji, po prostu przesuwając binarną reprezentację i o jeden bit w le-
wo. Podobnie, procedura RIGHT może szybko policzyć 2i + I przez przesunię­
cie binarnej reprezentacji i w lewo o jeden bit i dodanie na końcu jedynki.
Procedura PARENT może policzyć Li/2J przez przesunięcie i w prawo o jeden
bit. W dobrej implementacji algorytmu heapsort te trzy procedury są często
implementowane jako ,,makra" albo procedury „in-line".
Kopce mają również tzw. własność kopca: dla każdego węzła i, który nie
jest korzeniem, zachodzi

A[PARENT(i)];, A[i] (7.I)

to znaczy, że wartość w węźle jest nie większa niż wartość przechowywana


w jego ojcu. Stąd wynika, że największy element kopca jest umieszczony w ko-
rzeniu, a poddrzewa każdego węzła zawierają wartości mniejsze niż wartość
przechowywana w tym węźle.
Definiujemy wysokość węzła w drzewie jako liczbę krawędzi na najdłuższej
prostej ścieżce prowadzącej od tego węzła do liścia, a wysokość drzewa jako
wysokość jego korzenia. Ponieważ kopiec mający n elementów jest tworzony
na podstawie pełnego drzewa binarnego, jego wysokość wynosi 0(lgn) (patrz
zad. 7.1-2). Zobaczymy, że podstawowe operacje na kopcach działają w czasie

174
7.2. PRZYWRACANIE WŁASNO$CI KOPCA

co najwyżej proporcjonalnymdo wysokości drzewa, czyli OOgn). Resztę tego


rozdziału poświęcamy pięciu podstawowym procedurom i pokazujemy, jak
można ich użyć w algorytmie sortowania i strukturze kolejki priorytetowej.

• Procedura HEAPIFY, która działa w czasie O(lgn), służy do przywracania


własności kopca (7.1).
• Procedura BUILD-HEAP, która działa w czasie liniowym, tworzy kopiec
z nieuporządkowanej tablicy danych wejściowych.
• Procedura HEAPSORT, działająca w czasie O(nlgn), sortuje tablicę w miej-
scu.
• Procedury EXTRACT-MAX i INSERT, które działają w czasie O(lgn), pozwa-
lają na użycie kopca jako kolejki priorytetowej.

ZADANIA

7.1-1. Podaj największą i najmniejszą możliwą liczbę elementów w kopcu


o wysokości h.
7.1-2. Pokaż, że n-elementowy kopiec ma wysokość llgnj.
7.1-3. Pokaż, że największy element w poddrzewie kopca znajduje się w korze-
niu poddrzewa.
7.1-4. Gdzie w kopcu można znaleźć element najmniejszy?
7.1-5. Czy tablica, która jest odwrotnie posortowana, jest kopcem?
7.1-{;. Czy ciąg (23 0 17. 14, 6, 13, 10, I, 5, 7, 12) jest kopcem?

własności kopca
7.2. Przywracanie
HEAPIFY jest ważną procedurą służącą do manipulowania kopcami. Jej da-
nymi wejściowymi są: tablica A i indeks i tej tablicy. Przy wywołaniu HEAPIFY
Włada się, że drzewa binarne zaczepione w LEFT(i) i RIGHT(i) są kopcami,
ale że A[i] może być mniejszy od swoich synów, przez co narusza własność
kopca (7.1). Zadaniem HEAPIFY jest spowodowanie, żeby wartość A[i] ,,spły­
nęła" w dół kopca tak:, żeby poddrzewo zaczepione w węźle i stało się kopcem.

HEAPIFY(A, i)
I 1-LEFT(i)
2 r +- RIGHT(i)
3 if I.; heap-size[A]i A[~ > A[i]
4 then largest +- I
5 else largest +- i
6 if r ~ heap-size[A]i A[r] > A[largest]
7 then largest +- r

175
ROZDZIAŁ 7. HEAPSORT- SORTOWANIE PRZEZ KOPCOWANIE

8 if largesl =!-i
9 l:henzamień A[i]-A[largest]
10 HEAPIFY(A, largest)

Rysunek 7 .2 ilustruje działanie procedury HBAPIFY.W każdym kroku jest


wybierany największy z elementów A[i], A(LEFT(i)] i A[RIGHT(i)], a jego in-
deks jest zachowywany w zmiennej largest. Jeśli największy jest A[i], to pod-
drzewo zaczepione w i jest kopcem i procedura się zatrzymuje. W przeciwnym
razie jeden z synów jest największym elementem i następuje zamiana A[ i]
z A[largest], co powoduje, że węzeł i oraz jego synowie spełniają własność
kopca, Węzeł /argest ma jednak teraz początkową wartość A[i] i dlatego pod-
drzewo zaczepione w largest może nie spełniać własności kopca. Z tego powo-
du HEAPIFYmusi zostać wywołana rekurencyjnie na tym poddrzewie.
Czas działania HEAPIFY na poddrzewie rozmiaru n zaczepionym w da-
nym węźle i wynosi E>(l) na poprawienie zależności między A[i], A[LEFT(i)]

l l

2 ,.
~•.. . "·~ 3 2/ .
16
.A_,.A_

i ' '4 ,w 14
o 5 ,,
5 '
'·-:'% '
:,,.4
'
''.i:'1 '9 ..
'
l
10
'
,•.,

8
,,
;...
lo
'

'1·,'.
J
i1,'.}
• • ,K· )t,
:',°8 " ''
'
(al (b)

l
'16
2 /
,/
14 IO
' '
2 j

v:3··.
' ·: .l,
'
,, '
" '
10

''JJ
''
'"
4 l
lc I
Rys. 7.2. Działanie procedury HEAPIFY(A,2), gdzie heap-size[A]= IO. (a) Początkowa konfiguracja
kopca, w której wartość A[2] w węźle i = 2 narusza własność kopca, gdy nie jest on większy od obu
swoich synów. Własność kopca jest przywracana węzłowi 2 w (b) przez zamianę A[2] z A[4], co
narusza własność kopca w węźle 4. Rekurencyjne wywołanie HBAPIFY(A, 4) ustawia i= 4. Po
zamianie A[4] z A[9J, co jest pokazane w (c), węzeł 4 jest poprawiony, a rekurencyjne wywołanie
HEAPtFY(A, 9) nie zmienia więcej struktury danych

176
7.3. BUDOWANIE KOPCA

i A[RIGHT(i)] plus na rekurencyjne wywołanie HEAPIFY na


C'Z8.S potrzebny
poddrzewie zaczepionym w jednym z synów węzła i. Poddrzewa węzła mają
ka:Me rozmiar najwyżej 2n/3 - najgorszy przypadek występuje, gdy ostatni
rząd w drzewie jest wypełniony dokładnie do połowy - czas działania HEAPIFY
może zatem być opisany rekurencją

n:n).; n:2n/3) + 0(1)


Rozwiązaniem powyższej zależności jest, zgodnie z przypadkiem 2 twier-
dzenia o rekurencji uniwersalnej (tw. 4.1), T{n) = O(lgn). W inny sposób moż­
na scharakteryzować czas działania HEAPIFYna węźle o wysokości h jako O(h).

ZADANIA
7.2-1. Zilustruj (podobnie jak na rys. 7.2) działanie procedury HEAPIFY(A,3)
dla tablicy A - (27, 17, 3, 16, 13, IO, I, 5, 7, 12, 4, 8, 9, O).
7.2-2. Jalci jest skutek wywołania HEAPIFY(A, i), kiedy element A[i] jest więk­
szy niż jego synowie?
7.2-3. Jaki jest skutek wywołania HEAPIFY(A, i) dla i> heap-size[A]/2?
7.2-4. Kod dla procedury HEAPIFYjest efektywny, jeśli chodzi o stałe. Jedynie
wywołanie rekurencyjne w wierszu 10 może spowodować, że niektóre
kompilatory wytworzą nieefektywny kod. N apisz efektywną wersję HEAPI-
FY, która będzie używać iteracji (pętli) zamiast rekursji.
7.2-S. Wykaż, że czas działania procedury HEAPIFY na kopcu rozmiaru n
w najgorszym przypadku wynosi .O:Qgn).(Wskazówka: Dla kopca o n węz­
łach nadaj węzłom wartości, które spowodują rekurencyjne wywołania
HEAPIFY dla każdego węzła na ścieżce od korzenia do liścia).

7.3. Budowaniekopca
Procedury HEAPIFY możemy użyć w sposób wstępujący (ang. bottom-up) do
przekształcenia tablicy A[l .. n], gdzie n= length[A], w kopiec. Ponieważ ele-
menty podtablicy A[(ln/2J + I) .. n] są wszystkie liśćmi drzewa, zatem każdy
z nich jest 1-elementowym kopcem. Procedura BUILD-HEAP przechodzi przez
pozostałe węzły drzewa i wywołuje w każdym z nich HEAPIFY. Kolejność prze-
chodzenia węzłów zapewnia, że poddrzewa zaczepione w węźle i są kopcami,
kiedy HEAPIFY zostaje wywołana w tym węźle.

BUILD-HEAP(A)
I heap-size[AJ~ length[AJ
2 for i~ l/ength[A]/2J downto I
3 do HEAPIFY(A, i)

177
ROZDZIAŁ 7. HEAPSOAT - SORTOWANIE PRZEZ KOPCOWANIE

I
4
2 J

1 3
5 6 7 5
' ' '
/ /
I 2 16 9 IO 16
8 9
'
IO 8 9 10
:i'

14 • •
7
(al
14 8 7
(h)

4 4
2 J 2 J

l 3 1 lÓ
,, ' '
'14 /
' 5 /
' 7
' /
' 5
"9 /
' 7

8 9 IO
16 9 10
8
14
9 10 -
16 ·3\
..

2
• 7
(li.
2
• 7
(d)

I I

4 16
2
' s 2 J

16 10 14 ( 10

'
5

' 4
J J 5 6 J
' / 5 /

8
14
9 IO
7
6J 3
8
8
9 10
7 9 3•

2 8 1 2 4 1
(e) ro
Rys. 7.3. Działanie procedury BuILO-HBAP,pokazujące strukturę danych przed wywołaniem HEAPI-
FY w wierszu 3 BUILO-HBAP. (a) 10-elementowa tablica wejściowa i reprezentowane przez nią
drzewo binarne. Na rysunku widać indeks i pętli, który wskazuje na węzeł S przed wywołaniem
HEAPIFY(A, i). (b) Struktura danych, która jest rezultatem wywołania. Indeks pętli do następnego
wywołania wskazuje na węzeł 4. (c)-(e) Następne iteracje pętli for w BUII.D-HEAP. Zauważ, że kiedy
HEAPIFY jest wywoływana w węźle, oba poddrzewa tego węzła są kopcami. (Q Kopiec po zakoń­
czeniu działania BUII.D-HBAP

Na rysunku 7.3 widać przykład działania procedury BUILD~HEAP.

178
7.3. BUDOWANIE KOPCA

Możemy obliczyć proste ograniczenie górne na czas działania procedury


BUILD-HEAP w następujący sposób. Koszt każdego wywołania HEAPIFY wy-
nosi O(lgn), a jest O(n) tak.ich wywołań. Dlatego czas działania wynosi naj-
wyżej O(nlgn). To ograniczenie górne, choć jest poprawne, nie jest asymp-
totycznie dokładne.
Możemy uzyskać lepsze ograniczenie, zauważając, że czas działania HEA-
PIFY w węźle zależy od wysokości tego węzła, a wysokości większości węzłów
są małe. Nasza lepsza analiza opiera się na własności, że w n-.elementowym
1
kopcu jest najwyżej fn/21,+1 węzłów o wysokości h (patrz zad. 7.3-3).
Czas działania procedury HEAPIFY, gdy zostanie ona wywołana w węźle
o wysokości h, wynosi O(h) i dlatego możemy wyrazić całkowity koszt BUILD-
·HEAPjako

(7.2)

Ostatnią sumę można obliczyć p17.ez podstawienie x = 1/2 we wzorze (3.6),


co daje

:r,
• h 1/2
2• - ·<1- 112i2
-2
Dlatego C7.8.Sdziałania procedury BUILD-HEAP może być ograniczony przez

- O(n)

Stąd widać, że możemy zbudować kopiec z nieuporządkowanej tablicy w cza-


sie liniowym.

ZADANIA

7.3-1. Zilustruj (podobnie jak na rys. 7.3) działanie procedury BUILD-HEAP


dla tablicy A - (5. 3, 17, 10, 84, 19, 6, 22, 9).
7.3-2. Dlaczego chcemy, żeby indeks i pętli w wierszu 2 procedury BUILD-
-HEAP miniejszał się od llength[A]/2J do 1, 7.amiast zwiększać się od 1
do lfength[A]/2J?
7.J..3. Pokaż, że w n-elementowym kopcu istnieje najwyżej fn/21,+11 węzłów
o wysokości h.

179
ROZDZIAŁ 7. HEAPSORT- SORTOWANIEPRZEZKOPCOWANIE

7.4. Algorytmsortowaniaprzezkopcowanie(heapsort)
Algorytm heapsort rozpoczyna działanie, używając procedury BUILD-HEAPdo
skonstruowania kopca w tablicy wejściowej A[l „ n), gdzie n= length{A].Skoro
największy element tablicy znajduje się w korzeniu A[l], może on zostać umiew
szczony na swoim właściwym miejscu przez zamianę z A[n). Jeśli teraz „od-
rzucimy" węzeł n z kopca (przez zmniejszenie heap-size[A]),zauważymy, że
tablica A[l .. (n - 1)] może łatwo zostać przekształcona w kopiec. Synowie ko-

(14\
,/-
>
c,,,ie, (bi
(li)

.
1,1·
_.(i~
-

;· 3\
\:i) 2) c·
..-/ 'r---
\__ _J , -· • I

(d) ••• (c) •••


•• •·
• •••
___,•'


(
, l) I

••• lg) (hl ••• (i)

,. •
••••
••• u, (kJ

Rys. 7,4. Działanie


procedlll'y HEAPSORT.(a) Struktura kopca zaraz po jego zbudowaniu przez Bu.
ILD-HEAP. (b)-(j) Kopiec po każdym wywołaniu HEAPIFYw wierszu 5. Wartość i w tym momencie
jest pokazana na rysunku. Tylko jasnoszare węzły pozostaną, w kopcu. (k) Posortowana tablica A

180
7.5. KOLEJKI PRIORYTETOWE

rzenia pozostają kopcami, ale nowy korzeń może naruszać własność kopca
(7.1). Jedyne, co trzeba zrobić, żeby przywrócić własność kopca, to raz wywo-
łać HEAPIFY(A, 1), co pozostawi kopiec w A[l .. (n - 1)]. Algorytm heapsort
powtarza ten proces dla kopca o rozmiarze n - 1, aż do uzyskania kopca
o rozmiarze 2.

HEAPSORT(A)
I BUILD-HEAP(A)
2 for i- length[A] downto 2
3 do zamień A[l]+-+A[i]
4 heap-size[A]- heap-size[A]- 1
5 HEAPIFY(A, I)

Na rysunku 7.4 widać przykład działania algorytmu heapsort po początkowym


zbudowaniu kopca. Każdy kopiec jest pokazany na początku iteracji pętli for
w wierszu 2.
Czas działania procedury HEAPSORTwynosi O(nlgn), ponieważ wywoła­
nie BUILD-HEAP zajmuje czas O(n), a każde z n - l wywołań HEAPIFY zaj-
muje czas O(lg n).

ZADANIA

7.4-1. Zilustruj (podobnie jak na rys. 7 .4) działanie procedury HEAPSORTdla


tablicy A - (5, 13, 2, 25, 7, 17, 20, 8, 4).
7.4-2. Jaki jest czas działania algorytmu heapsort dla tablicy A o długości n,
która jest już posortowana rosnąco (malejąco)?
7.4-3. Pokaż, że czas działania algorytmu heapsort wynosi !l(nlgn).

7.5. Kolejkipriorytetowe
Heapsort jest doskonałym algorytmem, ale dobra implementacja algorytmu
quicksort, taka jak opisana w rozdz. 8, jest na ogół lepsza w praktyce. Pomimo
to kopiec jako struktura danych ma wiele zastosowań. W tym podrozdziale
opisujemy jedno z najbardziej popularnych zastosowań kopca: jako kolejki
priorytetowej.
Kolejka priorytetowa to struktura danych służąca do przechowywania
zbioru S elementów, z których każdy ma przyporządkowaną wartość, zwaną
kluczem. Na kolejce priorytetowej można wykonać następujące operacje.

INSERT(S, x) wstawia element x do zbioru S. Ta operacja może być zapisana


jako s~su{x}.
MAXIMUM(S) daje w wyniku element S o największym kluczu.

181
ROZDZIAŁ 7. HEAPSORT- SORTOWANIE PRZEZ KOPCOWANIE

EXTRACT-MAX(S)
usuwa i daje w wyniku element S o największym kluczu.

Jednym z zastosowań kolejki priorytetowej jest przydzielanie zasobów na


komputerze wykonującym zadanie współbieżnie. W kolejce priorytetowej są
zapamiętane zadania, które mają być wykonane, i ich priorytety względem
siebie. Kiedy zadanie kończy się lub zostaje przerwane, zadanie o największym.
priorytecie jest wybierane przez EXTRACT-MAX spośród zadań czekających.
Nowe zadanie może zostać dodane do kolejki w dowolnej chwili za pomocą
operacji INSERT.
Kolejka priorytetowa może również być użyta jako symulator Marzeń.
Elementami kolejki są Marzenia, które należy symulować, każde z przyporząd­
kowanym.czasem występowania, który służy jako klucz. Zdarzenia muszą być
symulowane w kolejności ich zajścia, ponieważ symulacja zdarzenia może spo-
wodować, że inne 7.darzenia będą symulowane w ptzyszłości. W tym za.stoso-
waniu naturalnym rozwiązaniem jest odwrócenie liniowego porządku kolejki
i wykorzystanie operacji MINIMUMi EXTRACT-MIN w miejsce operacji MAXI-
MUM i EXTRACT-MAX.Program symulacyjny korzysta w każdym kroku
z operacji ExTRACT-MINdo wybierania zdarzenia, które będzie symulował.
Kiedy zachodzą nowe zdarzenia, zostają one dodane do kolejki za pomocą
operacji INSERT.
Nie jest dziwne, że możemy użyć kopca do implementacji kolejki priory-
tetowej. Operacja HEAP-MAXIMUM daje w wyniku maksymalny element w kop-
cu w czasie 0(1 ): wystarczy odczytać wartość A[l]. Procedura HEAP-EXTRACT
-MAXjest analogiczna do treści pętli for (wiersze 3-5) procedury HEAPSORT:

HEAP-E>ITRACT-MAX(A)
I if heap-size[A]< 1
2 tben ermr „kopiec pusty"
3 max-A[!]
4 A[l]-A[heap-size[AD
5 heap-size[A]- heap-size[A]- I
6 HEAPIFY(A, I)
7 return max

Czas działania procedury HEAP-EXTRACT-MAX wynosi O(lgn), ponieważ wy-


konuje ona tylko stałą ilość pracy oprócz czasu OOgn) zużywanego przez pro-
cedurę HEAPIFY.
Procedura HEAP-INSERT wstawia węzeł do kopca A. Żeby to uczynić, naj-
pierw powiększa kopiec przez dodanie nowego liścia do drzewa. Następnie,
w sposób podobny do działania pętli wstawiającej (wiersze 5-7) procedury
INSERTION-SORT z pod.rozdz. 1.1, przechodzi ona ścieżkę od liścia do korze-
nia, próbując znaleźć właściwe miejsce dla nowego elementu.

182
7.5. KOLEJKIPRIORYTETOWE

HEAP-INSBRT(A, key)
1 heap-size[A]- heap-size[A]+ 1
2 i-heap-size[A]
3 whl1ei> 1 i A[PARBNT(i)] < key
4 do A[i]-A[PARBNT(i)]
5 i-PARBNT(i)
6 A[i]-ltey

Na rysunku 7.5 widać p.izykład dzialąnia procedury HEAP-INSERT. Czas dzia-


łania HBAP-INSBRT na n-elementowym kopcu wynosi O(lg n), ponieważ ścież­
ka poprowadzona od nowego liścia do kor:,enia ma długość O(lgn).
Podsumowując. kopiec umożliwia wykonywanie wszystkich operacji ko-
lejki priorytetowej na zbiou.e n elementów w czasie O(lgn).
ZADANIA
7.5-1. Zilustruj (podobnie jak na rys. 7,5) działanie procedury HBAP~
-INSBRT(A,3) dla kopca A= (15, 13, 9, 5, 12, 8, 7, 4, O, 6, 2, l}.

16 16

IO

7 9 3 8 7 9 3

2 4 I 2 4 I

(a) (b)

16 16

IO

9 3 8 14" 9 3

2 4 I 7 2 4 I 7

(o) (d)
Rys. 75. DZislanieprocedury HI!AP-INSEI.T. (a) Kopićc z tYJ.7.4(a) zanim wstawimydo niego wę&ł
z k11111e101s; (b) Nowy liść zoirta.jedodany do kopca. (c:)Ws:rtok:ina idei.oe z nowego liścia do
korzenia są kopiowane w dół, aż znajdzie si~ miejsce na klucz 15. (d) Klucz 1S jest wstawiony

183
ROZDZIAŁ 7. HEAPSORT- SORTOWANIE PRZEZ KOPCOWANIE

7 .S-.2. Opisz działanie procedury HEAP-EXfRACT -MAX dla kopca


A= (15, 13, 9, 5, 12, 8, 7, 4, O, 6, 2, 1).
7 .S-.3. Pokaż, jak za pomocą kolejki priorytetowej zaimplementować zwykłą
kolejkę (FIFO) i jak zaimplementować stos. (Kolejki FIFO i stosy są zde-
finiowane w podro7.dz. 11.1).
7.5-4. Podaj działającą w czasie 00gn) implementację procedury HEAP-
-INCREASE-KEY(A,i, k), która podstawia A[i] ~ mas(A[i], k) i odpowied-
nio zmienia strukturę kopca.
7.5-5. Procedura HEAP-DELETE(A,i) usuwa element w węźle i z kopca A.
Podaj implementację HEAP-DELETE,która działa w czasie OOgn) dla
n-elementowego kopca.
7.5-6. Podaj algorytm działający w czasie O(nlgk) służący do scalania k po-
sortowanych list, gdzie n jest łączną liczbą elementów na listach. (Wska-
zówka: Użyj kopca do k-krotnego scalania).

Problemy
7-1. Budowa kopca przez wstawianie
Procedura BUILD-HEAPz rozdz. 7.3 może zostać zaimplementowana przez
wielokrotne użycie HEAP-INSERTdo wstawiania elementów do kopca. Rozważ
następującą implementację:

BUILD-HEAP'(A)
l heap-size[AJ~ l
2 for i- 2 to length[A]
3 do HEAP-INSERT(A,A[i])

(a) Czy procedury BUILD-HEAPi BUILD-HEAP'zawsze tworzą taki sam ko-


piec, gdy zostaną uruchomione dla tej samej tablicy? Udowodnij, że tak
jest, albo podaj kontrprzykład.
(b) Pokaż, że w najgorszym przypadku procedura BUILD-HEAP'wymaga cza-
su 0(nlgn), żeby zbudować n-elementowy kopiec.

7-2. Analizakopcówrzędu d (d-arnycb)


Kopiec rzędu
d jest podobny do kopca binarnego, ale zamiast 2 synów węzły
mogą mieć d synów.

(a) Jak można reprezentować kopiec rzędu d w tablicy?


(b) Jak wyrazić wysokość kopca rzędu do n elementach za pomocą di n?
(c) Podaj efektywną implementację procedury ExrRACT-MAX. Wyrai. jej czas
działania za pomocą di n.

184
UWAGI DO ROZDZIAŁU

(d) Podaj efektywną implementację procedury INSERT. Wyraź jej czas działa­
nia za pomocą d i n.
(e) Podaj efektywną implementację procedury HEAP-INCREASE-KEY(A,i, k),
która za A[i] podstawia max(A[i], k) i odpowiednio modyfikuje strukturę
kopca. Wyraź jej czas działania za pomocą d i n.

Uwagido rozdziału
Algorytm heapsort został wynaleziony przez Williamsa [202], który również
opisał implementację kolejki priorytetowej za pomocą kopca. Procedura Bu-
lLD-HEAP została zaproponowana przez Floyda [69].
Rozdział 8

Quicksort- sortowanie
szybkie

Sortowanie szybkie (quicksort) jest algorytmem sortowania, którego pesy-


mistyczna złożoność czasowa wynosi 8(n 2 ) dla tablicy wejściowej zawierającej
n liczb. Pomimo tak długiego czasu działania w najgorszym przypadku al-
gorytm quicksort jest często najlepszym wyborem dla praktycznych zadań
sortowania, ponieważ w średnim przypadku jest niezmiernie efektywny: jego
OC1.Ckiwanyczas działania wynosi E>(nlgn), a stałe ukryte w notacji 8(nlgn)
są małe. Oprócz tego zaletą algorytmu jest fakt, że sortuje on w miejscu
(patrz str. 23) i działa dobrze nawet w środowiskach wykorzystujących pamięć
wirtualną.
Podrozdział 8.1 zawiera opis algorytmu quicksort i ważnej procedury, któ-
rej używa on do podziału danych. Ponieważ zachowanie algorytmu jest złożo­
ne, w pod.rozdz. 8.2 rozpoczniemy intuicyjną dyskusję jego zachowania, a do-
kładną analizę przedstawimy na końcu rozdziału. Podrozdział 8.3 dotyczy
dwóch wersji algorytmu quiclcsort, w których jest zastosowany generator liczb
losowych. Te „probabilistyczne" algorytmy mają wiele pożądanych własności.
Ich średni czas działania jest dobry i żadne określone dane wejściowe nie po-
wodują pogorszenia czasu ich działania. Analiza jednej z tych wersji będzie
przedstawiona w podrozdz. 8.4, gdzie pokażemy, że w najgorszym przypadku
działa ona w czasie O(n2 ), a w średnim przypadku -w czasie O(nlgn).

8.1. Opis algorytmu


Algorytm sortowania szybkiego, tak jak algorytm sortowania przez scalanie,
jest oparty na technice „dziel i zwyciężaj", która została wprowadzona w pod-
rozdz. 1.3.1. Podajemy tu trzy kroki metody „dziel i zwyciężaj" zastosowanej
do sortowania typowej podtablicy A[p .. r].

186
8.1. OPIS ALGORYTMU

Dziel: Tablica Afp .. rJ jest dzielona Gejelementy są przestawiane) na dwie nie-


puste podtablice A[p .. q] i A[q + I .. r] takie, że każdy element Afp .. q] jest
nie większy niż każdy element A[q + I .. r]. Indeks q jest obliczany przez
procedurę dzielącą.
Zwyciężaj: Dwie podtablice A[p .. q] i A[q + l .. r] są sortowane za pomocą
rekurencyjnych wywołań algorytmu quicksort.
Połącz: Ponieważ podtablice są sortowane w miejscu, nie potrzeba nic robić,
żeby je połączyć: cała tablica Afp „ r] jest już posortowana.
Następująca procedura jest implementacją algorytmu quick.sort.

QUICKSORT(A, p, r)
1 ilp<r
2 then q +-PARTITION(A, p, r)
J QUJCKSORT(A, p, q)
4 QUJCKSORT(A, q + I, r)

żeby posortować całą tablicę A, wywołujemy QUICKSORT(A, 1, length[A]).

Dzielenie tablicy
Kluczem do algorytmu jest procedura PARTITION, która przestawia elementy
podtablicy A[p .. r] w miejscu.

PARTITION(A, p, r)
I x~Afp]
2 i+-p-1
3J+-r+1
4 while TRUE
5 do re-peatj +- j - 1
6 until A[j] ,;; x
7 repeati+-i+l
8 until A[i];;, x
9 if i <J
10 tben zamień A[i]+-+A[j]
11 else return j

Rysunek 8.1 ilustruje działanie procedury PARTITION. Najpierw jest wybierany


=
element x A[p] z A[p .. r] jako element rozdzielający, względem którego będzie
dokonywany podział A[p .. r]. Następnie na początku i na końcu podtablicy
Afp .. r] są tworzone, odpowiednio, obszary Afp .. 11i AU .. r] takie, że każdy
element z A[p .. 11jest mniejszy lub równy x i każdy element z A[j .. r] jest większy
lub równy x. Na początku i= p- I ij = r + 1, więc oba obszary są puste.

187
ROZDZIAŁ 8. QUICKSORT - SORTOWANIE S2YBKIE

·,,, \.,•:

\\'j(,t,6'i'7
A' A

Rys. 8.1. Działanie procedury PARTITIONdla przykładowej tablicy. Jasnoszare elementy zostały
umieszczone we właściwych miejscach, a ciemnoszare jeszcze nie. (a) Tablicawejściowa z począ,t,
kowymi wartościami i ij znajdującymi się poza lewym i prawym końcem tablicy. Podział wzglę­
dem x = A[p] = 5. (b) Pozycje i i jw wierszu 9 po pierwszej iteratji pętli wbile. (c) Rezultat zamiany
elementów wskazywanych przez i i jw wierszu 10. (d) Położenie ; i jw wierszui 9 podczas trzeciej
i ostatniej iteracji pętli wbile. Procedura zatrzymuje się, poniewa:i.:i ;;,c
j, i jest zwracana wartość
q = j. Elementy tablicywłącznie z A[j} są mniejsze lub równe x = 5, a elementy tablicy występują­
ce po A[j] są większe lub równe x = 5

Wewnątrz pętli while, w wierszach 5-8, indeks j jest zmniejszany, a indeks


i - zwiększany, aż zajdzie A{i] ;;,cx ;;,cA[j]. Zakładając, że te nierówności są
ostre, A[i] jest za duże, żeby należeć do dolnego obszaru, a A[j] za małe, żeby
należeć do górnego. Dlatego przez zamianę A[i] z A[j] w wierszu 10 możemy
zwiększyć oba obszary. (Jeżeli nierówności nie są ostre, to i tak można doko-
nać zamiany).
Pętla while powtarza się, aż zajdzie i ;;,cj, a wtedy cała tablica Afp .. r] zo-
staje podzielona na takie dwie podtablice Afp .. q] i A[q + 1 .. r], gdzie
p ~ q < r, że żaden element z A[p .. q] nie jest większy od jakiegokolwiek ele-
mentu z A[ą + 1 .. r]. Wartość ą = j jest zwracana na końcu procedury.
Koncepcja działania procedury dzielącej jest prosta: umieszcza ona ele-
menty mniejsze niż x w dolnym obszarze tablicy, a elementy większe niż
x w górnym. Jednak pseudokod procedury PARTITIONjest dość sprytny ze
względu na pewne techniczne szczegóły. Na przykład indeksy i orazj nigdy nie
wychodzą poza zakres tablicy A[p .. r], choć nie jest to całkiem oczywiste na
podstawie lektury kodu. ż.eby podać inny przykład: jest istotne, że procedura
używa A[p} jako elementu roz.dzielającego x. Gdyby zamiast tego został użyty
element A[r] i okazało się, że jest on największym elementem w podtablicy
Afp .. r], PARTITJONzwróci do procedury QUICKSORTwartość ą = r i procedu-
ra QUICKSORTzapętli się. W problemie 8-1 należy udowodnić poprawność
działania PARTITION.

188
8.2. CZAS DZIAŁANIA ALGORYTMU QUICKSORT

Czas działania procedury PARTITION dla danej tablicy A[p .. r] wynosi


0(n), gdzie n= r - p + l (patrz zad. 8.1-3).

ZADANIA
8.1-1. Zilustruj (podobnie jak na rys. 8.1) działanie procedury PARTITIONdla
tablicy A= (13, 19, 9, 5, 12, 8, 7, 4, li, 2, 6, 21).
8.1-2. Jaką wartość q zwraca procedura PARTITION, gdy wszystkie elementy
A{p .. r] mają taką samą wartość?
8.1-3. Podaj krótkie uzasadnienie faktu, że czas działania procedury PARTI-
TION dla podtablicy o rozmiarze n wynosi 0(n).
8.1-4. Jak zmienić procedurę QUICKSORT, żeby sortowała w porządku nie-
rosnącym?

8.2. Czasdziałania algorytmuquicksort


Czas działania algorytmu quicksort zależy od tego, czy podziały są zrównowa-
żone, czy nie, a to z kolei zależy od tego, które elementy zostaną wybrane do
dzielenia. Jeśli podziały są zrównoważone, to algorytm jest asymptotycznie tak
szybki jak sortowanie przez scalanie. Kiedy jednak podziały są niezrównowa-
żone, algorytm może działać asymptotycznie tak wolno jak sortowanie przez
wstawianie. W tym podroz.dziale zajmujemy się nieformalnym omówieniem
działania algorytmu quicksort, zakładając, że podziały są zrównoważone bądź
. .
mezrownowazone.
.

Najgorszyprzypadekpodziałów
Najgorszy przypadek działania algorytmu quicksort zachodzi wtedy, kiedy
procedura dzieląca tworzy jeden obszar złożony z n - 1 elementów, a drugi
tylko z 1 elementu. (To stwierdzenie udowodnimy w podrozdz. 8.4.1). Załóż­
my, że takie niezrównoważone podziały będą wykonywane w każdym kroku
algorytmu. Ponieważ koszt podziału wynosi 0(n) i T(l) = 0(1), to równanie
rekurencyjne opisujące czas działania wygląda następująco:

T(n) = T(n - I)+ E>(n)

Żeby rozwiązać tę rekurencję, zauważamy, że T(l) = 0(1), i iterujmy:

T(n) = T(n - I)+ E>(n)

"
=L ®(kJ
k= 1

189
ROZDZIAŁ 8. OUICKSORT - SORTOWANIE 5ZYBKIE

- 0(n 2 )

Ostatni wiersz otrzymujemy dzięki obserwacji, że L" k jest szeregiem arytme-


l= 1
tycznym (3.2). Na rys11nku 8.2 widać drzewo rekursji dla najgorszego przypad-
ku działania algorytmu quicksort. (Patrz podrozdz. 4.2, gdzie są omówione
drzewa rekursji).

n .._,..........................................................
._..................
)11>.

I / " n
n-1 ....................................................................
~1~-

l / " n-2 ........................................................


~i,. n-1

n
1 / " n-3 ............................................
u,.. n-2

I/ "··
"
I /
!-·· 3
2 .....................

"-._ I ·········i•· 2

Rys. 8.2. Drzeworekursji dla algorytmu Qut(l(SORT,w którym procedura PARTITION uwsze umiesz..
cza tylko jeden element po jednej stronie podziału (najgorszyprzypadek:).W rezultacie czas działa­
nia wynosi 8(112)

Widać stąd, że jeśli podziały są


maksymalnie niezrównoważone w każdym
rekurencyjnym kroku algorytmu, to czas działania wynosi 0(n 2). Dlatego
pesymistyczny czas dzjałania algorytmu sortowania szybkiego nie jest lepszy
niż w przypadku sortowania przez wstawianie. Co więcej, algorytm quick.sort
ma czas działania 0(n 2 ), gdy tablica wejściowa jest całkiem posortowana
- często spotykana sytuacja, w której algorytm sortowania przez wstawianie
działa w czasie O(n).

Najlepszyprzypadekpodziałów
Jeśliprocedura dzieląca produkuje dwa obszary o rozmiarach n/2, to algorytm
quicksort działa o wiele szybciej. Równanie rekurencyjne ma wtedy postać

T(n) - 2T(n/2) + 0(n)


190
8.2. CZAS DZIAŁANIA ALGORYTMU QUICKSORT

,12 n/2 ............


* ......................... ;11t•- n

,/4/ -------,./4 n/4/ -------


n/4 ············-·-·····:li...
n

lg" ,( ';;,, .( ';;,, .( ';;,,


'' '' ' ' ,,
,(
''
~
,.
.. .. "
1 I 1 I 1 1 I I 1 1 I I I I l I l ..··-····C••- n

0(n lg n)
Ry!I. 8.3. Drzewo rekursji dla algorytmu Qmct:.SORT, w którym procedura PARTITIONzawsze równo-
miernie dzieli tablicę na dwa obszary (najlepszy przypadek). Czas d:ziałania algorytmu wynosi
0(nlgn)

i na podstawie przypadku 2 twierdzenia o rekurencji uniwersalnej ma rozwią­


zanie T(n) = E>(nlgn). Stąd widać, że najlepszy przypadek podziałów daje du-
żo szybszy algorytm. Na rysunku 8.3 widać drzewo rekursji dla najlepszego
przypadku działania algorytmu quicksort.

Podziały zrównoważone

Średni czas działania algorytmu quicksort jest dużo bliższy najlepszemu przypa-
dkowi niż najgorszemu,jak wykażemy w podrozdz. 8.4. Żeby zrozwnieć, dlacze-
go jest to możliwe, wystarczy zrozumieć, jak równowaga podziału jest odzwier-
ciedlana w równaniu rekurencyjnym, które opisuje czas działania algorytmu.
Załóżmy na przykład, że algorytm dzielący będzie zawsze dawał proporcje
podziału 9 do 1, co na pierwszy rzut oka wydaje się bardzo niezrównoważone.
Czas działania algorytmu quicksort opisuje wtedy równanie rekurencyjne
T(n) = T(9n/IO) + T(n/10) + n
w którym dla uproszczenia zastąpiliśmy E>(n)przez n. Na rysunku 8.4 widać
drzewo rekursji dla powyższego równania. Zauważmy, że każdy poziom drze-
wa ma koszt n, aż osiągnięty zostanie warunek brzegowy na głębokości
log 10 n = E>(lgn). Każdy z następnych poziomów, aż do głębokości log 1019 n =
= E>(lgn) ma koszt co najwyżej n. Całkowity koszt algorytmu wynosi zatem
E>(nlgn). Stąd widać, że dla podziału według proporcji 9 do 1 na każdym
poziomie rekursji, co intuicyjnie wydaje się podziałem niezrównoważonym,
algorytm quicksort działa w czasie E>(nlg n) - asymptotycznie takim samym,
jak gdyby podział następował w połowie. W rzeczywistości nawet podział 99

191
ROZDZIAŁ 8. QUICKSORT - SORTOWANIE SZVBKIE

1 9
Wn -10 n ···-·····-·······-···············-··~
n

1
./'"-._

100 n
9
100 n
9
100"
- -----
81
100 n ····--·-·····-·····-··;llto·
n

II \ , ,I \ , I \ /\
'
81 729 '
···-·-·- ..~!Io<· n
1 1000" 1000"
I \ I \ .....-.....-;.... Sn
' '
'\
I .......
_...,.,,. Sn

8(n lg n)
Rys. 8.4. Drzewo rekursji dla algorytmu QtJICKSORT,w którym procedura PARTITIONzawsze tworzy
podział 9 do I, co daje czas działania G(11lg11)

do 1 daje czas działania O(nlgn). Powodem tego jest fakt, że każdy podział
o stałym współczynnik.u proporcjonalności daje drzewo rekursji o głębokości
0(lgn), w którym koszt na każdym poziomie wynosi n. Czas działania wynosi
zatem 0{n lgn), kiedy tylko podziały mają stały współczynnik proporcjonalności.

Intuicje dotyczące przypadku średniego


Żeby zrozumieć działanie algorytmu quicksort w przypadku średnim, musimy
poczynić założenia o tym, jak często będą się pojawiały różne konfiguracje
danych wejściowych. Typowym założeniem jest uznanie, że każda permutacja
danych liczb jest jednakowo prawdopodobna. W następnym podrozdziale prze~
prowadzimy dyskusję tego założenia, ale najpierw zbadajmy jego konsekwencje.
Kiedy uruchamiamy algorytm quicksort dla losowej tablicy wejściowej, nie
jest prawdopodobne, że podziały będą takie same na każdym poziomie, jak
założyliśmy w naszej nieformalnej analizie. Należy oczekiwać, że niektóre po-
działy będą stosunkowo zrównoważone, a inne dosyć nierównoważone. W za~
daniu 8.2-5 trzeba na przykład pokazać, że dla około 80% przypadków proce-
dura PARTITION tworzy podział bardziej zrównoważony niż 9 do I, a dla
około 20% przypadków tworzy podział mniej zrównoważony niż 9 do 1.
W przypadku średnim procedura PARTITION tworzy mieszankę „dob-
rych" i „złych" podziałów. W drzewie rekursji dla śrffiniego przypadku wywo-
łania PARTITION dobre i złe podziały są rozrzucone losowo po całym drzewie.
Ze względów intuicyjnych załó.2llly jednak, że dobre i złe podziały są położone
na przemian i że podziały dobre to przypadki najlepsze, a podziały zie - naj-

192
8.2. CZAS DZIAŁANIA ALGORYTMU QUlCKSORT

gorsze. Na rysunku 8.5a widać dwa kolejne poziomy drzewa rekursji. W korze-
niu drzewa koszt podziału wynosi n, a utworzone podtablice mają rozmiar
n - 1 i 1 - najgorszy przypadek. Na następnym poziomie podtablica wielkości
n - 1 zostaje podzielona zgodnie z najlepszym przypadkiem na dwie podtabli-
ce rozmiaru (n - 1)/2. Załóżmy, że koszt graniczny wynosi 1 dla podtablicy
o długości 1.


/ ~ ······--·················Cl••·
0(n) n ·················--··················il~•·
0(n)
l
/
.....
'-----.._
/~
+
(n-1)12 1 (n-1)/2
(n-1)/2

(b)

Rys. 8.5. (a) Dwa poziomy drzewa rekursji dla algorytmu quicksorl. Podział w korzeniu kosztuje
11 i jest „zły": mamy dwie pod tablice rozmiaru 11 - I i I. Podział pod tablicy rozmiaru n - I
kosztuje n - I i daje „dobry" podział: dwie podtablice rozmiaru (11- 1)/2. (b) Pojedynczy poziom
drzewa rekursji, który jest gorszy niż połączone poziomy z (a), chOCjest bardzo 2'J"Ównoważony

W wyniku połączenia złego i dobrego podziału powstały trzy podtablice


o rozmiarach 1, (n - 1)/2, i (n - 1)/2, co dało koszt 2n -1 = 0(n). Z pewno-
ścią ta sytuacja nie jest gorsza niż sytuacja przedstawiona na rys.8.5b - poje-
dynczy podział, w wyniku którego powstały dwie podtablice o rozmiarach
(n - 1)/2 + 1 i (n - 1)/2, co dało koszt n= @(n). Jednak ta ostatnia sytuacja
jest niemal całkowicie zrównoważona, z pewnością lepsza niż podział 9 do 1.
Intuicyjnie, koszt @(n) złego podziału może zostać wchłonięty w koszt E>(n)
dobrego podziału, a końcowy podział jest dobry. Dlatego koszt działania al-
gorytmu quicksort, gdy poziomy z dobrymi i złymi podziałami występują na
przemian, jest taki jak dla samych dobrych podziałów: wciąż O(nlgn), ale
z większą stalą ukrytą w notacji O. Dokładną analizę średniego przypadku
przedstawimy w podrozdz. 8.4-2.

ZADANIA
8.2-1. Pokaż, że czas działania procedury QtnCKSORT wynosi 0(nlgn), gdy
wszystkie elementy tablicy A mają taką samą wartość.
8.2-2. Pokaż, że czas działania procedury QUICKSORT wynosi 0(n 2), kiedy
tablica A jest posortowana w porządku nierosnącym.
8.2-3. Banki często zapisują operacje dokonywane na rachunku w kolejności
ich przeprowadzania, ale wiele osób lubi otrzymywać swoje wyciągi ban-
kowe z wydatkami zapisanymi w kolejności numerów zrealizowanych cze-
ków. Ludzie na ogól wypisują czek za czekiem z ksiązeczk.i, a sprzedawcy
realizują je dość szybko. Problem zamiany kolejności zgodnej z czasem

193
ROZDZIAŁ 8, OUlCKSORT ·· SORTOWANIE SZYBKIE

przeprowadzania operacji na kolejność zgodną z numerami czeków jest


zatem problemem sortowania prawie posortowanych danych. Uzasadnij,
że procedura lNSERTION-SORT lepiej niż QUICKSORT nadaje się do roz-
wiązywania tego problemu.
8.2-4. Załó2llly, że podziały na każdym poziomie algorytmu quicksort są
dokonywane w stosunku l - er:do er:,gdzie O< er:~ 1/2 jest stalą. Pokaż,
7..enajmniejsza głębokość liścia w drzewie rekursji wynosi około
-lg n/lg(l - er:).(Nie przejmuj się zaokrąglaniem do liczb całkowitych).
* 8.2-5. Pokaż, że dla każdego stałego O < er:~ 1/2 prawdopodobieństwo tego,
że dla dowolnej tablicy danych wejściowych procedura PARTITION utwo-
rzy podział bardziej zrównoważony niż 1 - er:do er:,wynosi około 1 - 2cr:.
Dla jakiej wartości et prawdopodobieństwo otrzymania zrównoważonego
podziału wynosi 1/2?

8.3. Probabilistyczne
wersjealgorytmuquicksort
Badając zachowanie algorytmu quicksort dla średniego przypadku, uczynili-
śmy założenie, że wszystkie permutacje liczb na wejściu są jednak.owo praw-
dopodobne. Kiedy takie założenie jest usprawiedliwione, wielu ludzi wybiera
quicksort jako algorytm sortowania dość dużych ilości danych. Nie można
jednak oczekiwać, że to założenie można poczynić do wszystkich zastosowań.
(Patrz zad. 8.2-3). W tym podrozdziale wprowadzamy pojęcie algorytmu pro-
babilistycznego i opisujemy dwie probabilistyczne wersje algorytmu quicksort,
które nie wymagają powyższego założenia.
Zamiast zakładać coś o rozkładzie danych wejściowych można pewien roz-
kład wymusić. Załóżmy na przykład, że przed posortowaniem tablicy algorytm
quicksort w losowy sposób permu tuje jej elementy, żeby wymusić własność, że
każda permutacja jest jednakowo prawdopodobna. (!N zadaniu 8.34 trzeba
podać algorytm, który w sposób losowy permutuje elementy tablicy o roz-
miarze n w czasie O(n)). Ta mtiana nie poprawia pesymistycznego czasu dzia-
łania algorytmu, ale uniezależnia czas działania od uporządkowania danych
wejściowych.
Algorytm nazywamy probabilistycznym (ang. randomized algorithm), jeśli
jego zachowanie zależy nie tylko od danych wejściowych, lecz również od war~
tości podanych przez generator liczb losowych. Będziemy zakładali, że mamy
do dyspozycji generator liczb losowych RANDOM. Wywołanie RANDOM(a, b)
zwróci liczbę całkowitą z przedziału między a i b, łącznie z końcami, przy czym
każda liczba jest jednakowo prawdopodobna. Na przykład RANDOM(O, 1)
zwraca O z prawdopodobieństwem 1/2 i 1 z prawdopodobieństwem 1/2. Każda
liczba zwrócona przez RANDOM jest niezależna od poprzednio zwróconych
liczb. Można myśleć o RANDOM jako o procedurze zwracającej rezultat rzutu

194
8.3. PROBABILISTYCZNE WERSJE ALGORYTMU OUICKSORT

kostką mającą (b - a+ I) ścianek. (W rzeczywistości większość środowisk


programistycznych oferuje generator liczb pseudolosowych: detenninistyczny
algorytm, który zwraca liczby „wyglądające" na statystycznie losowe).
Probabilistyczna wersja algorytmu quicksort, tak jak wiele innych algoryt-
mów probabilistycznych, ma interesującą własność: żadne konkretne dane wej-
ściowe nie powodują pesymistycznego działania algorytmu. Zamiast tego najgor-
szy przypadek zależy od generatora liczb losowych. Nawet umyślnie nie można
spowodować najgorszego działania algorytmu quicksort, ponieważ losowe per-
mutacje sprawiają, że początkowa kolejność jest nieistotna. ProbabilistyC?.,ny
algorytm zadziała źle tylko wówczas, gdy generator liczb losowych utworzy
pechową permutację. Z zadania 13.4-4 wynika, że niemal wszystkie permutacje
powodują działanie algorytmu quicksort prawie tak dobre, jak w przypadku
średnim: jest bardzo mało pennutacji, które powodują działanie bliskie pesymi-
stycznemu.
Strategia probabilistyczna jest szczególnie dobra, kiedy istnieje wiele spo-
sobów, za pomocą których algorytm może działać, ale trudno jest ustalić, który
z nich jest na pewno dobry. Jeżeli wiele możliwych sposobów jest dobrych, to
dobrą strategią postępowania może być losowe wybranie jednego z nich. Czę­
sto algorytm musi dokonywać wielu wyborów podczas swojego wykonywania.
Jeżeli zalety dobrych wyborów przewyższają wady złych, to losowa strategia
wyborów może dać efektywny algorytm. Zauważyliśmy w podrozdz. 8.2, że
mieszanka dobrych i złych podziałów daje dobry czas działania algorytmu
quicksort, a zatem probabilistyczna wersja algorytmu powinna działać dobrze.
Modyfikując procedurę PARTITION, możemy utworzyć inną, probabilis-
tyczną wersję algorytmu quicksort, w której korzysta się ze strategii losowych
wyborów. W każdym kroku algorytmu quicksort, zanim tablica zostanie po-
dzielona, zamieniamy element A[p] z elementem wybranym losowo z A[p „ r].
Ta modyfikacja zapewnia, że element rozdzielający x = A[p] może być z takim
samym prawdopodobieństwem dowolnym spośród r - p + 1 elementów pod~
tablicy. Dlatego możemy oczekiwać, że w przypadku średnim podział tablicy
wejściowej będzie dość dobrze zrównoważony. Algorytm probabilistyczny,
który rozpoczyna działanie od losowej pennutacji danych wejściowych rów-
nież działa dobrze w średnim przypadku, ale jest trochę trudniejszy do prze-
analizowania niż ta wersja.
Zmiany w procedurach PARTITION i QUICKSORT są niewielkie. W nowej
procedurze dzielącej po prostu dokonujemy zamiany przed wykonaniem po-
działu:

RANDOMIZED-PARTITION(A,p, r)
1 i.._ RANDOM(p, r)
2 zamień A[p]+-+A[iJ
3 returnPARTITION(A, p, r)

195
ROZDZIAŁ 8. QUICKSORT - SORTOWANIE SZVBKIE

W nowym algorytmie quicksort będzie teraz wywoływana procedura RAN-


DOMIZED-PARTITIONzamiast PARTITION:

RANDOMIZED-QUJCKSORT(A, p, r)
1 ifp<r
2 then ą +-RANDOMIZRD-PARTITION(A,
p, r)
3 RANDOMIZED-QUJCKSORT(A, p, q)
4 RANDOMIZED-QUJCKSORT(A, q + I, r)

Przeanalizujemy ten algorytm w następnym podrozdziale.


ZADANIA
8.3-1. Dlaczego analizujemy średni czas działania algorytmu probabilistyczne-
go, a nie jego pesymistyczny czas?
8.3-2. Ile wywołań generatora liczb losowych RANDOMjest wykonywanych
podczas działania RANDOMIZED-QUICKSORT w przypadku najgorszym?
Jak zmieni się odpowiedź, gdy rozpatrzymy przypadek najlepszy?
* 8.3-3. Napisz implementację procedury RANDOM(a, b), która korzysta tylko
z rzutów symetryczną monetą. Jaki jest oczekiwany czas działania Twojej
procedury?
* 8.3-4. Podaj probabilistyczną procedurę, działającą w czasie 0(n), której dane
wejściowe stanowi tablica A[l .. n] i która wykonuje losową permutację
elementów tablicy.

8.4. Analizaalgorytmuquicksort
W podrozdziale 8.2 przekazywaliśmy pewne intuicje o pesymistycznym zacho-
waniu algorytmu quicksort i dlaczego oczekujemy, że algorytm ten będzie
działał szybko. W tym podrozdziale staranniej analizujemy jego zachowanie.
Zaczynamy od analizy przypadku pesymistycznego, która stosuje się zarówno
do procedury QUICKSORT,jaki RANDOMIZED-QUICKSORT, a kończymy ana-
lizą średniego C7.3.SU
działania dla RANDOMIZED-QUICKSORT.

8.4.1. Analiza przypadku pesymistycznego


W podrozdziale 8.2 pokazaliśmy, źe dla algorytmu quicksort najgorszy podział
na każdym poziomie rekursji powoduje, że czas jego działania wynosi 0(n 2),
co było intuicyjnie 11znawaneza pesymistyczny czas działania. Teraz udowod-
nimy to stwierdzenie.
Używając metody podstawiania (patrz podrozdz. 4.1), możemy pokazać,
że czas działania algorytmu quicksort wynosi O(n2 ). Niech T(n) będzie najgor-

196
8.4. ANALIZA ALGORYTMU OUICKSORT

szym czasem działania procedury QUICK.SORT dla danych wejściowych roz-


miaru n. Mamy równanie rekurencyjne

T(n) - max (T(q) + T(n - q)) + 0(n) (8.1)


1,;;q,;;n-1

gdzie parametr q przyjmuje wartości od 1 do n - 1, ponieważ procedura PAR·


TITION tworzy dwa obszary, z których każdy ma co najmniej 1 element. Zga-
dujemy, że Ttn) :s;:;cn2 dla pewnej stałej c. Podstawiając to oszacowanie do
(8.1), otrzymujemy

T(n) <; max (cq' + c(n - q)') + 0(n)


l,;;q„n-1

- c · max (q' + (n- q)') + 0(n)


1,;;ą,;;11-l

Wyrażenie q2 + (n - q)2 przyjmuje maksimum w przedziale 1 :s;:;q ~ n - 1


na jednym z końców przedziału, ponieważ druga pochodna wyrażenia wzglę­
dem q jest dodatnia (patrz zad. 8.4-2). Daje nam to ograniczenie
max (q2 + (n - q)2 ) :s;:;12 + (n - 1)2 = n 2 -2(n - 1). Kontynuując nasze
1,;;q,;;n-1
szacowanie T(n), otrzymujemy

T(n) <; en' - 2c(n - 1) + 0(n)

ponieważ możemy wybrać stałą c dość dużą, żeby wartość wyrażenia 2c(n - 1)
dominowała nad wartością wyrażenia 0(n).

8.4.2. Analiza przypadku średniego


Podaliśmy już intuicyjne uzasadnienie faktu, że średni czas działania procedury
RANDOMIZED-QUICKSORT wynosi 0(nlgn): jeśli podział tworzony przez
RANDOMIZED-PARTITION umieszcza przynajmniej stałą część wszystkich ele-
mentów w jednym obszarze, to drzewo rekursji ma głębokość 00gn) i 0(n)
czasu jest spędzane na każdym z 0(lg n) poziomów. Możemy przeanalizować
oczekiwany czas działania RANDOMIZED-QUICKSORT właśnie przez zrozumie-
nie, jak działa procedura dzieląca. Następnie napiszemy równanie rekurencyj-
ne na średni czas potrzebny do posortowania tablicy n elementów i rozwiąże­
my to równanie, szacując oczekiwany czas działania. W trak.cie rozwiązywania
równania rekurencyjnego znajdziemy dokładne ograniczenia pewnej interesu-
. .
JąceJ sumy.

197
ROZDZIAŁ 8. QUICKSORT- SORTOWANIE S2YBKIE

Analiza procedury dzielącej


Najpierw poczynimy kilka obserwacji dotyczących d7iałania procedury PAR-
TITION. Kiedy PARTITION jest wywoływana w wierszu 3 procedury RANDOMI-
ZED-PARTITION, element A[p] został już wymieniony z losowym elementem
z A[p .. r}. ż.eby uprościć analizę, załóżmy, że wszystkie liczby w tablicy wej-
ściowej są różne. Jeśli tak nie jest, to średni czas działania algorytmu quicksort
nadal wynosi O(nlg n), ale do udowodnienia tego potrzebna jest bardziej
skomplikowana analiza.
Pierwsza obserwacja polega na stwierdzeniu, że wartość q zwracana przez
procedurę PARTITION zależy tylko od rangi x = A[p] wśród elementów A[p .. r].
(Ranga rank(x) liczby x w zbiorze jest to liczba elementów mniejszych lub
równych x). Jeśli n = r - p + I będzie liczbą elementów w A[p .. r], to zamiana
Afp] z losowym elementem z A[p .. r] daje prawdopodobieństwo I/n tego, że
rank(x) = i dla i= 1, 2, ... , n.
Następnie obliczamy prawdopodobieństwa różnych wyników podziałów.
Jeśli rank(x) = 1, to po pierwszej iteracji pętli while w wierszach 4-11 procedu-
ry PARTITION indeks i zatrzyma się na i= p, a indeksjnaj = p. Dlatego, kiedy
zwracane jest q = j, dolna część podziału zawiera tylko element A[p]. Takie
zdarzenie zachodzi z prawdopodobieństwem 1/n,ponieważ jest to prawdopo-
dobieństwo zdarzenia, że rank(x) = 1.
Jeżeli rank(x) ~ 2, to istnieje co najmniej jeden element mniejszy niż
x = A[p]. Zatem przy pierwszej iteracji pętli wbile indeks i zatrzyma się na
i= p, alej zatrzyma się, zanim osiągnie p. Następnie dokonuje się zamiana,
która powoduje umieszczenie A[p] w górnej części podziału. Kiedy procedura
PARTITION zatrzymuje się, każdy z rank(x) - 1 elementów w dolnej części
podziału jest mniejszy niż x. Stąd dla każdego i= 1, 2, ... , n - 1, kiedy
rank(x) ~ 2, prawdopodobieństwo tego, że dolna część podziału ma i elemen-
tów, wynosi 1/n.
Łącząc te dwa przypadki, otrzymujemy konkluzję, że ro1.JI1.iarq - p + I
dolnej części podziału wynosi 1 z prawdopodobieństwem 2/n oraz i z praw-
dopodobieństwem I/n dla i= 2, 3, ... , n - 1.

Równanie rekurencyjne na średni czas działania


Sformułujemy teraz równanie rekurencyjne na oczekiwany czas działania pro-
cedury RANDOMIZ.ED-QUICKSORT. Niech T(n) oznacza średni czas potrzebny
do posortowania n-elementowej tablicy wejściowej. Wywołanie RANDOMI-
ZF.D-QUICKSORT z 1-elementową tablicą wejściową zajmuje czas stały, mamy
zatem T(l) = 0(1). Wywołanie RANDOMIZED-QUICKSORT z tablicą wejściową
A[l .. n] o długości n potrzebuje 0(n) czasu na podział tablicy. Procedura PAR-
TITION zwraca indeks ą, a następnie jest wywoływana rekurencyjnie RANDO-

198
8.4. ANALIZA ALGORYTMU QUICKSORT

MIZED-QUICKSORT z podtablicami wielkości


q i n - q. Stąd średni czas po-
trzebny na posortowanie n--elementowej tablicy można wyrazić równaniem

1( .-, )
T(n) - n T(I) + T(n - I)+ ,I, (T(q) + T(n - q)) + El(n) (8.2)

Wartość q ma niemal jednostajny rozkład, oprócz tego, że wartość q = 1 jest


dwukrotnie bardziej prawdopodobna od innych, jak to zauważyliśmy uprzed-
nio. Korzystając z faktów, że T(l) = 0(1) i T(n - I)= O(n 2 ) z analizy najgor-
szego przypadku, otrzymujemy

1 1
(T(l) + T(n - 1)) - - (0(1) + O(n'))
n n
- O(n)
i stąd wyrażenie E>(n) w równaniu (8.2) może pochłonąć wyrażenie
1
( T(I) + T(n - 1)). Możemy zatem przefonnułować równanie rekurencyjne
n
(8.2) do postaci
J n- 1
T(n) -
n
I
ą=1
(T(q) + T(n - q)) + El(n) (8.J)

Zauważmy, że dla k = 1, 2, ... , n - I każde wyrażenie T(k) sumy występuje raz


jako T(q), a raz jako T(n - q). Łącząc te dwa wyrażenia sumy, otrzymujemy

2 n-1
T(n) -
n
I
i=1
T(k) + El(n) (8.4)

Rozwiązanie równania rekurencyjnego

Możemy rozwiązać równanie rekurencyjne (8.4), używając metody podsta-


wień. Przyjmijmy założenie indukcyjne, że T(n) :i;; anlgn + b dla pewnych sta-
łych a > O i b > O, które trzeba będzie wyznaczyć. Możemy wybrać a i b wy-
starczająco duże, żeby anlgn + b było większe niż T{l). Wtedy dla n> 1 ma-
my podstawienie
2 n-1
T(n) - -
n
I
i=1
T(k) + El(n)
2 n-1
<; I (aklgk + b) + El(n)
n i= 1

199
ROZDZIAŁ 8. QUICKSORT - SORTOWANIE 5ZYBKIE

2an-l 2b
= -- L
nJ:,,,
klgk + -- (n -
n
1) + 0(n)
1

Pokażemy, że suma z ostatniego wiersza może zostać ograniczona przez

n-1 1 1
L
t-,,,1
klgk ~ ···· n lgn - ---n 2
2
2
8
(8.5)

Korzystając z tego ograniczenia, otrzymujemy

T(n)<;-2a(I-n , lgn---n 1 ') +-2b (n-l)+@(n)


n 2 8 n

a
~anlgn- n+2b+0(n)
4

= anlgn + b + (@(n)+ b - : •)

~anlgn+b

ponieważ możemy wybrać a dość duże, żeby wartość wyrażenia an/4 domino-
wała nad wartością. wyrażenia 0(n) + b. Stąd widać, że średni czas działania
algorytmu quicksort wynosi O(nlgn).

Dokładne oszacowanie głównej sumy


Pozostaje udowodnić ograniczenie (8.5) sumy
,-1
I klgk
t"' 1

Skoro każde wyrażenie ma wartość najwyżej nlgn, mamy ograniczenie

,- 1
L klgk ~ n2 1gn
t= 1

które jest ścisłe z dokładnością do stałego czynnika. To ograniczenie nie jest


jednak dosyć silne, żeby rozwiązać równanie rekurencyjne, podstawiając
Ttn) = O(n lgn). Dokładniej, żeby rozwiązać równanie rekurencyjne, potrzebu-
jemy ograniczenia ~ n2 lgn - O(n 2 ),

200
8.4. ANALIZA ALGORYTMU QUICKSORT

Ograniczenie to możemy otrzymać przez podział sumy na dwie części, tak


jak zostało to omówione w podroz.dz. 3.2 (str. 72) Otrzymamy wówczas

11-1 111121-1 11-1


I klgk - I klgk + I ktgk
k=l k""l k=f11/2l

Funkcja lg k w pierwszej sumie po prawej stronie jest ograniczona z góry


przez lg(n/2) = lg n - I. Funkcja lg k w drugiej sum.ie jest ograniczona z góry
przez lg n. Stąd
n-1
L klgk<;(lgn-1)
fn/21-1
L ·-'
k= 1
k+lgn I k

n-1 fll/21-1
-lgnI;k- I k
k=l A"'l

1 2 1 2
~ 2 nlgn-g:n
jeśli n;;;.:2. Jest to ograniczenie (8,5).
ZADANIA
8.4-1. Pokaż, że najlepszy czas działania algorytmu quicksort wynosi O:(nlg n).
8.4-2. Pokaż, że ą 2 + (n - ą) 2 przyjmuje maksimum w przedziale q = l, 2, ... ,
n - 1 dla ą = I lub q = n - I.
8.4-3. Pokaż, że oczekiwany czas działania procedury RANDOMIZF.D-QUICK-
SORTwynosi .Q(nlgn).
8.4-4. Czas działania algorytmu quicksort może zostać w praktyce poprawio-
ny, jeżeli skorzysta się z szybkiego czasu działania sortowania przez wsta-
wianie dla danych wejściowych, które są „prawie" posortowane. Kiedy
quicksort jest wywoływany dla podtablicy, która ma mniej niż k elemen-
tów, niech po prostu zwróci nieposortowaną tablicę. Po powrocie z wywo-
łania algorytmu quicksort uruchom sortowanie przez wstawianie na całej
tablicy, żeby zakończyć jej sortowanie. Pokaż, że ten algorytm sortowania
ma oczekiwany czas działania O(nk + n lg(n/k)). Jak powinno się dobierać
k zarówno w teorii, jak i w praktyce?
* 8.4-5. Udowodnij tożsamość

l 2 1
Jxinxdx = x lnx- x2
2 4
--------~···-
201
ROZDZIAŁ 8. QUICKSORT - SORTOWANIE S2YBKIE

a następnie użyj metody szacowania całkami do uzyskania lepszego niż


,-1
(8.5) ograniczenia górnego na L klgk .
.l CCCl
* 8.4-6. Zastanów się nad modyfikacją procedury PARTITION przez losowe wy-
bieranie trzech elementów z tablicy A i dzielenie względem ich mediany.
Oszacuj prawdopodobieństwo otrzymania w najgorszym przypadku po-
działu i:x do (1 - a), jako funkcji a: dla O < Cl<1.

Problemy

8-1. Poprawność podziału


Podaj dokładne uzasadnienie, że procedura PARTITION z podrozdz. 8.1 jest
poprawna. Udowodnij, że:

(a) Indeksy i ij nigdy nie odnoszą się do elementu A spoza przedziału [p .. r].
(b) Indeks j nie jest równy r, kiedy procedura PARTITION kończy działanie
(czyli że podział zawsze jest nietrywialny).
(c) Każdy element A[p ..;1 jest mniejszy lub równy każdemu elementowi
A[j + 1 „ r], kiedy procedura PARTITION kończy działanie.

8-2. Algorytm podziałówLomuta


Rozważ następującą wersję procedury PARTITION, której autorem jest N. Lo-
muto. żeby podzielić A[p „ r], w wersji tej tworzy się dwa obszary, A[p „ i]
i A[i + l ..J1, tak że każdy element w pierwszym obszarze jest mniejszy lub
równy x = A[r], a każdy element w drugim obszarze jest większy niż x.

LOMlITO-PARTITION(A, p, r)
l x~ A[r]
2 i+-p-1
3 forj+-ptor
4 do if A[j] .; x
5 theni+-i+l
6 zamień A[i]-A[j]
7 ili<r
8 then return i
9 else return i - l

(a) Uzasadnij poprawność procedury LOMUTO-PARTITION.


(b) Ile razy element może być przesuwany przez PARTITION i przez LOMUTO-
-PARTITION?

202
PROBLEMY

(c) Uzasadnij, że procedura LOMlITO-PARTITION, podobnie jak PARTITION,


działa na n-elementowej tablicy w czasie ®(n).
(d) Jak wpływa zastąpienie PARTITION przez LoMlITO-PARTITION na czas
działania procedury QUICKSORT, gdy wszystkie liczby w tablicy wejściowej
są takie same?
(e) Zdefmiuj procedurę RANDOMIZED-LOMlITO-PARTITION,która zamienia
A[r] z losowo wybranym elementem w A[p .. r], a następnie wywołuje proce-
durę LOMlITO-PARTITION. Wykaż, że prawdopodobieństwo zwrócenia wa-
rtości q przez RANDOMIZED-LOMUTO-PARTITION jest równe prawdopodo-
bieństwu zwrócenia tej wartości przez RANDOMIZED-PARTITION.

8-3. ,,Głupie" sortowanie


Profesorowie Howard i Fine zaproponowali następujący „elegancki" algorytm
sortowania:

STOOGE-SORT(A, i, j)
I if A[i] > A[j]
2 tbeo zamień A[i] +-+ A[j]
3 ifi+l~j
4 tben return
s k-L(j-i+IJ/JJ t> Zaokrąglenie w dól.
6 STOOGE-SORT(A, i, j - k) [> Pierwsze dwie trzecie.
7 STOOGE-SORT(A, i+ k, J) [> Ostatnie dwie trzecie.
8 STOOGE-SORT(A, i, j - k) [> Znowu pierwsze dwie trzecie.

(a) Uzasadnij, że STOOGE-SORT(A, 1, /ength[A]) poprawnie sortuje tablicę


A[! .. n], gdzie n - /ength[A].
(b) Podaj równanie rekurencyjne na pesymistyczny czas działania STOOGE-
·SORT i dokładne asymptotyczne (notacja 0) oszacowanie na pesymistycz-
ny czas działania.
(c) Porównaj pesymistyczny czas działania S'rOOGE·SORT z czasem działania
sortowania przez wstawianie, scalanie, kopcowanie i sortowania szybkiego.
Czy profesorowie zasługują na podwyżkę?

84. Głębokość
stosu dla algorytmu quicksort
Algorytm QUICKSORT z podrozdz. 8.1 zawiera dwa rekurencyjne wywołania
samego siebie. Po wywołaniu procedury PARTITION jest rekurencyjnie sorto-
wana lewa podtablica, a potem prawa podtablica. Drugie rekurencyjne wywo-
łanie QUICKSORT nie jest naprawdę potrzebne: można go uniknąć przez za-
stosowanie struktury iteracyjnej. Ta metoda, nazywana eliminacją rekursji koń­
cowej (ogonowej), jest stosowana automatycznie przez dobre kompilatory. Oto
wersja algorytmu quicksort, która symuluje rekursję ogonową.

--------------------~---~-
203
ROZDZIAŁ 8. QUICKSORT - SORTOWANIE SZVBKIE

QUICKSORT'(A, p, r)
1 whilep<r
2 do t> Dziel i sortuj lewą podtablicę.
3 ą-PARTITION(A, p, r)
4 QUICKSORT'(A, p, q)
5 p-q+l

(a) Udowodnij, że QIBCKSORT'(A, 1, length[A]) poprawnie sortuje tablicę A.

Kompilatory na ogól wykonują procedury rekurencyjne przez użycie stosu,


który zawiera istotne informacje, m.in. wartości parametrów dla każdego wy-
wołania rekurencyjnego. Informacja o ostatnim wywołaniu jest na szczycie
stosu, a informacja o pierwszym wywołaniu - na spodzie. Kiedy procedura jest
wywoływana, informacja o tym jest wkładana na stos; gdy się zakończy, infor-
macja jest zdejmowana ze stosu. Ponieważ zakładamy, że parametry będące
tablicami są w rzeczywistości reprezentowane jako wskaźniki, zatem informa-
cja o każdym wywołaniu procedury wymaga 0(1) miejsca na stosie. Głębokość
stosu to maksymalna ilość miejsca na stosie, jaka jest wykorzystywana podczas
całego obliczania.

(b) Opisz scenariusz, w którym głębokość stosu QUICKSORT' wynosi 0(n) dla
n-elementowej tablicy wejściowej.
(c) Zmodyfikuj kod dla QUICKSORT' tak, żeby w najgorszym przypadku głę-
bokość stosu wynosiła 0(lgn).

8,.5, Podział względem mediany trzech wartości


Jednym ze sposobów poprawienia procedury RANDOMJZBD-QUICKSORT jest
podział względem elementu x, który jest wybrany z pewnym rozmysłem., a nie
przez losowe wybranie elementu tablicy. Jednym z częstych podejść jest meto-
da mediany trzech wartości: wybierz x jako medianę (środkową wartość) zbioru
trzech elementów losowo wybranych z podtablicy. Na potrzeby tego zadania
załóżmy, że elementy tablicy A[l „ nJsą różne i n ;;i, 3. Oznacz111yposortowaną
tablicę wyjściową przez A'[l .. n]. Używając metody mediany trzech wartości
do wybrania elementu rozdzielającego x, określamy p 1 = Pr{x = A'[i]}.

(a) Podaj dokładnywzór na p 1 jak.o funkcji n oraz i dla i= 2, 3, ... , n - I.


(Zauważ, Ze p 1 =Pn= O).
(b) W jakim stopniu zwiększyliśmy prawdopodobieństwo wybrania
x - A'[L(n + l)/2j], mediany A[! .. n], w stosunku do zwykłej implemen-
tacji? Załóż, że n-+ oo, i podaj ograniczenie na stosunek tych prawdopo-
dobieństw.

=~-----------------------
204
UWAGI DO ROZDZIAŁU

(c) Jeśli 7.definiujemy „dobry'' podział jako wybór x = A'[i], gdzie


n/3 :E; i~ 2n/3, to o ile zwiększyliśmy prawdopodobieństwo uzyskania do-
brego podziału w porównaniu do zwykłej implementacji? (W.~kazówka:
Przybliż sumę przez całkę).
(d) Uzasadnij, że dla algorytmu quicksort metoda mediany trzech wartości
wpływa tylko na zmianę stałej jego czasu działania wynoszącego fl(n lg n).

Uwagido rozdziału
Procedura quicksort została wynaleziona przez Hoare'a [98]. Praca Sedgewi-
cka [174] jest dobrym źródłem wiadomości o szczegółach implementacji i ich
znaczeniu. Zalety algorytmów probabilistycznych były sformułowane przez
Rabina [165].
Rozdział 9

Sortowaniew czasie
liniowym

Opisaliśmy już kilka algorytmów, za pomocą których można posortować


n liczb w czasie O{nlgn). Dla sortowania przez scalanie oraz sortowania przez
kopcowanie to górne ograniczenie dotyczy pesymistycznego przypadku; dla
algorytmu sortowania szybkiego dotyczy to tylko średniego czasu działania.
Co więcej, dla każdego z tych algorytmów potrafimy wskazać ciąg n liczb, dla
których czas działania wynosi O:(nlgn).
Wszystkie wymienione algorytmy mają pewną istotną własność; porządek,
który wyznaczają, jest oparty tylko i wyłącznie na wynikach porównań między
elementami. Takie algorytmy sortowania nazywamy algorytmami sortującymi
za pomocą porównań. Wszystkie algorytmy sortujące, o których dotychczas
wspominaliśmy, sortują za pomocą porównań.
W podroz.dziale 9.1 wykażemy, że każdy algorytm sortujący musi w pesymi-
stycznym przypadku wykonać n(nlgn) porównań, aby posortować ciąg o dłu­
gości n elementów. Stąd wynika wniosek, że sortowanie przez scalanie i sortowa-
nie przez kopcowanie są asymptotycznie optymalne, tzn. nie istnieje algorytm
sortujący za pomocą porównań szybszy o więcej niż stały współczynnik.
W podrozdziałach 9.2, 9.3 i 9.4 przedstawimy trzy algorytmy sortujące,
działające w czasie liniowym: sortowanie przez zliczanie (ang. counting sort),
sortowanie pozycyjne (ang. radix sort) i sortowanie kubełkowe (ang. bucket
sort). Dolna granica O(nlgn) nie obowiązuje w odniesieniu do tych algoryt-
mów, ponieważ do posortowania elementów wykorzystują one nie tylko ope-
• • •
raCJę porownywarua.

9.1. Dolneograniczeniadla problemusortowania


W algorytmach sortujących za pomocą porównań jedynym źródłem informacji
o porządku między elementami ciągu (a 1 , a 2 , ... , a,.) są porównania między
nimi. Dla danych elementów a1 oraz al możemy wykonać jedno z porównań:
9.1. DOLNE OGRANICZENIA DLA PROBLEMU SORTOWANIA

a;< ai, a,~ aj, a1 = a;, aj~ aj lub a1 > ai, aby wyznaczyć ich względne położe­
nie. Nie możemy natomiast badać wartości elementów w sposób, który po-
zwalałby
. '
na określenie
.
ich względnego położenia inaczej niż przez bezpośred-
nie porownan1e.
W tym podrozdziale zakładamy bez zmniejszenia ogólności, że wszystkie
elementy do posortowania są parami różne. Przy takim założeniu porównania
typu a; = ai są zbędne, możemy więc przyjąć, że w ogóle nie są wykonywane.
Zauważmy też, że porównania następujących typów: a; ~ a;, a1 ~ a , a; > aj
1
i aj < aj są sobie równoważne, gdyż ich wykonanie daje taką samą infonnację
o wzajemnym położeniu a1 oraz aj. Możemy więc przyjąć, że wykonujemy
tylko porównania typu a1 ~ aj.

Drzewadecyzyjne
Algorytmy sortujące za pomocą porównań można prezentować w postaci
drzew decyzyjnych. Drzewo decyzyjne przedstawia porównania wykonywane
przez algorytm sortujący dla danych ustalonego rozmiaru. Sterowanie, prze-
pływ danych i inne aspekty algorytmu nie są w drzewie decyzyjnym uwzględ­
nione. Na rysunku 9.1 jest przedstawione drzewo decyzyjne odpowiadające
algorytmowi sortowania przez wstawianie z pod.rozdz. 1.1, działającemu na
ciągu 3-elementowym.

>

,.
.,,.,
(2.1,3)
,,
.,,.,>

'<
) (2,3,1) (3,2,1)

Rys. 9.1, Drzewo decyzyjne odpowiadające algorytmowi sorlowania przez wstawianie, działającemu
na ciągu 3-eleme:ntowym. Istnieje 3! = 6 możliwych permutacji ciągu wejściowego, więc drzewo
decyzyjne musi mieć co najmniej 6 liści

Każdy węzeł wewnętrzny w drzewie decyzyjnym ma etykietę a 1 : aj dla pew-


nych i oraz j z przedziału 1 ~ i, j ~ n, gdzie n jest liczbą elementów w ciągu
wejściowym. Z każdym liściem jest związana permutacja (n:(1), n:(2), ..., 11:(n)).
(W podrozdziale 6.1 są podane elementarne informacje na temat permutacji).
Wykonanie algorytmu sortującego odpowiada przejściu ścieżki od korzenia
drzewa decyzyjnego do jednego z jego liści. W każdym węźle wewnętrznym
zostaje wykonane porównanie typu a1 ~ ai. W lewym poddrzewie znajdują się
porównania wykonywane przez algorytm, jeśli okaże się, że a1 ~ aj, a prawe

207
ROZDZIAŁ 9. SORTOWANIE W CZASIE LINIOWYM

poddrzewo zawiera możliwe scenariusze dla przeciwnego przypadku, tzn. gdy


z porównania wynika, że a; > a1. Jeśli dochodzimy do liścia, oznacza to, że
algorytm znalazł już uporządkowanie elementów all(JJ ~ afl(i) ~ ••• ~ a11(,.)· Jeśli
algorytm sortujący jest poprawny, to każda z n1permutacji musi wystąpić jako
jeden z liści drzewa decyzyjnego.

Dolne ograniczenie na pesymistyczny czas sortowania


Długość najdłuższej ścieżki od korzenia drzewa decyzyjnego do dowolnego
z jego liści odpowiada pesymistycznej liczbie porównań wykonywanych przez
algorytm sortujący. Dolne ograniczenie na wysokość drzew decyzyjnych stano-
wi więc jednocześnie dolne ograniczenie na czas działania dowolnego algoryt-
mu sortującego za pomocą porównań. Następujące twierdzenie stanowi asym-
ptotycznie najlepsze tego typu dolne ograniczenie.

TwtERDZENIE 9.1.
Każde drzewo decyzyjne, odpowiadające algorytmowi poprawnie sortującemu
n elementów, ma wysokość !l(nlgn).

DOWÓD
Rozważmy drzewo decyzyjne o wysokości h odpowiadające algorytmowi sor-
tującemu n elementów. Liczba permutacji n elementów wynosi n!, a każda
permutacja odpowiada jednoznacznie pewnemu uporządkowaniu elementów,
drzewo musi więc mieć co najmniej n! liści. Drzewo o wysokości h nie może
mieć więcej niż 2" liści, mamy zatem

skąd po zlogarytmowaniu obu stron otrzymujemy

h ;a,;lg(n!)

ponieważ funkcja lg jest rosnąca. Ze wzoru Stirlinga (2.1 I) wynika, że

n!>(:)"
gdzie e = 2,71828 ... jest podstawą logarytmu naturalnego, więc

h;,lg(;)"
= nlgn - nlge
= [l(nlgn) •
208
9.1. DOLNE OGRANICZENIA DLA PROBLEMU SORTOWANIA

WNIOSEK9.2.
Sortowanie przez kopcowanie i sortowanie przez scalanie są asymptotycznie
optymalnymi algorytmami sortującymi za pomocą porównań.

DOWÓD
Górne ograniczenie O(nlgn) dla algorytmów sortowania przez kopcowanie
i przez scalanie jest równe dolnej granicy O(n lgn) z twierdzenia 9.1.


ZADANIA

9.1-1. Jaka jest najmniejsza możliwa głębokość liścia w drzewie decyzyjnym


odpowiadającym algorytmowi sortującemu za pomocą porównań?
9.1-2. Wyprowadź dokładne oszacowanie asymptotyczne na lg(n!), nie korzys-
tając ze wzoru Stirlinga. Oblicz w tym celu sumę L" lg k, używając metod
,I: "' 1
z podrozdz. 3.2.
9.1-3. Wykaż, że nie istnieje algorytm sortujący za pomocą porównań, który
działa w czasie liniowym dla co najmniej połowy z n! możliwych, istotnie
różnych danych długości n. Czy odpowiedź ulegnie zmianie, jeśli zapytamy
o ułamek 1/n(l/2") wszystkich danych długości n?
9.1-4. Profesor Salomon twierdzi, że dolna granica O(nlgn) na sortowanie
n liczb nie dotyczy jego komputera, w którym sterowanie w programie
może podjąć jedną z trzech dróg po każdym porównaniu a1 : aj, w zależno­
ści od tego, który z trzech możliwych wyników został stwierdzony: a, < a ,
1
a1 = aj czy a; > ai. Wykaż, że profesor nie ma racji. W tym celu udowod-
nij, że liczba nowego rodzaju porównań, potrzebnych do posortowania
n elementów, wynosi O(nlgn).
9.1-5. Udowodnij, że w pesymistycznym przypadku potrzeba 2n - 1 porów-
nań, aby scalić dwie posortowane listy zawierające po n elementów.
9.1-6. Niech dany będzie ciąg n elementów do posortowania. Ciąg wejściowy
składa się n/k podciągów, pok elementów w każdym. Elementy w każdym
podciągu są mniejsze niż elementy w następnym podciągu oraz większe od
elementów w poprzednim podciągu. Aby więc posortować cały ciąg o dłu­
gości n, wystarczy posortować każde k elementów we wszystkich n/k pod-
ciągach. Wykaż, że dolna granica na liczbę porównań wykonywanych
w tym wariancie problemu sortowania wynosi O(nlgk). (Wskazówka: Pro-
ste zsumowanie dolnych ograniczeń na posortowanie poszczególnych pod-
ciągów nie jest poprawnym dowodem tego dolnego ograniczenia).

209
ROZDZIAŁ 9. SORTOWANIE W CZASIE LINIOWYM

9.2. Sortowanieprzezzliczanie
W sortowaniu przez zliczanie zakładamy, że każdy z n sortowanych elementów
jest liczbą całkowitą z przedziału od I do k dla pewnego ustalonego k. Jeśli
k = O(n), to sortowanie działa w czasie O(n).
Główna idea sortowania przez zliczanie polega na wyznaczeniu dla każdej
liczby wejściowej x, ile elementów jest mniejszych od x. Mając tę liczbę, znamy
dokładną pozycję x w ciągu posortowanym, wystarczy ją więc bezpośrednio na
tej pozycji umieścić. Jeśli na przykład 17 elementów jest mniejszych od x, to
w ciągu posortowanym x powinien znaleźć się na pozycji 18. To postępowanie
należy nieco zmodyfikować w sytuacji, kiedy dozwolonych jest więcej elemen-
tów o tej samej wartości, ponieważ nie chcemy, by wszystkie tak.ie elementy
trafiły na tę samą pozycję.
W procedurze COUNTING-SORT przyjmujemy, że dane wejściowe są za-
warte w tablicy A[l .. n], więc length[A] = n. Potrzebne będą nam jeszcze dwie
dodatkowe tablice: w B[l .. n] zostaną umieszczone posortowane dane wejścio­
we, a w tablicy C[l „ k] będziemy zapamiętywać tymczasowe dane pomocnicze.

COUNTING-SORT(A, B, k)
I fori+-1 tok
2 do C[i] ~ O
3 for j +- l to length[A]
4 do C[A[ ill ~ C[A[ iTI+ 1
5 [> C[i] zawiera teraz liczbę elementów równych i.
6 fori+-2tok
7 do C[i] ~ C[i] + C[i - l]
8 [> C[i] zawiera teraz liczbę elementów mniejszych lub równych i.
9 for j +- length[A] downto 1
10 do B[C[A[ iil] ~ A[ i]
11 C[A[ i]]~ C[A[ iil - 1

Przykład działania algorytmu sortowania przez zliczanie znajduje się na


rys. 9.2. Po zainicjowaniu procedury w wierszach 1-2, w wierszach 34 rozpa-
trujemy po kolei wszystkie elementy. Jeśli wartość elementu jest równa i, to
zwiększamy C[i] o I. Dlatego po wykonaniu wierszy 34 w C[i] znajduje się
liczba elementów równych i, dla każdego i= 1, 2, ... , k. W wierszach 6-7
wyznaczamy dla każdego i= 1, 2, ... , k, ile elementów jest mniejszych lub
równych i; odbywa się to przez dodawanie po kolei wartości tablicy C.
Wreszcie w wierszach 9-11 wszystkie elementy A[jJ zostają umieszczone na
właściwych pozycjach w tablicy B. Jeśli wszystkie elementy są parami różne, to
przy pierwszym wykonaniu wiersza 9, dla każdego A[j] wartość C[A[JI] jest
numerem poprawnej pozycji elementu A[j] w tablicy wyjściowej, gdyż dokład-
--·-----------------------------
210
9,2. SORTOWANIE PRZEZ ZLICZANIE

12345678 12345678
,1,1,1,1,1,1,1,1,1 123456 B ... a
123456 cl2l2l•l1l7 lsl 123456

cl2lol2l,l•I •I cl2l2l•l•l 1lsl


,,, (b) (c)

B B 12345678

123456 123456 •l 1 l1 1,1,1,1,1,1,1


cl1l2l•l•l1lsl cl1l2l•lsl1lsl
(d) (e)

Rys. 9.2. Działanie procedury CoUNTING·SoRTdla tablicy wejściowej A[l .. 8], w której każ.dy ele-
ment jest dodatnią liczbą całkowitą nie większą od k = 6. (a) Tablica A oraz pomocnicza tablica
C po wykonaniu wiersza 4. (b) Tablica. C po wykonaniu wiersza 7. (c)--(e)Tablica B oraz pomoc-
nicza tablica C po wykonaniu odpowiednio jednej, dwóch oraz trzech iteracji pętli w wierszach
9-1L Tylko jasnoszare elementy tablicy B zostały wypełnione. (f) Ostateczna zawartośc tablicy B

nie C[A[j]] elementów jest mniejszych lub równych A[j]. Ponieważ jednak
elementy nie zawsze są parami różne, więc zmniejszamy C(A[j]] o jeden za
każdym razem, gdy wstawiamy wartość A[j] do tablicy B. Dzięki temu następ­
ny element o wartości A[j] Geśli taki istnieje) zostanie wstawiony do tablicy
B na pozycję o numerze o jeden mniejszym.
Jaki jest czas działania algorytmu sortowania przez zliczanie? Pętla for
w wierszach 1-2 działa w czasie O(k), pętla for w wierszach 3-4 działa w czasie
O(n), pętla for w wierszach 6-7 działa w czasie O(k), a pętla for w wierszach
9-11 działa w czasie O(n). Całkowity czas działania procedury wynosi więc
O(n + k). W praktyce używamy sortowania przez zlicranie, jeśli k = O(n); wte-
dy czas sortowania wynosi O(n).
Sortowanie przez zlicza.nie ma czas działania lepszy niż wynosi dolna gra-
nica O(nlgn) wyprowadzona w podrozdz. 9.1, ponieważ nie jest to sortowanie
za pomocą porównań. Zauważmy, że w procedurze CoUNTING-SORTnigdzie
nie występuje operacja porównywania dwóch elementów. Zamiast tego w sor-
towaniu przez zliczanie wykorzystujemy faktyczne wartości elementów, co po-
zwala nam wyznaczyć ich właściwe pozycje w ciągu posortowanym. Widać
więc, że ograniczenie dolne O(nlgn) dla problemu sortowania przestaje obo-
wiązywać, jeśli wychodzimy poza model sortowania za pomocą porównań.
Ważną własnością sortowania przez zliczanie jest jego stabilność: liczby
o tych samych wartościach występują w tablicy wynikowej w takiej samej ko-
lejności jak w tablicy początkowej. Oczywiście własność stabilności jest istotna

211
ROZDZIAŁ 9. SORTOWANIE W CZASIE LINIOWYM

tylko wtedy, gdy z sortowanymi elementami są związane dodatkowe dane.


O tym, jak ważna jest stabilność, przekonamy się w następnym podrozdziale.

ZADANIA
9.2-1. Zilustruj (podobnie jak na rys. 9.2) działanie procedury COUNTING-
-SORTdla tablicy A - (7, I, 3, I, 2, 4, 5, 7, 2, 4, 3).
9.2-2. Wykaż, że procedura COUNTING-SORTsortuje stabilnie.
9.2-3. Zmodyfikujmy pętlę for w wierszu 9 procedury COUNTJNG-SORTw na-
stępujący sposób:

9 for j +- 1 to length[A]

Wykaż, że algorytm nadal działa poprawnie. Czy nowa wersja algorytmu


zapewnia stabilność?
9.2-4. Załóżmy, że algorytm sortowania powinien umieszczać posortowany
ciąg bezpośrednio na wyjściu. Zmodyfikuj procedurę COUNTING-SORT
tak, aby wypisywała posortowany ciąg, nie zajmując więcej pamięci niż
potrzeba dla tablic A i C. (Wskazówka: Połącz elementy z A o tej samej
wartości klucza w listy. Gdzie można znaleźć „wolne" miejsce na prze-
chowywanie wskaź.ników listy z dowiązaniami?)
9.2-5. Zaprojektuj algorytm, który dla danych n liczb z przedziału od 1 do
k wykonuje wstępne obliczenia, a następnie na podstawie obliczonych da-
nych pozwala w czasie 0(1) określić, ile z danych n liczb leży w przedziale
[a .. b]. Twój algorytm powinien wykonywać wszystkie potrzebne oblicze-
nia wstępne w czasie O(n + k).

9.3. Sortowaniepozycyjne
Sortowanie pozycyjne to sposób sortowania stosowany w maszynach sortują­
cych karty, które teraz można zobaczyć już tylko w muzeach techniki kom-
puterowej. Każda karta miała 80 kolumn, a w każdej kolumnie można było
wybić dziurkę w jednym z 12 miejsc. Maszynę sortującą karty można było
mechanicznie „zaprogramować", aby rozdzieliła plik kart do 12 pojemników,
w zależności od położenia dziurki w ustalonej kolumnie. Operator mógł wtedy
zebrać karty, pojemnik po pojemniku, tak aby na wierzchu znajdowały się
karty przedziurkowane na pierwszym miejscu, zaraz pod nimi karty przedziur-
kowane na drugim miejscu itd.
Do zapisu cyfr dziesiętnych wystarczy I Omiejsc w każdej kolumnie. (Pozo-
stałe dwa miejsca są używane do kodowania znaków nienumerycznych). Licz-
ba d-cyfrowa zajmuje przy takim kodowaniu d kolumn. Ponieważ urządzenie
sortujące karty może w jednym kroku zbadać tylko jedną kolumnę w pliku

212
9.3. SORTOWANIE POZYCYJNE

kart, więcdo sortowania n kart, na których są zapisane liczby d-cyfrowe,


należy zaprojektować odpowiedni algorytm sortujący.
Intuicja podpowiada, aby posortować liczby według najbardziej znaczącej
cyfry, następnie rekurencyjnie posortować karty w każdym z pojemników, po
czym złożyć je w jeden plik kart w odpowiedniej kolejności. Niestety, ponieważ
karty w 9 ze wszystkich 10 pojemników należy odłożyć podczas sortowania
każdego z pojemników, takie postępowanie powoduje tworzenie wielu tym-
czasowych plików kart, co bardzo komplikuje algorytm. (Patrz zad. 9.3-5).
W sortowaniu pozycyjnym stosujemy mało intuicyjny trik, polegający na
posortowaniu kart w pierwszej kolejności według najmniej znaczącej cyfry. Na-
stępnie karty składa się w jeden plik w ten sposób, aby karty z pojemnika
Oznajdowały się przed kartami z pojemnika 1, które z kolei poprzedzają karty
z pojemnika 2 itd. Potem sortujemy cały plik według drugiej najmniej znaczą­
cej cyfry i składamy powstałe pliki podobnie jak w pierwszej fazie. Powtarza-
my ten proces dla wszystkich d pozycji. Okazuje się, że wtedy karty są już
poprawnie posortowane, jeśli interpretujemy je jako d-cyfrowe liczby. Do po-
sortowania pliku kart wystarczy więc wykonać d faz. Na rysunku 9.3 jest
pokazane działanie sortowania pozycyjnego dla „pliku" złożonego z siedmiu
liczb 3-cyfrowych.

329 720 720 329


457 355 329 355
657 436 436 436
839 457 839 457
436 657 355 657
7'/i! 329 457 720
355 839 657 839
1 1 1
Rys. 9.3. Działanie sortowania pozycyjnego dla ciągu złożonego z siedmiu liczb 3--cyfrowych.
W pierwszej kolumnie majduje się ciąg wejSciowy. W następnych kolumnach są pokazane ciągi
powstające w wyniku sortowania kolejno według coraz bardziej maczących cyfr. Pionowa strz.alka
wskazuje pozycję, według której sortowaliśmy, aby otrzymać dany ciąg z poprzedniego

W sortowaniu pozycyjnym istotny jest fakt, że sortowanie według kolej-


nych pozycji jest stabilne. Sortowanie wykonywane przez urządzenie sortujące
jest stabilne, lecz operator musi uważać, aby nie zmienić kolejności kart znaj-
dujących się w określonym pojemniku, mimo że wszystkie karty znajdujące się
w nim mają taką samą cyfrę na rozpatrywanej pozycji.
W zwyczajnym komputerze, który jest maszyną sekwencyjną ze swobod-
nym dostępem do pamięci, sortowanie pozycyjne stosuje się czasami do sor~
towania rekordów, w których na klucz składa się wiele pól. Na przykład sor-
towanie według daty oznacza sortowanie względem trzech pól: roku, miesiąca
i dnia. Możemy zastosować algorytm sortujący z funkcją porównującą, która

213
ROZDZIAŁ 9. SORTOWANIE W CZASIE LINIOWYM

dla danych dwóch dat porównuje lata; jeśli są sobie równe, to porównuje
miesiące; jeżeli i te się sobie równają, to porównuje dni. 7.amiast tego możemy
posortować zbiór dat trzy razy za pomocą pewnego stabilnego algorytmu sor-
towania: najpierw według dni, potem według miesięcy i w końcu według lat.
W następującej procedurze przyjm.ujemy, że każdy element w n-elemen-
towej tablicy A ma d cyfr, gdzie cyfra na pozycji 1 jest najmniej znacząca,
a cyfra na pozycji d jest najbardziej znacząca.

RADJX-SORT(A,d)
1 forirltod
2 do posortuj stabilnie tablicę A według cyfry i

Poprawność sortowania pozycyjnego można udowodnić przez indukcję


względem numeru pozycji, według której sortujemy (patrz zad. 9.3-3). Analiza
czasu działania tej procedury zależy od stabilnego sortowania, używanego jako
pomocnicza procedura sortująca. Jeśli każda z cyfr należy do przedziału od
1 do k oraz k nie jest zbyt duże, to należy użyć sortowania przez zliczanie.
Każdy przebieg przez n liczb d..cyfrowych wymaga czasu S(n + k). Wykonuje-
my w sumie d przebiegów, więc całkowity czas działania sortowania pozycyj-
nego wynosi wtedy €>(dn+ kd). Jeśli d jest stalą, a k = O(n), to sortowanie
pozycyjne działa w czasie liniowym.
Czasami przyjm.uje się założenie, że liczba bitów w słowie maszynowym
komputera wynosi 0(1gn); dla ustalenia uwagi przyjmijmy, że jest ona równa
dlgn, gdzie d jest pewną dodatnią stałą. Możemy więc traktować sortowane
liczby jako d--cyfrowe liczby zapisane w układzie o podstawie n. Dla przykładu
przyjmijmy, że sortujemy milion liczb 64-bitowych. Traktując je jako 4--cyf.
rowe liczby zapisane w układzie o podstawie 2 16 , możemy je posortować za
pomocą sortowania pozycyjnego w zaledwie czterech krokach. Daje to spory
zysk w porównaniu ze zwyczajnym sortowaniem za pomocą porównań działa­
jącym w czasie @(nlgn), w którym potrzeba wykonać około lg n= 20 operacji
na jedną liczbę do posortowania. Niestety, wersja sortowania pozycyjnego,
w której korzysta się z sortowania przez zliczanie jako pomocniczego stabil-
nego sortowania, w przeciwieństwie do wielu algorytmów sortujących za po-
mocą porównań, nie działa w miejscu. Jeżeli więc zależy nam bardziej na mini-
malizacji zajętości pamięci, to lepszy może się okazać na przykład algorytm
sortowania szybkiego.

ZADANIA
9.3-1. Zilustruj (podobnie jak na rys. 9,3) działanie procedury RADIX-SORT
dla następującego ciągu angielskich słów: COW, DOG, SEA, RUG,
ROW, MOB, BOX, TAB, BAR, EAR, TAR, DIG, BIG, TEA, NOW,
FOX

214
9.4. SORTOWANIE KUBEŁKOWE

9.3-2. Które z następujących algorytmów sortujących są stabilne: sortowanie


przez wstawianie, sortowanie przez scalanie, sortowanie przez kopcowa-
nie, sortowanie szybkie? Podaj metodę, która z dowolnego algorytmu sor-
tującego tworzy stabilny algorytm sortujący. Ile dodatkowej pamięci i cza-
su wymaga zastosowanie Twojej metody?
9.3-3. Udowodnij przez indukcję poprawność sortowania pozycyjnego.
W którym miejscu dowodu potrzebne jest założenie, że pomocniczy al-
gorytm sortowania jest stabilny?
9.34. Skonstruuj algorytm, który pozwala posortować n liczb całkowitych
z przedziału od 1 do n2 w czasie O(n).
* 9.3-S. Ile faz potrzeba w najgorszym przypadku do posortowania d-cyfrowych
liczb, jeśli zastosujemy pierwszy z opisanych algorytm sortujący karty? Ile
może się w tym czasie pojawić tymczasowych plików kart?

kubełkowe
9.4. Sortowanie
Średni czas działania sortowania kubełkowego jest liniowy. Podobnie jak sor-
towanie przez zliczanie, sortowanie kubełkowe jest szybkie, ponieważ przyj-
muje się pewne szczególne założenia o danych wejściowych. W sortowaniu
przez zliczanie przyjmowaliśmy założenie, że elementy do posortowania są ma-
łymi liczbami całkowitymi. Przy analizie sortowania kubełkowego będziemy
zakładać, że dane wejściowe są liczbami rzeczywistymi wybieranymi losowo
z przedziału [O, I), zgodnie z rozkładem jednostajnym. (Definicja rozkładu
jednostajnego znajduje się w podrozdz. 6.2).
Sortowanie kubełkowe opiera się na triku polegającym na podziale prze-
działu [O, 1) na n podprzedziałów jednakowych rozmiarów, tzw. kubełków,
a następnie „rozrzuceniu" n liczb do kubełków, do których należą. Ponieważ
liczby są jednostajnie rozłożone w przedziale [O, I), więc oczekujemy, że w każ­
dym z kubełków nie będzie ich zbyt wiele. Aby otrzymać ciąg wynikowy, sor-
tujemy najpierw liczby w każdym z kubełków, a następnie wypisujemy je, prze-
glądając po kolei kubełki.
W procedurze BuCKET-SORTprzyjmujemy, że dana jest n-elementowa tabli-
ca A, a każdy element A[i] w tablicy spełnia nierówności O ~ A[i] < 1. W proce-
durze korzystamy również z pomocniczej tablicy list (kubełków) B[O .. n~ 1]
oraz zakładamy, że są dostępne elementarne operacje na tych listach. (Implemen-
tacja tego typu elementarnych operacji na listach jest opisana w po drozd z. 11.2).

BUCKET-SORT(A)
l n - tength[A]
2 fori-lton
3 do wstaw A[i] do listy B[lnA[i]J]

215
ROZDZIAŁ 9. SORTOWANIE W CZASIE LINIOWYM

4 fori-Oton-1
5 do posortuj listę
B[i] przez wstawianie
6 połącz listy B[OJ,B[l], ..., B[n - 1] dokładnie w tej kolejności

Na rysunku 9,4 jest pokazane działanie sortowania kubełkowego dla tablicy


zawierającej 10 liczb.

o
,, " ,
2 :O,l7 1
3 '.ó.;w 2

40,U 3

5
6 ,0.?4
• '5
o.i),
7
8 ,o;u: ' '

'""'

9 ,O,a::J
'
8
' ' '
"""
"

10 9

(a) (b)
Rys. 9.4. Działanie procedury BuacET-SoRT. (a) Tablica A[l .. IO]. (b) Tablica B[O .. 9] posortowa-
nych list po wykonaniu wiersza S procedury. Na liście o numerze i majdują się wartości z prze-
działu [i/10, (i + 1)/10). Posortowany ciąg powstaje przez połączenie list w następującej kolejności:
B(O], 8(11 ..., B{9]

się
teraz sprawdzeniem poprawności działania sortowania ku-
Zajmiemy
bełkowego. Rozważmy w tym celu dwa elementy A[i] oraz A[j]. Jeśli oba
trafią do tego samego kubełka, to w ciągu wynikowym wystąpią w poprawnej
kolejności względem siebie, ponieważ wszystkie liczby z tego kubełka zostały
posortowane przez wstawianie, Przyjmijmy więc, że elementy A[i] oraz A[j]
należą do różnych kubełków. Niech będą to odpowiednio kubełki o numerach
i' orazj'; przyjmijmy też bez zmniejszenia ogólności, że i' <j'. Po połączeniu
list w wierszu 6 elementy z listy B[i1 znajdują się przed elementami z listy BU1,
więc element A[i] poprzedza element A[j] w ciągu wynikowym. Wystarczy
zatem wykazać, że A[i] ~ A[j]. Jeśli założymy przeciwnie, to otrzymamy

i' - L•A!iJJ
;,, LnA[jJJ

co prowadzi do sprzeczności, bo i' < j'. Wykazaliśmy więc, że sortowanie ku-


bełkowe jest poprawnym algorytmem sortującym.

216
9.4. SORTOWANIE KUBEŁKOWE

Z kolei przeanalizujemy czas działania procedury BUCKET-SORT.Zauważ­


my, że pesymistyczny czas wykonywania wszystkich wierszy oprócz 5 wynosi
O(n). Pozostaje więc dokonać analizy czasu, potrzebnego do posortowania
wszystkich list przez wstawianie, w wierszu 5.
Niech n; będzie zmienną losową oznaczającą liczbę elementów umieszczo-
nych w liście (kubełku) B[i]. Sortowanie przez wstawianie działa w czasie kwa-
dratowym (patrz podrozdz. 1.2), więc oczekiwany czas posortowania elemen-
tów na liście B[i] wynosi E[O(nl)] = O(E[nłJ). Całkowity oczekiwany czas po-
sortowania elementów na wszystkich listach wynosi zatem

:f: O(E[n/]) - o(:~:


E[nll) (9.1)

Aby obliczyć tę sumę, musimy określić rozkłady zmiennych losowych n 1• Ma-


my n elementów i n list. Prawdopodobieństwo, że dany element trafi do listy
B(i], wynosi 1/n, ponieważ do każdej listy trafiają elementy z 1/n części całego
przedziału [O, I). Sytuacja jest więc analogiczna do przykładu rozmieszczania
kul w pojemnikach z pod.rozdz. 6.6.2: marny n kul (elementów) oraz n pojem-
ników (list), a każda kula z jednakowym prawdopodobieństwem p = 1/n tra-
fia do określonego pojemnika, niezależnie od pozostałych kul. Zmienna loso-
wa n1 ma więc rozkład dwumianowy; stąd prawdopodobieństwo zdarzenia, że
n1 = k, wynosi b(k; n, p), czyli wartość oczekiwana wynosi E[ni] =np= l,
a wariancja Var{n1J = np(I - p) = 1 - 1/n. Korzystając z równości (6.30),
otrzymujemy

E[nłJ = Var[n1] + E 2 [n1]


1 2
-1--+l
n
1
-2-
n
- 0(1)

Podstawiając to oszacowanie do równania (9.1), otrzymujemy, że oczekiwany


czas działania sortowania kubełkowego jest liniowy.

ZADANIA

9.4-1. Zilustruj (podobnie jak na rys. 9.4) działanie procedury BUCK.ET-SORT


dla tablicy A - (0,79, 0,13, 0,16, 0,64, 0,39, 0,20, 0,89, 0,53, 0,71, 0,42).
9.4-2. Jaki jest pesymistyczny czas działania algorytmu sortowania kubełko­
wego? Jak w prosty sposób zmodyfikować ten algorytm, aby oczekiwany
czas był nadal liniowy, a czas pesymistyczny wynosił O(n lg n)?

217
ROZDZIAŁ 9. SORTOWANIE W CZASIE LINIOWYM

* 9.4-3. Danych jest n punktów p 1 = (x;, y1) leżących w kole jednostkowym, tzn.
jest spełniony warunek O< xf + yf ~ l dla i= 1, 2, ..., n. Załóżmy, że
punkty są rozmieszczone jednostajnie, czyli prawdopodobieństwo zdarze-
nia, że punkt znajduje się w dowolnym ustalonym obszarze kola jedno-
stkowego, jest proporcjonalne do pola tego obszaru. Zaprojektuj algorytm
działający średnio w czasie E>(n), sortujący n punktów według ich odległo­
ści d, = J"~r·+-Yf-od początku układu współrzędnych. (W.fkazówka: Po-
dziel koło na obszary odpowiadające jednostajnemu rozkładowi punktów
na kole jednostkowym).
* 9.44. Dystrybuantę P(x) zmiennej losowej X definiuje się jako P(x) =
= Pr{X ~ x}. Niech liczby z losowego ciągu mają ciągłą dystrybuantę P,
której wartości można liczyć w czasie 0(1). Zaprojektuj algorytm sortują­
cy losowe ciągi liczb, którego średni czas działania jest liniowy.

Problemy
9-1. Dolne ograniczenia na średni czas działania sortowania
za pomocą porównań
Naszym celem będzie wykazanie, że dolna granica na oczekiwany czas działa­
nia deteiministycznych lub probabilistycznych algorytmów sortowania za po-
mocą porównań wynosi O(nlgn). Rozpoczniemy od zbadania deterministycz-
nego algorytmu sortowania za pomocą porównań A, któremu odpowiada
drzewo decyzyjne TA. Zakładamy, że każda permutacja danych dla A jest jed-
nakowo prawdopodobna.

(a) Załóżmy, że z każdym liściem TA jest związane prawdopodobieństwo, iż


zostaje on osiągnięty na losowych danych wejściowych. Wykaż, że dokład­
nie n! liści ma prawdopodobieństwo 1/n!, a pozostałe mają prawdopodo-
bieństwo O.
(b) Niech D(1) oznacza zewnętrzną długość ścieżek drzewa T(czyli sumę głę­
bokości wszystkich liści w T). Niech T będzie drzewem o k > 1 liściach
oraz niech RT i LT będą odpowiednio prawym i lewym poddrzewem drze-
wa T. Wykaż, że D(T) = D(RT) + D(LT) + k.
(c) Niech d(m) będzie minimalną wartością D(T) dla wszystkich drzew
To m liściach. Wykaż, że d/,k) = min 1 ,,,, {dl.z)+ d/,k - 1) + k). (Wska-
zówka: Rozważ drzewo To k liściach, dla którego wartość D(1) jest mini-
malna. Niech i będzie liczbą liści w RT, a k - i liczbą liści w LT).
(d) Wykaż, że dla danej wartości k funkcja ilgi + (k- 1)lg(k - 1) osiąga mi-
nimum dla i= k/2. Wywnioskuj stąd, że d(k) = O(klgk).
(e) Wykaż, że D(TA) = O(n! lg(n!)) dla TA, oraz wywnioskuj stąd, że oczekiwa-
ny czas sortowania n elementów wynosi O(nlgn).

218
UWAGI DO ROZDZIAŁU

Rozważmy teraz probabilistyczny algorytm B, sortujący za pomocą porównań.


Możemy uogólnić model drzew decyzyjnych przez wprowadzenie dwóch rodza-
jów węzłów w takich drzewach: zwykłe węzły z porównaniami oraz węzły „zran-
domizowane". Węzeł zrandomizowany odpowiada w algorytmie B losowemu
wyborowi postaci RANDOM(l, r); taki węzeł ma r synów, z których każdy ma
jednakowe prawdopodobieństwo wyboru w czasie działania algorytmu.

(f) Wykaż, że dla każdego zrandomizowanego algorytmu B, sortującego za


pomocą porównań, istnieje deterministyczny algorytm A, sortujący za po-
mocą porównań, który nie wykonuje średnio więcej porównań niż B.

9-2. Liniowe sortowanie w miejscu

(a) Niech w tablicy znajduje się n rekordów do posortowania, o kluczach rów-


nych O lub 1. Podaj prosty algorytm sortowania w miejscu (tzn. używający
tylko stałej dodatkowej pamięci) działający w czasie liniowym.
(b) Czy Twój algorytm z punktu (a) można zastosować do posortowania ku-
bełkowego n rekordów, których klucze są b-bitowymi liczbami, w czasie
O(bn)? Wyjaśnij jak lub dlaczego nie można.
(c) Niech klucze n rekordów będą liczbami całkowitymi z przedziału od 1 do
k. Jak zmodyfikować sortowanie przez zliczanie, aby można było za jego
pomocą sortować w miejscu w czasie O(n + k)? Możesz użyć O(k) dodat-
kowej pamięci. (W.vkazówka: Zastanów się, jak to zrobić dla k = 3).

Uwagi do rozdziału
Drzew decyzyjnych do badania metod sortowania za pomocą porównań uży­
wali Ford i Johnson [72]. Wszechstronna monografia o metodach sortowania,
autorstwa Knutha [123], zawiera wiele wariacji na temat sortowania, między
innymi podane przez nas dolne ograniczenie złożoności problemu sortowania
za pomocą porównań. Dolne granice złożoności problemu sortowania przy
użyciu uogólnień modelu drzew decyzyjnych badał intensywnie Ben-Or [23].
Knuth podaje, że sortowanie przez zliczanie zostało wynalezione w 1954 r.
przez H. H. Sewarda. Przypisuje mu też pomysł użycia sortowania przez zlicza-
nie jako sortowania pomocniczego w sortowaniu pozycyjnym. Sortowanie po-
zycyjne, począwszy od najmniej znaczącej cyfry, od dawna było powszechnie
stosowane przez operatorów mechanicznych urządzeń sortujących karty. We-
dług Knutha pierwszą publikacją wspominającą tę metodę jest dokument
z 1929 r. autorstwa L. J. Comrie'a, opisujący urządzenia związane z kartami
dziurkowanymi. Sortowanie kubełkowe jest stosowane od 1956 r., kiedy to
ogólna jego idea została zaproponowana przez E. J. lssaca i R. C. Singletona.
Rozdział 1O --·-···-·--·----------------

Medianyi statystyki

pozycyJne

W uporządkowanym zbiorze n-elementowym i-ty co do wielkości element bę­


dziemy nazywać i-tą statystyką pozycyjną. Na przykład minimum zbioru jest jego
pierwszą statystyką pozycyjną (i =
I), a maksimum jest n-tą statystyką pozycyj-
ną (i= n). Mediana to, mówiąc nieformalnie, ,,środkowy" element zbioru. Jeśli
n jest nieparzyste, to mediana jest jednozoacznie określona jako element na
pozycji i= (n + 1)/2. Jeśli n jest parzyste, to zbiór ma dwie mediany; są nimi
elementy na pozycjach i = n/2 oraz i = n/2 + I. Niezależnie więc od parzystości
n mediany znajdują się na pozycjach i= l(n + 1)/2J oraz i= f(n + 1)/21.
W tym rozdziale zajmiemy się problemem wyboru i-tej statystyki pozycyj-
nej zbioru n elementów. Dla wygody będziemy zakładać, że zbiór składa się
z parami różnych liczb, ale wszystkie nasze rozważania można łatwo przenieść
na zbiory z powtórzeniami. Problem wyboru można sformułować w następują­
cy sposób:

Dane wejściowe: Zbiór A (różnych parami) n liczb oraz liczba i taka, że


1 ~ i~n.
Wynik: Element xEA większy od dokładnie i - 1 innych elementów zbioru A.

Problem wyboru można rozwiązać w czasie O(nlgn), sortując najpierw


liczby za pomocą sortowania przez kopcowanie albo przez scalanie, a następ­
nie odczytując i-ty element w posortowanej tablicy. Przekonamy się jednak, że
istnieją szybsze algorytmy.
W podrozdziale 10.1 zajmiemy się problemem wyboru minimum i maksi-
mum w zbiorze uporządkowanym. Ciekawszy jest ogólny problem wyboru,
któremu są poświęcone kolejne dwa podro7.działy. W podrozdziale 10.2 prze-
prowadzimy analizę praktycznego algorytmu, którego średni czas działania
wynosi O(n). W podrozdziale 10.3 opiszemy algorytm ciekawy głównie z teore-

220
10.1. MINIMUM I MAKSIMUM

tycznego punktu widzenia, który działa w czasie O(n) także w przypadku pesy-
mistycznym.

10.1. Minimum i maksimum


Ile potrzeba porównań, aby wyznaczyć minimum w zbiorze n-elementowym?
Łatwo jest osiągnąć górne ograniczenie n - 1 porównań: wystarczy porównać
po kolei każdy element zbioru z najmniejszym dotychczas napotkanym, aktua-
lizując dotychczasowe minimum w razie potrzeby. W następującej procedurze
zakładamy, że elementy zbioru są umieszczone w tablicy A, gdzie /enght{A]= n.

MIN!MUM(A)
1 min+- A[lJ
2 for i - 2 to /ength[A]
3 do jf min > A[i]
4 tben min-A[i]
5 return min

W podobny sposób można wyznaczyć maksimum za pomocą n - I po-


, '
rownan.
Można zadać pytanie, cz,y tyle porównań jest koniecznych? Odpowiedź na
nie jest pozytywna: można wykazać, że n - 1 porównań stanowi dolne ograni-
czenie dla problemu wyznaczania minimum. Każdy algorytm wyznaczający
minimum można traktować jako turniej między elementami. Każde porówna-
nie odpowiada pojedynkowi w turnieju, przy czym mniejszy z elementów wy-
grywa pojedynek. Każdy element, oprócz zwycięzcy turnieju, musi przegrać co
najmniej jeden pojedynek, konieczne jest więc wykonanie n - I porównań, aby
wyznaczyć minimum. Wynika stąd, że algorytm MTNIMUMjest optymalny ze
względu na liczbę wykonywanych porównań.
Ciekawym zagadnieniem jest wyznaczenie oczekiwanej liczby wykonań
wiersza 4. Rozwiązując problem 6-2, można się przekonać, że wartość ta wy-
nosi 0(lgn).

Jednoczesne wyznaczanie minimum i maksimum


W pewnych zastosowaniach zachodzi potrzeba wyznaczenia zarówno mini-
mum, jak i maksimum w zbiorze n elementów. Może to być na przykład pro-
gram graficzny skalujący zbiór punktów o współrzędnych ekranowych (x, y)
tak, aby zmieścił się na innym urządzeniu graficznym. W tym celu program
musi najpierw wyznaczyć minimum i maksimum wartości współrzędnych na
obu osiach.

221
ROZDZIAŁ 10. MEDIANY ł STATYSTYKI POZYCYJNE

Nie jest trudno podać algorytm, który wyznacza minimum oraz maksi-
mum w zbiorze n-elementowym, wykonujący asymptotycznie optymalną f!(n)
liczbę porównań. Wystarczy niezależ.nie wyznaczyć minimum i maksimum,
stosując po n - 1 porównań, czyli w sumie 2n - 2 porównania.
Okazuje się jednak, że wystarczy 3 In/21 porównań, aby wyznaczyć zarów-
no minimum, jak i maksimum. W tym celu pamiętamy minimum i maksimum
dotychczas rozważonych elementów. Zamiast porównywać każdy element
z dotychczasowym minimum i maksimum (co daje koszt dwóch porównań na
jeden element), analizujemy kolejne elementy w parach. Porównujemy naj-
pierw parę elementów ze sobą, a następnie mniejszy z nich z dotychczasowym
minimum, większy z dotychczasowym maksimum, co w sumie wymaga trzech
porównań na dwa elementy.

ZADANIA
10.1-1. Wykaż, żew pesymistycznym przypadku drugą co do wielkości spo-
śród n liczb możoa wyznaczyć za pomocą n+ flgnl - 2 porównań.
(Wskazówka: Wymacz również najmniejszy element).
* 10.1-2. Wykaż, że w pesymistycznym przypadku do wyznaczenia zarówno ma-
ksimum, jak: i minimum z n liczb jest koniecznych f3n/2l - 2 porównań.
(Wskazówka: Rozważ, ile liczb może potencjalnie stanowić albo maksi-
mum, albo minimum, oraz zbadaj, jak jedno porównanie może wpłynąć na
te wielkości).

10.2. Wybór w oczekiwanymczasieliniowym


Ogólny problem wyboru wydaje się trudniejszy od prostego problemu wyzna-
czania minimum, lecz o dziwo, asymptotyczny czas potrzebny do rozwiązania
obu problemów jest tak.i sam: E>(n). W tym podrozdziale przedstawiamy al-
gorytm dla problemu wyboru, zaprojektowany za pomocą metody „dziel
i zwyciężaj". Algorytm RANDOMIZED-SELECT jest podobny do algorytmu sor-
towania szybkiego (quicksort) z rozdz. 8. Podobnie jak w algorytmie quick-
sort, pomysł polega na rekurencyjnym podziale tablicy wejściowej. W przeci-
wieństwie jednak do algorytmu quicksort, w którym wywołujemy procedurę
rekurencyjnie dla obu części podziału, procedura RANDOMIZED-SELECT zo-
staje wykonana tylko dla jednej z części podziału. Różnica ta odbija się znaczą­
co na analizje złożoności: oczekiwany czas działania sortowania szybkiego wy-
nosi S(nlgn), natomiast oczekiwany czas działania procedury RANDOMIZED-
-SELECT wynosi tylko 0(n).
Procedura RANDOMIZED-SELECT korzysta z procedury RANDOMIZED-PA-
RTITION przedstawionej w pod.rozdz. 8.3. Podobnie więc jak RANDOMIZED-
-QUICK.SORT, jest to algorytm probabilistyczny, ponieważ jego zachowanie za-

222
10.2. WYBÓR W OCZEKIWANYM CZASIE LINIOWYM

leży w części od wyników działania generatora liczb losowych. Następująca


wyznacza i-ty co do wielkości element w tab-
procedura RANDOMIZED-SELECT
licy A[p .. rJ.

RANDOMIZED-SELECT(A, p, r, z)
1 ifp=r
2 then return A[p]
3 q +- RANDOMIZED-PARTITION(A,p, r)
4 k~ą-p+1
5 ifi~k
6 then return RANDOMIZED-SELECT(A,p, q, i)
7 else return RANDOMIZED-SELECT(A,q + 1, r, i - k)

Po wywołaniu procedury RANDOMIZED-PARTITIONw wierszu 3 tablica


A[p .. r] zostaje podzielona na dwie niepuste pod.tablice A[p .. q] oraz A[q + 1 „ r]
takie, że każ..dy element A[p .. q] jest mniejszy od każdego elementu A[q + 1 .. r].
W wierszu 4 zostaje obliczona liczba k elementów w podtablicy A[p .. q]. Na jej
podstawie algorytm może określić, w której z podtablic, A[p .. q] czy
A[q + I .. r], znajduje się i-ty co do wielkości element. Jeśli i~ k, to szukany
element znajduje się w dolnej części podziału i zostaje rekurencyjnie wybrany
z pod.tablicy A[p .. q] w wierszu 6. Jeśli natomiast i> k, to szukany element
znajduje się w górnej części podziału. Wiemy wtedy, że wszystkie k wartości
znajdujące się w podtablicy A[p .. qJsą mniejsze od i-tego co wielkości elementu
w tablicy, więc szukany element jest (i - k)-tym co do wielkości elementem
podtablicy A[q + 1 .. r], który zostaje wyznaczony rekurencyjnie w wierszu 7.
Pesymistyczny czas działania procedury RANDDMIZED-SELECTwynosi
S(n 2 ) (nawet jeśli szukamy po prostu minimum!), ponieważ możemy mieć
wyjątkowego pecha i zawsze dzielić zbiór względem największego pozostałego
elementu. Jednak zachowanie się tego algorytmu w średnim przypadku jest
w pełni zadowalające, a ponieważ jest on probabilistyczny, to żadne dane wej-
ściowe nie wymuszają pesymistycznego zachowania.
Zajmiemy się teraz wyznaczeniem górnego ograniczenia T(n) na oczekiwa-
ny czas działania procedury RANDOMIZED-SELECT dla tablicy o n elementach.
W podrozdziale 8.4 zauważyliśmy, że algorytm RANDOMIZED-PARTITION wy-
znacza podział, którego dolna część ma 1 element z prawdopodobieństwem
2/n, a i elementów z prawdopodobieństwem I/n, dla i= 2, 3, ... , n - 1. Za-
kładając, że funkcja T(n) jest monotonicznie rosnąca, w najgorszym. przypadku
w procedurze RANDOMIZED-SELECTi-ty element zawsze należy wyznaczyć
w większej części podziału. Mamy zatem następującą zależność rekurencyjną:

1(
T(n) <; n T(max(l, n - 1))
.-,
+ .~, T(max(k, n - k))
)+ O(n)

223
ROZDZIAŁ 10. MEDIANY I STATYSTYKI POZVCYJNE

1(
<, - T(n - 1) + 2
,-1
T(k)I )
+ O(n)
n fl:"'n/21
2 n-1
- -- L (k) + O(n)
n [l:=n/21
Drugi wiersz wynika z pierwszego, ponieważ max(l, n - 1) = n - l oraz

k, jeśli k-;, rn/21


max(k, n - k) - {
n-k jeśli k < 1n/2l
'
JeMi n jest nieparzyste, to kawy składnik T(in/21),T(1n/2l+ 1), ... , T(n -1)
występuje dwa razy w sumie, a jeśli n jest parzyste, to każdy składnik
T(in/21+ I), T(in/21+ 2), ..., T(n - 1) występuje dwa razy, a składnik
n fn/21) występuje raz. w każdym z tych przypadków suma z pierwszego
wiersza jest ograniczona z góry przez sumę w drugim wierszu, Trzeci wiersz
wynika z drugiego, gdyż w przypadku pesymistycznym 7\n - 1) = O(n 2 ), więc
składnik 1 T(n - 1) można wciągnąć pod składnik O(n).
n
Rozwią7,emy tę zależność rekurencyjną przez podstawienie. Załóżmy, że
T(n) :E;en dla pewnej stałej e, dla której są spełnione warunki początkowe
zależności rekurencyjnej. Stosując tę hipotezę indukcyjną, mamy

2 n-1
T(n) <, - Ick + O(n)
n r~=n/21
2c
<, ,;·
(,-1 r.,1-1
)
,I k - ,L k + O(n)
1 1

,;c(n-1)-:
(;-1)(;)
+ O(n)

-c(!•-~)+o(n)
:E;en

ponieważ możemy dobrać tak duże c, aby c(n/4 + 1/2) było większe niż ustało~
ny składnik rzędu O(n).

224
10,3. WYBÓR W PESYMISTYCZNYM CZASIE LINIOWYM

Stąd wynika, że wyznaczenie każdej statystyki pozycyjnej, a zwłaszcza me-


diany, wymaga średnio czasu liniowego.

ZADANIA

10.2-1. Napisz iteracyjną wersję procedury RANDOMIZED-SELECT.


10.2-2. Załóżmy, że chcemy użyć procedury RANDOMIZED-SELECT do wyzna-
czenia minimalnego elementu w tablicy A= (3, 2, 9, O, 7, 5, 4, 8, 6, 1).
Opisz ciąg podziałów, który powstaje w wyniku pesymistycznego zacho-
wania się procedury RANDOMIZED-SELECT.
10.2-3. Przypomnijmy, że jeśli w tablicy mogą się znajdować równe sobie ele-
menty, to procedura RANDOMIZED-PARTITIONdzieli pod.tablicę A[p .. r]
na dwie niepuste pod tablice A[p .. q] oraz A[q + I .. r] takie, że każdy ele-
ment w A[p .. qJ jest mniejszy lub równy dowolnemu elementowi
z A[q + 1 .. rJ. Czy procedura RANDOMIZED-SELECTdziała poprawnie
w sytuacji, gdy w tablicy znajdują się równe sobie elementy?

10.3. Wybór w pesymistycznym


czasieliniowym
Zajmiemy się teraz algorytmem wyboru, który w pesymistycznym przypadku
działa w czasie O(n). Podobnie jak RANDOMIZED-SELECT,algorytm SELECT
wyznacza szukany element przez rekurencyjne dzielenie tablicy wejściowej.
Trik polega tutaj na tym, że gwarantujemy dobry podział tablicy. Algorytm
SELECTużywa deterministycznej procedury podziału PARTITlON z algorytmu
quicksort (patrz podrozdz. 8.1), lecz procedura ta dostaje teraz element, wzglę­
dem którego ma zostać wykonany podział, jako argument.
Procedura SELECTwyznacza i-ty co do wielkości element w n-elementowej
tablicy w następujących krokach.

I. Podziel n elementów w tablicy wejściowej na Ln/5J grup po 5 elementów


oraz dokładnie jedną grupę, do której należy pozostałych n mod 5 elemen-
tów.
2. Wyznacz medianę każdej z fn/51 grup, sortując przez wstawianie elementy
w każdej grupie (co najwyżej 5 elementów) i wybierając środkowy element.
(Jeśli grupa ma parzystą liczbę elementów, to wybierz większą z dwóch
median).
3. Wywołaj rekurencyjnie procedurę SELECT, aby wyznaczyć medianę x zbio-
ru ln/5"] median wyznaczonych w kroku 2.
4. Podziel tablicę wejściową względem mediany median x za pomocą zmodyfi-
kowanej wersji procedury PARTITION. Niech k będzie liczbą elementów
w dolnej części podziału; wtedy w górnej części będzie n - k elementów.

225
ROZDZIAŁ 10. MEDIANY I STATYSTYKI POZYCYJNE

5. Wywołaj rekurencyjnie procedurę SELECT,aby wyznaczyć i-ty co do wiel-


kości element w dolnej części podziału, jeśli i~ k, lub (i - k)-ty element
w górej części, jeśli i > k.

Rys. 10.1. Analiza algorytmu SELECT.Wszystkie elementy są oznaczone jak.o małe kółeczka Kolum-
ny odpowiadają grupom. Mediany grup są omaczone na biało, a mediana median x jest wyróżnio­
na etykietą. Str1J11kiprowadzą od większych do mniejszych elementów. Widać więc, że 3 elementy
z każ.dej grupy elementów na prawo od x są większe niż x, a 3 elementy z każdej grupy elementów
na lewo od x są mniejsze niż x. Elementy większe od x są przedstawione na szarym tle

Zanim zajmiemy się analizą czasu działania procedury SELECT,wyznaczy-


my dolne ograniczenie na liczbę elementów większych od elementu x, wzglę­
dem którego dokonujemy podziału. Rysunek 10.1 może ułatwić zrozumienie
poniższych rachunków. Co najmniej połowa median wyznaczonych w kroku
2 jest większa lub równa medianie median x. Stąd wynik.a, że w co najmniej
In/51 grupach są po 3 elementy większe od x, oprócz jednej grupy, która ma
mniej niż 5 elementów, jeśli 5 nie dzieli się bez reszty przez n. Jedna z tych grup
sama zawiera x. Odliczając te dwie grupy, wnioskujemy, że liczba elementów
większych od x jest nie mniejsza niż

Analogicznie, liczba elementów mniejszych od x wynosi co najmn1eJ


3n/10 - 6. Wynika stąd, że w pesymistycznym przypadku procedura SELECT
zostaje wywołana rekurencyjnie w kroku 5 dla zbioru (7n/10 + 6)-elementowego.
Możemy teraz zapisać zależność rekurencyjną, opisującą pesymistyczny
czas działania T(n) algorytmu SELECT.Kroki I, 2 i 4 można wykonać w czasie
O(n). (Krok 2 składa się z O(n) wywołań procedury sortowania przez wstawia-
nie na zbiorach rozmiaru 0(1)). Krok 3 działa w czasie T(fn/51), a krok 5 co
najwyżej w czasie T(7n/10 + 6), jeśli przyjmiemy założenie, że T jest funkcją
monotonicznie rosnącą. Zauważmy, że 7n/10 + 6 < n dla n> 20 oraz że dla

226
10.3. WYBÓR W PESYMISTYCZNYM CZASIE LINIOWYM

danych o długości mniejszej niż 80 procedura wyboru działa w czasie 0(1).


Otrzymujemy więc następującą zależność rekurencyjną:

®(!), jeśli n~ 80
T(n),;; { T(in/51) + T(7n/10 + 6) + O(n), jeśli n> 80

Wykażemy przez podstawienie, że jej rozwiązaniem jest funkcja liniowa.


Przyjmijmy, że T(n) ~ en dla pewnej stałej c oraz wszystkich n ~ BO.Korzy-
stając z tej hipotezy indukcyjnej, otrzymujemy z naszej zależności rekuren-
cyjnej, że

T(n),;; c1n/5l + c(7n/10 + 6) + O(n)


~ cn/5 + c + ?cn/10 + 6c + O(n)

~ 9cn/10 + 7c + O(n)

~ en

ponieważ można wybrać c wystarczająco duże, aby c(n/10 - 7) było większe


niż składnik rzędu O(n) dla każdego n> 80. Pesymistyczny czas działania pro-
cedury SELECTjest więc liniowy.
Podobnie jak przy sortowaniu za pomocą porównań (patrz podrozdz. 9.1),
procedury SELECToraz RANDOMIZED-SELECTwyznaczają względny porządek
między elementami tylko przez porównywanie elementów. Stąd liniowy czas
działania nie wynika re szczególnych założeń na temat danych, tak jak dla
algorytmów sortowania z rozdz. 9. Sortowanie w modelu z porównaniami
wymaga czasu !l(nlgn), nawet jeśli chodzi o średni czas działania (patrz prob-
lem 9-1), więc metoda wyboru i-tego elementu przez posortowanie wszystkich
elementów i odczytanie wartości na pozycji i-tej, przedstawiona na początku
tego rozdziału, jest asymptotycznie nieoptymalna.

ZADANIA

10.3-1. W algorytmie SELECT wszystkie elementy są dzielone na grupy po


5 elementów. Czy ten algorytm będzie działał w czasie liniowym, jeśli bę­
dziemy tworzyć grupy po 7 elementów? Jaka jest odpowiedź w przypadku
podziału na grupy po 3 elementy?
10.3-2. Wykaż, że w algorytmie SELECT liczba elementów większych od me-
diany median x oraz liczba elementów mniejszych niż x jest nie mniejsza
niż In/41,jeśli n ~ 38.
10.3-3. Wykaż, że można zaimplementować algorytm quicksort tak, aby
w przypadku pesymistycznym działał w czasie O(nlgn).
* 10.3-4. Załóżmy, że algorytm wyznaczający i-tą co do wielkości liczbę spośród
n liczb może wykonywać na nich tylko operację porównywania. Wykaż, że

227
ROZDZIAŁ 10. MEDIANY I STATYSTYKI POZYCYJNE

nie wykonując żadnych dodatkowych porównań, można wyznaczyć, które


z i - 1 liczb są mniejsze od i-tej oraz które z n - i są od niej większe.
10.3-5. Przyjmij, że dany jest algorytm w postaci „czarnej skrzynki", który
w pesymistycznym przypadku wyznacza medianę w czasie liniowym. Za-
projektuj algorytm, który używając tej „czarnej skrzynki", wyznacza
w czasie liniowym dowolną statystykę pozycyjną.
10.3-{;. Kwantyle rzędu k w zbiorze n-elementowym, to k - I statystyk pozy-
cyjnych, które dzielą zbiór uporządkowany na k równolicznych (z dokład­
nością do 1) podzbiorów. Zaprojektuj algorytm działający w czasie
O(nlgk), wyznaczający dla danego zbioru kwantyle k-tego rzędu.
10.3-7. Zaprojektuj algorytm działający w czasie O(n), który dla danego zbio-
ru S parami różnych n kluczy oraz liczby dodatniej k ~ n wyznacza k liczb
w S, które są najbliższe medianie zbioru S.
10.3-8. Niech X[l .. n) i Y(l .. n] będą dwiema tablicami, zawierającymi ciągi
uporządkowane o długości n. Podaj algorytm działający w czasie O(lgn},
wyznaczający medianę wszystkich 2n elementów znajdujących się w tab-
licach X i Y.

Rys. 10.2. Chcemy wyznaczyć pozycję rurociągu wschód-zachód, dla której całkowita długość odnóg
północ-południe jest najmniejsm

10.3-9. Profesor Olay jest konsultantem koncernu naftowego, który planuje


budowę dużego rurociągu przebiegającego ze wschodu na zachód przez
pola naftowe, na których znajduje się n wież wiertniczych. Do każdej wie-
ży ma dochodzić odnoga głównego rurociągu po najkrótszej możliwej dro-
dze (albo na północ, albo na południe), tak jak na rys. 10.2. Jakiego al-
gorytmu powinien użyć profesor dla zadanych współrzędnych x i y wież,

228
PROBLEMY

aby wyznaczyć optymalne położenie głównego rurociągu (czyli takie, dla


którego suma długości odnóg jest minimalna)? Wykaż, że można takie
położenie wyznaczyć w czasie liniowym.

Problemy
10-1. Sortowanie największych i elementów
Dla danego zbioru n liczb chcemy wyznaczyć oraz posortować i największych
spośród nich, używając algorytmu opartego tylko na porównaniach. Zastosuj
optymalne (pod względem pesymistycznego czasu działania) algorytmy imple-
mentujące podane metody oraz dokonaj analizy czasu ich działania jako funk-
cji n oraz i.

(a) Posortuj liczby oraz wypisz i największych spośród nich.


(b) Zbuduj kolejkę priorytetową oraz wywołaj i razy procedurę EXfRACT-MAX.
(c) Zastosuj algorytm wyboru do wyznaczenia (n - i+ 1)-szej liczby, podziel
zbiór względem niej oraz posortuj i największych liczb.

10-2. Mediana ważona


Dla n parami różnych elementów x 1 , x 2 , ... , xn o dodatnich wagach w1 , w 2,

... ,Wn takich, że r"


/; 1
W;= 1, medianą ważoną jest element Xt Spełniający warunki

oraz

(a} Wykaż, że mediana elementów x 1 , x 2 , ••• , x„ jest medianą ważoną X; z wa-


gami w 1 = l/n dla i= 1, 2, ..., n.
(b) Jak wyznaczyć medianę ważoną n elementów w pesymistycznym czasie
O(nlgn), używając sortowania.
(c) Wskaż, jak wyznaczać medianę ważoną w pesymistycznym czasie E>(n}
przy użyciu algorytmu wyznaczania mediany, takiego jak SELECT z pod-
rozdz. 10.3.

Problem lokalizacji urzędu pocztowego można sformułować w następujący spo-


sób. Danych jest n punktów p 1 , p 2 , ... , Pn, którym odpowiadają wagi
w 1 , w 2 , ... , w,.. Zadanie polega na wyznaczeniu punktu p (nie musi to być jeden

-------c2cc29
ROZDZIAŁ 10. MEDIANY I STATYSTYKI POZYCYJNE

z podanych punktów), dla którego minimalną wartość osiąga suma


L" w d(p, p
1 1), gdzie t:J<.a,
b) jest odległością między punktami a i b.
I= 1

d) Wykaż, że mediana ważona jest rozwiązaniem I-wymiarowego problemu


lokalizacji urzędu pocztowego, w którym punktami są po prostu liczby
rzeczywiste, a odległość między punktami a i b wynosi d(a, b) = ja - bj.
(e) Zaprojektuj algorytm wyznaczający rozwiązanie 2-wymiarowego problemu
lokalizacji urzędu pocztowego, w którym punktami są pary współrzędnych
(x, y), a odległość między punktami a= (x 1, y 1 ) i b = (x 2 , yz) jest określo­
na przez tak zwaną metrykę miejską: d(a, b) = lx1 - x 2 1+ IY1 - Y2 !.

10-3, Male statystyki pozycyjne


Llczba porównań potrzebnych do wyznaczenia i-tej statystyki pozycyjnej ze
zbioru n liczb przez procedurę SELECT wynosi w pesymistycmym przypadku
T(n) = E>(n),lecz stała kryjąca się za notacją 9 jest stosunkowo duża. Jeśli
i jest małe w stosunku do n, to można zastosować inną procedurę, która używa
. .
nuJe mn1eJ porownan.
.
SELECTjako procedury pomocniczej, lecz w pesymistycznym przypadku wyko-
. '

(a) Opisz algorytm używający U1(n) porównań do wyznaczenia i-tego co do


wielkości elementu w zbiorze n-elementowym, gdzie i :i;;;n/2 oraz

jeśli n :i;;;2i
Utn) -{T(n),
n/2 + U/n/2) + T(21), w przeciwnym razie

(Wskazówka: Najpierw wykonaj Ln/2J porównań między rozłącznymi pa-


rami elementów, a następnie wywołaj procedurę rekurencyjnie dla zbioru
składającego się z elementów, które okazały się mniejszymi w parach).

(b) Wykaż, że U.(n) - n+ O(T(21) lg(n/1)).


(c) Wykaż, że jeśli i jest stałą, to Ui(n) =n+ O(lgn).
(d) Wykaż, że jeśli i - n/k dla k;;, 2, to U,(n) - n + O(T(2n/k) !gk).

Uwagido rozdziału
Algorytm wyszukiwania mediany, działający w pesymistycznym przypadku
w czasie liniowym, został wynaleziony przez Bluma, Floyda, Pratta, Rivesta
i Tacjana [29J. Szybki, w sensie średniego czasu działania, algorytm podał Hoa-
re [97]. Floyd i Rivest [70] zaproponowali ulepszoną jego wersję, w której zbiór
jest dzielony rekurencyjnie względem elementu wybranego z małej próbki
wszystkich elementów.
Część 11

Struktury
danyc
Wprowadzenie

Zbiory są w informatyce równie fundamentalnym pojęciem jak w matematyce.


Te rozważane w matematyce są jednak niezmienne, natomiast zbiory, na któ-
rych działają algorytmy, mogą się powiększać, zmniejszać lub zmieniać w cza-
sie w inny sposób. Takie zbiory nazywamy dyoamicznymi.W następnych pię­
ciu ro7.działacb przedstawimy podstawowe metody reprezentowania oraz prze-
twarz.ania skończonych zbiorów dynamicznych za pomocą komputera.
W zastosowaniach algorytmicznych będzie wymaganych wiele różnych
operacji na zbiorach. W wielu algorytmach wystarcza na przykład tylko moż­
liwość wstawiania elementów do zbioru, usuwania elementów ze zbioru oraz
sprawdzania, czy dany element należy do zbioru. Zbiór dynamiczny, na któ-
rym można wykonywać takie operacje, nazywamy słownikiem. W innych al-
gorytmach są wymagane niejednokrotnie bardziej skomplikowane operacje.
Na przykład kolejki priorytetowe, które zostały wprowadzone w rozdz. 7
w postaci kopców, umożliwiają wstawianie elementów oraz usuwanie najM
mniejszego elementu w zbiorze. Najlepsza metoda realizacji zbiorów dynaM
micznycb zależy oczywiście od operacji, które mają być wykonywane na takich
zbiorach dynamicznych.

Elementyzbioru dynamicznego
W większości realizacji zbiorów dynamicznych każdy element zbioru jest reM
prezentowany przez obiekt, którego pola można odczytywać oraz modyfikoM
wać, jeśli dysponujemy wskaźnikiem do tego obiektu. (W ro7.dziale 11 omówi-
my realizację obiektów i wskaźników w środowiskach programistycznych,
w których wskażniki nie występują jako wbudowane typy danych). W nie~
których rodzajach zbiorów dynamicznych zakłada się, że jedno z pól każdego
obiektu jest wyróżnione jako jego klucz (ang. key). Jeśli klucze wszystkich

232
WPROWADZENIE

elementów są różne, to o zbiorze dynamicznym możemy myśleć jako o zbiorze


kluczy. Obiekt może także zawierać dodatkowe dane, które są zawarte w in-
nych polach obiektu, ale nie wpływają w istotny sposób na realizację zbioru.
Oprócz tego elementy mogą mieć także pola, których wartości są zmieniane
przez operacje na zbiorze; pola te mogą zawierać pewne pomocnicze dane albo
wskaźniki do innych obiektów w zbiorze.
W implementacjach zbiorów dynamicznych niekiedy przyjmuje się założe­
nie, że klucze należą do zbioru liniowo uporządkowanego, takiego jak liczby
rzeczywiste czy słowa z porządkiem alfabetycznym. (Zbiór liniowo uporząd­
kowany spełnia warunek trychotomii, zdefiniowany na str. 53). Liniowy po-
rządek na elementach zbioru pozwala na przykład zdefiniować pojęcie naj-
mniejszego elementu w zbiorze albo pojęcie następnika.

Operacje na zbiorach dynamicznych


Operacje na zbiorach dynamicznych można podzielić na dwie grupy: zapyta-
nia, które pozwalają tylko uzyskać pewne informacje na temat zbioru, oraz
operacjemodyfikujące, które mogą zmienić zbiór. Oto lista typowych operacji
na zbiorach dynamicznych. W większości konkretnych zastosowań zbiorów
będą wymagane tylko niektóre z nich.

SEARCH(S,k) Zapytanie, które dla danego zbioru S oraz wartości klucza k,


daje w wyniku wskaźnik x do takiego elementu w zbiorze S, że key[x]=k
lub NIL, jeśli żaden taki element nie należy do S.
INSERT(S, x) Operacja modyfikująca, która do zbioru S dodaje element
wskazywany przez x. Zwykle zakładamy, że wartości wszystkich pól ele-
mentu wskazywanego przez x istotnych dla realizacji zbioru zostały już
za1ntCJowane.
DELETE(S, x) Operacja modyfikująca, która dla danego wskaźnika x do
elementu w zbiorze S usuwa ten element ze zbioru S. (Należy zwrócić
uwagę na to, że argumentem jest tutaj wskaźnik do elementu x, a nie
wartość klucza).
MINIMUM(S) Zapytanie dotyczące liniowo uporządkowanego zbioru S, któ-
re daje w wyniku element S o najmniejszym kluczu.
MAXIMUM(S) Zapytanie dotyczące liniowo uporządkowanego zbioru S, któ-
re daje w wyniku element S o największym kluczu.
SUCCESSOR(S,x) Zapytanie, które dla danego elementu x o kluczu należą­
cym do uporządkowanego zbioru S daje w wyniku następnik elementu
x w S (czyli najmniejszy element ze zbioru S, większy od x) albo stałą NIL,
jeśli x jest największym elementem w S.
PREDECESSOR(S,x) Zapytanie, które dla danego elementu x o kluczu należą­
cym do uporządkowanego zbioru S daje w wyniku poprzednik elementu
----------------------~-- ..·--~=
233
CZĘ$C Ili. STRUKTURY DANYCH

x w S (czyli największy element re zbioru S, mniejszy od x) albo stałą NIL,


jeśli x jest najmniejszym elementem w S.

Zapytania SUCCESSORi PREDECESSORuogólnia się często na zbiory,


w których mogą występować elementy o jednakowych kluczach. Dla zbioru
n kluczy przyjmuje się, że w wyniku wywołania operacji MINIMUM, po którym
następuje n - 1 wywołań zapytania SUCCESSOR,otrzymuje się wszystkie ele-
menty zbioru w kolejności zgodnej z porządkiem sortowania względem kluczy.
Czas wymagany do wykonania operacji na zbiorze mierzy się zwykle
jako funkcję ro1llliaru zbioru, który występuje jako jeden z jej argumentów.
W rozdziale 14 opiszemy na przykład strukturę danych, za pomocą której
można wykonywać wszystkie powyższe operacje na zbiorze n-elementowym
w czasie O(lgn).

Zawartość części 111


W rozdziałach 11-15 omówimy różne struktury danych, za pomocą których
można realizować zbiory dynamiczne. Część z nich będzie później użyta do
konstrukcji efektywnych algorytmów do rozwiązywania wielu problemów. In-
na ważna struktura danych - kopiec - została już wprowadzona w rozdz. 7.
W rozdziale 11 przedstawimy podstawy realizacji prostych struktur da-
nych, takich jak stosy, kolejki, listy z dowiązaniami oraz drzewa ukorzenione.
Omówimy też metodę reprezentowania wskaźników w środowiskach progra-
mistycznych, w których nie ma wbudowanych wskaźnikowych typów danych.
Większość tego materiału powinna być znana każdemu, kto przeszedł elemen-
tarny kurs programowania.
W rozdziale 12 wprowadzimy tablice z haszowaniem, które umożliwiają
realizację operacji słownikowych INSERT, DELETE oraz SEARCH. W najgor-
szym przypadku operacja SEARCHprzy użyciu haszowania wymaga 0(n) cza-
su, ale wartość oczekiwana czasu działania operacji na tablicach z haszowa-
niem wynosi 0(1). Analiza haszowania korzysta z rach11nku prawdopodobień­
stwa, ale do zrozumienia materiału zawartego w większej części rozdziału nie
jest wymagane od czytelnika specjalne przygotowanie.
Drzewa poszukiwań binarnych, które omówimy w rozdz. I 3, umożliwiają
wykonywanie wszystkich wymienionych wyżej operacji na zbiorach dynamicz-
nych. W najgorszym przypadku każda operacja wymaga czasu 0(n) na drze-
wie o n węzłach, lecz dla losowo skonstruowanych drzew poszukiwań binar-
nych oczekiwany czas wszystkich operacji wynosi O(lgn). Drzewa poszukiwań
binarnych stanowią podstawę konstrukcji wielu innych struktur danych.
Drzewa czerwono-czarne, które są odmianą drzew poszukiwań binarnych
wprowadzimy w rozdz. 14. W przeciwieństwie do zwyczajnych drzew poszuki-
wań binarnych, czas działania operacji na drzewach czerwono-czarnych wy-

234
WPROWADZENIE

nosi O(lgn), nawet w najgorszym przypadku. Drzewo czerwono-czarne jest


zrównoważonym drzewem poszukiwań. W rozdziale 19 opiszemy inny rodzaj
drzew zrównoważonych, zwanych B-drzewami. Pomimo komplikacji występu­
jących przy konstruowaniu drzew czerwono~czarnych większość ich istotnych
własności można zrozumieć, nie wgłębiając się w szczegóły. Dokładne zapo-
znanie się z ich implementacją może być jednak bardzo pouczające.
W rozdziale 15 pokażemy, jak wzbogacać strukturę drzew czerwono-czar-
nych, aby można było wykonywać operacje spoza powyższej listy. Najpierw
przedstawimy pewne rozszerzenie, które pozwala dynamicznie obliczać statys-
tyki pozycyjne danego zbioru kluczy. Następnie rozważymy adaptację, która
umożliwia operacje na przedziałach liczb rzeczywistych.
Rozdział 11

Elementarnestruktury
danych

W tym rozdziale zajmiemy się realizacją zbiorów dynamicznych za pomocą


prostych struktur danych, w których korzysta się ze wskaźników. Wskaźnik.i
mogą posłużyć do implementacji wielu bardzo skomplikowanych struktur da-
nych. My ograniczymy się na razie do najbardziej elementarnych spośród nich:
stosów, kolejek, list i drzew. Omówimy również metodę reprezentowania stru-
ktur wskaźnik.owych za pomocą tablic.

11.1. Stosyi kolejki


Stosy i kolejki są implementacjami zbiorów dynamicznych, w których element
usuwany za pomocą operacji DELETE jest wyznaczony jednoznacznie. W przy-
padku stosu ze zbioru jest usuwany element, który został do niego dodany
najpóźniej (w języku angielskim określa się taką strategię jak.o last-in, first-out
lub w skrócie LIFO). Dla odmiany w przypadku kolejki jest usuwany zawsze
element „najstarszy" w zbiorze, tj. dodany do niego najwcześniej (taką strate-
gię w literaturze anglosaskiej nazywa się first-in, first-out lub Fll'O). Istnieje
wiele efektywnych implementacji kolejek i stosów. W tym podrozdziale zaj-
miemy się ich realizacją za pomocą zwykłej tablicy.

Stosy
Operację INSERT, wstawiania elementu do stosu, nazywa się zwyczajowo
PUSH, a bezargumentowa operacja DELETE, usuwania elementu ze stosu, jest
nazywana POP. Te nazwy nawiązują do tenninologii stosowanej w odniesieniu
do rzeczywistych „stosów", takich jak stosy talerzy spotykane w barach samo-
obsługowych. Talerze są zdejmowane z takiego stosu w kolejności odwrotnej

236
11.1. STOSY I KOLEJKI

do tej, w której były nań wstawiane, ponieważ bezpośrednio dostępny jest


zawsze tylko talerz na wierzchu.
Jak widać na rys. 11.1, stos zawierający nie więcej niż n elementów można
zaimplementować w tablicy S[l „ n]. Z taką tablicą jest związany dodatkowy
atrybut top[S], którego wartość jest numerem ostatnio wstawionego elementu.
Stos składa się z elementów S[l .. top[S]], gdzie S[l] jest elementem na dnie
stosu, a S[top[S]] jest elementem na wierzchołku stosu.
Jeśli top[S] = O, to stos jest pusty, czyli nie zawiera żadnych elementów.
Do sprawdzania, czy stos jest pusty, używamy operacji SrACK-EMPTY.Próba
zdjęcia elementu z pustego stosu powinna być sygnalizowana jako błąd niedo-
miaru. Jeśli top[S] jest większe niż n, to mówimy, że stos jest przepełniony.
(W naszej implementacji pominiemy obsługę błędu przepełnienia).
Operacje na stosie bardzo łatwo jest zaimplementować.

STACK-EMPTY(S)
I if top[S] - O
2 then return TRUE
3 else return F ALSE

PUSH(S,x)
I top[SJ- top[S] + I
2 S[top[S]]- x
POP(S)
l if STACK-EMPTY(S)
2 then error „niedomiar"
3 else top[S] - top[SJ - I
4 return S[top[S] + I]

Na rysunku 11.1 widać wyniki działania operacji PUSH i POP. Każda z trzech
operacji na stosach działa w czasie 0(1).

l 2 3 4 5 6 7 I 2 3 4 5 6 7 I 2 3 4 5 6 7
s lisi6 I 21911ft s [~~161219111!31!]
s 1,sl6l219111
t t t
top[S] =4 top[SJ = 6 top[S]: 5

(•) (b) (c)

Rys. 11.1. Implementacja stosu S z.apomocą tablicy. Elementy stosu znajdują się tylko na jasno-
szarych pozycjach. (a) Stos S ma 4 elementy. Na jego wierzchołku znajduje się element 9. (b) Stos
S po wykonaniu operacji PuSH(S, 17) i PuSH(S, 3). (c) Operacja PoP(S) na stosie S daje w wyniku
element 3, który był najpóźniej wstawiony do S. Mimo że element 3 nadal znajduje się w tablicy,
nie należy już do stosu, bo na jego wierzchołku jest element 17

237
ROZDZIAŁ 11. ELEMENTARNE STRUKTURY DANYCH

Kolejki
Operację wstawiania do kolejki nazywa się zwyczajowo ENQUEUE,a operację
usuwania DEQUEUE (podobnie jak operacja POP na stosach, DEQUEUEjest
bezargumentowa). Kolejka funkcjonuje jak kolejka ludzi w sklepie: ma począ­
tek (głowę) oraz koniec (ogon). Kiedy wstawiamy nowy element do kolejki,
zostaje on umieszczony na końcu kolejki (w ogonie); podobnie nowo przybywa-
jący klient zawsze staje (a przynajmniej powinien) na końcu kolejki. Element
może zostać usunięty z kolejki tylko wtedy, gdy znajduje się na jej początku
(w głowie); podobnie w sklepie w pierwszej kolejności jest obsługiwany klient
z początku kolejki, tj. ten który oczekiwał najdłużej. (Na szczęście w naszych
kolejkach nie będzie elementów, które próbują „wpychać" się poza kolejnością).
Na rysunku 11.2 jest pokazane, jak można zaffllplementować kolejkę o co
najwyżej n - l elementach za pomocą tablicy Q[l .. n}. Atrybut head[Q] takiej
kolejki wskazuje na jej głowę, tj. początek, natomiast atrybut tail[Q] wyznacza
następną wolną pozycję, na którą można wstawić do kolejki nowy element.
Elementy kolejki znajdują się na pozycjach head[Q], head[Q] + 1, ...,
tai/[Q1 - 1; umawiamy się tutaj, że tablica Q jest „cykliczna", tzn. pozycja
o numerze 1 jest bezpośrednim następnikiem pozycji o numerze n. Jeśli
head[Q] - tail[Q], to kolejka jest pusta, Początkowo head[Q] - tail[Q] - I.
Jeżeli kolejka jest pusta, to próba usunięcia elementu z kolejki za pomocą

(a)

head{QJ ==7 rai/[QJ ==I 2

(b)

tail[Q] = 3 head{Q]: 7

(c)

1ai/[QJ"" 3 head[Q] "'8

Rys. 11.2. Implementacja kolejki w tablicy Q[l „12]. Elementy kolejki majdują się tylko na jasno-
szarych pozycjach. (a) Kolejka zawiera 5 elementów na pozycjach Q[7 .. 1I]. (b) Ta sama kolejka
po wykonaniu operacji ENQUEUE(Q,17), ENQUEUE{Q,3) oraz ENQUEUE(Q,5). (c) Operacja DEQU-
EUE{Q)daje w wyniku wartość 15, która :majdowała się w chwili wywołania w głowie kolejki Po
jej wykonaniu w głowie majduje się liczba 6

238
11.1. STOSY I KOLEJKI

operacji DEQUEUE jest sygnalizowana jak.o błąd niedomiaru. Jeśli head[Q] =


= tail[Q] + 1, to kolejka jest pełna. Próba wstawienia nowego elementu do
kolejki jest w takiej sytuacji sygnalizowana jako błąd przepełnienia.
W poniższych procedurach pominęliśmy szczegóły obsługi błędów przepeł­
nienia lub niedomiaru. (Zadanie 11.1-4 polega na uzupełnieniu tych procedur
o obsługę tych dwu błędnych sytuacji).

ENQUEUE(Q,x)
I Q[tail[QD- x
2 if tail[Q] - length[Q]
3 theu tail[Q] ..._1
4 clse lail[Q] - lail[Q] +I
DEQUEUE(Q)
I x- Q[head[QD
2 if head[Q] - length[Q]
3 then head[Q] - I
4 else head[Q] - head[Q] + I
5 return x

Na rysunku 11.2 jest zilustrowane działanie operacji ENQUEUE i DEQUEUE.


Obie procedury działają w czasie 0(1).

ZADANIA

11.1-1. Zilustruj (podobnie jak na rys. 11.1) wynik wykonania ciągu operacji
PUSH(S, 4), PUSH(S, I), PUSH(S, 3), POP(S), PUSH(S, 8) oraz POP(S) na
początkowo pustym stosie S znajdującym się w tablicy S[l .. 6].
11.1-2. Wyjaśnij,jak. zaimplementować dwa stosy w jednej tablicy A[l .. n], aby
do przepełnienia któregoś z nich dochodziło dopiero wtedy, gdy liczba
elementów w obu stosach osiąga n. Procedury PUSH i POP powinny działać
w czasie 0(1 ).
11.1-3. Zilustruj (podobnie jak na rys. 11.2) wynik wykonania ciągu operacji
ENQUEUE(Q,4), ENQUEUE(Q,I), ENQUEUE(Q,3), DEQUEUE(Q),ENQU"
EUE(Q, 8), oraz DEQUEUE(Q) na początkowo pustej kolejce Q znajdującej
się w tablicy Q[l .. 6].
11.1-4. Uzupełnij procedury ENQUEUEi DEQUElffi o wykrywanie błędów prze-
pełnienia i niedomiaru.
11.1-5. W stosach wstawianie i usuwanie elementów odbywa się na jednym
z końców, w kolejkach wstawia się elementy na jednym końcu, a usuwa
z drugiego. Kolejka dwustronna (dwukierunkowa) jest strukturą danych
pozwalającą na wstawianie i usuwanie elementów na obu końcach. Napisz
cztery procedury działające w czasie 0(1), służące do wstawiania i usuwa-
nia elementów z obu końców kolejki przechowywanej w tablicy.

239
ROZDZIAŁ 11. ELEMENTARNE STRUKTURY DANYCH

11.1--6.Pokaż, jak zaimplementować kolejkę, używając dwóch stosów. Oszacuj


czas działania
operacji na takiej kolejce.
11.1-7. Pokaż, jak zaimplementować stos za pomocą dwóch kolejek, Oszacuj
czas działania operacji na takim stosie.

11.2. Listy
Lista z dowiązaniami jest strukturą danych, w której elementy są ułożone w li-
niowym porządku. Jednak w przeciwieństwie do tablicy, w której porządek.jest
wyznaczony przez jej indeksy, porządek na liście z dowiązaniami określają
wskaźniki związane z każdym elementem listy. Listy z dowiązaniami są prostą
i elastyczną strukturą, służącą do reprezentowania zbiorów dynamicznych,
umożliwiającą wykonywanie wszystkich operacji (choć nie zawsze optymalnie)
wymienionych na str. 233.
Jak można zobaczyć na rys. 11.3, każdy element listy dwukien1nkowej
L (ang. doubly linked list) jest rekordem składającym się z trzech pól: key
(zawiera klucz elementu), next oraz prev. W takim rekordzie mogą się jeszcze
znajdować inne dane. Dla danego elementu x na liście next[x] wskazuje na jego
następnik na liście, a prev[x] wskazuje na jego poprzednik. Jeśli prev{x] = NIL,
to element x nie ma poprzednika, jest więc pierwszym elementem listy. Mówi-
my wtedy, że x jest głową tej listy. Jeśli next(x] = NIL, to x nie ma następnika,
jest więc ostatnim elementem listy lub jej ogonem. Atrybut head[L]wskazuje na
pierwszy element listy. Jeżeli head[L] = NIL, to lista jest pusta.
Zależnie od potrzeby stosuje się listy różnego rodzaju. Listy mogą być na
przykład jednokierunkowe lub dwukien1nkowe, posortowane lub nieposorto-

prev key nexl


\ I /
,,,,,,d11.,
- >j/l • I -J;=
...=.·1k::::Iil
1•~1:3.1,=''"bl
::::1~•II
:CC-J;:k=''kl
Jl::i:1Ll/~I

(b) ,,,,,,[LI -->j,1[2/]125~1:::J.1.-='''kl


Jli•Il5:1.;:::=1·r.~.
n1,.~1:cc11;.=·b1,
1CJ;1.='·-i;1
IJ!J• J1:I,IZJ

,,, ,,,d11.1--· ll2/]l25~l::::'J'J:;;='1'k.


Jti,II5:1.;:::='"!'l~
..fili•~l:'.'5:k,
=·:>:1b•·11
I1l[ZJ/I
Rys. 11.3. (a) Lista dwukierunkowa L reprezentująca zbiór dynamiczny {1, 4, 9, 16}. Każdy element
listy jest rekordem złożonym z pól zawierających klucz oraz wskaźniki (zilustrowane za pomocą
strzałek) do następnego i poprzedniego elementu na liscie. Pola next ogona oraz prev głowy listy są
równe NIL, co zostało omaczone za pomocą ukośnej kreski. Atrybut head[LJwskazuje na głowę
listy L. (b) Po wykonaniu operacji Ltsr-lNSERT(L, x), gdzie key[xJ = 25, w głowie listy majduje się
nowy rekord z kluczem 25. Pole next[x] zawiera wskaźnik do poprzedniej głowy z kluczem 9. (c)
Wynik wykonania operacj] LIST·DELBTI!(L,x), gdzie x wskazuje na element listy o kluczu 4

240
11.2. LISTY

wane, cykliczne lub nie. Jeśli lista jest jednokierunkowa (ang. singly linked list),
to w jej elementach pomijamy wskaźnik prev. Jeśli lista jest posortowana, to
kolejność elementów na liście jest zgodna z porządkiem na ich kluczach; ele-
ment o najmniejszym kluczu znajduje się w głowie listy, a ten o największym
kluczu w jej ogonie. Jeżeli lista jest nieposortowana, to kolejność elementów jest
dowolna. W liście cyklicznej pole prev elementu w głowie wskazuje na ogon,
a pole next w ogonie wskazuje na głowę. Elementy takiej listy tworzą więc
pierścień. Do końca tego podrozdziału przyjmujemy założenie, że listy, na któ-
rych operujemy, są nieposortowane i dwukierunkowe.

Wyszukiwaniena listach z dowiązaniami


Procedura LIST-SEARCH(L, k) wyznacza pierwszy element o kluczu k na liście
L za pomocą prostego liniowego przeglądania. W wyniku wywołania LIST-
-SEARCH(L, k) otrzymuje się wskaźnik do tego elementu, a jeśli nie ma na liście
żadnego elementu o kluczu k, to jest zwracana wartość NIL. W wyniku wywo-
łania LIST-SEARCH(L, 4) w odniesieniu do listy z rys. 11.3a otrzymuje się
wskaźnik do jej trzeciego elementu, natomiast w wyniku wywołania LIST-SE.
ARCH(L, 7) - wartość NIL.

LIST-SEARCH(L, k)
I x-head[L]
2 while x # NIL i key[x] # k
3 do x +- next(x]
4 return X

Pesymistyczny czas działania procedury LIST-SEARCH na liście o n elementach


wynosi E>(n),ponieważ niekiedy konieczne jest przejście całej listy.

Wstawianiedo listy z dowiązaniami


Procedura LIST-INSERT(L, x) przyłącza element x (którego pole key zostało
wcześniej zainicjowane) na początek listy (patrz rys. 11.3b).

LIST-INSERT(L, x)
I next[x] +- head[L]
2 lf head[L] # NIL
3 tbenprev[head[L]]- x
4 head[L]-x
5 prev[x]+- NIL

Procedura LIST-INSERT na liście o n elementach działa w czasie 0(1).

241
ROZDZIAŁ 11. ELEMENTARNE STRUKTURY DANYCH

Usuwaniez list z dowiązaniami


Wywołanie procedury LIST-DELETEpowoduje usunięcie elementu x z listy L. Do
LIST-DELETEzostaje przekazany wskaźnik do elementu x, po czym element ten
zostaje „wycięty" z listy przez modyfikację wartości odpowiednich wskaźników.
W celu usunięcia elementu o zadanej wartości klucza należy najpierw wywołać
procedurę LIST-SEARCH,aby wyznaczyć wskaźnik do takiego elementu.

LIST-DELETE(L, x)
1 if prev[x] #- NIL
2 then next[prev{x]]+- next[x]
3 e]se head[L] +- next{x]
4 if next[x] i: NIL
5 tben prev[next[x]]+- prev{x]

Usunięcie elementu z listy z dowiązaniami jest pokazane na rys. 11.3c. Proce-


dura LIST-DELETE działa w czasie 0(1), lecz pesymistyczny koszt usunięcia
elementu o zadanym kluczu wynosi E>(n),ponieważ musimy najpierw wywołać
procedurę LIST-SEARCH.

Wartownicy
Gdyby można było pominąć warunki brzegowe dotyczące głowy i ogona listy,
treść procedury LIST-DELETEznacznie by się uprościła.

LIST-DELETE'(L, X)
I next[prev{x]]+- next[x]
2 prev{next[x]]+- prev[x]

Wartownikjest „sztucznym" elementem, który pozwala uprościć warunki


brzegowe. Przyjmijmy dla przykładu, iż z listą L jest związany element nil[L],
który odgrywa rolę stałej NIL, ale jest rekordem o takich samych polach jak
wszystkie zwykle elementy listy. Każde wystąpienie stałej NIL w naszych proce-
durach zamieniamy na wskaźnik do wartownika nil[L], Jak. widać na rys. 11.4,
sprawia to, że zwykła lista dwukierunkowa staje się w istocie listą cykliczną,
w której wartownik nil[L] znajduje się między głową a ogonem; pole
next[nil[L]] wskazuje na głowę listy, a prev[nil[L]]wskazuje na jej ogon. Za-
równo pole next ogona, jak i pole prev głowy listy wskazują na nil[L], Ponie-
waż next[nil[L11wskazuje na głowę listy, nie ma więc w ogóle potrzeby parnię~
tać atrybutu head[LJ; wystarczy zastąpić wszystkie odwołania do niego przez
next[nil[L]]. Lista pusta składa się z samego tylko wartownika i wtedy oba
pola next[nil[L]] oraz prev[nil[L]] wskazują na nil[L].

242
11.2. LISTY

I
(a) ni/Il.I -

l
(bł nil[LI
~.4 I• I I.'I I I I ' ki
I• I 1.·1-I16 I 1.-'I-
(c) nil[l] r:.... ·1 125 I I.·1-I• I I.'I J I6 J '.t4 I• I '.t4 I I I 'kI
(d} nil[LJ l~ I,,I I.'I I• I I.'I I16I l.'I I• I I 41
Rys. 11.4. Lista L z dowiązaniami, z wartownikiem nif[L] (ciemnoszary), to cykliczna lista dwu-
kierunkowa, w której element nil[L] znajduje się zawsze między głową a ogonem. Atrybut headfL]
nie jest już niezbędny, ponieważ na głowę wskazuje zawsze next[nil[LJ]. (a) Lista pusta. {b) Lista
z rys. 11.3a z kluczem 9 w głowie i kluczem l w ogonie. (c) Ta sama lista po wykonaniu LIST·
-INSERT'(L, x), gd7ie key[x] = 25. Nowy element został umieszczony w głowie listy. (d) Lista po
usunięciu elementu o kluczu I. W ogonie znajduje się teraz element o kluczu 4

Treść procedury LisT-SEARCH pozostaje bez zmian, należy tylko odniesie-


nia do NIL oraz head[L] zastąpić w wyżej określony sposób.

LIST-SEARCH'(L, k)
l x- next(nil[L]]
2 whilex cf,;nil[L] i key[x] cf,;k
3 do x .__next[x]
4 returnX

Do usuwania elementów z listy służy króciutka procedura LIST-DELETE'.


Nowe elementy wstawiamy do listy za pomocą następującej procedury.

LIST-INSERT'(L, x)
I next[x] .__next[nil[L]]
2 prev[next[nil[L]]]+-- x
3 next[nil[LJ]-x
4 prev[x]- nil[LJ

Na rysunku 11.4 widać wyniki działania procedur LIST-INSERT' oraz


LIST-DELETE' na przykładowej liście.
Użycie wartowników nie jest zwykle w stanie poprawić asymptotycznej
złożoności operacji na strukturze danych, lecz często prowadzi do zmniejszenia
stałych współczynników. Korzyść wynikająca z zastosowania wartowników
w pętlach programu polega często na poprawie czytelności programu, a nie
szybkości jego działania. W przypadku list z dowiązaniami rzeczywiście udało

243
ROZDZIAŁ 11. ELEMENTARNE STRUKTURY DANYCH

się znacznie uprościć treść procedur, lecz czas działania procedur LIST-INSERT'
i LIST-DELETE'skrócił się zaledwie o 0(1). Niekiedy jednak użycie wartow-
ników prowadzi do skrócenia treści pętli i wtedy daje to w efekcie 2l'.D.niejszenie
współczynnika przy, powied2'llly, n lub n2 w złożoności czasowej operacji na
struktur7.e danych.
Nie należy jednak stosować wartowników zupełnie bezkrytycznie i bez
ograniczeń. Jeśli pracujemy z dużą liczbą małych list, to marnujemy znaczącą
część pamięci na ich wartowników. W tej książce używamy wartowników tylko
wówczas, gdy pozwalają znacznie uprościć treść procedur.
ZADANIA
11.2-1. Czy da się tak zaimplementować operację INSERTna liście jednokie-
runkowej, aby działała w czasie 0(1)? A jak jest z operacją DELETE?
11.2-2. Zaimplementuj stos za pomocą listy jednokierunkowej L. Operacje
PUSH i POP powinny działać w czasie 0(1).
11.2-3. Z.aimplementuj kolejkę za pomocą listy jednokierunkowej L. Operacje
ENQUEUBi DBQUEUEpowinny działać w czasie 0(1).
11.24. Zaimplementuj operacje słownikowe INSERT,DELETEoraz SEARCHza
pomocą jednokierunkowych list cyklicznych. Jakie są czasy działania tych
procedur?
11.2-5. Argumentami operacji UNION są dwa zbiory rozłączne S 1 i S 2 , a wy-
nikiem jej działania jest zbiór S = S 1 u S 2 składający się z wszystkich ele-
mentów zbiorów S 1 i S 2 • Reprezentacje zbiorów S 1 i S 2 ulegają zwykle
zniszczeniu w wyniku wykonania operacji UNION.Zaprojektuj odpowied-
nią listową strukturę danych, umożliwiającą wykonywanie operacji
UNIONw czasie 0(1).
11.2-6. Napisz procedurę, która łączy dwie jednokierunkowe, posortowane li-
sty w jedną jednokierunkową, posortowaną listę, bez użycia wartowników.
Następnie 2'Jllodyfikujją, dodając wartownika o kluczu oo na koniec każ­
dej z list. Porównaj stopień komplikacji obu procedur.
11.2-7. Napisz nierekurencyjną procedurę odwracającą kolejność elementów
na liście jednokierunkowej, działającą w czasie 0(n). Dodatkowa pamięć
(oprócz tej zajmowanej przez samą listę) powinna być stała (tj. niezależna
od liczby elementów na liście).
* 11.2-8. Wyjaśnij, jak. zaimplementować listę dwukierunkową, używając tylko
jednego wskaźnika np[x] na jeden element, zamiast dwóch (next i prev).
Przyjmij założenie, że wszystkie wskaźniki można reprezentować za pomo-
cą k-bitowych liczb całkowitych i zdefiniuj np[x] w następujący sposób:
np[x] = next[x] XOR prev[x], tj. wartość k-bitowej operacji „wykluczające
LUB" na liczbach next[x] i prev[x]. (Wartość NIL jest reprezentowana
przez liczbę O). Zwróć szczególną uwagę na to, jakie dane są potrzebne,
aby móc odwoływać się do głowy listy. Zaprojektuj operacje SEARCH,

244
11.3. REPREZENTOWANIE STRUKTUR WSKAZNIKOWYCH ZA POMOCĄ TABLIC

INSERT oraz DELETE na takiej liście. Pokaż także, jak odwracać kolejność
elementów na takiej liście w czasie 0(1).

11.3. Reprezentowanie strukturwskaźnikowych


za pomocą tablic
Jak realizować struktury danych wykorzystujące wskaźniki w językach, takich
jak na przykład Fortran, w których nie występuje w ogóle pojęcie wskaźnika?
W tym podrozdziale przedstawimy dwie metody reprezentacji wskaźnik.owych
struktur danych, bez odwoływania się do typów wskaźnikowych. Do symulacji
wskaźników użyjemy tablic.

Reprezentacja wielotablicowa
Zbiór rekordów o takiej samej strukturze można reprezentować za pomocą
tablic, z których każda odpowiada pewnemu polu rekordów. Na rysunku 11.5
jest przedstawiona reprezentacja listy z rys. 11.3a za pomocą trzech tablic.
Tablica key zawiera wartości kluczy znajdujących się na liście, a wskaźniki
znajdują się w tablicach next oraz prev. Dla danego indeksu x wartości key[x],
next[x] oraz prev{x] określają cały element listy, Przy takiej interpretacji rolę
wskaźników odgrywają indeksy w tablicach key, next oraz prev.
Na liście z rys. 11.3a element o kluczu 4 znajduje się bezpośrednio za
elementem o kluczu 16. Na rysunku 11.5 klucz 4 znajduje się w key[2], a klucz
16 w key{5], więc next[5] = 2 oraz pret{2] = 5. Chociaż w tablicy next na pozy-
cji odpowiadającej ogonowi listy oraz w tablicy prev na pozycji odpowiadającej
głowie listy znajduje się stała NIL, jednak zazwyczaj umieszcza się tam liczbę
całkowitą (jak np. O lub -1 ), która z pewnością nie oznacza żadnego popraw-
nego indeksu w tablicach. W zmiennej L jest pamiętany numer pozycji, na
której znajduje się głowa listy.

Rys. 11.5. Lista z rys, l l.3a reprezentowana za pomocą tablic key, next i prev. Ka:Wa kolumna
stanowi pojedynczy element listy. Wskaźniki odpowiadają indeksom umieszczonym ponad tabli-
cami; strzałki ilustrują tylko, jak należy je interpretować, Jasnoszare pozycje zawierają elementy
znajdują.ce się aktuaJnie na liście. W zmiennej L jest przechowywany indeks głowy listy

245
,, ,,,_ ...___
____ ,.,_,.,~, ...
__,,,_,.,_,,, -~..·-··
W treści procedur używaliśmy nawiasów kwadratowych zarówno do ozna-
czenia indeksowania w tablicy, jak i wyboru pola rekordu lub atrybutu struk-
tury danych. Znaczenia key[x], next[x] oraz prev[x} pokrywają się z tradycyjną
notacją stosowaną w wielu językach programowania.

Reprezentacjajednotablicowa
Komórki pamięci komputera są zwykle adresowane za pomocą liczb całkowi­
tych od O do M - 1, gdzie M jest liczbą dostępnych komórek. W realizacjach
wielu języków programowania rekordy zajmują spójne obszary pamięci.
Wskaźnik do rekordu jest wtedy po prostu adresem komórki pamięci, w której
zaczyna się jego opis. Adresy poszczególnych pól rekordu otrzymuje się przez
dodawanie do powyższego wskaźnika odpowiednich liczb, określających prze-
sunięcie pola względem początku rekordu.
Taką samą strategię możemy zastosować do reprezentowania rekordów
w środowiskach programistycznych, w których nie ma wskaźnikowych typów
danych. Na rysunku 11.6 widać, w jaki sposób w pojedynczej tablicy A można
przechowywać listę z rys. 11.3a i 11.5. Każdy element listy zajmuje spójny
fragment tablicy A[j .. k]. Każdemu polu pojedynczego rekordu odpowiada
przesunięcie, będące liczbą z przedziału od Odok - j, a wskaźnikiem do rekor-
du jest po prostu indeks j. Przesunięcia odpowiadające polom key, next i prev,
przy reprezentacji jak na rys. 1I .6, wynoszą odpowiednio O, 1 i 2. Aby od-
czytać wartość prev[i], mając dane i, należy do wskaźnika i dodać przesunięcie
2. Otrzymamy w ten sposób właściwy indeks w tablicy A - poszukiwana war-
tość znajduje się więc w A[i + 2].
-Reprezentacja jednotablicowa jest o tyle elastyczna, że umożliwia przecho-
wywanie obiektów o różnych rozmiarach w jednej tablicy. Operacje na takim
heterogenicznym zbiorze obiektów są bardziej złożone niż na zbiorze, w któ-
rym wszystkie obiekty mają identyczne pola. Większość struktur danych, które

L [i9j
A

nexl

Rys. 11.6. Lista z rys. I I.Ja oraz 11.5 reprezentowana w pojedynczej tablicy A. Każdy element listy
zajmuje sp6jny fragment tablicy o długości 3. Trzy poJa key, next oraz prev odpowiadają od-
powiednio przesunięciom O, 1 i 2. Wskaźnikiem do rekordu jest indeks w tablicy, pod którym
majduje się jego początek. Pola w tablicy zawierające elementy listy są jasnoszare, a strzałki
ilustrują kolejność elementów na liście
11.3. REPREZENTOWANIE STRUKTUR WSKAi:NIKOWYCH ZA POMOCĄ TABLIC

będziemy rozważali, składa się z homogenicznych elementów, dla naszych ce-


lów zadowolimy się więc reprezentacją wielotablicową.

Przydzielaniei zwalnianie pamięci


W celu wstawienia klucza do zbioru dynamicznego reprezentowanego za po-
mocą listy dwukierunkowej musimy najpierw wyznaczyć wskaźnik do aktual-
nie nie używanego fragmentu pamięci. Jeśli więc utrzymujemy dynamiczną
strukturę wskaźnikową, to powinniśmy zadbać o metodę przydziału wolnych
miejsc w pamięci komputera. W niektórych systemach do określania, które
miejsca w pamięci są wolne, a które zajęte, służy specjalny program zwany
programem czyszczenia pamięci (ang. garbage co/Jector) - odśmiecaczem.
Wiele programów użytkowych jest jednak na tyle prostych, że mogą same
zająć się zwracaniem nie używanych fragmentów pamięci do systemu zarządza­
nia pamięcią. Zajmiemy się teraz zagadnieniem przydzielania i zwalniania pa-
mięci dla homogenicznych zbiorów elementów na przykładzie list dwukierun-
kowych w reprezentacji wielotablicowej.
Przyjmijmy, że tablice w wielotablicowej reprezentacji listy dwukierunko-
wej mają długość m oraz że w pewnej chwili na liście znajduje się n ,s;;;m ele-
mentów. W takiej sytuacji n rekordów reprezentuje elementy należące do listy,
a pozostałe m - n rekordów jest wolnych. Wolne rekordy mogą posłużyć do
zapamiętania elementów, które będą wstawiane do listy w przyszłości.
Wolne rekordy będziemy przechowywać na specjalnej liście jednokierun-
kowej, którą będziemy nazywać listą wolnych pozycji. Do jej reprezentacji
wystarczy nam tablica next zawierająca odpowiednie wskaźniki. Wskaźnik do
głowy tej listy będzie pamiętany w m:1iennej free. Jeśli zbiór dynamicmy re-
prezentowany przez listę L jest niepusty, to lista wolnych pozycji przeplata się
(w tablicy next) z listą L, jak widać na rys. 11.7. Należy zwrócić uwagę, że
każdy obiekt jest w tej reprezentacji albo na liście L, albo na liście wolnych
pozycji, ale żaden nie jest na obu z nieb jednocześnie.
Lista wolnych pozycji jest stosem: przydzielana jest zawsze ostatnio zwol-
niona pozycja. Jako operacji przydzielania i zwalniania pamięci można więc
używać odpowiednio listowych implementacji operacji na stosie Pop oraz
PUSH. Przyjmujemy, że zmienna globalna free wskazuje w poniższych procedu~
rach na pierwszy element na liście wolnych pozycji.

ALLOCATE~0BJECT()
1 if free = NIL
2 then error „brak pamięci"
3 else x +- free
4 free+- next[x]
5 return x

247
ROZDZIAŁ 11. ELEMENTARNE STRUKTURY DANYCH

.tree rł---- - I 2 3 4 5 6 7 8
fr,, li I 2 3 4 5 6 7 8

0
~

l '7 ~ next l next 3 /


key key

P'"' P'"'
(a) (b)

free lfl1 I 2 3 4 5 6 7 8

l II next
key

P'"'
(c)
Rys. 11.7. Wyniki działania procedur Au.ocAn-Olm!cr i Flt.EE-Oamcr. (a) Lista z rys. 11.S (jasno-
szare) oraz lista wolnych rekordów (ciemnoszare). Strzałki ilustrują wskaźniki listy wolnych rekor-
dów. (b) Wynik wywołania Au.ocATB-OllJEcr() (które wyznacza wartość 4), wpisania wartości 25
w pole key[4] oraz wywołania LIST-INSERT(L, 4). Po wykonaniu tych operacji w głowie listy wol-
nych rekordów znajduje się rekord o numerze 8, który był wskazywany przez nexl (4) na liście
wolnych rekordów. (c) Po wykonaniu operacji LIST-DELBTE(L,5) wywołujemy FREE-Oall!CT(S).
Obiekt o numerze 5 staje się nową głową listy wolnych rekordów, jej nastęi,oikiem zostaje obiekt
o numerze 8

FREE-0DJECT(x)
1 next[x] +- free
2 free+- x

Początkowo lista wolnych pozycji zawiera wszystkich n nie zajętych pozy-


cji. Gdy na liście wolnych pozycji wyczerpią się wszystkie elementy, procedura
ALLOCATE-0BJECT sygnalizuje błąd. Często używa się jednej listy wolnych
pozycji do obsługi wielu list z dowiązaniami jednocześnie. Na rysunku 11.8 są
pokazane dwie listy oraz lista wolnych pozycji, przeplatające się w tablicach
key, next oraz prev.
Obie procedury działają w czasie 0(1), dzięki czemu dają się stosować
w praktyce. Analogiczne procedury daje się stosować ws1ydzie tam, gdzie ma-

_tree Im I 2 J 5 6 7
' 9 IO

L, ne.,t
111!key
L, 131
J prev
___

RyL 11.8. Dwie listy L 1 (ja&nosrne) i L 2 (ciemnoszare) oraz lista wolnych pozycji (zacze.t1liona)

248
11.4. REPREZENTOWANIE DRZEW (UKORZENIONYCH)

my do czynienia z homogenicznym zbiorem obiektów, których jedno z pól pełni


funkcję pola next, służąc do reprezentowania listy wolnych fragmentów pamięci.

ZADANIA

11.3-1. Zilustruj wielotablicową reprezentację ciągu (13, 4, 8, 19, 5, 11) w po-


staci listy dwukien,nkowej. Porównaj ją z analogiczną reprezentacją w po-
staci listy jednokierunkowej.
11.3-2. Napisz procedury ALLOCATE-0BJECT i fREE-OBJECT dla homogenicz-
nego zbioru elementów w reprezentacji jednotablicowej.
11.3-3. Dlaczego procedury ALLOCATE-0BJECT oraz FREE-0BJECT nie muszą
inicjować ani aktualizować wartości pola prev?
11.3-4. Często wymaga się, aby elementy listy dwukierunkowej zajmowały za-
wsze spójny obszar pamięci, na przykład pierwszych m pozycji w reprezen-
tacji wielotablicowej. (Sytuacja taka zachodzi na przy.kład w systemach ze
stronicowaną pamięcią wirtualną). Zaprojektuj procedury ALLOCATE-0B-
JECT oraz FREE-0BJECT tak, aby spełniały ten warunek. Możesz przy tym
przyjąć założenie, że nie ma wskaźników do elementów na liście spoza
samej listy. (Wskazówka: Użyj tablicowej implementacji stosu).
11.3-5. Niech L będzie listą dwuk.ien1nkową o długości m, reprezentowaną za
pomocą tablic key, prev i next o rozmiarze n. Załóżmy, że działamy na
tych tablicach za pomocą procedur ALLOCATE-0BJECT i FREE-0BJECT,
które utrzymują dwukierunkową listę wolnych pozycji F. Przyjmijmy też,
że spośród n dostępnych pozycji dokładnie m znajduje się na liście L,
a n - m na liście wolnych pozycji. Napisz procedurę CoMPACTIFY-LIST(L,
F), która dla danej listy L i listy wolnych pozycji F przesuwa elementy
z L tak, aby zajmowały w tablicy pozycje 1, 2, ... , m, oraz tak modyfikuje
listę F, że jest nadal poprawna i zajmuje pozycje m + I, m + 2, ... , n.
Procedura COMPACTIFY-LIST powinna działać w czasie 0(m), używając
przy tym dodatkowej pamięci stałego rozmiaru. Uzasadnij dokładnie po-
prawność swojej procedury.

11.4. Reprezentowanie
drzew(ukorzenionych)
Metody reprezentowania list opisane w poprzednim podrozdziale można za-
adaptować do dowolnych homogenicznych struktur danych. W tym podroz-
dziale zajmiemy się zagadnieniem reprezentacji drzew ukorzenionych za pomo-
cą struktur wskaźnikowych. Najpierw przyjrzymy się drzewom binarnym,
a następnie omówimy metodę reprezentowania drzew, w których każdy węzeł
ma dowolną liczbę następników (synów).
Węzły drzewa będziemy reprezentować za pomocą rekordów. Podobnie
jak w przypadku list zakładamy, że każdy węzeł ma pole key, tj. klucz. Pozo-

249
ROZDZIAŁ 11. ELEMENTARNE STRUKTURY DANYCH

stałe pola służą do zapamiętywania wskaźników do innych węzłów; ich inter-


pretacja zależy od rodzaju drzewa.

Drzewa binarne
Jak widać
na rys. 11.9, w każdym węźle drzewa binarnego Tpamiętamy wska-
źniki do ojca oraz lewego i prawego syna, odpowiednio w polach p, left i right.
Jeśli p[x] = NIL, to x jest korzeniem drzewa. Jeśli węzeł x nie ma lewego syna,
to left[x] = NIL i podobnie dla prawego syna. Atrybut root[T] zawiera wskaź­
nik do korzenia drzewa T. Jeżeli więc root[T] = NIL, to znaczy, że drzewo
jest puste.

roo1[n

// / //

Rys. 11.9. Reprezentacja drzewa binarnego T. Kai.dy węzeł x ma trzy pola: p[x] (górne), /e/t[x] (lewe
dolne) i right[x] (prawe dolne). Pola key nie zostały na tym rysunku uwzględnione

Drzewa ukorzenioneo dowolnym stopniu rozgałęzień


Metodę reprezentacji drzew binarnych można uogólnić do reprezentacji drzew,
w których liczba synów każdego węzła nie jest większa niż pewna stała k: pola
left i right należy wtedy zastąpić polami son1, son2 , ... , son1;,Metody tej nie daje
się jedak zastosować, jeśli liczba synów węzła nie jest ograniczona, ponieważ
nie wiadomo z góry, ile pól (lub tablic w reprezentacji wielotablicowej) należy
zarezerwować. Co gorsza, nawet jeśli liczba synów jest ograniczona przez pew-
ną dużą stalą, lecz większość węzłów ma w istocie mało synów, to przy powyż­
szej reprezentacji marnuje się dużo pamięci.
Rozwiązaniem tego problemu jest pewne niekonwencjonalne użycie drzew
binarnych, które umożliwia reprezentowanie drzewa o dowolnej liczbie następ-

250
11.4. REPREZENTOWANIE DRZEW (UKORZENIONYCH)

root[71

Rys. Il.IO. Reprezentacja „na lewo syn, na prawo brat" drzewa T. Każdy węzeł x ma pola: p[x]
(górne), kft-childfx] (lewe dolne) i right-sihling(x](prawe dolne). Klucze nie zostały na tym rysun-
ku uwzględnione

ników. Metoda ta umożliwia reprezentację dowolnego dr:zewa o n węzłach


w pamięci O(n). Reprezentacja „na lewo syn, na prawo brat" jest pokazana na
rys. 11.10. Tak jak poprzednio, każdy węzeł drzewa ma polep wskazujące na
ojca, a root[T] wskazuje na korzeń drzewa T. Jednak zamiast wskażników do
wszystkich synów, każdy węzeł x ma tylko dwa wskaźniki:
I. left-child[x] wskazuje na najbardziej lewego syna x,
2. right-siblingf_x]wskazuje na najbliższego, znajdującego się na prawo brata
węzła x.

Jeśli węzełx nie ma synów, to left-child{x] = NIL, a jeśli x jest najbardziej na


prawo wysuniętym synem swojego ojca, to right-sibling{x]= NIL.

Alternatywne reprezentacje drzew


Niekiedy stosuje się inne niż opisane powyżej reprezentacje drzew ukorzenio-
nych. Na przykład w rozdziale 7 kopiec, mający strukturę pełnego drzewa
binarnego, był reprezentowany za pomocą tablicy. Drzewa, które występują
w rozdz. 22, są przeglądane tylko w kierunku „do korzenia", w ich węzełach
jest więc pamiętany tylko wskaźnik do ojca; nie ma potrzeby pamiętania
wskaźników do synów. Istnieje jeszcze wiele innych metod. Dobór najodpo-
wiedniejszej zależy zwykle od konkretnego zastosowania.

251
ROZDZIAŁ 11. ELEMENTARNE STRUKTURY DANYCH

ZADANIA

11.4-1. Narysuj drzewo binarne (którego korzeń ma indeks 6) reprezentowane


przez następujące tablice.

Indeks key left n'"ght


I 12 7 3
2 15 8 NIL
3 4 IO NIL
4 10 5 9
5 2 NIL NIL
6 18 l 4
7 7 NIL NIL
8 14 6 2
9 21 NIL NIL
10 5 NIL NIL

11.4-2. Napisz procedurę rekurencyjną działającą. w czasie O(n), która dla da-
nego drzewa binarnego o n węzłach wypisuje klucze wszystkich węzłów.
11.4-3. Napisz nierekurencyjną procedurę, która w czasie O(n) wypisuje klucze
wszystkich węzłów drzewa binarnego o n węzłach. Użyj stosu jako pomoc-
niczej struktury danych.
11.4-4. Napisz procedurę działającą. w czasie O(n), która wypisuje wszystkie
klucze dowolnego drzewa ukorzenionego o n węzłach, przedstawionego za
pomocą reprezentacji „na lewo syn, na prawo brat".
* 11.4-S. Napisz nierekurencyjną procedurę działającą w czasie O(n), która dla
danego drzewa binarnego o n węzłach wypisuje wszystkie jego klucze.
Twoja procedura może wykorzystywać tylko stałą liczbę dodatkowych
komórek pamięci oraz nie powinna zmieniać (nawet tymczasowo) stru-
ktury drzewa.
* 11.4-6. W reprezentacji „na lewo syn, na prawo brat" dowolnego drzewa
w każdym węźle są pamiętane trzy wskaźniki: /eft-child, right-sihling oraz
parent. Dzięki temu z kazdego węzła można wyznaczyć ojca i uzyskać do
niego dostęp. Wskaż, jak zachować tę własność, pamiętając w każdym
węźle tylko dwa wskaźniki oraz jedną zmienną boolowską.

Problemy
11-1. Porównanie list
Jakie są pesymistyczne złożoności asymptotyczne poszczególnych operacji na
zbiorach dynamicznych dla wymienionych w poniższej tabeli czterech typów list?

252
PROBLEMY

Nieposortowana Posortowana Nieposortowana Posortowana I


jednokierunkowa jednokierunkowa dwukierunkowa dwukierunkowa
SEARCH(L,k)
' •

INSERT(L,x)

DELETE(L,x) .

x)
SUCCESSOR(L,
I
hEDECESSOR(L,x) I
I
MINIMUM(L) I
MAXIMUM(L)

11-2. Listowa reprezentacjakopcówzlącz.alnycb


Na kopcachzłączalnycb można wykonywać następujące operacje: MAK.E-HEAP
(która tworzy pusty kopiec złączalny), INSERT, MINIMUM, EXTRACT-MIN
oraz UNION. Opracuj realizacje listowe kopców złączalnych dla następujących
rodzajów list:

(a) listy posortowane;


(b) listy nieposortowane;
(c) listy nieposortowane; zbiory dynamiczne, które mają zostać złączone są
zawsze rozłączne.

Zaprojektuj każdą z operacji tak, aby była jak najbardziej efektywna. Oszacuj
czasy działania operacji, jako funkcje rozmiaru zbiorów dynamicznych na któ-
rych działają:

11-3. Wyszukiwaniena posortowanejliście zajmujęcej spójnyobszarpamięci


W wyniku rozwiązania zadania 11.3-4. otrzymujemy metodę utrzymywania
n-elementowej listy w spójnym obszarze tablicy (na jej początkowych n pozyc-
jach). Przyjmijmy, że wszystkie klucze są różne oraz że lista jest posortowana,
tzn. key[i] < key{next[i]] dla wszystkich i= 1, 2, ... , n takich, że next[i] 'F NIL.
Przekonamy się, że przy takich założeniach następujący algorytm probabilis-
tyczny pozwala na wyszukiwanie na liście zajmującej spójny obszar pamięci
znacznie szybciej niż w czasie liniowym.

COMPACT-L!ST-SEARCH(L, k)
I i-head[L]
2 n - length[L]
3 wbile i #a NIL i key(i] < k

253
ROZDZIAŁ 11. ELEMENTARNE STRUKTURY DANYCH

4 do j +-RANDOM(!, n)
5 if key[i] < key[j] i key[j] < k
6 then i+- j
7 i+- next[i]
8 if key[i] - k
9 then return i
10 return NIL

Jeślipominiemy wiersze 4-6 tej procedury, to uzyskamy zwyczajny algo-


rytm wyszukiwania na posortowanej liście, w którym indeks i przebiega kolej-
no wszystkie pozycje listy. W wierszach 4-6 zostaje podjęta próba przeskocze-
nia do przodu na losowo wybraną pozycję j. Talci przeskok jest opłacalny, jeśli
key[)] jest większe niż key[i], a przy tym mniejsze niż k. W takim przypadku
j jest pozycją, która wraz ze wszystkimi leżącymi na liście między i a), może
zostać bezpiecznie pominięta. Dzięki temu, że lista jest zwarta mamy gwaran-
cję, że dowolna wartość j z przedziału od I do n jest indeksem pewnego elemen-
tu listy, a nie „dziurą" znajdującą się na liście wolnych pozycji.

(a) Dlaczego zakładamy przy analizie procedury COMPACT-LIST-SEARCH,że


wszystkie klucze są różne? Wykaż, że losowe przeskoki nie poprawiają
złożoności asymptotycznej, jeśli lista może zawierać wiele elementów o ta-
kim samym kluczu.

Na potrzeby analizy czasu działania procedury COMPACT-LIST-SEARCH


wyróżnimy w jej wykonaniach dwie fazy. W pierwszej fazie zaniedbujemy po-
stępy osiągnięte w celu znalezienia k, osiągnięte w wierszach 7-9. Oznacza to,
że w fazie I przemieszczamy się po liście tylko za pomocą losowych przesko-
ków. Analogicznie, w fazie 2 pomijamy wyniki wykonania kodu w wierszach
4-6, czyli jest wykonywane zwyczajne liniowe przeszukiwanie.
Niech X 1 będzie zmienną losową wyrażającą odległość na liście (tzn. dłu­
gość łańcucha kolejnych wskaźników next) między pozycją i a szukanym klu-
czem k po t iteracjach w fazie 1.

(b) Wykaż, że oczekiwany czas działania procedury COMPACT-LIST-SEARCH


wynosi O(t + E[Xr]) dla każdego t ~ O.
"
(c) Wykaż, że E[XrJ.:;,;;L (1 - r/n) 1• (Wskazówka: Skorzystaj z tożsamości
r=i
(6.28)).
•-1
(d) Wykaż, że L rr.:;,;;nr+1 /(t + 1).
(e) Udowodnij, że E[X,J .:;,;;
n/(t + 1), oraz wyjaśnij intuicyjny sens tej zależności.

254
UWAGI DO ROZDZIAŁU

(f) Wykaż, że oczekiwany czas działania procedury COMPACT-LIST-SEARCH


wynosi O(-./ n).

Uwagido rozdziału
Książki Abo, Hopcrofta i Ullmana (5] oraz Knutha (121] są znakomitymi
źródłami informacji na temat elementarnych struktur danych. W książce Gon-
neta [90] można znaleźć dane eksperymentalne dotyczące wielu operacji wyko-
nywanych na strukturach danych.
Trudno sprecyzować, jakie jest pochodzenie stosów i kolejek jak.o struktur
danych używanych w informatyce, ponieważ analogiczne pojęcia występowały
już wcześniej w matematyce i praktyce biurowej, zanim jeszcze pojawiły się
komputery. K.nuth (121] wspomina A. M. Turinga, który w 1947 r. opracował
metodę łączenia pod.procedur przy użyciu stosów.
Wskaźnikowe struktury danych również należą do „folkloru" informa-
tycmego. Według K.nutha wskaźników używano już w pierwszych kompute-
rach z pamięciami bębnowymi. W języku A-1 stworzonym przez G. M. Hop-
pera w 1951 r. wyrażenia algebraiczne były reprezentowane za pomocą drzew
binarnych. Wyeksponowanie znaczenia wskaźników i ich popularyzację Knuth
przypisuje językowi IPL-11, stworzonemu w 1956 r. przez A. Newella,
J. C. Shawa oraz H. A. Simona. W zaprojektowanym przez nich w 1957 r.
języku IPL-111 są wbudowane jawne operacje na stosach.
Rozdział 12

Tablicez haszowaniem

W wielu zastosowaniach używa się zbiorów dynamicznych, na których są wy-


konywane tylko operacje słownikowe: INSERT, SEARCH i DELETE. W kom-
pilatorach języków programowania na przykład utrzymuje się tablicę symboli,
w której k.luczarni elementów są dowolne ciągi znaków odpowiadające iden-
tyfikatorom. Tablica z haszowaniem jest efektywną strukturą danych służącą
do reprezentacji słowników. Mimo że wyszukiwanie elementu w tablicy z ha-
szowaniem może trwać tyle, ile wyszukiwanie na liście z dowiązaniami - 0(n)
w najgorszym przypadku - w praktyce haszowaniet daje znakomite wyniki.
Przy rozsądnych załoi.eniach można wykazać, że cerek.iwany czas wyszukiwa-
nia elementu w tablicy z haszowaniem wynosi 0(1).
Tablica z haszowaniem jest uogólnieniem zwyczajnej tablicy. Adresowanie
bezpośrednie umożliwia uzyskanie dostępu do dowolnej pozycji w tablicy w CT.a-
sie 0(1). W podrozdziale 12.1 omówimy bardziej szczegółowo adresowanie
bezpośrednie. Jego stosowanie ogranicza się jednak do sytuacji, w których stać
nas na zarezerwowanie pozycji w tablicy dla każdej możliwej wartości klucza.
Jeżeli liczba przechowywanych elementów jest mała w stosunku do liczby
wszystkich możliwych kluczy, to tablice z haszowaniem stają się bardzo atrak-
cyjną i efektywną alternatywą dla adresowania bezpośredniego, ponieważ roz-
miar tablicy z haszowaniem jest zwykle proporcjonalny do liczby elementów,
które zawiera. Indeks tablicy, pod którym majduje się element, nie jest już po
prostu Gakw adresowaniu bezpośrednim) jego kluczem, ale może być obliczo-
ny na podstawie klucza. W podrozdziale 12.2 przedstawimy główne pojęcia,
a w podrozdziale 12.3 omówimy obliczanie indeksów w tablicy za pomocą
funkcji haszujących. Przedstawimy i przeanalizujemy wiele możliwych warian-

' W literaturze jako tłumaczenie ang. hashing spotyka się również słowo mieszanie lub roz-
praszanie (przyp. red.).

256
12.1. TABLICE Z ADRESOWANIEM BEZPOŚREDNIM

tów haszowania. Należy jeszcze raz podkreślić, że haszowanie jest niezwykle


efektywną i praktyczną metodą: średni czas działania podstawowych operacji
słownikowych na tablicach z haszowaniem wynosi 0(1).

12.1. Tablicez adresowaniembezpośrednim


Adresowanie bezpośrednie jest prostą metodą, która jest bardzo skuteczna,
jeśli uniwersum kluczy U jest rozsądnie małe. Załóżmy, że dla pewnych celów
używamy zbioru dynamicznego, którego elementy mają klucze należące do
uniwersum U= {O,1, ..., m - 1}, gdziem nie jest zbyt duże. Przyjmujemy przy
tym, że żadne dwa elementy nie mają identycznych kluczy.
Przy powyższych założeniach zbiór dynamiczny możemy reprezentować za
pomocą tablicy (lub tablicy z adresowaniem bezpośrednim) T(O .. m - 11,w której
każdej pozycji odpowiada klucz należący do uniwersum U. Ta metoda jest
zilustrowana na rys. 12.1; na pozycji kw tablicy znajduje się wskaźnik do elementu
o kluczu k. Jeśli do zbioru nie należy żaden element o kluczu k, to T[k] = NIL.
Implementacja operacji słownikowych jest trywialna.

DIRECT-AoDRESS-SEARCH(T, k)
return T[k]
DIRECT-AnDRESS-INSERT(T, x)
T[key[x]J - x
DIRECT-AnDRESS-DELETE(T, x)
T[key[x]] - NIL

Ki"o Doda(kowc
dane

'
J

'

Rys. 12.1. Reprezentacja zbioru dynamicmego za pomocą tablicy T z adresowaniem bezpośrednim.


Każdy klucz z uniwersum U= {O, I, ... , 9} odpov.iada pewnemu indeksowi w tablicy. Zbiór
K = {2, 3, 5, 8} wyznacza pozycje w tablicy, na których :znajdują się wskaźniki do elementów. Na
pozostałych pozycjach (ciemnoszarych) jest zapisana wartość NIL

257
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

Każda z tych operacji jest szybka - działa


w czasie 0(1).
W niektórych zastosowaniach elementy zbioru dynamicznego mogą być
zapamiętywane w samej tablicy. Zamiast przechowywać klucz elementu oraz
pewne dodatkowe dane w rekordzie poza tablicą, do którego wskaźnik jest
pamiętany na odpowiedniej pozycji w tablicy, możemy umieścić cały element
na tej pozycji w tablicy, oszczędzając w ten sposób pamięć. Co więcej, często
nie ma w ogóle potrzeby zapamiętywania klucza elementu, ponieważ jest on
jednoznacznie wyznaczony przez indeks pozycji w tablicy, na której się znaj~
duje ten element. Jeżeli jednak nie zapamiętujemy kluczy; to musimy zapewnić
jakąś metodę określania, czy pozycja w tablicy jest pusta.

ZADANIA
12.1-1. Niech zbiór dynamiczny S będzie reprezentowany przez tablicę
To długości m, z adresowaniem bezpośrednim. Opisz procedurę wyszuku-
jącą największy element zbioru S. Jaki jest pesymistyczny czas działania
Twojej procedury?
12.1-2. Wektor bitowy jest tablicą bitów (zer i jedynek). Wektor bitowy o dłu­
gości m zajmuje mniej pamięci niż tablica m wskaźników. Opisz metodę
reprezentowania zbiorów dynamicznych za pomocą wektorów bitowych
(przyjmując, że w skład elementów nie wchodzą żadne dodatkowe dane).
Operacje słownikowe powinny działać w czasie 0(1).
12.1-3. Zaproponuj metodę implementacji tablicy z adresowaniem bezpośred­
nim, w której klucze pamiętanych elementów nie muszą być różne, a z każ­
dym elementem mogą być związane pewne dodatkowe dane. Wszystkie
trzy operacje słownikowe (INSERT, DELETE oraz SEARCH) powinny dzia-
łać w czasie 0(1). (Argumentem procedury DELETE jest wskaźnik do obie-
ktu, który ma zostać usunięty, a nie sam klucz).
* 12.1-4. Chcemy reprezentować słownik za pomocą bezpośredniego adresowa-
nia w ogromnej tablicy. Na początku w tablicy mogą znajdować się przypa-
dkowe wartości, a jej inicjowanie nie wchodzi w rachubę ze względu na jej
duży rozmiar. Zaprojektuj metodę reprezentowania słownika z adresowa-
niem bezpośrednim w ogromnej tablicy. Każdy przechowywany element
powinien zajmować tylko 0(1) pamięci, operacje SEARCH, INSERT i DELE~
TE powinny działać w czasie 0(1), a inicjowanie tej struktury danych
w czasie 0(1). (Wskazówka: Użyj dodatkowego stosu o rozmiarze równym
liczbie elementów przechowywanych w tablicy, za pomocą którego można
określać, czy dana pozycja w dużej tablicy zawiera sensowną wartość).

12.2. Tablicez haszowaniem


Adresowanie bezpośrednie ma jedną podstawową (i często dyskwalifikującą)
wadę: jeśli uniwersum kluczy U jest zbyt duże, to przechowywanie w pamięci
komputera tablicy To ro2llliarze IUImoże być nierealne. Co więcej, zbiór
12.2. TABLICE Z HASZOWANIEM

K kluczy elementów należących do zbioru dynamicznego może być tak mały


w porównaniu z U, że większość pamięci zarezerwowanej dla T będzie się
niepotrzebnie marnować.
Jeśli zbiór K kluczy przechowywanych w słowniku jest znacznie mniejszy
niż uniwersum U wszystkich możliwych kluczy, to tablica z haswwaniem zaj-
muje znacznie mniej pamięci niż zwyczajna tablica z adresowaniem bezpośred­
nim. Okazuje się, że pamięć zajmowaną przez tablicę z haszowaniem można
ograniczyć do @(I.Kl), a wyszukiwanie w takiej tablicy nadal działa w czasie
0(1). (Należy jednak pamiętać, że to ograniczenie dotyczy tutaj tylko średniego
czasu wykonania, natomiast w adresowaniu bezpośrednim jest również słuszne
dla pesymistycznej zlożono.fci czasowej).
W tablicy z adresowaniem bezpośrednim element o kluczu k zostaje umie-
szczony na pozycji o indeksie k. W tablicy z haszowaniem ten element trafia na
pozycję h(k) - do obliczenia pozycji dla klucza k używa się funkcji haszującej h.
Ta funkcja odwzorowuje uniwersum kluczy U w zbiór pozycji tablicy z haszo-
waniem T[O .. m - 1]:

h:U-{O, l, ...,m-1)

Główna idea haszowania jest pokazana na rys. 12.2. Funkcje haszujące wpro-
wadza się, aby zmniejszyć liczbę potrzebnych pozycji w tablicy z IUJdo.m, co
. . . . . .
moze znacznie ogran1czyc wymagarua pam1ęc1owe.
.
T
• • ..........
.. "
.
""
,,,,,
,,.,,,. ...
'""" ' : ::

.... : '.: . . .
h( kl )
.. ...
.
., ' hl k 4)
.
......
K
*, .. • ••
. ""

{kl~= h(k:)=h(k.5)
. •• .
re zbioru)
,, ""

'' ...
'" ,.,
'
h1k3)

m,
Rys. 12.2. Funkcja haszująca Ir przyporządkowuje pozycje w tablicy z haszowaniem kluczom z uni-
wersum U. Klucze k 2 i k~ kolidują ze sobą, ponieważ odpowiada im ta sama pozycja

Ceną, jaką płacimy za te ogromne oszczędności pamięci, jest możliwość


kolizji, tj. sytuacji, w której funkcja haszująca przypisuje dwu różnym kluczom
tę samą pozycję w tablicy. Na szczęście istnieją efektywne metody rozwiązywa­
nia konfliktów wywołanych przez kolizje.

259
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

Oczywiście byłoby
w ogóle unikać kolizji. Zasadniczy jest tutaj
najlepiej
dobór funkcji haszującej h. Jednym z możliwych sposobów uniknięcia lub
przynajmniej zminimalizowania liczby kolizji jest wybranie funkcji h, która
wydaje się być „losowa". Angielski odpowiednik słowa „haszowanie" - ,,hash-
ing" - kojarzący się z losowym mieszaniem i siekaniem, dość dobrze oddaje
istotę tego podejścia. (Oczywiście funkcja haszująca h musi być deterministycz-
na, tzn. dla danego argumentu k musi dawać zawsze ten sam wynik h(k)). Ze
względu na fakt, że IUI > m, w U muszą być takie dwa klucze, dla których
funkcja haszująca ma taką samą wartość; całkowite uniknięcie kolizji nie jest
więc możliwe. Jeśli nawet użyjemy dobrze dobranej, ,,losowej" funkcji haszują­
cej, która minimalizuje liczbę kolizji, to mimo wszystko nadal potrzebna jest
nam metoda ich rozwiązywania, jeśli już wystąpią.
W pozostałej części tego podrozdziału przedstawimy najprostszą technikę
rozwiązywania kolizji, nazywaną metodą łańcuchową. W podrozdziale 12.4
opiszemy inne podejście do rozwiązywania kolizji, zwane adresowaniem ot-
wartym.

Rozwiązywanie kolizji metodą łańcuchową

W metodzie łańcuchowej wszystkie elementy, którym odpowiada ta sama pozy-


cja w tablicy, zostają umieszczone na jednej liście (patrz rys. 12.3). Na pozycji
jw tablicy jest pamiętany wskaźnik do początku listy tych wszystkich elemen-
tów, dla których funkcja h daje wartośćj. Jeśli w zbiorze nie ma takich elemen-
tów, to pozycja j ma wartość NIL.
Jeśli rozwiązujemy kolizje metodą łańcuchową, to operacje słownikowe na
tablicy T daje się łatwo zaimplementować.

,,,,,,

lc.c,,.
'
''
:,,:.,,.
,,,,
;;.Ti::;;,"1,.t.
,,,,,,,
"
,,.,.,,,
,,,,.,,.,
=~~
·:::J=::1---1''~,
->[~·

,, /
"'' ,, ,,

"' ,, /

Rys. 12.3, Rozwiązywame kolizji metodą łańcuchową. Na każdej pozycji jw tablicy T znajduje się
wskaźnik do listy wszystkich kluczy, d.Jaktórych funkcja haszują.ca. h daje wartośc j. Na przykład
h(k 1) = h(k4 ) oraz h(k 5 ) ""h(k 2) = h(k 1)

260
12.2. TABLICE Z HASZOWANIEM

CJłAINED-HASH-INSERT(T, x)
wstaw x na początek
listy T[h(key[x])]
CHAINED-HASH-SEARCH(T, k)
wyszukaj element o kluczu k na liście T[h(k)]
CHAINED-HASH-DELETE(T, x)
usuń element x z listy T[h(key[x])J

Wstawianie działa zawsze w czasie 0(1). Pesymistyczny czas działania wy-


szukiwania jest proporcjonalny do długości listy; poniżej przedstawiamy bar-
dziej szczegółową analizę. Jeśli listy są dwukierunkowe, to operację usunięcia
można zawsze wykonać w czasie 0(1). (Jeśli listy są jednokierunkowe, to musi-
my najpierw odszukać element x na liście T[h(key[x])], aby odpowiednio za-
ktualizować wskaźnik next jego poprzednika; czasy działania wyszukiwania
i usuwania są wtedy praktycznie takie same).

Analiza haszowania metodą łańcuchową


Na ile optymalne jest haszowanie, jeśli do rozwiązywania kolizji używamy
metody łańcuchowej? W szczególności interesujące jest, jaki jest czas działania
operacji wyszukiwania elementu o danym kluczu?
Dla danej tablicy Tom pozycjach, w której znajduje się n elementów, jej
współczynnik zapełnienia a określamy jako n/m, czyli średnią liczbę elementów
w łańcuchu. W naszej analizie głównym parametrem będzie właśnie o:. Będzie­
my badać złożoność procedur dla ustalonego a, przy n i m dążących do nie-
skończoności. (Wartość IX może być mniejsza, równa lub większa niż l).
W najgorszym przypadku zachowanie się tablic z haszowaniem z wyko-
rzystaniem metody łańcuchowej rozwiązywania kolizji jest bardzo nieefektyw-
ne: wszystkich n kluczy jest odwzorowywanych na tę samą pozycję w tablicy,
tworząc listę o długości n. Pesymistyczny czas wyszukiwania wynosi więc E>(n)
plus czas potrzebny na obliczenie wartości funkcji haszującej ~ nie stanowi
to żadnej poprawy w stosunku do implementacji z jedną listą dla wszystkich
elementów.
Średnie zachowanie się haszowania zależy od tego, na ile równomiernie
(w średnim przypadku) funkcja haszująca h rozmieszcza zbiór przechowywa-
nych kluczy na m pozycjach tablicy. Tym zagadnieniem zajmiemy się w pod-
rozdz. 12.3, a tymczasem założymy, że losowo wybrany element z jednakowym
prawdopodobieństwem trafia na każdą z m pozycji, niezależnie od tego gdzie
trafiają inne elementy, Jeśli spełnione będzie to założenie, to będziemy mówić
o prostym równomiernym haszowaniu.
Przyjmujemy zwykle, że wartość funkcji haszującej h(k) można obliczyć
w czasie 0(1), czas potrzebny na wyszukanie elementu o kluczu k zależy
więc liniowo od długości listy T[h(k)]. Zaniedbując stały czas potrzebny na

·-------ce ........
.
261
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

obliczenie wartości funkcji i dostęp do pozycji h(k), skupimy się teraz na


znalezieniu oczekiwanej liczby elementów, które musi rozpatrzyć procedura
wyszukująca, czyli liczby elementów na liście T[h(k)J, dla których sprawdza-
my, czy ich klucze są równe k. Rozważymy dwa przypadki. W pierwszym
wyszukiwanie kończy się porażką - szukany element nie zostaje odnaleziony
(żaden element w tablicy nie ma klucza k). W drugim przypadku wyszukiwanie
kończy się sukcesem - element o kluczu k zostaje znaleziony w tablicy.

TwlERDZENIE 12.1.
W tablicy z haszowaniem wykorzystującym łańcuchową metodę rozwiązywa­
nia kolizji, przy założeniu o prostym równomiernym haszowaniu, średni czas
działania procedury wyszukiwania zakończonego porażką wynosi 0(1 + a:).

DOWÓD
Przy założeniu prostego równomiernego haszowania każdy klucz k jest zjed-
nakowym prawdopodobieństwem odwzorowywany na dowolną z m pozycji
w tablicy. Średni czas wyszukiwania zakończonego porażką jest więc równy
średniemu czasowi przejścia do końca jednej z m list. Średnia długość takiej
listy jest równa współczynnikowi zapełnienia tablicy a= n/m. Stąd oczekiwana
liczba elementów sprawdzonych w czasie wyszukiwania zakończonego porażką
jest równa a:, całkowity czas (wliczając czas potrzebny na obliczenie h(k) oraz
dostęp do pozycji T[h(k)]) wynosi więc 0(1 + a).


TwlERDZENIE 12.l.
W tablicy z haszowaniem wykorzystującym łańcuchową metodę rozwiązywa­
nia kolizji, przy założeniu o prostym równomiernym haszowaniu, średni czas
działania procedury wyszukiwania zakończonego sukcesem wynosi 0(1 + ix).

DOWÓD
Możemy przyjąć, że klucz, którego szukamy, jest z jednakowym prawdopodo-
bieństwem dowolnym spośród n kluczy znajdujących się w tablicy. Założymy
również, że procedura OfAINED-HASH-INSERT wstawia nowe elementy na
końcu listy, a nie na początku. (Z rozwiązania zad. 12.2-3 wynika, że średni
czas wyszukiwania nie zależy od tego, czy wstawiamy elementy na początek,
czy na koniec listy). Oczekiwana liczba rozpatrzonych w czasie wyszukiwania
elementów jest o l większa niż liczba określająca długość, jaką miała lista, na
której znajduje się szukany element, w chwilę przed jego dodaniem do tej listy
(ponieważ każdy nowy element zostaje dodany na koniec listy). W celu oblicze-
nia oczekiwanej liczby sprawdzonych elementów należy więc wziąć średnią, po
wszystkich n elementach w tablicy, z 1 plus oczekiwana długość listy, do której
został dodany i-ty element. Oczekiwana długość tej listy wynosi (i -1)/m, więc

-----·-------- -------------------
262
12.2. TABLICE Z HASZOWANIEM

oczekiwana liczba elementów rozpatrzonych w czasie wyszukiwania zakończo­


nego sukcesem wynosi

I"( I+
n,L, i-1)
m - I+
I" (i- I)
nm,L,

-1 + " - I-
2 2m

W rezultacie całkowity oczekiwany czas działania procedury wyszukiwania,


gdy kończy się ono sukcesem (wliczając tak.że koszt obliczenia wartości funkcji
haszującej), wynosi 0(2 + •/2 - l/2m) - 0(1 + ,).

Jakie wnioski płyną z tej analizy? Otóż, jeśli liczba pozycji w tablicy z ha-
szowaniem jest co najmniej proporcjonalna do liczby elementów w tablicy,
czyli zachodzi n= O(m), to jednocześnie a= n/m = O(m)/m = 0(1). W takim
przypadku średni czas wyszukiwania jest ograniczony przez stałą. Z wcześniej­
szej dyskusji wiadomo, że pesymistyczny czas wstawiania jest 0(1) (patrz zad.
12.2-3), a usuwanie ma również koszt pesymistyczny 0(1), jeżeli listy są dwu-
kierunkowe. Średni czas wszystkich operacji słownikowych na tablicach z ha-
szowaniem za pomocą łańcuchowej metody rozwiązywania kolizji można więc
ograniczyć przez 0(1).

ZADANIA

12.2-1. Załóimy, że funkcja haszująca h odwzorowuje n różnych kluczy w tab-


licę To długości m. Jaka jest oczekiwana liczba kolizji? Mówiąc precyzyj-
niej, jaka jest oczekiwana liczba elementów zbioru {(x, y): h(x) = h(y)}?
12.2-2. Zilustruj ciąg wstawień elementów o kluczach 5, 28, 19, 15, 20, 33, 12,
17, 10 do tablicy z haszowaniem wykorzystującej do rozwiązywania
kolizji metodę łańcuchową. Przyjmijmy, że tablica zawiera 9 pozycji,
a h(k) = k mod 9 jest funkcją haszującą.
12.2-3. Wykaż, że oczekiwany czas wyszukiwania nie zależy od tego, C'Z'Jwsta-
wiamy elementy na początek, C'Z'Jna koniec listy. (Wskazówka: Wykaż, że
oczekiwany czas wyszukiwania jest jednakowy dla dowolnych dwóch upo-
rLądkowań listy).
12.2-4. Profesor Marley wysunął hipotezę, że jeśli wszystkie listy w metodzie
łańcuchowej będą posortowane, to może to znacznie poprawić efektywność

263
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

tablicy z haszowaniem. Jak modyflkacja profesora wpływa na c:.r.asdziałania


operacji wstawiania, usuwania oraz wyszukiwania (zakończonego sukcesem
lub porażką)?
12.2,.5. Zaproponuj metodę przydzielania i zwalniania pamięci dla elementów
wewnątrz samej tablicy z haszowaniem, łącząc w tym celu wszystkie wolne
pozycje w tablicy za pomocą odpowiedniej listy. Przyjmij przy tym założe­
nie, że na jednej pozycji można zapamiętać znacznik oraz albo jeden ele-
ment i wskaźnik, albo dwa wskaźniki. Oczekiwany czas działania wszyst-
kich operacji słownikowych oraz operacji na liście wolnych pozycji powi-
nien być 0(1). Czy lista wolnych pozycji musi być dwukierunkowa, czy
wystarczy lista jednokierunkowa?
12.2--6.Wykaż, że jeśli IUl > nm, to istnieje podzbiór U o rozmiarze n, składa­
jący się z kluczy, które są odwzorowywane na tę samą pozycję w tablicy.
Z tego faktu wynika, że pesymistyczny czas działania wyszukiwania w tab-
licy z haszowaniem wynosi 0(n), jeśli do rozwiązywania kolizji stosujemy
metodę łańcuchową.

12.3. Funkcjehaszujące
W tym podro7.dziale zajmujemy się zagadnieniem projektowania dobrych
funkcji haszujących i przedstawiamy trzy metody ich tworzenia: haszowanie
modularne, haszowanie przez mnożenie oraz haszowanie uniwersalne.

Jakie są cechy dobrej funkcji haszującej?

Dobra funkcja haszująca powinna spełniać (w przybliżeniu) założenie pro-


stego równomiernego haszowania: losowo wybrany klucz jest z jednak.owym
prawdopodobieństwem odwzorowywany na każdą z m pozycji. Aby wyrazić
ten warunek bardziej formalnie, załóżmy, że wybieramy losowo klucz
z U zgodnie z rozkładem prawdopodobieństwa P; tzn. P(k) jest prawdopo-
dobieństwem, że wybierzemy k. Wtedy warunek prostego równomiernego
haszowania oznacza, że

I
L P(k) - - dla j- O, I, ..., m - I (12.1)
.t:li(.t)"'i m

Niestety, ogólnie nie daje się sprawdzić tego warunku, ponieważ zwykle nie
znamy P.
Czasem (rzadko) znamy rozkład P. Niech na przykład klucze będą losowy-
mi liczbami rzeczywistymi k rozłożonymi niezależnie i równomiernie w prze-
k < l. W tym przypadku można wykazać, że funkcja haszująca
dziale O ;:;,_;

264
12.3. FUNKCJE HASZUJĄCE

h(k)- LkmJ
spełnia równanie (12.1).
W praktyce przy doborze funkcji haszujących stosuje się rozmaite metody
heurystyczne. Jakościowe infonnacje na temat Pokazują się przy tym niejed-
nokrotnie bardzo użyteczne. We:hny na przykład tablicę symboli kompilatora,
w której kluczami są napisy reprezentujące identyfikatory występujące w pro-
gramie. Jest zwykle duże prawdopodobieństwo, że podobne symbole (np. adres
i adresy) występują w jednym programie. Dobra funkcja haszująca powinna
minimalizować szansę, że takie niewiele różniące się symbole będą odwzorowa-
ne na tę samą pozycję w tablicy z haszowaniem.
Typowe podejście polega na takim doborze wartości funkcji haszującej,
aby były one maksymalnie niezależne od możliwych tendencji mogących wy-
stępować w danych. Na przykład w haszowaniu modularnym (które omawia-
my poniżej) wartość funkcji haszującej jest równa reszcie z dzielenia klucza
przez pewną ustaloną liczbę pierwszą. Jeżeli nie ma żadnych związków między
tą liczbą pierwszą a rozkładem prawdopodobieństwa P, to metoda ta daje
bardzo dobre wyniki.
Należy na koniec wspomnieć, że w niektórych zastosowaniach wymagamy
spełnienia przez funkcję haszującą jeszcze silniejszych warunków niż samo pro-
ste równomierne haszowanie. Możemy na przykład postulować, aby „bliskim"
(w pewnym sensie) kluczom odpowiadały znacznie od siebie oddalone wartości
funkcji haszującej. (raka własność będzie szczególnie pożądana, jeśli do roz-
wiązywania kolizji użyjemy metody adresowania liniowego z podrozdz. 12.4).

Utożsamienie kluczy z liczbami naturalnymi

Dziedziną większości funkcji haszujących jest zbiór liczb naturalnych


N = {O, 1, 2, ... }. Jeśli więc klucze nie są liczbami naturalnymi, to należy ustalić
ich odwzorowanie w zbiór liczb naturalnych. Na przykład kluczowi będącemu
ciągiem znaków można przyporządkować liczbę naturalną, traktując go jako
ciąg cyfr w odpowiednim systemie pozycyjnym. I tak, identyfikator pi można
interpretować jako parę liczb całkowitych (112, 105), ponieważ w kodzie ASCII
p = 112, a i = 105. Traktując napis pi jako zapis liczby w układzie o podstawie
128, można go utożsamić z liczbą (112· 128) + 105 = 14441. W praktycznych
zastosowaniach jest zwykle dość łatwo zaprojektować taką prostą metodę od-
wzorowywania kluczy w (niekoniecznie male) liczby naturalne. W dalszej części
rozdziału będziemy już zakładać, że jako klucze występują liczby naturalne.

12.3.1. Haszowanie modularne


Funkcja haszująca stosowana w haszowaniu modularnym na kluczu k daje
wartość będącą resztą z dzielenia k przez m, gdziem jest liczbą pozycji w tabli-
cy, tzn. zachodzi
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

h(k) - kmodm

Jeśli na przykład w tablicy z haszowaniem jest m = 12 pozycji, to dla klucza


k = 100 mamy h(k) = 4, Haszowanie modularne wymaga wykonania jednego
dzielenia całkowitego, działa więc dość szybko.
W metodzie modularnej należy unikać pewnych wartości m. Na przykład
m nie powinno być potęgą 2, ponieważ jeśli m = 2P, to h(k) jest liczbą po-
wstającą po prostu z p najmniej znaczących bitów liczby k. Jeśli nie mamy przy
tym gwarancji, że rozkład prawdopodobieństwa jest taki, że każdy z p-bito-
wych wzorców jest równie prawdopodobny, to lepiej używać funkcji haszują­
cej, która zależy od wszystkich bitów w kluczu. Podobnie należy unikać potęg
10, jeśli kluczami występującymi w rozwiązywanym problemie są liczby dzie-
siętne, ponieważ wartość funkcji baszującej nie zależy wtedy od wszystkich cyfr
dziesiętnych k. Wreszcie można wykazać, że jeśli m = 2P- I oraz k jest cią­
giem znaków interpretowanych jako liczba w układzie o podstawie 2P,to war-
tości funkcji baszującej na dwóch ciągach, różniących się tylko odwróceniem
kolejności dwu sąsiednich znaków, są sobie równe.
Dobrymi wartościami m są liczby pierwsze niezbyt bliskie potęgom 2. Za-
łóżmy na przykład, że chcemy używać tablicy z haszowaniem wykorzystującej
do rozwiązywania kolizji metodę łańcuchową, w której będziemy przechowy-
wać około n= 2000 ciągów znak.ów, przy czym każdy znak składa się z 8 bi-
tów. Podejmujemy przy tym decyzję, że dopuszczamy przeglądanie list o śred­
niej długości 3 w razie porażki przy wyszukiwaniu, decydujemy się więc na
użycie tablicy z haszowaniem o długości m = 701. Liczba 701 jest dobra, po-
nieważ jest liczbą pierwszą leżącą blisko 2000/a = 2000/3 (gdzie a = 3, jak
postulowaliśmy powyżej), a zarazem nie leży blisko żadnej potęgi 2. Jeśli każdy
klucz k będziemy interpretować jak.o liczbę, to naszą funkcją haszującą będzie

h(k) - kmod 701

Dla bezpieczeństwa dobrze jest sprawdzić empirycznie, na ile równomiernie


tak.a funkcja „rozrzuca" na pozycje w tablicy zbiory kluczy pochodzące z „rze-
czywistych" danych.

12.3.2. Haszowanieprzezmnożenie
Tworząc funkcję haszującą za pomocą mnoZenia, obliczenia przeprowadza się
w dwóch krokach. Najpierw mnożymy klucz k przez stałą A z przedziału
O< A < I i wyi.naczamy ułamkową część kA. Następnie mnożymy tę wartość
przez m; wartość funkcji podłogi z uzyskanej liczby jest wartością funkcji ha-
szującej. Symbolicznie można więc wyrazić tę funkcję następująco:

h(k) - Lm(kAmod l)J

266
12.3. FUNKCJE HASZUJĄCE

gdzie „kA mod I" oznacza ułamkową część kA, tj. kA - LkAJ.
Zaletą haszowania przez mnożenie jest dowolność wyboru m. Zwykle jed-
=
nak wybieramy jakom pewną potęgę 2 - m 2Pdla pewnej liczby naturalnej
p - ponieważ możemy wtedy łatwo zaimplementować funkcję haszującą na
większości komputerów w następujący sposób. Załóżmy, że słowo maszynowe
ma długość w bitów oraz że k mieści się w jednym słowie. Jak widać na rys.
12.4, najpierw mnożymy k przez w-bitową liczbę całkowitą LA· 2wJ. Wynik jest
2w-bitową liczbą r 12w + r 0 , gdzie r 1 jest bardziej znaczącym, a r 0 mniej znaczą­
cym słowem iloczynu. Szukana p-bitowa wartość funkcji haszującej składa się
z p najbardziej znaczących bitów liczby r0 .


X I
,·~·---~~c____ _,1 ~ I
'---~ Wybieramy p bitów
I w,•i
Rys. 12.4. Haszowanie przez mnożenie. Reprezenlacja w-bitowa klucza k zostaje pomnożona przez
w-bitową liczbę LA· 2"'J, gdzie O < A < I jest odpowiednią stałą. Najbardziej maczącycb p bitów
dolnej w-bitowej połowy powyżBzego iloczynu jest wyznaczaną wartością funkcji haszującej h{k)

Chociaż metoda ta działa poprawnie dla dowolnej stałej A, okazuje się, że


dla pewnych jej wartości zachowuje się lepiej niż dla pozostałych. Optymalny
wybór tej stałej zależy od charakteru rozpraszanych danych. W książce Knu-
tha [123] znajduje się bardziej drobiazgowa analiza, z której wynika, że stała

As, (.j 5 - 1)/2 - 0,6180339887... (12.2)


jest szczególnie dobra.
Weźmy dla przykładu k = 123456, m = 10000 oraz A ze wzoru (12.2).
Wtedy

h(k)- L10000·(123456·0,61803 ... mod l)J


L10000·(76300,0041151... mod l)J
· 0,0041151..J
LIOOOO
L41,1s1..J
- 41

267
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

12.3.3. Haszowanie uniwersalne

Jeśli wyobrazimy sobie, że klucze wstawiane do tablicy z haszowaniem są do-


bierane przez „złośliwego przeciwnika", to nie można wykluczyć sytuacji,
w której wszystkich n kluczy jest odwzorowanych na tę samą pozycję w tablicy.
Wtedy nawet średni czas działania operacji wyszukiwania w tablicy z haszowa-
niem wynosi 0(n). Każda ustalona funkcja haszująca jest podatna na tego
typu zagrożenie. Jedynym skutecznym sposobem polepszenia tej sytuacji jest
losowe dobieranie funkcji haszującej i to w sposób niezależny od wstawianych
do tablicy kluczy. Przy takim podejściu, określanym jako haszowanie uniwer-
salne, średnie czasy działania operacji na tablicach z haszowaniem są małe,
niezależnie od tego jakie klucze są wybierane przez „przeciwnika".
W haszowaniu uniwersalnym funkcja haszująca jest dobierana losowo
z rodziny funkcji, która ma pewne szczególne własności. Podobnie jak w przy-
padku sortowania szybkiego, losowość sprawia, że algorytm może się zacho-
wywać różnie nawet przy tych samych danych, dzięki czemu nie zawsze za-
chowuje się „źle", nawet dla „złośliwych" danych. Przy takim podejściu, nieza-
leżnie od danych wejściowych, średnie czasy działania operacji na tablicach
z haszowaniem są małe. I tak, w przykładzie z tablicą symboli kompilatora
wybór identyfikatorów stosowanych w programie nie może teraz istotnie po-
gorszyć rezultatów stosowania tablicy z haszowaniem. Taka sytuacja zachodzi
tylko wtedy, gdy kompilator wybiera losowo funkcję haszującą, która rozpra-
sza zbiór identyfikatorów bardzo nierównomiernie, ale prawdopodobieństwo
takiego zachowania jest niewielkie i jest takie samo dla wszystkich równolicz-
nych zbiorów identyfikatorów.
Niech .1f będzie skończoną rodziną funkcji haszujących, które odwzoro-
wują dane uniwersum kluczy U w zbiór {O, 1, ... , m - 1}. Taką rodzinę będzie­
my nazywać uniwersalną, jeśli dla każdej pary różnych kluczy x, y E U liczba
funkcji haszujących he :lt', dla których h(x) = h(y), jest równa dokładnie
1-*"l/m. Innymi słowy, jeśli losowo wybierzemy funkcję haszującą h z rodziny
.1f, to prawdopodobieństwo kolizji między x a y Geżeli x 'F y) wynosi dokład~
nie 1/m. Jest ono zarazem równe prawdopodobieństwu kolizji, gdyby h(x)
i h(y) były wybierane losowo ze zbioru {O, I, ..., m - l},
Z następującego twierdzenia wynika, że zastosowanie uniwersalnej rodziny
funkcji haszujących daje korzystnie małe oczekiwane czasy działania operacji
na tablicach z haszowaniem.

TWIERDZENIE 12.3.
Niech h będzie funkcją wybraną
losowo z uniwersalnej rodziny funkcji haszu-
jących. Jeśli rozpraszamy za jej pomocą n kluczy w tablicy o ro2ID.iarze m,
gdzie n ~ m, to oczekiwana liczba kolizji, w które wchodzi ustalony klucz
x jest mniejsza niż 1.
------~~ _,,-- -----------------·---
268
12.3. FUNKCJE HASZUJĄCE

DOWÓD
Dla każdej pary y, z różnych kluczy niech cyz będzie zmienną losową, która
przyjmuje wartość 1, jeśli h(y) = h(z) (tzn. jeśli y i z wchodzą w kolizję, gdy
używamy h), a w przeciwnym razie O. Z definicji uniwersalnej rodziny funkcji
haszujących wynika, że ustalona para kluczy koliduje ze sobą z prawdopodo-
bieństwem 1/m, więc

E[c,,J ~ 1/m

Niech Cx będzie liczbą kolizji, w które wchod7i klucz x w tablicy To rozmiarze


m, zawierającej n kluczy. Z tożsamości (6.24) wynika, że

E[CJ ~ L E[c,,J
,,,
„r

- n-1
.
m

Ponieważ n:;;; m, więc E[Cxl < 1.


Zajmiemy się teraz zagadnieniem budowania uniwersalnych rodzin funkcji
haszujących. Nie jest to trudne zadanie, jeżeli używa się do tego celu prostych
narzędzi teorii liczb. Przyjmijmy, że rozmiar tablicy m będzie liczbą pierwszą
(podobnie jak to czyniliśmy w metodzie modularnej). Rozłóżmy klucz x na
r + I bajtów (tj. znaków lub podciągów binarnych o ustalonej długości), co
symbolicznie zapisujemy jako x = (x 0 , x 1 , ... , x,). Wymagamy przy tym jed-
nak, aby maksymalna wartość bajtu nie była większa odm. Niech a= (a 0 , a 1 ,
..., a,) oznacza ciąg r + 1 elementów wybranych losowo 7.e zbioru {O, 1, ... ,
m- I}. Odpowiadająca temu ciągowi funkcja haszująca h11E.Yt' jest zdefinio-
wana następująco:

h11(x) = I' a;x;modm (12.3)


jca O

Przy takiej definicji rodzina funkcji .1f

(12.4)

mam'+ 1 elementów.

269
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

TwIERDZENlE12.4.
Rodzina Jll', zdefiniowana przez równości (12.3) oraz (12.4), jest uniwersalną
rodziną funkcji haszujących.

DOWÓD
Rozważmy parę różnych kluczy x, y. Niech x 0 'F y 0 . (Podobne rozumowanie
można przeprowadzić, jeśli x i y różnią się na dowolnej innej pozycji). Dla
każdego ustalonego ciągu a 1 , a2 , ••• , a, istnieje dokładnie jedna możliwa war-
tość a 0 , dla której zachodzi równość h(x) = h(y); takie a 0 jest rozwiązaniem
równania modularnego

a0 (x 0 - y 0 )- - I' a/x, - y,)(modm)


J-,, 1

Aby się o tym przekonać, należy zauważyć, że m jest liczbą pierwszą; liczba
x 0 -y 0 ma więc element odwrotny modulo m, czyli istnieje dokładnie jedno
rozwiązanie module m (patrz podrozdz. 33,4). Stąd wynika, że każda para
różnych kluczy x i y koliduje dla dokładnie m' wartości a, ponieważ dokładnie
jedna kolizja przypada na każdy możliwy ciąg (a 1 , a2 , ... , a,) (tzn. dla jedynej
wartości a 0 wyznaczonej powyżej). Wszystkich możliwych ciągów a jest nt+ 1 ,
klucze x i y wchodzą więc w kolizję z prawdopodobieństwem dokładnie
m'jm•+ 1 = 1/m. Stąd wynika, że rodzina Jll' jest uniwersalna.

ZADANlA

12.3-1. Przeszukujemy listę o długości n, w której każdy element zawiera klucz
k oraz odpowiadającą mu wartość funkcji haszującej h(k). Kluczami są
długie ciągi znaków. Jak możemy wykorzystać wartości funkcji haszującej
do wyszukiwania na liście elementu o danym kluczu?
12.3-2. W tablicy z haszowaniem o długości m przechowujemy napisy; napis
(ciąg znaków) o długości r traktujemy jako liczbę zapisaną w systemie
o podstawie 128; stosujemy haszowanie metodą modularną. Liczbę
m można łatwo reprezentować za pomocą 32-bitowego słowa maszyno-
wego, ale ciąg r znaków, traktowany jako liczba zapisana w układzie
o podstawie 128, jest zwykle tak duiy, że zajmuje wiele słów. Jak obliczać
wartości modularnej funkcji haszującej na długich napisach, używając tyl-
ko stałej dodatkowej pamięci?
12.3-3. Rozważmy modularną funkcję haszującą h(k) = kmodm dla
m = 29 - l oraz kluczy k będących ciągami znaków, interpretowanymi
jako liczby zapisane w układzie o podstawie 29 • Wykaż, że jeśli napis
x można uzyskać z napisu y przez permutację jego znaków, to h(x) = h(y).
Podaj przykład zastosowania, w którym ta własność dyskwalifikuje h jako
funkcję haszującą.

270
12.4. ADRESOWANIE OTWARTE

12.3-4. Rozważmy tablicę z haszowaniem o rozmiarze m = 1000 oraz funkcję


haszującą h(k) - Lm(kA mod l)J dla A - (./ 5 - 1)/2. Oblicz pozycje, na
które trafią klucze 61, 62, 63, 64 i 65.
12.J..5. Wykaż, że jeśli w równości (12.3) ograniczymy się tylko do ciągów a,
w których każdy składnik a1 jest różny od zera, to rodzina funkcji
Jf = {h.,}, zdefiniowana przez równość (12.4), nie jest uniwersalna.
(Wskazówka: Rozpatrz klucze x = O i y = 1).

12.4. Adresowanieotwarte
W metodzie adresowania otwartego wszystkie elementy są przechowywane
wprost w tablicy. Każda pozycja w tablicy zawiera więc albo element zbioru
dynamicznego, albo stałą NIL. Wyszukiwanie elementu polega na systematycz-
nym sprawdzaniu pozycji w tablicy, aż zostanie znaleziony szukany element albo
wiadomo już, że na pewno nie ma go w tablicy. Nie ma żadnych dodatkowych
list i żadne elementy nie są przechowywane poza tablicą, jak w metodzie łańcu­
chowej. Dlatego, jeśli używamy adresowania otwartego, to współczynnik zapeł­
nienia tx nie może nigdy przekroczyć 1, aby nie nastąpiło „przepełnienie" tablicy.
Moglibyśmy oczywiście przechowywać listy, takie jak w metodzie łańcu­
chowej, wewnątrz tablicy, korzystając z nie zajętych pozycji (patrz zad. 12.2-5),
ale adresowanie otwarte umożliwia całkowite wyeliminowanie konieczności
używania wskaźników. Zamiast śledzić wskaźniki, obliczamy ciąg pozycji, któ-
re należy sprawdzić. Dodatkowo, dzięki zaoszczędzeniu pamięci można umieś­
cić w tablicy więcej elementów przy takiej samej zajętości pamięci, co daje
w efekcie (przynajmniej teoretycznie) mniej kolizji i szybszy dostęp.
Wstawianie do tablicy z wykorzystaniem adresowania otwartego wymaga
znalezienia w niej wolnej pozycji. Kolejność, w jakiej sprawdzamy pozycje
w tablicy, powinna zależeć od wstawianego klucza, ponieważ przy każdym usta-
lonym porządku czas wyszukiwania wolnej pozycji jest 0(n). W tym celu zmo-
dyfikujemy funkcję haszującą, która będzie teraz dwuargumentowa; drugi ar-
gument będzie oznaczał numer (począwszy od O) w ciągu pozycji rozpatrywa-
nych w czasie wyszukiwania wolnego miejsca dla klucza będącego pierwszym
argumentem. Będziemy zatem używać funkcji

h:U x {O,I, ...,m - I}- {O,I, ...,m -1}

o tej własności, że dla każdego klucza k ciąg pozycji (ciąg kontrolny klucza k)

(h(k, O), h(k, !), .. , h(k, m - !))

jest permutacją ciągu (O, I, ... , m - I). Wynika stąd, że jeśli tablica będzie
prawie zupełnie wypełniona, to przy próbie wstawienia nowego klucza zostaną

271
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

sprawdzone wszystkie bez wyjątku pozycje w tablicy. W poniższej procedurze


zakładamy dla uproszczenia, że elementami przechowywanymi w tablicy z ha-
szowaniem T są same klucze bez żadnych dodatkowych atrybutów; klucz
k utożsamiamy z elementem zawierającym k. Na każdej pozycji znajduje się
albo pewien klucz, albo stała NIL (jeśli pozycja jest wolna),

HASH-lNSERT(T, k)
l i+- o
2 repeat j +- h(k, i)
3 if T[j] - NIL
4 then T[j] ~ k
5 returoj
6 elsei+-i+l
7 untili=m
8 error „przepełnienie tablicy z haszowaniem"

Algorytm wyszukiwania klucza k przegląda ten sarn ciąg pozycji, które


odwiedził algorytm wstawiania, gdy klucz k był dodawany do tablicy. Dlatego
wyszukiwanie można przerwać, gdy napotkamy na pustą pozycję, ponieważ
klucz k byłby wstawiony na tę pozycję i na pewno nie na żadną dalszą pozycję
w jego ciągu kontrolnym. (Zauważmy, że to rozumowanie jest uzasadnione,
tylko jeśli założymy, że w międzyczasie nie usuwamy żadnych elementów z tab-
licy). Procedura HASH-SEARCH dla danej tablicy Ti klucza k daje w wyniku
liczbę j, jeśli na pozycji j-tej w tablicy T znajduje się klucz k, albo stałą NIL,
jeżeli k nie występuje w ogóle w tablicy T.

HASH-SEARCH(T, k)
1 i+- O
2 repeatj ~h(k, i)
3 uT[j] - k
4 theo return j
5 i+-i+l
6 until T[j] = NIL lub i = m
7 return NIL

Usuwanie z tablic z haszowaniem przez adresowanie otwarte jest dość


trudne. Jeśli usuwamy klucz znajdujący się na pozycji i, to nie możemy po
prostu oznaczyć tej pozycji jako wolnej, wpisując na niej stałą NIL. Przy takim
postępowaniu odcięlibyśmy dostęp do kluczy k, przy wstawianiu których od-
wiedzona została pozycja i i była wówczas zajęta. Ten problem można roz-
wiązać, wpisując na przykład na taką pozycję specjalną stałą DELETEDzamiast
stałej NIL. Procedura HASH-SEARCH powinna wtedy kontynuować poszuk.iwa-

272
12.4. ADRESOWANIE OTWARTE

nia, gdy natknie się na wartość DELETED, natomiast procedura HASH-INSERT


może traktować taką pozycję jako nie zajętą i wstawić na nią nowy klucz. Przy
takim podejściu okazuje się jednak, że czas wyszukiwania nie zależy w istocie
od współczynnika zapełnienia et. Z tego powodu w zastosowaniach, które wy-
magają usuwania kluczy, do rozwiązywania kolizji używa się raczej metody
łańcuchowej.
Dla celów analizy przyjmujemy, że spełniony jest warunek równomiernego
haszowania: zakładamy, że dla każdego klucza wszystkich m! permutacji zbioru
{O, 1, ... , m - I} jest jednakowo prawdopodobnych jako jego ciągi kontrolne.
Warunek równomiernego haszowania jest uogólnieniem wprowadzonego
wcześniej pojęcia prostego równomiernego haszowania na sytuację, w której
wartościami funkcji haszującej nie są same pozycje, ale cale ciągi kontrolne.
W praktyce trudno jest spełnić wyidealizowany warunek równomiernego ha-
szowania, ale wystarczają zwykle właściwe przybliżenia (takie jak np. opisane
poniżej haszowanie dwukrotne).
W adresowaniu otwartym stosuje się zwykle jeden z trzech sposobów ob-
liczania ciągów kontrolnych: adresowanie liniowe, adresowanie kwadratowe
i haszowanie dwukrotne. Wszystkie te metody gwarantują, że (h(k, O),
h(k, I), ... , h(k, m - I)) jest permutatją zbioru (O, I, ... , m - I) dla każdego
klucza k, Żadna z nich nie spełnia jednak warunku równomiernego haszowa-
nia, ponieważ wszystkie mogą generować co najwyżej m 2 różnych ciągów kon-
trolnych (podczas gdy równomierne haszowanie wymaga aż ml ciągów). Dwu-
krotne haszowanie generuje najwięcej różnych ciągów kontrolnych i, jak moż­
na oczekiwać, wydaje się dawać najlepsze efekty.

Adresowanie liniowe
Dla zwykłej funkcji haszującej h': U-+ {O, 1, ... , m - 1} w metodzie adresowa-
nia liniowego stosuje się funkcję

h(k, ;J - (h'(k) + ;Jmodm

dla i= O, I, ... , m - l. Dla danego klucza k jego ciąg kontrolny zaczyna się od
pozycji T[h'(k)]. Następną pozycją w tym ciągu jest T[h'(k) + I] i tak dalej, aż
do pozytji T[m - I]. Dalej występują pozytje T[O], T[I], ... , T[h'(k) - I]. Pierw-
sza pozycja w ciągu wyznacza cały ciąg jednoznacznie, w metodzie adresowania
liniowego generowanych jest więc tylko m różnych ciągów kontrolnych.
Adresowanie liniowe jest bardzo łatwe do realizacji, ale ma poważną wadę
polegającą na tendencji do grupowania się (ang. primary c/ustering) zajętych
pozycji. Długie spójne ciągi zajętych pozycji szybko się powiększają, co znacz-
nie spowalnia operację wyszukiwania. Jeśli na przykład w tablicy znajduje się
n= m/2 kluczy, które zajmują tylko pozycje o parzystych numerach, a pozycje

273
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

o numerach nieparzystych są wolne, to średnia liczba porównań przy wyszuki-


waniu, które kończy się porażką, wynosi 1,5. Jeśli jednak jest zajętych począt­
kowych n = m/2 pozycji, to średnia liczba potrzebnych porównań jest już rów-
na około n/4 = m/8. Tymczasem wiadomo, że w adresowaniu liniowym istnieje
silna tendencja do grupowania się kluczy, bo jeśli wolną pozycję poprzedza
i pozycji zajętych, to prawdopodobieństwo jej zapełnienia wynosi (i+ 1)/m,
czyli jest zwykle znacznie większe niż prawdopodobieństwo 1/m, z którym
zajęta zostaje pozycja, przed którą znajduje się inna wolna pozycja. Ciągi zaję­
tych pozycji szybko rosną, co sprawia, że adresowanie liniowe jest bardzo
odległe od ideału równomiernego haszowania.

Adresowaniekwadratowe
W adresowaniu kwadratowym stosuje się funkcje haszujące postaci

h(k, i) - (h'(k) + c1 i + c,i')modm (12.5)

gdzie (podobnie jak w adresowaniu liniowym) h' jest dodatkową funkcją ha-
szującą, c 1 i Cz#- O są pewnymi stałymi, a i= O, 1, ... , m - 1. Pierwszą od-
wiedzoną pozycją jest T[h'(k)]; kolejno rozpatrywane pozycje są oddalone od
początkowej o wielkość zależną od kwadratu numeru pozycji i w ciągu kon-
trolnym. Ta metoda jest lepsza od adresowania liniowego, ale aby była po-
prawna, należy narzucić pewne warunki na liczby c 1 , Cz im. Jeden ze sposo-
bów właściwego doboru tych parametrów jest przedstawiony w problemie 12-
-4. Jeśli jednak dwa klucze mają takie same początkowe pozycje, to i cale ich
ciągi kontrolne są równe, ponieważ z h(k 1 , O)= h(kz,O) wynika, że h(k 1 ,
i) = h(kz, i). Prowadzi to do mniej groźnego zjawiska grupowania, określa­
nego jako grupowanie wtórne (ang. secondary c/ustering). Podobnie jak w ad-
resowaniu liniowym, początkowa pozycja określa jednoznacznie cały ciąg kon-
trolny, korzysta się więc tylko z m różnych ciągów kontrolnych.

Haszowanie dwukrotne
Haszowanie dwukrotne jest jedną z najlepszych praktycznych metod rozwiązy­
wania kolizji za pomocą adresowania otwartego, ponieważ powstające permu-
tacje mają wiele cech permutacji losowych. W basz-0waniu dwukrotnym funkcja
haszująca ma postać

h(k, i) - (h1(k) + ih2 (k))modm


gdzie h 1 i hz są pomocniczymi funkcjami haszującymi. Pierws1..ą pozycją w cią­
gu kontrolnym klucza kjest T[h 1 (k)]; kolejne pozycje są oddalone od począt-

?7A
12.4. ADRESOWANIEOTWARTE

kowej o h2 (k) modulo m. W przeciwieństwie do adresowania liniowego i kwad-


ratowego ciąg kontrolny zależy tutaj na dwa sposoby od k, tj. sama pozycja
początkowa nie określa go jednoznacznie. Na rysunku 12.5 znajduje się przy-
kład wstawiania do tablicy z dwukrotnym haszowaniem.

Rys. 12.S. Wstawianie do tablicy z dwukrotnym haszowaniem. Mamy tablicę


o rozmiarze 13 z funkcjami h 1 (k) = k mod 13 i h2 (k) = I + (kmod 11). Pottie-
waż 14 = I mod 13 oraz 14= ]mod Il.klucz l4zostaniewięcwst.awionyna
wolną pozycję 9 po wcześniejszym sprawdzeniu, że pozycje 1 oraz S są zajęte

Aby mieć gwarancję, że w razie potrzeby przeszukana zostanie cała tabli-


ca, musimy zapewnić, że wartość h2 (k) jest względnie pierwsza z rozmiarem
tablicy m. W przeciwnym razie,jeśli największy wspólny dzielnik liczb mi h 2 (k)
jest równy d > 1 dla pewnego k, to w ciągu kontrolnym klucza k znajdzie się
tylko m/d różnych pozycji tablicy (patrz rozdz. 33). Warunek ten można na
przykład łatwo spełnić, dobierając pewną potęgę 2 jako wartość m oraz zapew-
niając, że h2 daje tylko wartości nieparzyste. Inny sposób polega na wyborze
liczby pierwszej jako wartości m oraz zagwarantowaniu, że wartościami funkcji
h 2 są zawsze liczby dodatnie mniejsze niż m. Na przykład dla liczby pierwszej
• • •
m mozna przyJąc

h,(k) -kmodm

h,(k) - I + (kmodm')
gdzie m' jest nieco mniejsze niż m (np. m - 1 lub m - 2). Jeśli na przykład
k = 123 456 im= 701, to h 1 (k) = 80 oraz h 2 (k) = 257, to jako pierwszą pozy-
cję w ciągu kontrolnym wybieramy 80, a następne pozycje co 257 (mod.ulam).
Haszowanie dwukrotne ma tę przewagę nad adresowaniem liniowym
i kwadratowym, że dopuszcza użycie @(m2 ) istotnie różnych ciągów kontrol-
nych (a nie tylko @(m)), ponieważ każda para (h 1 (k), h2 (k)) wyznacza inny ciąg
kontrolny, a dla różnych kluczy wartości h 1 (k) i h2 (k) zmieniają się niezależnie.

275
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

Dzięki temu haszowanie dwukrotne bardzo dobrze przybliża „idealne" wa-


runki haszowania równomiernego.

Analiza adresowania otwartego


W naszej analizie adresowania otwartego, podobnie jak w przypadku metody
łańcuchowej, określimy zachowanie się haszowania dla ustalonego współczynni­
ka zapełnienia a, przy n im dążących do nieskończoności. Przypomnijmy, że jeśli
w tablicy o m pozycjach znajduje się n elementów, to średnia liczba elementów
przypadających na jedną pozycję wynosi a: = n/m. W adresowaniu otwartym na
pozycję może przypadać co najwyżej jeden element, więc n .:s:; m, czyli a .:s:;1.
Zakładamy, że spełniony jest warunek równomiernego haszowania.
W tym wyidealizowanym modelu ciąg kontrolny (h(k, O), h(k, 1), ... , h(k,
m - 1)) dla każdego k jest z jednakowym prawdopodobieństwem równy do-
wolnej permutacji ciągu (O, 1, ... , m - I). Oznacza to, że każda permutacja ma
jednakowe szanse bycia ciągiem kontrolnym dla konkretnej operacji wstawie-
nia lub wyszukiwania. Każdemu ustalonemu kluczowi odpowiada oczywiście
jednoznacznie dokładnie jeden ciąg kontrolny. W powyższym stwierdzeniu
chodzi o to, że dla zadanego rozkładu prawdopodobieństwa występowania
kluczy oraz zachowania funkcji haszującej na kluczach prawdopodobieństwa
wystąpienia każdego ciągu kontrolnego są sobie równe.
Analizę oczekiwanej liczby porównań w haszowaniu przez adresowanie
otwarte przy założeniu równomiernego haszowania rozpoczniemy od analizy
liczby porównań wykonywanych w czasie wyszukiwania elementu, którego nie
ma w tablicy.

TwIERDZENIE 12.S.
Jeśli współczynnik zapełnieniatablicy z haszowaniem wynosi a: = n/m < 1, to
oczekiwana liczba porównań kluczy w czasie wyszukiwania elementu, który
nie występuje w tablicy, jest nie większa niż 1/(l - a), o ile jest spełnione
założenie o równomiernym haszowaniu.

DOWÓD
W czasie wyszukiwania elementu, które nie zakończy się sukcesem, każdy
klucz jest porównywany z kluczami znajdującymi się na pozycjach z ciągu
kontrolnego; wyszukiwanie zostaje przerwane po napotkaniu pierwszej wolnej
pozycji w ciągu kontrolnym szukanego klucza. z.definiujmy

p 1 = Pr{dokladnie i początkowych pozycji w ciągu kontrolnym jest zajętych}

dla i= O, 1, 2, ... Jeśli i> n, to p 1 = O, ponieważ jest tylko n zajętych pozycji


w całej tablicy. Oczekiwana liczba porównań jest więc równa
.
276
12.4. ADRESOWANIE OTWARTE


1+ I
i=O
ip, (12.6)

Niech

ą; = Pr{co najmniej i początkowych pozycji w ciągu kontrolnym jest zajętych}

dla i = O, 1, 2, ... Do obliczenia (12.6) użyjemy teraz tożsamości (6.28):

• •
I ip, - I ą,
i"O i=l

Jak.a jest wartość q, dla i~ I? Prawdopodobieństwo, że pierwsza pozycja


w ciągu jest zajęta, wynosi n/m, więc

n
m

Przy założeniu
równomiernego haszowania w drugim porównaniu fjeśli jest
jeszcze w ogóle konieczne) odwołujemy się do jednej z m - I pozostałych po~
zycji, z których n - 1 jest zajętych. Drugie porównanie wykonujemy tylko
wtedy, kiedy pierwsza pozycja była zajęta, więc

Ogólnie, i-te porównanie wykonujemy tylko wtedy, kiedy pierwsze i - l pozy-


cji było zajętych, a każda z pozostałych m - i + 1 pozycji z jednakowym praw-
dopodobieństwem jest i-tą w ciągu kontrolnym (w tym n - i+ 1 spośród nich
jest zajętych). Stąd

.; (;)'
= r:t,j
dla i= 1, 2, ... , n, ponieważ (n - J)/(m - J) ~ n/m, jeśli n~ m orazj ~O.Po
n porównaniach wszystkich n zajętych pozycji zostało już odwiedzonych i nie
będą one więcej brane pod uwagę, więc ą; = O dla i> n.

277
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

Po tych pr1:ygotowaniach jesteśmy już w stanie oszacować wartość wyraże­


nia (12.6). Przy założeniu, że a:< I, średnią liczbę porównań przy wyszukiwa-
niu elementu nie znajdującego się w tablicy można oszacować następująco:

1+
"
z:ip; - 1
.
+ z: ą;
Ja,Q 1"'1

:s;-I+a:+(X2+a:3+ ... (12.7)

1
I-•

Nierówność (12.7) ma dość jasną intuicyjną interpretację: pierwsze porównanie


jest wykonywane zawsze, z prawdopodobieństwem a: koniecme jest drugie po-
równanie, z prawdopodobieństwem a:2 konieczne jest trzecie porównanie itd .

Jeśli (Xjest pewną stałą mniejszą niż I, to z twierdzenia 12.5 wynik.a, że
wyszukiwanie elementu zakończone porażką działa w czasie 0(1). Dla przy-
kładu, jeśli tablica jest w połowie wypełniona, to średnia liczba porównań
w czasie wyszukiwania zakończonego porażką nie jest większa niż 1/(1 -
- 0,5) = 2. Jeśli tablica jest wypełniona w 90%, to średnia liczba porównań
nie przekracza 1/(1 - 0,9) - 10.
Z twierdzenia 12.5 wynika natychmiast oszacowanie czasu działania pro-
cedury HASH-INSERT.

WNIOSEK12.6.
Wstawianie do tablicy z haszowaniem przez adresowanie otwarte, jeżeli współ­
czynnik zapełnienia tablicy wynosi a:, wymaga średnio co najwyżej 1/(1 - a:)
porównań, o ile spełniony jest warunek równomiernego haszowania.

DOWÓD
Element może zostać wstawiony do tablicy tylko wtedy, kiedy jest w niej jesz-
cze miejsce, tj. jeśli (X< 1. Wstawienie elementu wymaga malezienia w tablicy
wolnej pozycji, na której będzie go można zapisać. Aby znaleźć takie wolne
miejsce, wystarczy wykonać procedurę wyszukiwania wstawianego elementu.
Stąd oczekiwana liczba potrzebnych porównań nie przekracza 1/(1 - a:).


Teraz zajmiemy się obliczeniem oczekiwanej liczby porównań wykonywa-
nych przez procedurę wyszukiwania w przypadku, gdy szukany element znaj-
duje się w tablicy.

278
12.4. ADRESOWANIE OTWARTE

TwJERDZENIE 12.7.
Załóżmy, że element znajduje się w tablicy z haszowaniem przez adresowanie
otwarte, a współczynnik zapełnienia tablicy o:spełnia nierówność o:< 1. Wtedy
oczekiwana liczba porównań wykonywanych w czasie wyszukiwania tego ele-
mentu jest nie większa niż
I 1 1
-ln~-
o: 1-o:
+ o:
jeżeli jest spełniony warunek równomiernego haszowania oraz każdy klucz
znajdujący się w tablicy jest tym wyszukiwanym z jednakowym prawdopodo-
bieństwem.

DOWÓD
Wyszukanie elementu k wymaga wykonania dokładnie takiego samego ciągu
porównań, jak w czasie jego wstawiania. Z wniosku 12.6 wynika, że jeśli k był
(i+ 1)-szym elementem wstawionym do tablicy, to oczekiwana liczba porów-
nań potrzebnych do jego odszukania nie jest większa niż 1/(1 - i/m) =
= m/(m - i). Uśredniając po wszystkich n kluczach znajdujących się w tablicy,
otrzymujemy oczekiwaną liczbę porównań;

,
gdzie H, = L 1/j jest i-tą liczbą hannoniczną (patrz równość (3.5)). Korzysta-
i"1
jąc z zale7.ności In i~ H; ~ In i+ 1 (patrz nierówności (3.11) oraz (3.12)), otrzy-
mujemy następujące oszacowanie oczekiwanej liczby porównań potrzebnych do
znalezienia elementu w tablicy z haszowaniem przez adresowanie otwarte

1 1
···· (H. - II.-.) ,; (In m +1- ln(m - n))
" "1 m 1
·In--+
o: m-n o:
I I I
--In- - +-
o: 1-o: o:

Jeśli tablica jest wypełniona w połowie, to oczekiwana liczba porównań


jest mniejsza niż 3,387. Średnia liczba porównań w tablicy wypełnionej w 90%
jest mniejsza niż 3,670.

279
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

ZADANIA

12.4-1. Do tablicy z haszowaniem o długości m = 11 wstawiamy klucze 10, 22,


31, 4, 15, 28, 17, 88, 59, używając adresowania otwartego do rozwiązywa­
nia kolizji oraz funkcji haszującej h'(k) = k mod m. Zilustruj wyniki wsta-
wienia tych elementów, jeśli użyjemy: adresowania liniowego, adresowania
kwadratowego dla c1 = 1 i c2 = 3 oraz dwukrotnego haszowania z funkcją
h,(k)-1 + (kmod(m - 1)).
12.4-2. Zaimplementuj procedurę HASH-DELETE zgodnie z opisem umieszczo-
nym w tekście oraz tak zmodyftkuj procedury HASH-INSERT i HASH-SE-
ARCH, aby poprawnie obsługiwały specjalną stałą DELETED.
* 12.4-3. Załóżmy, że rozwiązujemy kolizje za pomocą dwukrotnego haszowa-
nia z funkcją haszującą h(k, i) - (h,(k) + ih,(k))modm. Wykaż, że ciąg
kontrolny (h(k, O), h(k, 1), ... , h(k, m - 1)) jest permutacją ciągu pozycji
(O, 1, ... , m - 1) wtedy i tylko wtedy, gdy h,(k) jest względnie pierwsze
z m. (Wskazówka: Patrz rozdz. 33).
12.4-4. Rozważmy tablicę z równomiernym haszowaniem o współczynniku za-
pełnienia a= 1/2. Jaka jest oczekiwana liczba porównań potrzebnych do
odszukania elementu znajdującego się w tej tablicy. Wykonaj podobne
rachunki dla współczynników zapełnienia 3/4 oraz 7/8.
* 12.4-5. Wstawiamy n kluczy do tablicy z równomiernym haszowaniem przez
adresowanie otwarte (tablica ma rozmiar m), Niech p(n, m) będzie
prawdopodobieństwem, że nie zajdzie żadna kolizja. Udowodnij, że
p(n, m) ~ e-1!(,,-lJf2m,(Wskazówka: Patrz nierówność (2. 7)). Wykaż, że jeśli
n przekracza J m-, to prawdopodobieństwo uniknięcia kolizji gwałtownie
maleje do zera.
* 12.4-6. Oszacowanie częściowych sum szeregu harmonicznego można sprowa-
dzić do postaci

H =Inn+,,,+-----
' , '
2n (12.8)

Liczbę y = 0,5772156649 ... nazywa się stalą Eulera, as należy do prz.edzia-


łu O< s < 1. (Wyprowadzenie tego wzoru można znaleźć w książce Knu-
tha [121)). Jak to oszacowanie wpływa na tezę i dowód twierdzenia 12.7?
* 12.4-7. Rozważmy tablicę z haszowaniem przez adresowanie otwarte o współ­
czynniku zapełnienia a. Znajdź niezerową wartość a, dla której oczekiwa-
na liczba porównań potrzebnych do stwierdzenia, że elementu nie ma w ta-
blicy, jest dwa razy większa niż oczekiwana liczba porównań potrzebnych
do odszukania elementu, który znajduje się w tablicy. Przyjmij, że średnia
liczba porównań potrzebnych do odszukania elementu w tablicy jest
w przybliżeniu równa (l/a)ln(l/(1- •)).

280
PROBLEMY

Problemy
12-1. Szacowanie liczby porównań wykonywanych przez operacje na tablicach
z haszowaniem
W tablicy z haszowaniem o długości m znajduje się n elementów, gdzie
n~ m/2. Do rozwiązywania kolizji używamy adresowania otwartego.
(a) Wykaż, że jeśli przyjmiemy założenie o równomiernym haszowaniu, to dla
i= 1, 2, ... , n prawdopodobieństwo zdarzenia, że wstawienie i-tego elemen-
tu wymaga więcej niż k porównań, jest nie większe niż 2-t_
(b) Wykaż, że dla i= 1, 2, ... , n prawdopodobieństwo zdarzenia, że operacja
wstawienia i-tego elementu wymaga ponad 2 lg n porównań, wynosi co
najwyżej 1/n2 •

Niech zmienna losowa X; oznacza liczbę porównań wykonywanych przez


operację wstawienia i-tego elementu. Z punktu (b) wynika, że Pr{X >
1
> 21gn} ~ l/n . Niech zmienna losowa X= max 1 _,.;_,. 0 X 1 oznacza największą
2

liczbę porównań wykonanych przez jedną z n operacji wstawiania.

(c) Wykaż, że Pr{X> 2lgn} s; I/n.


(d) Wykaż, że oczekiwana liczba porównań wynosi E[X] = O(lgn).

12-2. Wyszukiwanie w zbiorze statycznym


Należy zaimplementować zbiór n elementów o kluczach będących liczbami
całkowitymi. Zbiór ma być statyczny (tj. nie będziemy na nim wykonywali
operacji INSERT ani DELETE), wystarczy więc zaimplementować operację
SEARCH.Przed podjęciem wykonywania ciągu operacji SEARCHmożna zużyć
dowolnie dużo czasu na przygotowanie struktury, tak aby później wyszukiwa-
nie odbywało się szybko.

(a) Wykaż, że operację SEARCHmożna tak zaimplementować, aby w pesymis-


tycznym przypadku działała w czasie O(lg n), nie zajmując przy tym żadnej
dodatkowej pamięci poza tą zajmowaną przez same elementy zbioru.
(b) Rozważ implementację zbioru za pomocą tablicy z adresowaniem otwar-
tym o rozmiarze m, przy założeniu o równomiernym haszowaniu. Jaki jest
minimalny rozmiar dodatkowej pamięci m - n, dla którego średnia liczba
porównań potrzebnych procedurze SEARCH do wykrycia, że element nie
znajduje się w zbiorze, jest nie większa niż w punkcie (a)? Oszacuj tę wiel-
kość asymptotycznie jako funkcję n.

12-3. Długość list w metodzie łańcuchowej


Do tablicy z haszowaniem o długości n, w której kolizje rozwiązujemy metodą
łańcuchową, wstawiamy n elementów. Losowo wybrany klucz z jednakowym
ROZDZIAŁ 12. TABLICE Z HASZOWANIEM

prawdopodobieństwem trafia na dowolną spośród n pozycji w tablicy. Niech


M będzie maksymalną liczbą kluczy, które były odwwrowane na tę samą
pozycję. Wykaż, że wartość oczekiwaną M można ograniczyć z góry przez
O(lg n/lg lg n).

(a) Wykaż, że prawdopodobieństwo Qk zdarzenia, iż k kluczy jest odwzorowa-


nych na ustaloną pozycję wynosi

(b) Niech Pk będzie prawdopodobieństwem zdarzenia, że M = k (lub równo-


ważnie prawdopodobieństwem, że na pozycji, na której znajduje się naj-
więcej elementów, jest ich w istocie k). Wykaż, że P1:~ n Ql.
(c) Za pomocą wzoru Stirlinga (2.1 I) wykaż, że Q1:< el/Jr!.
(d) Wykaż, że istnieje stała c > 1 taka, że Ql, < l/n 3 dla k 0 = clgn/lglgn.
Wywnioskuj stąd, że P1: < l/n 2 dla k 0 = clgn/lglgn .

(e) Wykaż, że

E[M]~Pr{M> ~_l_gn}·n+Pr{M~ ~.!.g__


n_}· .~.lgn
!glgn lglgn !glgn

Wywnioskuj stąd, że E[M] - O(lgnftglgn).

12-4. Adresowaniekwadratowe
Załóżmy, że szukamy klucza kw tablicy z haszowaniem o pozycjach O, I, ... ,
m - l, oraz załóżmy, że mamy funkcję haszującą h, która odwzorowuje uni-
wersum kluczy w zbiór {O, 1, ..., m - 1}. Wyszukiwanie przebiega w następują­
cych krokach.

1. Oblicz wartość i+- h(k) oraz przypisz j +- O.


2. Porównaj klucz na pozycji i-tej z szukanym kluczem k. Jeśli szukany klucz
został znaleziony lub pozycja nie jest zajęta, to zakończ wyszukiwanie.
3. Przypiszj +- (j + 1) mod m oraz i +-(i+ 1) mod m oraz przejdź do kroku 2.

Załóżmy, że m jest potęgą 2.

(a) Wykaż, że powyższa metoda wyszukiwania jest wariantem metody adre-


sowania kwadratowego; wskaż odpowiednie stale c 1 oraz c 2 z równania
(12.5).
(b) Wykaż, że w pesymistycznym przypadku powyższy algorytm sprawdza
wszystkie pozycje w tablicy.

282
UWAGI DO ROZDZIAŁU

12-5. Haszowanie k-uniwersalne


Niech X = {h} będzie rodziną funkcji haszujących, które odwzorowują uni-
wersum kluczy Uw zbiór {O, 1, ... , m- l}. Powiemy, że X jest k-uniwersalna,
jeśli dla każdego ustalonego ciągu k różnych kluczy (x 1 , x 2 , ... , x1;) oraz funk-
cji h wybranej losowo z Jl' ciąg (h(x 1), h(x 2 ), ... , h(x,J) jest z jednakowym
prawdopodobieństwem równy dowolnemu spośród mt ciągów k elementów
zbioru {0,1, ... ,m - I}.

(a) Wykaż, że jeśli X jest 2-uniwersalna, to jest uniwersalna.


(b) Wykaż, że rodzina X zdefiniowana w podrozdz. 12.3.3 nie jest 2-uni-
wersalna.
(c) Wykaż, że jeśli zmodyfikujemy definicję rodziny Jl' w podrozdz. 12.3.3,
tak że każda funkcja zawiera także stały składnik. b, tj. jeśli

to Jl' jest 2-uniwersalna.

Uwagido rozdziału
Książki K.nutha [123) i Gonneta [90] są znakomitym źródłem przykładów ana-
lizy tablic z haszowaniem. Wynalezienie tablic z haszowaniem Knuth przypisu-
je H. P. Luhnowi (1953), który stosował metodę łańcuchową do rozwiązywa­
nia kolizji. Mniej więcej w tym samym czasie G. M. Amdahl zaproponował
metodę adresowania otwartego.
Rozdział 13

Drzewaposzukiwań
binarnych

Drzewa poszukiwań binarnych, w skrócie BST (od ang. binary search trees), są
strukturami, na których można wykonywać różne operacje właściwe dla zbio-
rów dynamicznych, takie jak SEARCH,MINIMUM,MAXIMUM,PREDECESSOR,
SUCCESSOR,INSERToraz DELETE. Drzewo poszukiwań może więc być użyte
:zarówno jako słownik, jak i jako kolejka priorytetowa.
Podstawowe operacje na drzewach poszukiwań binarnych wymagają czasu
proporcjonalnego do wysokości drzewa. W pełnym drzewie binarnym o n węz­
łach takie operacje działają w najgorszym przypadku w czasie 0(lgn). Jeśli
jednak drzewo składa się z jednej gałęzi o długości n, to te same operacje
wymagają w pesymistycznym przypadku czasu E>(n). W podrozdziale 13.4
przekonamy się, że wysokość losowo zbudowanego drzewa poszukiwań binar-
nych wynosi O(lgn), podstawowe operacje na zbiorach dynamicznych działają
więc w czasie 0(lgn).
W praktyce nie mo7.emy zawsze :.r.agwarantować, że drzewa poszukiwań
binarnych są konstruowane losowo, ale istnieją odmiany drzew BST, dla któ-
rych pesymistyczny czas wykonywania podstawowych operacji jest mały.
W rozdziale 14 omówimy jeden z takich sposobów modyfikacji drzew BST,
tzw. drzewa czerwono-czarne, których wysokość wynosi O(lgn). W rozdziale
19 zaś poznamy B-drzewa, które znakomicie nadają się do przechowywania
danych na zewnętrznych nośnikach o dostępie swobodnym (dyskach).
Najpierw przedstawimy podstawowe własności drzew BST. W następnych
podrozdziałach opiszemy: w jaki sposób należy przechodzić drzewo BST, aby
wypisać znajdujące się w nim wartości w kolejności zgodnej z porządkiem
określonym przez klucze, jak wyszukiwać wartości w drzewie, jak znajdować
najmniejszy lub największy element, jak wyznaczać bezpośredni poprzednik
lub następnik danego elementu oraz jak wstawiać i usuwać elementy z drzewa
BST. Elementarne własności drzew podaliśmy w rozdz. 5.

284
13.1, CO TO JEST DRZEWO POSZUKIWAŃ BINARNYCH?

13.1. Co to jest drzewo poszukiwań binarnych?

Drzewo poszukiwań binarnych, jak sama nazwa wskazuje, ma strukturę drze-


wa binarnego (patrz rys. 13.1). Takie drzewo można zrealizować za pomocą
struktury danych z dowiązaniami, w której każdy węzeł jest obiektem. Oprócz
pola key każdy węzeł zawiera pola left, right oraz p, które wskazują odpowied-
nio na jego lewego syna, prawego syna oraz ojca. Jeśli węzeł nie ma następnika
albo poprzednika, to odpowiednie pole ma wartość NIL. Węzeł w korzeniu
drzewa jest jedynym węzłem, którego pole wskazujące na ojca ma wartość NIL.

5 2

3 7 3
'
2 5 8 7

' 8

(a) (b)

Rys. 13.1. Drzewo poszukiwań binarnych. Dla kai'.dego węzła x klucze majdując(l się w jego lewym
poddrzewie są nie większe niż key[xJ, a klucze w jego prawym poddrzewie są nie mniejsze niż
key[x]. Ten sam zbiór wartości może być przedstawiony za pomocą wielu różnych drzew BST.
Pesymistycmy czas działania większości operacji na drzewach BST jest proporcjonalny do wyso-
kości drzewa. (a) Drzewo BST o wysokości 2 składające się z 6 węzłów. (b) Nieco mniej efektywne
drzewo BST zawierające te same klucze; jego wysokość wynosi 4

Klucze są przechowywane w drzewie BST w taki sposób, aby spełniona


była własność drzewa BST:

Niech x będzie węzłem drzewa BST. Jeśli y jest węzłem znajdującym


się w lewym poddrzewie węzła x, to key[y] ~ key[x]. Jeśli y jest węzłem
znajdującym się w prawym poddrzewie węzła x, to key[xJ ~ key[y].

Spójrzmy na rys. 13.la: w korzeniu drzewa znajduje się klucz 5, klucze 2,


3 oraz 5 w jego lewym poddrzewie są nie większe niż 5, a klucze 7 oraz 8 znaj-
dujące się w jego prawym poddrzewie są nie mniejsze niż 5. Ta sama własność
jest spełniona w każdym węźle drzewa. Na przykład klucz 3 na rys. 13.la jest
nie mniejszy niż klucz 2 znajdujący się w jego lewym poddrzewie oraz nie
większy niż klucz 5 znajdujący się w jego prawym poddrzewie.

285
ROZDZIAŁ 13. DRZEWA POSZUKIWAl'il BINARNYCH

Własnośćdrzewa BST umożliwia wypisanie wszystkich znajdujących się


w nim kluczy w sposób uporządkowany za pomocą prostego algorytmu reku-
rencyjnego zwanego przechodzeniem dnewa metodą inorder. Nazwa tego al-
gorytmu wynika stąd, że klucz korzenia poddrzewa zostaje wypisany między
wartościami z jego lewego poddrzewa a wartościami z jego prawego poddrze-
wa. Podobnie algorytm przechodzenia drzewa metodą preorder wypisuje klucz
korzenia przed wypisaniem wartości znajdująch się w obu poddrzewach, a al-
gorytm przechodzenia drzewa metodą postorder wypisuje klucz korzenia po wy-
pisaniu wartości znajdujących się w poddrzewach). Wywołanie 1NORDER-
-TREE-WALK(root[7J) powoduje wypisanie wszystkich elementów drzewa po-
szukiwań binarnych T.

INORDER-TREE-WALK(x)
I ifx#-NIL
2 then INORDER-TREE-WALK(/e/t[x])
3 wypisz key[x]
4 INORDER-TREE-WALK(right[x])

Na przykładdla obu drzew z rys. 13.1 powyższy algorytm wypisuje znajdujące


się w nich klucze w kolejności 2, 3, 5, 5, 7, 8. Poprawność algorytmu można
łatwo wykazać przez indukcję, korzystając bezpośrednio z własności drzewa
BST. Przejście całego drzewa BST o n węzłach zajmuje czas E>(n),ponieważ na
każdy węzeł w drzewie przypadają dokładnie dwa rekurencyjne wywołania
procedury - po jednym dla lewego i prawego syna.

ZADANIA

13.1-1. Narysuj drzewa BST o wysokości 2, 3, 4, 5 oraz 6 zawierające na-


stępujący zbiór kluczy: {1, 4, 5, 10, 16, 17, 21}.
13.1-2. Jaka jest różnica między własnością drzewa BST a własnością kopca
(7 .1)? Czy własność kopca umożliwia wypisywanie kluczy drzewa o n węz­
łach w czasie O(n) we właściwej kolejności? Odpowiedź uzasadnij.
13.1-3. Zaprojektuj nierekurencyjny algorytm przechodzenia drzewa w porzą­
dku inorder. (Wskazówka: Istnieje łatwe rozwiązanie, w którym korzysta
się ze stosu jak.o pomocniczej struktury danych, oraz nieco bardziej skom-
plikowane, choć eleganckie rozwiązanie, nie wymagające użycia stosu, o ile
założymy, że jest dostępna operacja porównywania wskaźników).
13.1-4. Podaj rekurencyjne algorytmy przechodzenia drzewa w porządku pre-
order i postorder, działające w czasie E>(n)na drzewie o n węzłach.
13.1-5. Wiadomo, że sortowanie n elementów wymaga czasu f!(nlgn) w modelu
z porównaniami jak.o operacjami elementarnymi. Na podstawie tego faktu
wykaż, że pesymistyczny czas działania każdego algorytmu konstruowania
drLCwa BST z dowolnej listy n elementów wynosi w tym modelu Q(nlgn).

286
13.2. WYSZUKIWANIE W DRZEWIE POSZUKIWAN BINARNYCH

13.2. Wyszukiwaniew drzewieposzukiwań binarnych


Podstawową operacją wykonywaną na drzewie BST jest wyszukanie znajdują­
cego się w nim klucza. Oprócz operacji SEARCH można na takim drzewie
wykonywać operacje MINlMUM, MAXIMUM, SUCCESSOR i PREDECESSOR.
W tym podrozdziale zajmiemy się nimi bardziej szczegółowo. Przekonamy się
przy tym, że każdą z nich można zaimplementować w taki sposób, aby czas jej
wykonania na drzewie o wysokości h nie przekraczał O(h).

Wyszukiwanie
Do wyszukiwania w drzewie BST węzła, który zawiera dany klucz, można użyć
następującej procedury. Mając dany wskaźnik do korzenia drzewa oraz klucz
k, procedura TREE-SEARCH wyznacza wskaźnik do węzła zawierającego klucz
k, jeżeli taki węzeł istnieje. W przeciwnym razie daje w wyniku wartość NIL.

TREE-SEARCH(x, k)
1 if x = NIL lub k = key[x]
2 then return x
3 if k < key[x]
4 then return TREE-SEARCH(lefi[x], k)
5 else return TREE-SEARCH(righl[x],k)

Procedura ta rozpoczyna wyszukiwanie w korzeniu i schodzi po ścieżce w dół


drzewa (patrz rys. 13.2). Dla każdego węzła x, który napotka, porównuje klucz
k z wartością key[x]. Jeśli te wartości są równe, to wyszukiwanie zostaje prze-
rwane. Jeśli k jest mniejsze niż key[xJ, to dalsze wyszukiwanie przebiega już
tylko w lewym poddrzewie węzła x, ponieważ z własności drzewa BST wynika,
że k nie mo7..eznajdować się w prawym poddrzewie. Analogicznie, jeśli k jest
większe niż key[x], to wyszukiwanie zostaje ograniczone do prawego poddrze-
wa. Liczba węzłów odwiedzonych podczas rekurencyjnego zejścia z korzenia
drzewa, a zarazem czas działania procedury TREE-SEARCH, wynosi O(h), gdzie
h jest wysokością drzewa.
Tę samą procedurę można zapisać iteracyjnie przez „rozwinięcie" rekursji
w pętlę wbile. Na większości komputerów ta druga wersja jest efektywniejsza.

ITERATIVE-TREE-SEARCH(x,k)
1 while x ::/=-NIL i k ::/=-key{xJ
2 do if k < key[x]
3 then x ...._feft[x]
4 else x ...._right[x]
5 return x

287
ROZDZIAŁ 13. DRZEWA POSZUKIWAŃ BINARNYCH

15

6
Il\
3 1" •
11•
~
' -•lót·
...

2 4 13


Rys. 13.2. Wyszukiwanie w drzewie BST. Wyszukanie klucza 13 wymaga przejścia po ścieżce
15-+ 6-> 7-> 13. Najmniejszym kluczem w drzewie jest 2. Aby do niego dotrzeć, na1eży podą.ż.ać
za.wsze wedhig wskażników /eft, począwszy od korzenia. Największy klucz (tutaj 20) w drzewie
mozna mależc, podążając od korzenia według wskaźników right. Następnikiem węzła o kluczu 15
jest węzeł o kluczu 17, ponieważ jest to najmniejszy klucz w prawym poddrzewie węzła 15. Węzeł
o kluczu 13 nie ma prawego poddrzewa, jego następnikiem jest więc najniższy przodek, którego
lewy syn jest również przodkiem 13. Następnikiem węzła o kluczu 13 jest więc węzeł o kluczu 15

Minimum i maksimum
Element w drzewie BST o najmniejszym kluczu można łatwo odszukać, podą­
żając według wskaźników /eft, począwszy od korzenia, aż napotkamy NIL
(patrz rys. 13.2). Następująca procedura wymacza wskaźnik do minimalnego
elementu poddrzewa o korzeniu w węźle x.

TREE-MINIMUM(x)
I while left[x] ,' NIL
2 do x +-- left[x]
3 return x

Poprawność procedury TREE-MINIMUM wynika z własności drzewa BST. Je-


śli węzeł x nie ma lewego poddrzewa, to najmniejszym elementem w pod-
drzewie o korzeniu x jest key[x], ponieważ każdy klucz w jego prawym pod-
drzewie jest co najmniej tak duży jak key[x]. Jeśli natomiast węzeł x ma lewe
poddrzewo, to najmniejszy klucz w poddrzewie o korzeniu x znajduje się na
pewno w poddrzewie o korzeniu /eft[x}, bo każdy węzeł w lewym poddrzewie
jest nie większy niż key[x], a wszystkie klucze w prawym poddrzewie są nie
mniejsze niż key[x].
Procedura TREE-MAXIMUMjest analogiczna - różnica jest tylko taka, że
przebiegamy po wskaźnikach right.

288
13.2. WYSZUKIWANIE W DRZEWIE POSZUKIWAŃ BINARNYCH

TREE-MAXIMUM(x)
1 while right[x] '# NIL
2 do x +- right[x]
3 return X

Obie procedury działają na drzewie o wysokości h w czasie O(h), ponieważ


przechodzą tylko po ścieżce w dół drzewa.

Następniki i poprzedniki
Często zachodzi potrzeba wyznaczenia następnik.a danego węzła w drzewie
BST, tj. następnego węzła odwiedzanego w czasie przechodzenia drzewa w po-
rządku inorder. Jeśli wszystkie klucze są różne, to następnikiem węzła x jest
węzeł o najmniejszym kluczu większym niż key[x]. Struktura drzewa BST umo-
żliwia wyznaczenie następnika węzła bez konieczności wykonywania żadnych
porównań kluczy. Następująca procedura wyznacza następnik danego węzła x,
nie wykonując przy tym żadnych porównań kluczy. Jeśli x ma największy
klucz w drzewie, to zostaje wyznaczona wartość NIL.

TREE-SUCCESSOR(x)
1 if right[x] '# NIL
2 then return 1'REE-MINIMUM(right[x])
3 y-p[x]
4 whiley ;< NIL i X - right[y]
5 dox+-y
6 y-p[y]
7 returny

W procedurze TREE-SUCCESSOR są rozpatrzone dwa przypadki. Jeśli


prawe poddrzewo węzła x jest niepuste, to następnik.iem x jest po prostu
najbardziej na lewo położony węzeł w prawym poddrzewie, który zostaje
wyznaczony w wierszu 2 za pomocą wywołania TREE-MIN™UM(right[x]).
Na przykład następnikiem węzła o kluczu 15 na rys. 13.2 jest węzeł zawiera-
jący klucz 17.
Jeśli jednak węzeł x nie ma prawego poddrzewa, choć ma następnik y, to
y jest najniższym przodkiem węzła x, którego lewy syn jest także przodkiem x.
Na rysunku 13.2 następnikiem węzła o kluczu 13 jest węzeł z kluczem 15. Aby
go wyznaczyć, wystarczy przejść w górę drzewa, aż do napotkania węzła, który
jest lewym synem swego ojca; odbywa się to w wierszach 3-7 procedury TREE-
-SUCCESSOR.
Czas działania procedury TREE-SUCCESSORna drzewie o wysokości h wy-
nosi O(h), ponieważ przechodzi ona albo po ścieżce w górę drzewa, albo po

289
ROZDZIAŁ 13. DRZEWA POSZUKIWAf.ł BINARNYCH

ścieżcew dól drzewa. Procedura TREE-PREDECESSOR,analogiczna do proce-


dury TREE-SUCCESSOR, również działa w czasie O(h).
Podsumowując, wykazaliśmy następujące twierdzenie.

TwIERDZENIE 13.1.
Następujące operacje na zbiorach dynamicznych: SEARCH, MIN1MUM, MAXI~
MUM, SUCCESSORoraz PREDECESSORsą wykonywane na drzewie binarnym
o wysokości h w czasie O(h).

ZADANIA

13.2-1. Przyjmijmy, że w drzewie BST znajdują się liczby od 1 do 1000 i chce-
my wyszukać liczbę 363. Które z poniższych ciągów węzłów nie mogą
zostać sprawdzone w procedurze SEARCH7

(a) 2,252,401, 398, 330, 344, 397, 363;


(b) 924, 220,911, 244, 898, 258, 362, 363;
(c) 925,202,911,240,912,245,363;
(d) 2, 399, 387, 219, 266, 382, 381, 278, 363;
(e) 935, 278, 347,621,299, 392, 358, 363.

13.2-2. Profesor Bunyan utrzymuje, że od.kryl ważną własność drzew BST.


Przyjmijmy, że wyszukiwanie klucza kw drzewie BST kończy się w liściu.
Rozważmy trzy zbiory: A, do którego należą klucze znajdujące się na lewo
od ścieżki wyszukiwania, B, składający się z kluczy leżących na ścieżce,
oraz C, do którego należą klucze leżące na prawo od ścieżki. Profesor
Bunyan uważa, że dla każdych trzech kluczy aEA, bEB oraz cEC za-
chodzą nierówności a~ b ~ c. Podaj możliwie najmniejszy kontrprzykład,
obalający hipotezę profesora.
13.2-3. Korzystając z własności drzewa BST, przeprowadź ścisły dowód po-
prawności działania procedury TREE-SUCCESSOR.
13.2-4. Przejście drzewa binarnego o n węzłach w porządku inorder można
zrealizować w następujący sposób: najpierw wyszukujemy najmniejszy ele-
ment w drzewie za pomocą procedury TREE-MINIMUM, a następnie n - I
razy wywołujemy procedurę TREE-SUCCESSOR. Wykaż, że ten algorytm
działa w czasie 0(n).
13.2-5. Wykaż, że niezależnie od wyboru początkowego węzła łączny czas wy-
konania ciągu k wywołań procedury TREE-SUCCESSORna drzewie BST
o wysokości h wynosi O(k + h).
13.2-6. Niech T będzie drzewem BST, x liściem w tym drzewie, a y jego ojcem.
Wykaż, że key[y] jest albo najmniejszym kluczem w T większym niż key[x],
albo największym kluczem w drzewie, mniejszym niż key[x].

290
13.3. OPERACJE WSTAWIANIA I USUWANIA

13.3. Operacjewstawianiai usuwania


Operacje wstawiania i usuwania zmieniają zbiór dynamiczny reprezentowany
przez drzewo BST. 'fa zmiana wymaga przeorganizowania struktury drzewa,
ale w taki sposób, aby została zachowana własność drzewa BST. Jak się prze-
konamy, modyfikacja drzewa niezbędna przy wstawieniu nowego elementu jest
dość łatwa, ale usunięcie elementu okazuje się już stosunkowo skomplikowane.

Wstawianie
Nową wartość v można wstawić do drzewa poszukiwań binarnych T za pomo-
cą procedury TREE-INSERT. Do procedury przekazujemy jako argument węzeł
z, w którym key[z] = v, left[z] = NIL oraz right[z] = NIL. W wyniku wykonania
procedury drzewo T oraz niektóre pola z są modyfikowane w sposób, który
odpowiada wstawieniu z we właściwe miejsce w drzewie.

TREE-INSERT(T, z)
1 y+-NIL
2 x+- root[TJ
3 while X cf. NIL
4 doy+-x
5 if key[z] < key[x]
6 then x +- left[x]
7 else x +- right[x]
8 p[z]-y
9 ify=NIL
IO then root[TJ +- z
11 else if key[z] < key[y]
12 then left[y] +- z
13 else right[y] +- z

Na rysunku 13.3 jest zilustrowany sposób działania procedury TREE-IN-


SERT. Podobnie jak w przypadku procedur TREE-SEARCH i ITERATIVE-TREE-
-SEARCH, procedura TREE-INSERT rozpoczyna przeglądanie w korzeniu, a na-
stępnie przebiega po ścieżce w dół drzewa. Wskaźnik x przebiega po ścieżce,
a zmienna y zawiera zawsze wskazanie na ojca x. Po zainicjowaniu wartości
:zmiennych w pętli while w wierszach 3-7 wskaźniki x i y są przesuwane w dół
drzewa w lewo lub w prawo, w zależności od wyniku porównania key[z]
z key[x], aż do chwili, w której zmienna x przyjmie wartość NIL. Ta właśnie
wartość NIL zajmuje miejsce w drzewie, w którym należy umieścić wskaźnik na
węzeł z. Wstawienie z do drzewa (tzn. wiążące się z tym przypisania właściwych
wartości odpowiednim wskaźnikom) odbywa się w wierszach 8-13.

291
ROZDZIAŁ 13. DRZEWA POSZUKIWAŃ BINARNYCH

12

18

15

17
Rys, 13.3. Wstawienie węzła z kluczem 13 do drzewa poszukiwań binarnych. Jasnoszare węzły wcho-
dzą w skład ścieżki od korzenia do miejsca, w którym węzeł zostaje wstawiony. Przerywaną linią.
jest oznaczony wskaźnik, który zostaje utworzony w wyniku dodania elementu do drzewa

Procedura TREE-lNSERT, podobnie jak inne elementarne operacje na drze-


wach poszukiwań, działa na drzewie o wysokości h w czasie O(h).

Usuwanie
Argumentem procedury służącej do usuwania danego węzła z z drzewa po-
szukiwań binarnych jest wskaźnik do z. W procedurze tej są rozpatrywane trzy
przypadki przedstawione na rys. 13.4. Jeśli z nie ma synów, to w jego ojcu p[z]
zastępujemy wskaźnik do z wartością NIL. Jeśli węzeł ma tylko jednego syna,
to „wycinamy" z przez ustalenie wskaźnika między jego ojcem a jedynym
synem. Wreszcie, jeśli węzeł ma dwóch synów, to wycinamy następnik y węzła
z, o którym wiadomo, że nie ma lewego syna (patrz zad. 13.3-4), oraz za-
stępujemy zawartość z zawartością y.
W treści procedury TREE-DELETE powyższe trzy przypadki są realizowane
nieco inaczej.

TREE-DELETE(T, z)
1 if left[z] - NIL lub right[z] - NIL
2 tbeny+-z
3 else y +-TREE-SUCCESSOR(z)
4 if /eft[y] # NIL
5 then x +- left[y]
6 else x +- right[y]
7 ifx-#NIL
8 tbenp[x]-p[y]
9 if p[y] - NJL
10 tben root[T]+- x
11 else if y -left[p[y]J
12 tben left[p[y]] ~ x

292
13.3. OPERACJE WSTAWIANIA I USUWANIA

J5:
' ' •'
-'16
•,,_J 5 16,
'_, 'i(J.
___ 12
,'
20
)S; ·23 J8',

..6
- /

'
,,
--·
"
15,
' '
20
''
3
'--·
' '
t!ł\
'
'· .i
23\

,, 6 ', : 16:
l1l 20, ,,' ·-- ' i --··20
• ,yi : 12) '
,'
' ' 12'
"
l()\ ' 13',
'

'I., 1• 'lf, '23' lÓ':·,


.• 13' (8': 2:~ 18', 23'
,,
\@ '•.:Y' •,.,j \ .,_.,_.,
,, I

7
,, ,I ' ,, ,,'

Rys.. 13.4. Usunięcie węzła z z drzewa prn;zukiwań binarnych. W ka:alym przypadku faktycznie usu-
rrięly węzeł jest jasnoszary.(•) Jeśli z nie ma synów, to zostaje po prostu usunięty. (b) Jeśli z ma
tylko jednego syna, to wycinamy z. (c) Jeśli z ma dwóch synów, to wycinamy y, który jest następ­
nikiem z i ma co najwyżej jednego syna, po czym zastępujemy zawartość z iawartością y

13 else right[pfy]]+---x
14 if y -=fez
15 thcn key[z) - key(y)
16 I> Jeśli y ma inne pola, to je także należy skopiować.
17 returny

W wierszach 1-3 zostaje wyznaczony węzeł y, który zostanie usunięty~ drzewa.


Węzeł y może być albo węzłem wejściowym z (jeśli z ma co najwyżej jednego
syna), albo następnikiem z (jeśli z ma dwóch synów). Następnie w wierszach
4-6 zmiennej x zostaje przypisana różna od NIL wartość y albo wartość NIL,
jeśli y nie ma żadnych synów. Węzeł y zostaje usunięty w wierszach 7-13
przez odpowiednią modyfikację wartości wskaźników p[y] i x. Pełna imple-
mentacja operacji usunięcia węzła y okazuje się dość skomplikowana, ponie-
waż trzeba osobno rozpatrzyć szczególne przypadki: gdy x = NIL lub gdy y jest
korzeniem. Wreszcie w wierszach 14-16 zawarto~ć y zostaje przepisana do z

293
ROZDZIAŁ 13. DRZEWA POSZUKIWAN BINARNYCH

(niszcząc poprzednią zawartośćz}, jeżeli następnik. z został usunięty. W wierszu


17 do procedury wołającej zostaje przekazany węzeł y. Procedura ta może go
wstawić na listę wolnych pozycji. Czas działania procedury TREE-DELETE na
drzewie o wysokości h wynosi O(h}.

Następujące twierdzenie podsumowuje uzyskane rezultaty.

Tw!ERDZENIE 13.2.
Operacje INSERT i DELETE działają na drzewie BST w czasie O(h), gdzie h jest
wysokością drzewa.

ZADANIA

13.3-1. Napisz rekurencyjną wersję procedury TREE-lNSERT.
13.3-2. Przyjmijmy, że tworzymy drzewo BST, wstawiając po kolei różne pa-
rami wartości. Wykaż, że liczba węzłów rozpatrywanych przy wyszukiwa-
niu wartości w drzewie jest o jeden większa niż liczba węzłów cxlwiedzo-
nych podczas wstawiania tej wartości do drzewa.
13.3-3. Dany zbiór n liczb można posortować, budując z nich najpierw drzewo
BST (wywołując procedurę TREE-INSERT po kolei dla każdej liczby), a na-
stępnie wypisując je według porządku inorder w drzewie. Jaki jest pesymis-
tyczny czas działania tego algorytmu sortowania? Jaki jest najmniejszy
możliwy czas jego działania?
13.3-4. Wykaż, że jeśli w drzewie BST węzeł ma dwóch synów, to jego następ­
nik nie ma lewego syna, a jego poprzednik nie ma prawego syna.
13.3-S. Załóżmy, że w innej strukturze danych znajduje się wskaźnik do węzła
y w drzewie BST. Rozważmy sytuację, w której z - poprzednik węzła
y- został usunięty z drzewa przez procedurę TREE-DELETE. Jaki problem
może wyniknąć w takiej sytuacji? Jak poprawić procedurę TREE-DELETE,
aby rozwiązać ten problem?
13.3-6. Czy operacja usuwania jest „przemienna" w takim sensie, że usuwając
węzły x oraz y z drzewa BS'f, otrzymujemy takie samo drzewo niezależnie
od kolejności, w jakiej je usuwamy? Udowodnij, że tak: jest lub podaj
kontrprzykład.
13.3-7, Jeśli węzeł z w procedurze TREE-DELETB ma dwóch synów, to może­
my usunąć jego poprzednik zamiast jego następnik.a. Niektórzy przekonu-
ją, że „sprawiedliwa" strategia polegająca na zrównaniu priorytetu po-
przednika i następnika pozwala uzyskać w praktyce lepsze efekty. Jak
można zmodyfikować procedurę TREE-DELETE, aby realizowała ona tego
typu „sprawiedliwą" strategię?

294
* 13.4. LOSOWO SKONSTRUOWANE DRZEWA POSZUKIWAŃ BINARNYCH
~-----------------------------
* 13.4. Losowoskonstruowanedrzewaposzukiwań binarnych
Wykazaliśmy, że wszystkie podstawowe operacje na drzewach BST są wykony~
wane w czasie O(h), gdzie h jest wysokością drzewa. Wysokość drzewa BST
ulega jednak ciągłym m:iianom podczas wstawiania lub usuwania elementów.
Aby stwierdzić coś w praktyce o szybkości wykonywania operacji na drzewach
BST, rozsądnie jest przyjąć pewne założenia statystyczne, dotyczące rozkładu
kluczy w ciągu operacji wstawiania i usuwania.
Niestety niewiele wiadomo o średniej wysokości drzewa BST, jeśli powstaje
ono w wyniku ciągu operacji wstawiania i usuwania elementów. Jeśli jednak
drzewo powstaje w wyniku wykonania samych tylko operacji wstawiania, to
potrafimy przeprowadzić odpowiednią analizę. Niech losowo skonstruowane
drzewo BST o n kluczach będzie drzewem powstającym przez wykonanie ciągu
operacji wstawiania kluczy w losowej kolejności do początkowo pustego drzewa.
Zakładamy przy tym, że każda z n! permutacji kluczy jest jednakowo prawdopo-
dobna. (Zadanie 13.4-2 polega na wykazaniu, że jeśli założymy, iż każde drzewo
poszukiwań binarnych o n kluczach jest jednakowo prawdopodobne, to uzyska-
my pojęcie istotnie różne od losowo skonstruowanego drzewa BST). W tym
podrozdziale będziemy chcieli wykazać, że oczekiwana wysokość losowo skon-
struowanego drzewa BST, do którego należy n kluczy, wynosi O(lgn).
Na początek zajmiemy się zbadaniem struktury drzew BST skonstruowa-
nych za pomocą samych tylko operacji wstawiania.

LEMAT13.3.
Jeśli T jest drzewem powstałym w wyniku wstawienia n różnych kluczy k 1,
k 2 , ••• , k~ (w takiej właśnie kolejności) do początkowo pustego drzewa po-
szukiwań binarnych, to k 1 jest przodkiem ki w T, dla 1 ~ i< j ,s;;n, wtedy
i tylko wtedy, gdy

lub

DOWÓD
=- Niech ki będzie przodkiem kr Rozważmy drzewo T; będące wynikiem
wstawienia elementów k 1 , k 2 , ..• , k;. Ścieżka w T; od korzenia do węzła ki
jest taka sama jak ścieżka od korzenia do k 1 w drzewie T. Dlatego też, jeśli
wstawiamy kJ do drzewa T1, to zostanie on lewym albo prawym synem k;.
W rezultacie (patrz. zad. 13.2-6) k;jest albo najmniejszym kluczem spośród
k 1, k 2 , ••• , k 1 większym od ki, albo największym kluczem spośród k 1 , k 2 , ..• ,
k 1 mniejszym niż kJ.

295
ROZDZIAŁ 13. DRZEWA POSZUKIWAŃ BINARNYCH

<= Niech k1 będzie najmniejszym kluczem spośród k 1 , k 2 , ••• , k; większym od


ki. (Jeżeli ki jest największym kluczem spośród k 1 , k 2 , ••• , k 1 mniejszym od
ki, to dowód jest analogiczny). Wyniki porównań na ścieżce w drzewie
T prowadzącej od korzenia do k 1 są tak.ie same dla elementów k1 oraz ki.
Dlatego, aby wstawić element ki, przebiegamy po ścieżce do k 1, a następnie
wstawiamy k1 jak.o potomka k1•

Wnioskiem z lematu 13.3 jest dokładny wzór na głębokość klucza w drze-
wie w zależności od permutacji wstawianych kluczy.

WNIOSEK13.4.
Niech T będzie drzewem powstałym przez wstawienie n parami różnych kluczy
k 1 , k 2 , ••• , kn (w takiej właśnie kolejności) do początkowo pustego drzewa
poszukiwań binarnych. Dla danego klucza ki, gdzie 1 ::!,,j::;,,n, określmy

oraz
L; = {k 1: I ~ i <j oraz k 1 < k 1 < ki dla każdego/< i takiego, że k 1 > k 1}

Wtedy na ścieżce od korzenia do klucza k1 znajdują się dokładnie klucze


z GJu L 1, a głębokość kluc:za k1 w T wynosi


Na rysunku 13.5 są pokazane zbiory G1 i Li' Zbiór G1 zawiera wszystkie
klucze k 1 wstawione przed k 1, takie że k 1 jest najmniejszym kluczem spośród
k 1 , k 2, ... , k 1 większym od k 1• (Zbiór Li jest symetryczny do G1). Aby lepiej
zrozumieć konstrukcję zbioru G , omówimy teraz sposób wyznaczania jego
1
elementów, Z kluczy k 1 , k 2 , ••• , k 1 _ 1 rozważamy tylko te, które są większe
od k1. Na rysunku klucze te zostały oznaczone jak.o GJ. Rozpatrując po
kolei każdy z kluczy, pamiętamy cały czas ich minimum. Zbiór G1 składa
się z tych elementów, które w chwili ich rozpatrywania są mniejsz.e od do-
tychczasowego minimum.
Dla celów analizy dokonamy pewnego uproszczenia. Załóżmy, że po kolei
wstawiamy do zbioru dynamicznego n parami różnych liczb. Ile razy, średnio,
jest aktualizowane dotychczasowe minimum, jeśli przyjmiemy, że każda per-
mutacja wstawianych liczb jest jednak.owo prawdopodobna? Aby odpowie-
dzieć na to pytanie, załóżmy, że i-tą wstawianą liczbą jest k;, dla i= 1, 2,
..., n. Prawdopodobieństwo, że k1 jest najmniejszą z i początkowych liczb jest

296
* 13.4. LOSOWO SKONSTRUOWANE DRZEWA POSZUK!WAN BINARNYCH

4 29

3 7 10 26

k.; 17
'
18

(a)

Klw,re 21 9 4 25 7 12 3 10 19 29 17 6 26 18
G'; 21 25 19 29
G.; 2( (9
L:; 9 4 7 12 3 IO
L.; 9 12

(b)

Rys. 13.5, Zbiory G1 oraz L 1, do których należą klucze na ścieżce od korzenia drzewa poszukiwań
binarnych do klucza k 1 = l 1. (a) Węzły o kluczach w G1 są czarne, a węzły o kluczach ze zbioru L
1
białe. Pozostałe węzły są szare. Ścieżka z korzenia drzewa do węzła o kluczu k jest pogrubiona.
1
Klucze na lewo od przerywanej linii są mniejsze niż kJ>a klucze położone na prawo od niej są
większe. Drzewo zostało skonstruowane za pomocą ciągu operacji wstawiania kluczy w kolejności
podanej w górnej części. (b) Zbiór G~ = {21, 25, 19, 29} składa się z elementów wstawionych przed
17, większych od 17. Zbiór G1 = {21, 19} składa się z elementów, które są mniejsze niż dotych·
czasowe minimum elementów z Gj. Tak więc klucz 21 należy do G1, ponieważ jest pierwszy w ko-
lejności. Klucz 25 nie należy do G1, ponieważ jest większy niż dotychczasowe minimum 21. Klucz
19 należy do G1, ponieważ jest mniejszy niż dotychczasowe minimum 21. Klucz 29 nie należy do
G1, bo jest większy od dotychczasowego minimum 19. Zbiory LJ oraz L1 są względem siebie
symetryczne

równe I/i, ponieważ ranga k 1 z jednakowym prawdopodobieństwem przyjmuje


jedną z i wartości. Stąd wynika, że oczekiwana liczba aktualizacji minimum
zbioru wynosi

~ I~ H
L, . "
i= 1 I

297
ROZDZIAŁ 13. DRZEWA POSZUKIWAŃ BINARNYCH

gdzie H" = ln n+ 0(1) jest n-tą liczbą harmoniczną (patrz równanie (3.5) oraz
problem 6.2).
Wartość oczekiwana liczby zmian wartości minimalnej wynosi więc
w przybliżeniu 1n n, a z następującego lematu wynika, że prawdopodobień­
stwo, iż ta liczba jest istotnie większa, jest bardzo małe.

LEMAT13.5.
Niech k 1 , k 2 , ... ,k 11 będzie losową permutacją n parami różnych liczb oraz
niech IS1będzie zmienną losową równą liczności zbioru

S = {k 1: I ~ i~ n oraz k 1 > k; dla każdego / < i} (13.1)

Wtedy Pr{ISI ;;i:,(ft+ l)H"} ~ 1/n2 , gdzie H" jest n-tą liczbą harmoniczną,
ap „
4,32 spełnia równaoie (!np - I)P - 2.

DOWÓD
Liczność zbioru S można traktować jak.o liczbę sukcesów w schemacie Ber-
noulliego o długości n, jeśli sukces w i-tej próbie oznacza, że k1jest mniejsze od
k 1 , k 2 , ... , k1_ 1 . Sukces w i-tej próbie występuje z prawdopodobieństwem 1/i.
Próby są niezależne, zatem prawdopodobieństwo, że k 1 jest najmniejsze spo-
śród k 1 , k2 , ••. , k 1, jest niezależne od względnego porządku elementów k 1 , k 2 ,
... , k;-1·
Do oszacowania prawdopodobieństwa, że ]SI~ (ft+ l)H 11 użyjemy twier-
dzenia 6.6. Wartość oczekiwana ISI wynosi µ = Hn ~ Inn. Paniewa.z P> I,
z twierdzenia 6.6 wnioskujemy więc, że

Pr{ISI;;, (P + l)H.) - Pr{ISI - µ > PH.)

<; (;;:)'B•
= ,f..1-ln/f)/JH,
~ e-(lnP-1).8lnn

= n-(ln/J-1)/J
= 1/n 2

co wynika z definicji p.

Udało się
nam zgromadzić narzędzia, których użyjemy teraz do oszacowa-
nia wysokości losowo zbudowanego drzewa poszukiwań binarnych.

298
* 13.4. LOSOWO SKONSTRUOWANE DRZEWA POSZUKIWAii! BINARNYCH

TwIERDZENIE 13.6.
Średnia wysokość losowo zbudowanego drzewa BST składającego się z n para·
mi różnych kluczy wynosi O(lgn).

DOWÓD
Niech k 1 , k 2 , •.• , k„ będzie losową permutacją n kluczy, a T drzewem BS1
powstałym przez wstawienie kluczy do początkowo pustego drzewa w kolejno·
ści określonej przez tę permutację. Rozważmy najpierw prawdopodobieństwo,
że głębokość d(k 1, 1) danego klucza ki wynosi co najmniej t dla dowolnej
wartości t. Z wniosku 13.4 wynika, że jeśli głębokość d(k , 1) klucza ki wynosi
1
co najmniej t, to liczba elementów w jednym ze zbiorów G1 oraz L jest równa
1
co najmniej t/2. Stąd

Pr{d(k1, 1);,, t},; Pr{IG);,, t/2} + Pr{IL);,, t/2) (13.2)

Rozpatrzmy najpierw Pr{IGJI ;;i, t/2}. Mamy

Pr{IGJI;,, t/2)
= Pr{]{ki: 1 ~ i <j oraz k 1 > k 1 > k1 dla każdego/< i}I ;;i, t/2}
~ Pr{l{k 1:i~n oraz k 1 > k; dla każdego I< i}J;;;i,t/2}
- Pr{ISI;,, 1/2)
gdzie Sjest określone jak we wzorze (13.1). Rozumowanie przebiega tu na-
stępująco: prawdopodobieństwo nie zmniejszy się, jeśli rozszerzymy zakres
iz i <j do i~ n, ponieważ dodamy wtedy do zbioru więcej elementów. PodobM
nie, prawdopodobieństwo nie zmaleje, jeśli usuniemy warunek, że k 1 > kJ, po-
nieważ zastępujemy tylko permutację potencjalnie mniejszej niż n liczby ele-
mentów (tych k 1, które są większe od kJ) permutacją n elementów.
Rozumując „symetrycznie", możemy wykazać, że

Pr{IL) ;,, 1/2},; Pr{ISI;,, 1/2}


Korzystając z nierówności (13.2), otrzymujemy więc

Pr{d(k1, 1);,, 1) ,; 2 Pr{ISJ;,,1/2}

Jeśli dobierzemy t = 2(P + l)H,., gdzie H„ jest n-tą liczbą harmoniczną,


a p ~ 4,32 spełnia równanie (lnp- l)P = 2, to stosując lemat 13.5, wnios-
kujemy, że

Pr{d(k1, 1);,, 2(P + l)H,} ,; 2Pr{ISI;,,(P + I) H,)


~ 2/n2

299
ROZDZIAŁ 13. DRZEWA POSZUKlWAril BINARNYCH

Jeśli losowo zbudowane drzewo poszukiwań binarnych ma co najwyżej


n węzłów, to prawdopodobieństwo, że dowolny węzeł ma głębokość co najw
mniej 2(/J + l)H," wynosi co najwyżej n(2/n 2) = 2/n (z nierówności Boole'a
(6.22)). Stąd wynika, że z prawdopodobieństwem co najmniej 1 - 2/n wyso~
kość losowo zbudowanego drzewa BST jest mniejsza niż 2(P + l)H 11, a z praw~
dopodobieństwem co najwyżej 2/n wynosi co najmniej (2/1 + 1)H, ale nie więw
cej niż n. Jej wartość oczekiwana jest więc nie większa niż (2(ft + l)H,,)
(I - 2/n) + n(2/n) = O(lgn).

ZADANIA
13.4-1. Opisz drzewo BST zawierające n węzłów, dla którego średnia głębow
kość węzłów wynosi 0(lgn), ale wysokość drzewa jest ro(lgn). Jak duża
może być wysokość drzewa BST o n węzłach, w którym średnia głębokość
węzłów wynosi 0(lg n)?
13.4-2. Wykaż, że pojęcie losowego drzewa BST, przy założeniu, iż każde
drzewo BST o n węzłach występuje z jednak.owym prawdopodobieństwem,
istotnie różni się od pojęcia losowo zbudowanego drzewa BST zdefinio-
wanego w tym podrozdziale. (Wskazówka: Rozpatrz wszystkie przypadki
dla n= 3).
* 13.4-3. Dla danej stałej r ~ l ustal, dla jakich liczb t prawdopodobieństwo
:zdarzenia, że wysokość losowo zbudowanego drzewa BST wynosi co naj-
mniej tH,,, jest mniejsze niż 1/n'.
* 13.4-4. Rozważmy algorytm RANDOMIZED-QtnCKSORTdziałający na tablicy
n liczb. Wykaż, że dla dowolnej stałej k > D dla wszystkich oprócz O(l/nk)
części wszystkich n! permutatji czas działania tego algorytmu wynosi
O(nlgn).

Problemy
13-1. Drzewa poszukiwań
binarnych z powtarzającymi się kluczami
Powtarzające się klucze mogą niekorzystnie wpływać na implementację
drzew BST.
(a) Jaki jest asymptotyczny czas działania ciągu n operatji TREE-INSERT,jeśli
do początkowo pustego drzewa BST wstawiamy n elementów o identycz-
nych kluczach?
Proponujemy w następujący sposób ulepszyć procedurę TREE·INSERT: przed
wierszem 5 należy sprawdzać, cr,y key[z] = key{x], a przed wierszem 11, czy
key[z] = key[y]. Jeśli równości zachodzą, to stosujemy jedną z poniższych stra·
tegii. Dla każdej z nich wyznacz asymptotyczny czas potrzebny do wstawienia

300
PROBLEMY

n elementów o jednakowych kluczach do początkowo pustego drzewa poszu1d-


wań binarnych. (Strategie te zostały opisane w wersji dla wiersza 5, w którym
porównujemy klucze z oraz x. Odpowiednie strategie dla wiersza 11 otrzyma-
my, zastępując x przez y).

(b) Dla każdego węzła pamiętaj zmienną logiczną b[x] i w zależności od jej
wartości przypisuj zmiennej x wartość left[x] albo right[x]. Wartość zmien-
nej b[x] jest zmieniana na przeciwną (TRUE albo FALSE) za każdym razem,
gdy procedura TREE-INSERT odwiedza węzeł x.
(c) W węźle x jest przechowywana lista elementów o jednakowych kluczach;
z zostaje wstawiony do tej listy.
(d) Przypisz losowo zmiennej x jedną z wartości left[x] albo right[x]. (Opisz
zachowanie w przypadku pesymistycznym oraz podaj nieformalną analizę
zachowania w przypadku średnim).

13--2. Drzewa pozycyjne


Dla danych dwóch napisów a= a0 a 1 ... ap i b = b0 b 1 ... bą, gdzie każdy znak
a1 oraz bi pochodzi z pewnego uporządkowanego zbioru, mówimy, że napis
a leksykograficznie poprzedza napis b, jeśli albo

1. istnieje taka liczba j, O ~j ~ min(p, q), że a1 = b1 dla wszystkich

i= O, 1, ... , j - 1 oraz ai < b1,


albo

2. p < q oraz a1 = b1 dla każdego i= O, 1, ... , p.

Jeśli na przykład a i b są ciągami bitów, to 10100 < 10110, bo zachodzi


warunek 1 (dlaj = 3), a 10100 < 101000 z warunku 2. Porządek leksykografi-
czny jest podobny do stosowanego w większości słowników i encyklopedii.
Do drzewa pozycyjnego przedstawionego na rys. 13.6 należą ciągi bitowe
1011, 10,011,100 i O. Szukając klucza a= a0 a 1 .•• ap, w węźle o głębokości i
kierujemy się w lewo, jeśli a 1 = O, lub w prawo, o ile a1 = 1. Niech S będzie
zbiorem różnych ciągów bitowych o długości n. Pokaż, jak zastosować drzewo
pozycyjne do posortowania leksykograficznie zbioru S w czasie El(n). Na przy-
kład dla drzewa z rys. 13.6 wynikiem sortowania powinien być ciąg O, Ol 1, 10,
100, 1011.

13-3. Średnia głębokość wierzcholka w losowo zbudowanym dr.zewie poszukiwań


binarnych
Zajmiemy się teraz wykazaniem, że średnia głębokość węzła w losowo zbudo-
wanym drzewie poszukiwań binarnych o n węzłach wynosi O(lg n). Ten wynik

301
ROZDZIAŁ 13. DRZEWA POSZUKIWAŃ BINARNYCH

o 1

o
1 o

10

011 100

1011

Rys. 13.6. Drzewo pozycyjne z.awierające ciągi bitowe 101l, IO, 011, 100 i O. Klucz każdego węzła
można wyznaczyć jednoznacznie ze ścieżki od korzenia do tego węzła. Nie ma więc potrzeby
zapamiętywania kluczy w węzłach; na rysunku klucze zostały przedstawione tylko dla ilustracji.
Ciemnoszare węzły odpowiadają kluczom, które nie należą do zbioru; w drzewie znajdują się tylko
jako fragmenty ścieżki do innych węzłów

jest w istocie słabszy niż teza twierdzenia 13.6, ale metoda, jakiej użyjemy,
ukazuje zaskakujące podobieństwo konstruowania drzew poszukiwań binar-
nych i działania algorytmu RANDOMIZED-QUICKSORT z pod.rozdz. 8.3.
Przypomnijmy sobie najpierw z ro7.dz. 5, że wewnętrzna długość ścieżki
P(1) drzewa binarnego T jest sumą głębokości wszystkich węzłów x drzewa T;
głębokość węzła x oznaczamy przez d(x, 1).

(a) Wykaż, że średnia głębokość węzła w T wynosi

l l
.I
n=T
d(x, n ~ n P(n
Wystarczy więc teraz wykazać, że wartość oczekiwana P(T) wynosi O(nlgn).

(b) Niech TL oraz TR oznaczają odpowiednio lewe i prawe poddrzewo T. Wy-


każ, że jeśli Tma n węzłów, to

P(n ~ P(T J + P(T,) + n - l

(c) Niech P(n) oznacza średnią wartość wewnętrznej długości ścieżki losowo
zbudowanego drzewa poszukiwań binarnych o n węzłach. Wykaż, że
=~·-------·-----------------
302
PROBLEMY

1 11- l
P(n) - I (P(O + P(n - i - I)+ n - I)
n '""o

(d) Wykaż, że P(n) można wyrazić w następujący sposób:

2 11-1
P(n) -
n t= 1
I P(k) + ®(n)

(e) Przytocz argument użyty przy analizie probabilistycznej wersji algorytmu


quicksort, aby wykazać, że P(n) = O(n lg n).

W każdym rekurencyjnym wywołaniu procedury quicksort wybieramy losowo


element, względem którego dzielimy zbiór sortowanych elementów. Każdy wę­
zeł drzewa poszukiwań binarnych dzieli zbiór elementów na te, które znajdują
się odpowiednio w lewym lub prawym poddrzewie tego węzła.

(f) Opisz implementację algorytmu quicksort, w której porównania wykony-


wane w celu posortowania elementów są takie same jak porównania wyko-
nywane w trakcie wstawiania elementów do drzewa poszukiwań binarnych.
(Wykonywane porównania muszą być takie same, choć ich kolejność może
być inna).

13-4. Zliczanie różnych dr.iewbinarnych


Niech b„ oznacza liczbę różnych drzew binarnych o n węzłach. Zajmiemy
się teraz wyznaczeniem wzoru na b„ oraz asymptotycznym oszacowaniem
tej liczby.

(a) Wykaż, że b0 = 1 oraz że dla n~ 1


•-1
b,. = L hth,.-1-t
k= o

(b) Niech B(x) będzie funkcją tworzącą


B(x) - I b.x"
11= 0

(patrz problem 4-6, gdzie znajdziesz definicję funkcji tworzącej). Wykaż, że


B(x) = x B(x) 2 + I, skąd wynika, że

I ,---
B(x) - (I - .j I - 4x)
2x

303
ROZDZIAŁ 13. DRZEWA POSZUKIWAŃ BINARNYCH

Rozwinięcie Taylora funkcji /(x) wokół punktu x = a jest dane wzorem

ro [<'I( )
/(x) - L x - a (x - a)'
l.cO k!

gdzieJ<tl(x) jest wartością k-tej pochodnej funkcji/w p11nkcie x.

(c) Wykaż, że

b - ---
~ n+ 1
I (2") n

(n-ta liczba Catalana) korzystając z rozwinięcia Taylora funkcji


Jl - 4-xwokół punktu x = O. (Zamiast używać rozwinięcia Taylora, mo-
żesz skorzystać z uogólnienia wzoru dwumianowego (6.5) dla dowolnych
rzeczywistych wykładników n, w którym dla dowolnej liczby r.leczywistej

n oraz liczby całkowitej k traktujemy (:) jako n(n - l) ... (n - k + 1)/k!,


jeżeli k ~ O, oraz O w przeciwnym razie).

(d) Wykaż, że

4"
b. - .;·· . 312 (I + 0(1/n))
nn

---- ______________________
""""""""""""""""' _
Uwagido rozdziału
Książka Knutha [123] zawiera solidne omówienie zarówno prostych drzew
BST, jak. i wielu ich modyfikacji. Drzewa BST zostały wynalezione niezależnie
przez wiele osób pod koniec lat pięćdziesiątych.
Rozdział 14

Drzewaczerwono-czarne

W rozdziale 13 pokazaliśmy, że za pomocą drzew poszukiwań binarnych moż­


na tak zaimplementować podstawowe operacje na zbiorach dynamicznych (ta-
kie jak SEARCH, PREDECESSOR, SUCCESSOR, MINIMUM, MAXIMUM, INSERT
oraz DELETE), aby dla drzewa o wysokości h działały one w czasie O(h). Ope-
racje te działają więc szybko, jeżeli wysokość drzewa poszukiwań jest mała.
Jeśli jerlnak wysokość drzewa jest duża, to koszty operacji mogą być równie
duże jak dla zwykłych list. W drzewach czerwono-czarnych stosuje się jedną
z metod, która pozwala utrzymywać drzewa poszukiwań w postaci „zrówno-
ważonej", dzięki czemu pesymistyczną złożoność operacji na zbiorach dyna-
micznych można ograniczyć przez O(lgn).

14.1. Własności drzewczerwono-czarnych


Drzewo czerwono-czarne jest drzewem poszukiwań binarnych, w którym na
każdy węzeł przypada jeden dodatkowy bit infonnacji: jego kolor, który może
być albo czerwony (RED), albo czarny (BLACK).Przez narzucenie odpowied-
nich warunków na możliwe ciągi kolorów węzłów leżących na dowolnej ścieżce
biegnącej od korzenia do liścia drzewa czerwono-czarnego gwarantujemy, że
każda ścieżka jest co najwyżej dwa razy dłuższa niż dowolna inna, dzięki cze-
mu drzewo jest w przybliżeniu zrównoważone.
Każdy węzeł drzewa zawiera pola color, key, /eft, right oraz p. Jeśli syn lub
ojciec węzła nie istnieje, to odpowiedni wskaźnik ma wartość NIL, Wskaźniki
równe NIL będziemy traktować jako wskazania na zewnętrzne węzły drzewa
poszukiwań binarnych (liście), a zwyczajne węzły drzewa zawierające klucze
będą pełniły funkcję wewnętrznych węzłów drzewa.

305
ROZDZIAŁ 14. DRZEWA CZERWONO-CZARNE

Drzewo BST jest drzewem czerwono-czarnym, jeśli ma następujące włas­


ności czerwonCH:Zarne:

(1) każdy węzeł jest albo czerwony, albo czarny;


(2) każdy liść (NIL) jest czarny;
(3) jeśli węzeł jest czerwony, to obaj jego synowie są czarni;
(4) każda prosta ścieżka z ustalonego węzła do liścia ma tyle samo czarnych
węzłów.

Przykładowe drzewo czerwono-czarne widać na rys. 14.1.

._ - _________ __

~---~-----
,~- -
.,,.
2 '-- 2 'li' -

Rys. 14.1. Drr.ewo czerwono-czarne; czarne wę:zly mają na rys. kolor czarny, a czerwone - kolor
szary. Każdy węzeł drzewa czerwono-czarnego jest albo czerwony, albo czarny; każdy liść (NIL)
jest c1..amy;obaj synowie czerwonego węzła są czami; każda prosta ścieżka z węzła do potomnego
liścia zawiera tyle samo czarnych węzłów. Przy ka:Wym niepustym węźle jest zamaczana jego
czarna wysokość; węzły NIL mają czarną wysokośc O

Liczbę czarnych węzłów na dowolnej ścieżce z węzła x (wykluczając x)


do liścia nazywamy czarną wysokością węzła, którą oznaczamy przez bh(x).
Wielkość ta jest dobrze zdefinowana dzięki własności (4). Przez czarną wyso-
kość drzewa czerwono-czarnego będziemy rozumieć czarną wysokość jego
korzenia.
Z następującego faktu wynika, że drzewa czerwono-czarne są efektywnymi
drzewami poszukiwań.

LEMAT14.1.
Drzewo czerwono-czarne o n węzłach wewnętrznych ma wysokość co najwyżej
2lg(n + !).

DOWÓD
Wykażemy najpierw, że każde poddrzewo o korzeniu w dowolnym węźle x ma
co najmniej 2hh(xJ - 1 węzłów wewnętrznych.
Dowodzimy tego faktu przez in-
dukcję względem wysokości węzła x. Jeśli x ma wysokość O, to x musi być
liściem (NIL), a poddr?.ewo o korzeniu w x zawiera w istocie co najmniej

306
14.1. WłASNOSCI DRZEW CZERWONO-CZARNYCH

2hb.(xJ- 1 = 2° - I = O węzłów wewnętrznych. Krok indukcyjny wygląda na-


stępująco: niech x będzie węzłem wewnętrznym o dodatniej wysokości i dwóch
synach. Każdy z synów ma czarną wysokość równą albo bh(x), albo
bh(x) - 1, w zależności od tego, czy jest odpowiednio czerwony czy czarny.
Wysokość syna węzła x jest mniejsza niż wysokość x, z założenia indukcyjnego
wynika więc, że każde z poddrzew o korzeniach w synach x ma co najmniej
2bh{xJ-I - 1 węzłów wewnętrznych. Stąd już wynika, że poddrzewo o korzeniu
w x zawiera co najmniej (2bh(r)-i - 1) + (2bh(xJ-J - 1) + 1 = 2bh(x) - I węzłów
wewnętrznych, co należało wykazać.
Niech h będzie wysokością drzewa. Z własności (3) wynika, że co najmniej
połowa węzłów na każdej prostej ścieżce od korzenia do liścia (nie wliczając
korzenia) jest czarna. Stąd wynika, że czarna wysokość drzewa wynosi co
najmniej h/2, czyli
n~21112 -1
Przenosząc 1 na lewą stronę i logarytmując obie strony, otrzymujemy
lg(n + I);,, h/2, czyli h,; 21g(n+ !).

Z powyższego lematu wynika natychmiast, że operacje na zbiorach dyna-
micznych, takie jak SEARCH,MINIMUM, MAXIMUM, SUCCESSORi PREDECES-
SOR,można tak zaimplementować na drzewach czerwono-czarnych, aby dzia-
łały w czasie O(lgn), ponieważ (jak wykazaliśmy w rozdz. 13) procedury te
działają w czasie O(h) na drzewie o wysokości h, a każde drzewo czerwono-
-czarne o n węzłach ma wysokość O(lg n). Procedury TREE-INSERT i TREE-
-DELETEz rozdz. 13 działają w czasie O(lgn) także dla drzew czerwono-czar-
nych, jednak nie realizują dokładnie operacji INSERT i DELETE, ponieważ nie
dają gwarancji, że powstałe w ich wyniku drzewa spełniają nadal własności
czerwono-czarne. W podrozdziałach 14.3 oraz 14.4 przekonamy się jednak, że
obie te operacje daje się mimo wszystko zrealizować w czasie O(lgn) także na
drzewach czerwono-czarnych.

ZADANIA

14.1-1. Narysuj pełne drzewo binarne o wysokości 3 zawierające klucze ze


zbioru {I, 2, ... , 15}. Dodaj stałe NIL jako liście oraz tak pokoloruj węzły
na trzy różne sposoby, aby czarna wysokość powstałych drzew wynosiła
odpowiednio 2, 3 oraz 4.
14.1-2. Przyjmijmy, że korzeń w drzewie czerwono-czarnym jest czerwony.
Czy jeśli pokolorujemy go na czarno, to drzewo będzie nadal miało włas­
ności czerwono-czarne?
14.1-3. Wykaż, że najdłuższa prosta ścieżka z węzła x do liścia w drzewie
czerwono-czarnym jest co najwyżej dwa razy dłuższa niż najkrótsza ścież­
ka z węzła x do pewnego liścia.

307
ROZDZIAŁ 14. DRZEWA CZERWONO-CZARNE

14.1-4. Ile wynosi największa liczba węzłów wewnętrznych


w drzewie czerwo-
no-czarnym o czarnej wysokości Kl Jaka jest najmniejsza taka liczba?
14.1~5.Opisz drzewo czerwono-czarne o n kluczach, w którym występuje naj-
większy możliwy stosunek liczby czerwonych węzłów wewnętrznych do
liczby czarnych węzłów wewnętrznych. Jaki jest ten stosunek? Dla jakiego
drzewa ten stosunek jest możliwie najmniejszy i ile wynosi?

14.2. Operacjerotacji
Operacje TREE-lNSERT i TREE-DELETE działają na drzewach czerwono-czar-
nych o n kluczach w czasie O(lgn). Ponieważ modyfikują one strukturę drze-
wa, mogą więc przestać być spełnione własności z pod.rozdz. 14.1. Aby je przy-
wrócić, należy zmienić kolory pewnych węzłów w drzewie i zmodyfikować
wartości niektórych wskaźników.

y
X y
, LEFr-ROTATE(T,
x)
a • r
Rys. 14.2. Operatja rotatji na drzewie DST. Operacja RioHT-ROTATE(T, x) za.mienia konfigurację
wętlów po lewej stronie na konfigurację po prawej przez zmianę wartości stałej liczby wskaźDików.
Z konfiguracji po prawej stronie można przejść z powrotem do konfiguracji po lewej, stosując
odwrotną operację: 1.EFT-ROTATE(T,y). Węzły x i y mogą był położone gdziekolwiek w drzewie
poszukiwań binarnych. Litery o:,p oraz y symbolizują dowolne poddrzewa. Operacja rotacji za.
chowu je porządek inorder kluczy: klucz.ew poddrzewie o:są mniejsz.e od key[x], który jest mniejszy
niż klucze w poddrzewie p, które są z kolei mniejsze niż key{y),od którego większ.e są klucze
w poddrzewie y

Strukturę wskaźnikowązmienia się za pomocą rotacji, która jest lokalną


operacją na drzewie poszukiwań binarnych, zachowującą uporządkowanie
inorder kluczy w drzewie. Na rysunku 14.2 są pokazane dwa rodzaje rotacji:
lewe i prawe. Lewą rotację na węźle x można wykonać tylko wtedy, gdy jego
prawy syn y nie jest równy NIL. Lewa rotacja polega na „obrocie" wokół
krawędzi między węzłami x i y. W wyniku rotacji y staje się nowym korz.eniem
poddrzewa, x zostaje jego lewym synem, a lewy syn węzła y zostaje prawym
synem węzła x.
W procedurze LEFT-ROTATE zakładamy, że right[x] 'F NIL.

LEFT-ROTATE(T, x)
1 y ~ right[x] t> Inicjuj y.
2 right[x] ~ left[y] I> Zamień lewe poddrzewo y na prawe poddrzewo x.

308
14.2. OPERACJE ROTACJI

3 if /eft[y] ,I, NlL


4 then p[left[yJJ ~ x
5 p[yJ +- p[x] t> Przyłącz ojca x jak.o ojca y.
6 if p[x] ~ NlL
7 then root[T] +- y
8 else if x ~ teft[p[xJJ
9 then left[p[xJJ ~ y
IO else right[p[xJJ~ y
11 left[yJ +- x t> Przyłącz x jako lewego syna y.
12 p[xJ~ y

Na rysunku 14.3 jest przedstawiony przykład działania operacji LEFT-ROTA-


TE. Procedura RIGHT-ROTATEzachowuje się bardzo podobnie. Obie procedu-
ry działają w czasie 0(1). Rotacja zmienia tylko wartości wskaźników; pozo-
stałe pola węzłów drzewa pozostają bez zmian.

2 14 19

LEFf"ROTATE(T,
x) /
I 12 17 22

'i 20
'

3 6 19

2 9 14 22
12 17 20

Rys. 14.3. Przykład. działania procedury LEFT-ROTATE(T,x) na drzewie DST. Liście (węzły NIL) ZO·
stały pominięte. Przejście w porządku inorder dla obu drzew (oryginalnego i zmodyfikowanego
przez operację rotacji) daje ten sam ciąg kluczy

ZADANIA

14.2-1. Narysuj drzewo czerwono-czarne powstałe po wykonaniu operacji


TREE-lNSERT na drzewie z rys. 14.1 z kluczem 36. Czy jeśli wstawiony

309
ROZDZIAŁ 14. DRZEWA CZERWONO-CZARNE

węzeł
pokolorujemy na czerwono, to otrzymamy w wyniku drzewo czer-
wono-czarne? A co będzie, gdy pokolorujemy go na czarno?
14.2-2. Napisz procedurę RIGHT-ROTATE.
14.2-3. Wykaż, że operacja rotacji zachowuje porządek inorder kluczy w drze-
wie binarnym.
14.2-4. Niech a, b i c będą dowolnymi węzłami w poddrzewach a:, fi i y, od-
powiednio, lewego drzewa na rys. 14.2. Jak się zmieniają głębokości a,
b oraz c po wykonaniu operacji lewej rotacji węzła x z rysunku?
14.2-5. Wykaż, że każde drzewo o n węzłach można przekształcić w dowolne
inne drzewo o n węzłach za pomocą O(n) operacji rotacji. (Wskazówka:
Wykaż najpierw, że co najwyżej n - I rotacji wystarczy, aby przekształcić
dowolne drzewo w łańcuch).

14.3. Operacjawstawiania
Wstawienie nowego węzła do drzewa czerwono-czarnego o n węzłach można
wykonać w czasie O(lgn}. Najpierw wstawiamy węzeł x do drzewa T za po-
mocą operacji TREE-INSERT(podrozdz.13.3), tak jak.by to było zwykłe drzewo
BST, po czym kolorujemy x na czerwono. Aby zagwarantować zachowywanie
przez operację wstawiania własności czerwono-czarnych, musimy naprawić po-
wstałe drzewo, zmieniając kolory oraz wykonując odpowiednie rotacje. Więk­
sza część procedury RB-INSERT dotyczy obsługi różnych przypadków, które
zachodzą w czasie naprawy drzewa zmodyfikowanego przez wstawienie no-
wego węzła.

RB-INSERT(T, x)
1 TREE-INSERT(T, x)
2 color[x] - RED
3 while x 'F root[T] i color[p[x]] = RED
4 do if p[x] - le/l[p[p[x]]]
5 theny - right[p[p[x] ]]
6 if color[y] - RED
7 then color[p[x]] - BLACK r.>Przypadek 1
8 color[y] - BLACK t> Przypadek I
9 co/or[p[p[x]] J - RED t> Przypadek I
IO x- p[p[x]] r.>Przypadek I
Il else if x - right[p[x]]
12 then x- p[x] r.>Przypadek 2
13 LEFT-ROTATE(T, x) r.>Przypadek 2
14 co/or[p[x]] - BLACK r.>Przypadek 3
15 color[p[p[x] J - RED r.>Przypadek 3
~~--------~-- ..,_,,, ________________ _
310
14.3, OPERACJA WSTAWIANIA

16 RIGHT-ROTATE(T,p[p[x]]) c> Przypadek 3


17 else (tak samo jak część tben z zamienionymi rolami „right"
oraz „left")
18 color[root[1]]- BLACK

Procedura RB-INSERT nie jest wcale taka skomplikowana, na jaką wyglą­


da. Analizę jej treści można podzielić na trzy etapy. Po pierwsze, określimy
charakter zaburzeń własności czerwono-czarnych wprowadzonych w wierszach
1 i 2, gdzie wstawiany element zostaje pokolorowany na czerwono. Po drugie,
ustalimy cel, który chcemy osiągnąć w pętli while w wierszach 3-17. Na koniec
przeanalizujemy każdy z trzech przypadków, które obejmuje pętla wbile, aby
przekonać się, że główny cel zostaje w niej osiągnięty. Na rysunku 14.4 poka-
zaliśmy przykład działania procedury RB-INSERT na pewnym drzewie czerwo-
no-czarnym.
Która z własności czerwono-czarnych może zostać naruszona w kodzie
poza wierszami 1-2? Własność (1) z pewnością nie przestaje zachodzić, podob-
nie jak i własność (2), ponieważ nowo wstawiony czerwony węzeł ma stale NIL
jako swoje dzieci. Własność (4) oznaczająca, że liczba czarnych węzłów na
każdej ścieżce z danego węzła do liścia jest taka sama, również pozostaje speł­
niona, ponieważ węzeł x zastępuje (czarny) liść NIL, a x jest czerwony z (czar-
nymi) stałymi w roli synów. Jedyną własnością, która może nie być spełniona,
jest własność (3) - czerwony węzeł nie może mieć czerwonego syna. Dokład­
niej, własność (3) nie jest spełniona, jeśli ojciec węzła x jest C".lerwony,ponieważ
x zostaje pokolorowany na czerwono w wierszu 2. Na rysunku 14.4a przed-
stawiliśmy taką sytuację wynikłą po wstawieniu węzła x.
W pętli while, w wierszach 3-17, jest realizowane przesunięcie zaburzenia
własności (3) w górę drzewa, przy zachowaniu jako niezmiennika własności
(4). Na początku każdej iteracji pętli x wskazuje na czerwony węzeł, którego
ojciec też jest czerwony - jedyne zaburzenie własności czerwono-czarnych
w drzewie. Możliwe są dwa wyniki wykonania pętli: wskaźnik x przesunie się
w górę drzewa lub zostaną wykonane pewne rotacje, a wykonywanie pętli
zostaje przerwane.
W pętli wbile jest rozważanych sześć przypadków, ale trzy spośród nich są
symetryczne w stosunku do pozostałych trzech, w zależności od tego czy ojciec
p[x] węzła x jest lewym czy prawym synem dziadka p[p[x]] węzła x, co zostaje
rozstrzygnięte w wierszu 4. W powyższym programie są uwzględnione tylko
przypadki, w których p[x] jest lewym synem swojego ojca. Przyjmujemy istotne
założenie, że korzeń drzewa jest czarny - własność, którą ustalamy w wierszu
18 za każdym razem, gdy kończymy wykonywanie procedury - dzięki temu
p[x] nie jest korzeniem. Stąd wynika, że p[p[x]] istnieje.
Przypadek 1 odróżniamy od przypadków 2 i 3, rozpatrując kolor brata
ojca węzła x, tzn. jego „stryja". W wierszu 5 powodujemy, że y wskazuje na

311
ROZDZIAŁ 14. DRZEWA CZERWONO-CZARNE

2
(a) IS
s 8 y

X 4 '
'. Przypadek I
t

2
(b) IS

4
Przypadek 2
t

7
(c) X 2 IS

.
4 i Przypadek 3

X 2 11

(d)
4 IS

Rys. 14.4. Działanie procedury RB-INSERT.(a) Węzeł x został właśnie wstawiony. 7.arówno x, jak
i jego ojciec p[x] są pokolorowane na czerwono, nie jest więc spełniony warunek (3). Stryj y węzła
x jest czerwony, zachodzi więc przypadek I z treści procedury. Węzły zostają, przekolorowane,
a wskaznik x zostaje przeniesiony wyżej w drzewie, w wyniku czego otrzymujemy drzewo (b).
Znowu x oraz jego ojciec są czerwone, ale tym razem stryj y węrla x jest czarny. Węz.el x jest
prawym synem swego ojca p[x], zachodzi więc przypadek 2. Wykonana zostaje lewa rotatja,
w wynik.uktórej powstaje drzewo przedstawione w punkcie (e). Teraz x jest lewym synem swojego
ojca, zachodzi więc przypadek 3. Wykonanie prawej rotacji daje w wyniku drzewo (d), które jest
poprawnym drzewem c::u;rwono-czamym

stryja węzła x, tj. na węzeł right[p{p[x]]], a w wierszu 6 sprawdzamy kolor


węzła wskazywanego przez y. Jeśli y jest czerwony, to zachodzi przypadek 1.

312
14.3. OPERACJA WSTAWIANIA

W przeciwnym razie zachodzi przypadek 2 lub 3. We wszystkich tych sytuac-


jach dziadek p[p[x]] węzła x jest czarny, ponieważ ojciec (tj. p[x]) jest czerwo-
ny, a własność (3) jest zaburzona tylko między x a p{x].
Sytuacja w przypadku I (wiersze 7-10) jest przedstawiona na rys. 14.5.
Przypadek 1 zachodzi,jeśli zarówno p[x], jak i y są czerwone. Ponieważ _p[p[x]]
jest czarny, możemy więc pokolorować na czarno zarówno _p[x],jak i y (roz-
wiązując problem sąsiadujących ze sobą czerwonych węzłów x i _p[x])oraz
pokolorować p[p[x]] na czerwono, co zapobiega zaburzeniu własności (4). Je-
dyny problem może zaistnieć w sytuacji, kiedy ojciec p[p[x]] jest czerwony.
Wtedy należy powtórzyć pętlę while z węzłem _p[_p[x]]w roli x .

..................
,,,,,,,,,,,,,,,,,,,,,,,,

. ..
( a) A ----
,,

B

r r

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.
N o~_!--@_.
.
__
_
··.a
(b)

A
8
'
u
{ ',
A r
a
•µ a µ
Rys. 14,5. Przypadek I z procedury RB-INSERT. Własność (3) zostaje nBiuszona, ponieważ x oraz
p[x] Uego ojciec) są czerwone. Podejmowane działania nie zaJeżą od tego, czy (a) x jest prawym czy
(b) lewym synem. Każde z poddrzew ar:,fJ,-;,ó i e ma czarny korzeń, a co więcej, każde z nich ma tę
samą czarną wysokość. Kolory niektór~h węzłów zostają zmienione, ale zostaje zachowana włas­
ność (4), Ze każ.da ścieżka biegnąca :z węzła w dół do liścia ma taką samą liczbę czarnych węzłów.
Działanie pętli widie zostaje wznowione z węzłem p[p[x]] w roli x. Jedyne naruszenie własności (3)
może tera.z wystąpić tylko między nowym x, który jest czerwony, a jego ojcem, jeżeli jest również
pokolorowany na czerwono

W przypadkach 2 i 3 węzeł y, który jest stryjem x, ma kolor czarny. Przy-


padki te różnią się tym, że x jest prawym lub lewym synem swojego ojca p[xJ.
Wiersze 12 i 13 dotyczą przypadku 2, który jest zilustrowany (wraz z przypad-
kiem 3) na rys. 14.6. W przypadku 2 węzeł x jest prawym synem. Stosujemy
wtedy lewą rotację i otrzymujemy sytuację jak w przypadku 3 (wiersze 14-16),
w którym węzeł x jest lewym synem. Oba węzły x i p[x] są czerwone, rotacja nie
zmienia więc czarnej wysokości węzłów ani nie narusza własności (4). Niezależ­
nie od tego, czy do przypadku 3 docieramy bezpośrednio, czy przez sytuację
z przypadku 2, kolor węzła y (stryja x) jest czarny, bo w przeciwnym razie

313
ROZDZIAŁ 14. DRZEWA CZERWONO-CZARNE

zaszedłby wcześniej przypadek I. Wykonujemy pewne zmiany kolorów i prawą


rotację, która zachowuje własność (4), po czym nie trzeba już nic robić, bo
żadne dwa czerwone węzły ze sobą nie sąsiadują. Wykonywanie pętli while
zostaje przerwane, ponieważ p[x] ma kolor czarny.

Przypadek 2 Przypadek 3
••••••••••••••.••••••
,....... ,11,, .........
,..,................
;u,,

A y B 8y ' A C

a B ' X A y a y ;;
Y a
Rys. 14.6. Przypadki 2 i 3 z procedury RB-INSERT.Podobnie jak w przypadku I, własność (3) zostaje
naru~zona w przypadku 2 lub 3, ponieważ x oraz jego ojciec p(x} mają jednocześnie kolor czerwo-
ny. Każde z poddrzew a:, /1,y i ,5 ma czarny korzeń oraz tę samą czarną wysokośC. Przypadek
2 zostaje sprowadzony do przypadku 3 za pomocą lewej rotacji, która zachowuje własność (4):
wszystkie ścieżki biegnące z węzła w dół do liścia mają tę samą liczbę czarnych węzłów. W przypa-
dku 3 odbywają się pewne przekolorowania oraz jest wykonywana prawa rotacja, które równie:i:
zachowują własność (4). Wykonywanie pętli while zostaje wtedy przerwane, ponieważ własność (3)
jest już spełniona: nie ma sąsiadujących ze sobą czerwonych węzłów

Jaki jest czas działania procedury RB-INSERT? Ponieważ wysokość drzewa


czerwono~czarnego o n węzłach można ograniczyć przez O(lgn), wywołanie
procedury TREB-lNSERT zajmuje więc O(lg n) czasu. Wykonanie pętli while
zostaje powtórzone tylko wtedy, kiedy zajdzie przypadek 1, ale wówczas
wskaźnik x zostaje przesunięty do góry w drzewie. Liczba wykonań treści pętli
white jest więc ograniczona przez O(lgn). Stąd wynika, że procedura RB-IN-
SERT działa w czasie O(lgn). Co ciekawe, zawsze są wykonywane co najwyżej
dwie rotacje, ponieważ wykonywanie pętli whiJe zostaje przerwane, jeśli tylko
zajdzie jeden z przypadków 2 lub 3.

ZADANIA
14.3-1. W wierszu 2 procedury RB-INSERT właśnie wstawionemu węzłowi x
zostaje przypisany kolor czerwony. Zauważmy, że gdybyśmy pokolorowali
x na czarno, to nie zostałaby naruszona własność (3) drzew czerwono-
-czarnych. Dlaczego więc nie kolorujemy węzła x na czarno?
14.3-2. W wierszu 18 procedury RB-INSERT przypisujemy czarny kolor korze-
niowi. Jaka z tego wynika korzyść?
14.3-3. Narysuj drzewo czerwono-czarne, które powstaje w wyniku wstawie-
nia po kolei elementów 41, 38, 31, 12, 19, 8 do początkowo pustego drze-
wa czerwono-czarnego.
14.3-4. Przyjmijmy, że czarna wysokość każdego z poddrzew ex, P, y, I>,
e z rys. 14.5 i 14.6 wynosi k. Wyznacz czarną wysokość każdego węzła,

314
14.4. OPERACJA USUWANIA

a następnie sprawdź, czy własność (4) jest zachowana przez opisane prze-
kształcenia.
14.3-5. Rozważmy drzewo czerwono-czarne powstałe przez wstawienie n węz­
łów za pomocą procedury RB-INSERT. Wykaź, że jeśli n> 1, to drzewo
ma co najmniej jeden czerwony węzeł.
14.3-6. Wskaż, jak efektywnie zaimplementować procedurę RB-INSERT,jeśli
w reprezentacji drzew czerwono-czarnych nie ma wskaźników do ojca każ­
dego węzła.

14.4. Operacjausuwania
Podobnie jak pozostałe elementarne operacje na drzewie czerwono-czarnym
o n węzłach, usuwanie elementu jest wykonywane w czasie O(lg n). Usuwanie
jest tylko nieco bardziej skomplikowane niż wstawianie węzła.
Aby uprościć obsługę warunków brzegowych, będziemy używać wartow-
nika reprezentującego stałą NIL (patrz str. 242). Dla drzewa czerwono-czar-
nego T wartownik nil[T] jest węzłem o takich samych polach jak wszystkie
inne węzły. Wartością jego pola co/or jest BLACK,a jego pozostałe pola - p,
left, right oraz key - mogą przyjmować dowolne wartości. W drzewie czerwo-
no-czarnym wszystkie wskaźniki do NIL zostają zastąpione wskaźnikami do
wartownika nil[TJ.
Wartownika używamy po to, aby móc traktować węzeł NIL, będący synem
węzła x, jako zwyczajny węzeł, którego ojcem jest x. Można by dodać różnych
wartowników w miejsce każdego NIL w drzewie, tak aby dla każdej wartości
NIL był dobrze określony jej ojciec, ale byłoby to niepotrzebne marnowanie
pamięci. Zamiast tego używamy jednego wartownika nil[T], który reprezen-
tuje wszystkie stałe NIL. Jeśli jednak chcemy manipulować synem węzła x, to
musimy zadbać o to, aby najpierw przypisać wskazanie na x polu p[nil[T]J.
Procedura RB-DELETE powstaje w wyniku niewielkiej przeróbki procedu-
ry TREE-DELETE (patrz podrozdz. 13.3). Po wycięciu usuwanego węzła jest
wywoływana pomocnicza procedura RB-DELETE-FIXUP,która przekolorowu-
je węzły i wykonuje rotacje w celu przywrócenia własności czerwono-czarnych.

RB-DELETE(T, z)
I if left[z] = nil[T] lub right[z]= nil[T]
2 theny+-z
3 else y -TREE-SUCCESSOR(z)
4 if left[y] #c nil(T]
5 dien x - teft[y]
6 else x +- right[y]
7 p[x] - p[y]
-------
315
ROZDZIAŁ 14. DRZEWA CZERWONO-CZARNE

8 if p[y] = nil[T]
9 then root[T] ..._x
10 else if y = /eft[p[y]]
li then left[p[y]]-x
12 else right[p[y]] '"- x
13 ify#z
14 thenkey[z]- key[y]
15 t> Jeśli y ma inne pola, to należy je również skopiować.
16 if color[y] = BLACK
17 tben RB-DELETE-FIXUP(T, x)
18 returny

Procedury TREE-DELETEi RB-DELETEróżnią się w trzech aspektach. Po


pierwsze, wszystkie odniesienia do NIL w proceduu.e TREE-DELETEzostały
w procedurze RB-DELETEzastąpione przez odniesienia do wartownik.a nil[T].
Po drugie, sprawdzenie warunku, czy x jest równe NIL, z wiersza 7 procedury
TREE-DELETEzostało usunięte, a przypisanie p[x] '"- p[y] jest wykonywane
bezwarunkowo w wierszu 7 procedury RB-DELETE.Stąd, jeśli x jest wartow-
nikiem nil[T], to jego polep wskazuje na ojca usuniętego węzła y. Po trzecie,
w wiersz.ach16-17 zostaje wywołana procedura RB-DELBTB-FIXUP, o ile y jest
czarny. Jeżeli y jest czerwony, to własności czerwono-czarne są nadal zachowa-
ne po usunięciu y, ponieważ czarne wysokości węzłów się nie zmieniły oraz
żadne czerwone węzły nie stały się sąsiadujące. Węzeł x przekazywany do pro-
cedury RB-DELETE-FIXUP był albo jedynym synem węzła y przed jego usunię­
ciem (o ile y miał syna innego niż NIL), albo wartownikiem nil[T], jeśli y nie
miał synów. W tym drugim przypadku przypisanie w wierszu 7 daje gwarancję,
że ojciec x jest teraz węzłem, który był poprzednio ojcem y, niezależnie od tego,
czy x jest węzłem wewnętrznym, czy wartownikiem nil[T].
Wykażemy teraz, że procedura RB-DELETE-FIXUP przywraca drzewu wła-
' .
snosc1 czerwono-czarne.

RB-DELETE-FIXUP(T, x)
I while x =Froot[T] i color[x]= BLACK
2 do if x = left[p[x]]
3 then w- right[p[x]]
4 if color[w]= RED
5 then color[w]..._BLACK. t> Przypadek 1
6 co/o,[p[x]]-RED t> Przypadek I
7 LEFT-ROTATE(T, p[x]) t> Przypadek I
8 w- right[p[x]] t> Przypadek I
9 if colo,[left[w]] = BLACK i color[right[w]]= BLACK
10 then color[w]..._RED t> Przypadek 2
14.4. OPERACJA USUWANIA

Il x-p[x] t> Przypadek 2


12 else if color[right[w]]= BLACK
13 then color[left[w]]+- BLACK t> Przypadek 3
14 color[wJ+- RED t> Przypadek 3
15 RIGHT-ROTATE(T, w) t>- Przypadek 3
16 w- ,ight[p[x]] t> Przypadek 3
17 co/o,'(w] - co/o,'(p[x]] t> Przypadek 4
18 color[p[xJJ+- BLACK t> Przypadek 4
19 color[right[w]]+- BLACK t> Przypadek 4
20 LEFT-ROTATE(T,p[x]) t> Przypadek 4
21 x+-root[T] t> Przypadek 4
22 else (tak samo jak część tben
z zamienionymi rolami „right" oraz „left")
23 color[x] +- BLACK.

Jeśli usunięty przez procedurę RB-DELETE węzeł y był czarny, to jego


usunięcie sprawia, że każda ścieżka poprzednio zawierająca y ma o jeden czar~
ny węzeł mniej. Dlatego naruszona zostaje własność (4) w każdym przodku
węzła y. Można naprawić tę sytuację, traktując węzeł x tak, jakby był „nad-
miarowo" czarny. Inaczej mówiąc, umawiamy się, że dodajemy 1 do liczby
czarnych węzłów leżących na każdej ścieżce zawierającej x. Przy takiej inter-
pretacji własność (4) jest spełniona. Jeśli usuniemy czarny węzeł y, to „przeno-
simy" jego „czarną jednostkę" na jego syna. Jedyny problem, jaki może teraz
powstać, polega na tym, że x może się stać „podwójnie czarny", co z kolei
narusza własność (1).
Procedura RB-DELETE-FIXUP dąży do przywrócenia własności (1). W pę­
tli wbile w wierszach 1-22 ma nastąpić przesunięcie nadmiarowych „czarnych
jednostek" w górę drzewa, tak aby: (1) x wskazywał na czerwony węzeł (wtedy
kolorujemy go na czarno w wierszu 23), (2) x wskazywał na korzeń (wtedy
można po prostu „zapomnieć" nadmiarową „czarną jednostkę") lub (3) dało
się wykonać odpowiednie rotacje i przekolorowania.
W pętli wbile wskaźnik. x zawsze wskazuje na czarny węzeł o nadmiarowej
„czarnej jednostce" nie będący korzeniem. W wierszu 2 ustalamy, czy x jest
lewym czy prawym synem p[x]. (Podaliśmy kod dla sytuacji, w której x jest
lewym synem; sytuacja, w której x jest prawym synem - wiersz 22 - jest syme~
tryczna). Zmienna w wskazuje na brata węzła x. Węzeł x jest „podwójnie"
czarny, w nie może więc być równy nil[T]. W przeciwnym razie liczba czarnych
węzłów na ścieżce z p[x] do liścia w (równego NIL) byłaby mniejsza niż liczba
,,czarnych jednostek" na ścieżce z p[x] do x.
Cztery przypadki rozpatrywane w treści procedury RB-DELETE~FIXUP są
pokazane na rys. 14.7. Zanim rozpatrzymy szczegółowo każdy z tych przypad-
ków, zastanówmy się, jak możemy się przekonać, że przekształcenia wykony-

-----------------------~ 317
ROZDZIAŁ 14. DRZEWACZERWONO-CZARNE

Przypadek 1
............. ,,,,.
,,,,,, ...
,,,,...............

I ,1

Ib I
. '
Przypadek 2
.....................................··!I••· Nowe x 8 f

. ,. Przypadek 3
,,,.,
........................................
. '
Nowe w

(d)
.' Przypadek 4
............. ,,,,
,.,,,,,,....................
D '
'

C c'

Nowex = roo/[71

Rys. 14.7. Przypadki rozważane w pętli while procedury RB-DELETE. Najciemniejsze węzły mają
kolor czarny, ciemnosmre mają kolor czerwony, a jasnoszare węzły mogą byi: zarówno czerwone,
jak i czarne; ich kolory są oznaczone przez c i c'. Litery tr, p, ..., { odpowiadają dowolnym
poddrzewom. W każdym przypadku konfiguracja po lewej stronie jest przekształcona na kon-
figurację po prawej stronie przez przekolorowllIUe niektórych węzłów i/lub wykonanie rotacji.
Węzeł wskazywany przez zmienną x jest „podwójnie czarny". Wykonywanie pętli jest kontynuo-
wane tylko po zajściu przypadku 2. (a) Przypadek 1 zostaje sprowadzony do przypadku 2, 3 lub
4 przez zamianę kolorów węzłów B i D oraz wykonanie lewej rotacji. (b) W przypadku 2 nad-
miarowa „cza.ma jednostka" węzła x zostaje przesunięta do góry w drzewie przez pokolorowanie
węzła Dna czerwono i przesunięcie wskaźnika x do węzła B. Jeśli przypadek 2 zachodzi po zajściu
przypadku I, to wykonywanie pętli whllezostaje przerwane, ponieważ c jest kolorem czerwonym.
(c) Przypadek 3 sprowadza się do przypadku 4 przez zamianę kolorów węzłów Ci D oraz wykona-
nie prawej rotacji. (d) W przypadku 4 nadmiarowa „czarna jednostka" węzła x może zostać
usunięta przez przekolorowanie pewnych węzłów oraz wykonanie lewej rotacji (nie naruszając
przy tym własności czerwono-czarnych), po czym wykonywanie pętli zostaje przerwane

318
14.4. OPERACJA USUWANIA

wane we wszystkich tych przypadkach zachowują własność (4). Zasadnicza


obserwacja polega na tym, że w każdym z przypadków liczba czarnych węzłów
między korzeniem (łącznie z korzeniem) przedstawionego poddrzewa a każdym
z poddrzew IX, p, ..., ( jest zachowywana przez przekształcenia. Na przykład na
rys. 14.7a, który ilustruje przypadek 1, liczba czarnych węzłów między korze-
niem a każdym z poddrzew a; lub Pwynosi 3, zarówno przed, jak i po wykona-
niu przekształcenia. (Należy zwrócić uwagę, że x wnosi dwie „czarne jedno-
stki"). Podobnie liczba czarnych węzłów między korzeniem a każdym z pod-
drzew y, ó, e oraz ( wynosi 2 zarówno przed, jak i po wykonaniu przekształce­
nia. Na rysunku 14.7b w obliczeniach musimy uwzględnić kolor c, który może
być zarówno czerwony, jak i czarny. Jeśli 7.definiujemy count(RED) = O
i count(BLACK) = I, to liczba czarnych węzłów między korzeniem a poddrze-
wem IX wynosi 2 + count(c) zarówno przed, jak i po wykonaniu przekształce­
nia. Pozostałe przypadki można sprawdzić w analogiczny sposób (zad. 14.4-5).
Przypadek 1 (wiersze 5-8 procedury RB-DELETE-FIXUP oraz rys. 14.7a)
zachodzi, jeśli węzeł w, brat węzła x, jest czerwony. Węzeł w musi mieć czar-
nych synów, można więc zamienić kolory w i p[xJ, a następnie wykonać lewą
rotację w p[x], nie naruszając przy tym żadnej z własności czerwono-czarnych.
Nowy brat węzła x, jeden z synów w, jest teraz czarny, udało się więc sprowa-
dzić przypadek I do jednego z przypadków 2, 3 lub 4.
Przypadki 2, 3 i 4 zachodzą, jeśli węzeł w jest czarny; różnią się od siebie
tym, jakie kolory mają synowie w. W przypadku 2 (wiersze 10-11 procedury
RB-DELETE-FIXUP i rys. 14.7b) obaj synowie w są pokolorowani na czarno.
Ponieważ w jest również czarny, usuwamy więc po jednej „czarnej jednostce"
z x oraz w, po czym x pozostaje czarny, a w staje się czerwony, za to p[x]
otrzymuje dodatkową „czarną jednostkę". Powtarzamy wtedy pętlę while, tym
razem z p[x] w roli x. Zauważmy, że jeśli dochodzi do przypadku 2 przez
przejście z przypadku 1, to kolor c nowego węzła wskazywanego przez x jest
czerwony, a ponieważ p[x] był czerwony, wykonywanie pętli zostaje więc zaraz
potem przerwane.
Przypadek 3 (wiersze 13-16 i rys. 14.7c) zachodzi, gdy w i jego prawy syn
są czarne, a jego lewy syn jest czerwony. Możemy wtedy zamienić kolory w i je-
go lewego syna left[w], a następnie wykonać prawą rotację na w, nie naruszając
przy tym żadnej z własności czerwono-czarnych. Nowy brat w węzła x jest
teraz czarny, a jego prawy syn czerwony, udało się więc nam przeksztacić
przypadek 3 na przypadek 4.
Przypadek 4 (wiersze 17-21 i rys. 14.7d) zachodzi, gdy brat w węzła x jest
czarny, a prawy syn węzła w jest czerwony. Przez dokonanie pewnych przeko-
lorowań oraz lewej rotacji w węźle p[x] możemy usunąć nadmiarową „czarną
jednostkę" w x, nie naruszając przy tym własności czerwono-czarnych. Przypi-
sanie zmiennej x wskazania na korzeń drzewa powoduje przerwanie wykony-
wania pętli while.

319
ROZDZIAŁ 14. DRZEWA CZERWONO-CZARNE

Jaki jest czas działania procedury RB-DELETE? Wysokość drzewa czerwo-


no-czarnego o n węzłach można ograniczyć przez O(lgn), wobec tego całkowi­
ty koszt czasowy, nie wliczając wywołania procedury RB-DELETE-FIXUP, wy-
nosi O(lgn). W procedurze RB-DELETE-f'IXUP, po zajściu jednego z przypad-
ków I, 3 lub 4, jest wykonywana tylko stała liczba przekolorowań oraz co
najwyżej trzy rotacje. Tylko w przypadku 2 wykonywanie pętli while może być
powtórzone, ale wtedy wskaźnik x przesuwa się w górę drzewa co najwyżej
O(lgn) razy i nie wykonuje się przy tym żadnych rotacji. Procedura RB-DELE-
TE-FIXUP działa zatem w czasie 00gn) i wykonuje co najwyżej trzy rotacje;
całkowity czas działania procedury RB-DELETE wynosi więc także O(lgn).

ZADANIA
14.4-1. Wykaż, że po wykonaniu procedury RB-DELETE korzeń drzewa czer-
wono-czarnego jest zawsze pokolorowany na czarno.
14.4-2. W zadaniu 14.3-3 skonstruowałeś drzewo czerwono-czarne przez wsta-
wianie po kolei elementów 41, 38, 31, 12, 19, 8 do początkowo pustego
drzewa. Narysuj teraz ciąg drzew czerwono-czarnych powstających w wy-
'"niku usuwania elementów w następującej kolejności: 8, 12, 19, 31, 38, 41.
14.4-3. W których wierszach procedury RB-DELETE-FIXUP odczytujemy lub
modyftk.ujemy zawartość wartownika nil[T]?
14.4-4. Uprość treść procedury LEFr-ROTATE, używając wartownika zamiast
NIL oraz drugiego wartownika, który wskazuje na korzeń drzewa.
14.4-5. Dla każdego z przypadków na rys. 14.7 podaj liczbę czarnych
węzłów na ścieżce od korzenia poddrzewa do każdego z poddrzew a, p, ...,
( oraz sprawdź, że odpowiednie przekształcenia nie zmieniają tych liczb.
Jeśli węzeł ma kolor club c', to do symbolicznych obliczeń użyj oznaczeń
count(c) lub count(c').
14.4-6. Załóżmy, że węzeł x został wstawiony do drzewa czerwono-czarnego
za pomocą procedury RB-INSERT, a następnie natychmiast usunięty za
pomocą procedury RB-DELETE. Czy powstałe w wyniku drzewo czerwo-
no-czarne jest takie samo jak początkowe? Odpowiedź uzasadnij.

Problemy
14-1. Trwale zbiory dynamiczne
W czasie wykonywania pewnych algorytmów zachodzi czasami potrzeba zapa-
miętywania starszych wersji zbiorów dynamicznych. Tego typu zbiory nazywa-
my trwałymi. Jednym ze sposobów implementacji zbiorów trwałych jest zapa-
miętywanie całej ich zawartości przy każdej modyfikacji, ale takie postępowa­
nie może drastycznie spowolnić działanie programu i zwiększyć jego zapotrze-
bowanie na pamięć. Postaramy się robić to bardziej efektywnie.

320
PROBLEMY

4 '

3 8 3

2 7 IO 2

(•) (b)

Rys. 14,8. (a) Drzewo poszukiwań binarnych o kluczach 2, 3, 4, 7, 8, JO. (b) Trwałe drzewo BST
powstałe przez dodanie klucza 5, Najnowsza wersja zbioru składa się z węzłów osiągalnych z ko-
rzenia r', a poprzednia wersja zawiera węzły osiągalne z,. Ciemnoszare węzły były dodane przy
wstawianiu klucza 5

Rozważmy zbiór trwały sz


operacjami INSERT, DELETE i SEARCH, re-
prezentowany za pomocą drzewa binarnego jak na rys. 14.8a. Dla każdej wer-
sji zbioru pamiętamy oddzielnie korzeń odpowiadającego mu drzewa. Aby
wstawić klucz 5 do drzewa, tworzymy najpierw nowy węzeł o kluczu 5. Węzeł
ten staje się lewym synem nowego węzła o kluczu 7, ponieważ nie możemy
7lllodyfikować istniejącego węzła o kluczu 7. Podobnie, nowy węzeł o kluczu
7 zostaje lewym synem nowego węzła o kluczu 8, którego prawym synem
zostaje istniejący węzeł o kluczu 10. Nowy węzeł o kluczu 8 zostaje z kolei
prawym synem nowego korzenia r' o kluczu 4, którego lewym synem zostaje
istniejący węzeł o kluczu 3. W ten sposób kopiujemy tylko część drzewa, a po-
zostałe węzły są wspólnie wykorzystywane przez stare i nowe drzewo, co zo-
stało zilustrowane na rys. 14.8b.

(a) Jakie węzły muszą ulec zmianie w ogólnym przypadku, gdy wstawiamy
klucz k do trwałego drzewa poszukiwań binarnych lub usuwamy z niego
węzeł y?
(b) Napisz procedurę PERSISTENT-TREE-INSERT, która dla danego trwałego
drzewa T oraz klucza k wyznacza nowe trwale drzewo T', powstające przez
dodanie k do T. Przyjmij, że każdy węzeł w drzewie ma pola key, left oraz
right, ale nie ma pola wskazującego na ojca. (Patrz również zad. 14.3-6).
(c) Jaka jest złożoność czasowa i pamięciowa Twojej implementacji procedury
PERSJSTENT-TREE-INSERTjako funkcja wysokości h trwałego drzewa po-
szukiwań binarnych T? (Złożoność pamięciowa jest proporcjonalna do
liczby dodanych węzłów).

321
ROZDZIAŁ 14. DRZEWA CZERWONO-CZARNE

(d) Załóżmy, że w każdym węźle znajduje się pole wskazujące na ojca tego
węzła. Wtedy w procedurze PERSISTENT-TREE-INSERT należy wykonać
dodatkowe operacje kopiowania. Wykaż, że w takim przypadku złożoność
czasowa i pamięciowa procedury PERSISTENT-TREE-lNSERT wynosi O(n),
gdzie n jest liczbą węzłów w drzewie.
(e) Jak użyć drzew czerwono-czarnych, aby zagwarantować, żeby pesymistycz-
ny czas wykonywania operacji oraz zużywana pamięć w przypadku opera-
cji wstawiania lub usuwania wynosiły O(lgn).

14.2. Złączanie drzew czenvono-czarnych


Operacja złączania dla danych dwóch zbiorów dynamicznych S 1 i S 2 oraz
elementu x takiego, że dla każdego x 1 ES 1 i x 2 ES 2 zachodzi key[x 1]~
~ key[x] ~ key[x 2 ], wyznacza zbiór S = S 1 u {x} u S 2 • Zajmiemy się teraz im-
plementacją operacji złączania na drzewach czerwono-czarnych.

(a) Dla danego drzewa czerwono-czarnego T jego czarną wysokość zapa-


miętujemy jako atrybut bh[T]. Wykaż, że można aktualizować wartość
tego atrybutu w procedurach RB-INSERT i RB-DELETE, bez potrzeby
przydzielania dodatkowej pamięci, nie zwiększając przy tym ich asym-
ptotycznej złożoności czasowej. Wykaż, że przechodząc drzewo T w dół,
możemy wyznaczyć czarną wysokość każdego kolejno odwiedzanego węzła
w czasie 0(1).

Chcemy zaimplementować operację RB-JOIN(T 1 , x, T2 ), która niszcząc T1


i T2 , konstruuje drzewo czerwono-czarne T= T 1 u {x} u T 2 • Niech n będzie
sumaryczną liczbą węzłów w drzewach T 1 i T2 •

(b) Przyjmij bez zmniejszenia ogólności, że bh{T1] )- hh[T2 ]. Opisz algorytm


działający w czasie O(lgn), wyszukujący czarny węzeł y w T 1 o najwięk­
szym możliwym kluczu spośród węzłów, których czarna wysokość wynosi
bh[T,].
(c) Niech T'Jbędzie poddrzewem o korzeniu wy. Opisz, jak zastąpić TY przez
T'Ju {x} u T 2 w czasie 0(1), zachowując przy tym własność drzewa BST.
(d) Jaki kolor przypisać węzłowi x, aby nie naruszyć własności czerwono-czar-
nych I, 2 i 4? Wskaż, jak w czasie O(lgn) przywrócić własność (3).
(e) Wykaż, że czas działania procedury RB-JoIN wynosi O(lgn).

Uwagi do rozdziału
Pomysł równoważenia drzew poszukiwań przedstawili Adel'son-Vel'skii i Lan-
dis [21, którzy w 1962 r. wprowadzili klasę drzew zwanych „drzewami AVL".

322
UWAGIDO ROZDZIAŁU

Do równoważenia drzew A VL używa się rotacji, lecz modyfikując zawartość


drzewa, trzeba czasem wykonać 00g n) rotacji, aby przywrócić równowagę
w drzewie o n węzłach. Inną klasą drzew wyszukiwań są tzw. ,,2-3 drzewa",
wprowadzone przez J. E. Hopcrofta (praca nie opublikowana) w 1970 r. Zró-
wnoważenie w 2-3 drzewie utrzymuje się przez działania na stopniach węzłów
drzewa. W ro7.dziale 19 omówimy uogólnienie 2-3 drzew, tj. B-drzewa wpro-
wadzone przez Bayera i McCreighta [18].
Drzewa czerwono-czarne zostały wynalezione przez Bayera [17], który na-
zywał je „symetrycznymi binarnymi B-drzewami". Guibas i Sedgewick [93)
zbadali szczegółowo ich własności i wprowadzili kolorowanie węzłów na czar-
.
no 1 czerwono.
Spośród wielu innych wariantów zrównoważonych drzew binarnych naj-
ciekawsze wydają się „samoorganizujące się" drzewa typu splay, wprowadzo-
ne przez Sleatora i Tarjana [l 77J. (Dobry opis tych drzew można znaleźć
w pracy Tarjana [188]). W drzewach typu splay równoważenie nie odbywa
się według jakiegoś jawnego kryterium, takiego jak kolor w drzewach czer-
wono-czarnych. Zamiast tego w czasie każdej operacji wyszukiwania wyko-
nywana jest operacja „rozchylania" (na którą składają się rotacje). Koszt za-
mortyzowany (patrz rozdz. 18) każdej operacji na drzewie o n węzłach można
ograniczyć przez O(lgn).
Rozdział 15

Wzbogacaniestrukturdanych

W pewnych praktycznych sytuacjach wystarczy zastosować „podręcznikową"


strukturę danych - na przykład listę dwukierunkową, tablicę z haszowaniem
lub drzewo poszukiwań binarnych - ale zwykle trzeba wykazać się jakąś dozą
pomysłowości. Z kolei raczej rzadko zdarza się, że programista musi utworzyć
zupełnie nowy typ struktury danych. Najczęściej wystarczy zaadaptować książ­
kową strukturę danych do konkretnego zastosowania, wzbogacając ją o doda-
tkowe atrybuty, w których są pamiętane pomocnicze informacje. Następnie
należy zaprojektować nowe operacje na tak zmodyfikowanej strukturze da-
nych, niezbędne w jej nowym zastosowaniu. Adaptacja struktury danych nie
zawsze jest łatwa, ponieważ pomocnicze informacje przechowywane w struk-
turze muszą być poprawnie aktualizowane i zachowywane przez standardowe
operacje na tej strukturze.
W tym rozdziale omówimy dwie struktury danych powstałe przez wzbo-
gacenie drzew czerwono-czarnych. W podrozdziale 15.l opiszemy strukturę
danych umożliwiającą wyznaczanie statystyk pozycyjnych na zbiorze dyna-
micznym. W takiej strukturze możemy szybko wyszukiwać i-ty co do wielkości
element w zbiorze lub pozycję danego elementu w liniowym uporządkowaniu
całego zbioru. W podrozdziale 15.2 w bardziej ogólny sposób zajmiemy się
zagadnieniem wzbogacania struktury danych oraz przedstawimy twierdzenie,
które może uprościć adaptowanie drzew czerwono-czarnych. W podrozdziale
15.3 użyjemy tego twierdzenia przy projektowaniu struktury danych do za-
pamiętywania zbioru przedziałów na prostej. Dla zadanego przedziału będzie­
my w stanie szybko wyszukać przedział ze zbioru, który ma z nim niepustą
część wspólną.

3•~2~4------------------------
15.1. DYNAMICZNE STATYSTYKI PDZVCYJNE

15.1. Dynamiczne
statystyki
pozycyjne

W rozd7iale 10 wprowadziliśmy pojęcie statystyki pozycyjnej. W szczególności


i-ta statystyka pozycyjna zbioru n-elementowego, gdzie ie{I, 2, ..., n}, jest po
prostu i-tym co do wielkości elementem zbioru według porządku liniowego
w zbiorze kluczy. Przekonaliśmy się tam, że każdą statystykę pozycyjną można
wyznaczyć w zbiorze nieuporządkowanym w czasie O(n). W tym podrozdziale
dokonamy modyfikacji drzew czerwono-czarnych, która umożliwi wyznacza-
nie dowolnej statystyk.i pozycyjnej w czasie O(lgn). Pokażemy również, jak
wyznaczać rangę elementu (tj. numer jego pozycji w liniowo uporządkowanym
zbiorze) w czasie O(lgn).

sue

Rys. 15.1. Drzewo statystyk pozycyjnych powstałe przez wzbogacenie drzewa czerwono-czarnego.
2.aczemione węzły mają kolor czarny, a jasnoszare - czerwony. Kamy węzeł x ma dodatkowe pole
size[xJ zawierające liczbę węzłów w poddrzewie o korzeniu w wężle x

Struktura danych umożliwiająca szybkie wyszukiwanie statystyk pozycyj-


nych jest pokazana na rys. 15.1. Drzewo statystyk pozycyjnych T jest drzewem
czerwono-czarnym, w którym z każdym węzłem są związane pewne pomoc-
nicze informacje. Oprócz pól występujących w każdym węźle x zwykłego drze-
wa czerwono-czarnego, tj. key[x], color[x], p[x], left[x] i right[x], znajduje się
jeszcze pole size[x]. Zapamiętywana jest w nim liczba (wewnętrznych) węzłów
w poddrzewie o korzeniu w x (włączając x), tj. rozmiar tego poddrzewa. Jeśli
zdefiniujemy size(NIL] jako O, to zachodzi tożsamość

dze[xJ - size[left[xJJ + .vize[righ~xJ


J+ I

(Aby poprawnie obsługiwać warunek brzegowy dla wartości NIL, w konkretnej


implementacji możemy wykonywać jawne porównanie z NIL przed każdym
odwołaniem do pola size lub podobnie jak w podrozdz. 14.4 użyć wartownika
nil[T] zamiast stałej NIL, przy czym size[nil[T]] = O).
--------·-·--------
325
ROZDZIAŁ 15. WZBOGACANIE STRUKTUR DANYCH

Wyznaczanieelementu o zadanejrandze
Zanim opiszemy, jak aktualizować informacje o rozmiarze poddrzew w trakcie
wstawiania i usuwania elementów, przyjrzyjmy się, w jaki sposób można te
informacje wykorzystać przy obliczaniu dwóch rodzajów statystyk pozycyj-
nych. Najpierw zajmiemy się implementacją procedury OS-SELECT(x, i), która
wyznacza wskaźnik do węzła zawierającego i-ty co do wielkości klucz w pod-
drzewie o korzeniu w x. Wywołanie procedury OS-SELECT(root[T],i) powodu-
je znalezienie i-tego co do wielkości klucza w drzewie statystyk pozycyjnych T.

0S-SELECT(x, i)
1 r ~ size[left[x]] + 1
2 ifi=r
3 then return x
4 elseif i < r
5 then returnOS-SELECT(left[x],i)
6 else returnOS-SELECT(righl[x],i - r)

Zasada działania procedury OS-SELECTjest podobna do tej z algorytmu


selekcji z rozdziału 10. Wartość size[left[x]] określa liczbę węzłów z poddrzewa
o korzeniu w x, które występują wcześniej niż x w porządku in order. Stąd
size[left[x]]+ 1 jest rangą elementu x w poddrzewie o korzeniu w x.
W wierszu 1 procedury OS-SELECT obliczamy r, tj. rangę elementu
x w poddrzewie o korzeniu w węźle x. Jeśli i= r, to element x jest i-tym co do
wielkości elementem; w wierszu 3 przekazujemy więc x jako wartość wywoła­
nia procedury. Jeśli i< r, to i-ty co do wielkości element znajduje się w lewym
poddrzewie węzła x; szukamy go więc tam rekurencyjnie w wierszu 5. Jeśli
i > r, to i-ty co do wielkości element leży w prawym poddrzewie węzła x.
W poddrzewie o korzeniu w x znajduje się r elementów, które leżą wcześniej
niż x w porządku in order, i-ty co do wielkości element w poddrzewie o korze-
niu w x jest więc jednocześnie (i - r)-tym co do wielkości elementem w pod-
drzewie o korzeniu w węźle right[x]. Ten element zostaje wyznaczony rekuren-
cyjnie w wierszu 6.
Aby się przekonać, jak działa procedura OS-SELECT, rozważmy przykła­
dowo wyszukiwanie 17-tego co do wielkości elementu w drzewie statystyk po-
zycyjnych przedstawionym na rys. 15.1. Rozpoczynamy od i= 17 oraz ze
zmienną x wskazującą na korzeń, w którym znajduje się klucz 26, Rozmiar
lewego poddrzewa korzenia wynosi 12, ranga klucza 26 jest więc równa 13,
Stąd wnioskujemy, że element o randze 17 jest 17 -13 = 4 (czwartym) co do
wielkości elementem w prawym poddrzewie korzenia. Po rekurencyjnym wy-
wołaniu mamy sytuację, w której x wskazuje na węzeł o kluczu 41, a i= 4,
W lewym poddrzewie x znajduje się 5 węzłów, wobec tego x ma w poddrzewie,

326
15.1. DYNAMICZNE STATYSTYKI POZVCYJNE

którego jest korzeniem, rangę 6. Stąd wynika, że węzeł o randze 4 jest czwar-
tym co do wielkości elementem w lewym poddrzewie. Po rekurencyjnym wy-
wołaniu x wskazuje na węzeł o kluczu 30 i randze 2 w poddrzewie. Wyszukuje-
my więc rekurencyjnie 4 - 2 = 2 (drugi) element w poddrzewie o korzeniu
w węźle zawierającym klucz 38. Lewe poddrzewo ma teraz rozmiar I, co ozna-
cza, że x jest drugim co do wielkości elementem. Dlatego wartością wyznaczo-
ną przez procedurę OS-SELECT jest wskaźnik do węzła o kluczu 38.
Każde rekurencyjne wywołanie procedury powoduje przejście o jeden po-
ziom niżej w drzewie statystyk pozycyjnych, całkowity czas działania procedu-
ry OS-SELECT jest zatem co najwyżej proporcjonalny do wysokości drzewa.
Ponieważ jest to drzewo czerwono-czarne, jego wysokość wynosi O(lg n), gdzie
n jest liczbą węzłów. Czas działania procedury OS-SELECTna n-elementowym
zbiorze dynamicznym można więc ograniczyć przez O(lgn).

Wyznaczanie rangi elementu


Dla danego wskaźnika do węzła x w drzewie statystyk pozycyjnych T, proce-
dura OS-RANK wyznacza pozycję elementu x w liniowym porządku inorder
w drzewie T.

OS-RANK(T,x)
I r +- size[left[x]] + I
2 y+-x
3 while y i=-root[T]
4 do if y - right[p[y]]
5 then r - r + size[/eft[p[y]]] + I
6 y-p[y]
7 return r

Procedura OS-RANK działa w taki oto sposób. Ranga węzła x to, inaczej
mówiąc, liczba o jeden większa od liczby węzłów, które poprzedzają x przy
przechodzeniu drzewa metodą inorder. Utrzymywany jest następujący nie-
zmiennik: na początku pętli while, w wierszach 3-6, r jest rangą elementu key[x]
w poddrzewie o korzeniu w węźle y. Niezmiennik ten jest zachowywany w taki
o to sposób, W wierszu 1 przypisujemy zmiennej r rangę elementu key[x]
w poddrzewie o korzeniu w x. Przypisujący+- x w wierszu 2, sprawiamy, że
niezmiennik jest spełniony za pierwszym razem, gdy sprawdzamy warunek
w wierszu 3. W każdej iteracji pętli while rozważamy poddrzewo o korzeniu
w p[y]. Policzyliśmy już liczbę węzłów w poddrzewie o korzeniu w węźle y,
które poprzedzają x przy przechodzeniu drzewa metodą inord.er, musimy więc
do tego dodać liczbę węzłów w poddrzewie, którego korzeniem jest brat węzła
y oraz dodać I, jeśli p[y] też poprzedza x. Jeśli y jest lewym synem, to ani p[y],

---·
327
ROZDZIAŁ 15. WZBOGACANIE STRUKTUR DANYCH

ani żaden węzełw prawym poddrzewie p[y] nie poprzedza x, zatem nic nie
dodajemy do r. W przeciwnym razie y jest prawym synem i wszystkie węzły
w lewym poddrzewie p[y] poprzedzają x, jak również p[y]. Dlatego w wierszu
5 dodajemy size{left[y]] + 1 do bieżącej wartości r. Przypisując y....-p[y] spra-
wiamy, że niezmiennik znowu jest spełniony przed kolejną iteracją pętli.
Dla y = root[T] procedura wymacza wartość r, która jest równa randze ele-
mentu key[x].
Dla przykładu prześledźmy wykonanie procedury OS-RANK na drzewie
statystyk pozycyjnych z rys. 15.1 przy wyznaczaniu rangi elementu o kluczu
38. Oto wartości key[y] oraz r na początku pętli while w kolejnych iteracjach:

Iteracja key[y] r
I 38 2
2 30 4
3 41 4
4 26 17

Wymaczona zostaje ranga 17.


Każda iteracja pętli while wymaga czasu 0(1), a y przesuwa się w każdej
z nich o jeden poziom w górę drzewa, wobec tego pesymistyczny czas działania
procedury OS-RANK jest nie większy niż wysokość drzewa, tj. O(lg n) dla drze-
wa statystyk pozycyjnych o n węzłach.

Aktualizowanie rozmiarów poddrzew


Jeśli w każdym węźle znajdują się poprawnie wypełnione pola size, to za pomo-
cą procedur OS-SELECT oraz OS-RANK można szybko obliczać statystyki po-
zycyjne. Jeśli jednak nie potraftmy efektywnie poprawiać tych wartości pod-
czas wykonywania prostych operacji na drzewach czerwono-czarnych, to cała
nasza praca byłaby daremna. Wykażemy więc teraz, że ro2'llliary poddrzew
można efektywnie aktualizować zarówno podczas wstawiania, jak i usuwania
elementów z drzewa (dokładniej, aktualizacja rozmiarów poddrzew nie wpły­
wa na asymptotyczną złożoność tych operacji).
Z podrozdziału 14.3 wiadomo, że operacja wstawiania do drzewa czerwo-
no-czarnego składa się z dwóch etapów. W pierwszym etapie przebiegamy
drzewo w dół, począwszy od korzenia, oraz wstawiamy nowy węzeł jako syna
jednego z istniejących już węzłów. W drugim etapie przebiegamy drzewo z po-
wrotem w górę, zmieniając przy tym w razie czego kolory, a na koniec wyko-
nując, być może, pewne rotacje, aby przywrócić własności czerwono-czarne.
Aktualizacja rozmiarów poddrzew w pierwszym etapie polega po prostu
na dodawaniu 1 do .rize{x] dla każdego węzła x na ścieżce przebiegającej od
korzenia w stronę liści. Pole size dla nowo wstawionego węzła należy zainic-

328
15.1. DYNAMICZNE STATYSTYKI POZVCYJNE

jować wartością I. Na ścieżce, po której przebiega algorytm w pierwszym eta-


pie, jest co najwyżej O(lgn) węzłów, dodatkowy koszt aktualizacji pól size
wynosi więc O(lgn).
W drugim etapie jedyne zmiany w strukturze drzewa są powodowane
przez rotacje (co najwyżej dwie). Rotacje są operacjami lokalnymi: mogą naru-
sz.yć poprawność pól size tylko w dwóch sąsiadujących ze sobą węzłach, wokół
których odbywa się rotacja. Do treści procedury LEFr-ROTATE(T, x) z pod-
rozdz. 14.2 dodajemy następujące wiersze:

13 size[y]+--size{x]
14 size[xJ~ size[left[xJJ+ size[right[xJJ+ I

Na rysunku 15.2 widać poprawki, które należy wykonać. Zmiana potrzeb-


na w procedurze RIGHT-ROTATEjest analogiczna.

RIGHT.ROT ATE(T. y)
...................
,.,,................
,.,1,,,
,,,1,••,.........................._.•••••••.•
LEFr-RoT ATF(T. x)
,, "
I
/4,

Rys. 15.2. Aktualizacja rozmiarów poddrzew w czasie rotacji. Jedyne dwa pola, które trzeba za"
ktualizować, przylegają do krawędzi, wokół której jest wykonywana rot.acja. Zmiany mają charak-
ter lokalny, do ich przeprowadzenia potrzebne są tylko wartości pól size węzłów x, y oraz korzeni
poddrzew oznaczonych przez tróJkąty

W czasie wstawiania nowego elementu do drzewa czerwono-czarnego są


wykonywane co najwyżej dwie rotacje, aktualizacja wartości pól size w drugim
etapie wymaga więc co najwyżej 0(1) dodatkowego czasu. Stąd wynika, że
całkowity czas potrzebny do wstawienia elementu do drzewa statystyk pozy-
cyjnych o n węzłach jest O(lgn), czyli asymptotyc.:mie taki sam jak czas wsta-
wiania do zwykłego drzewa czerwono-czarnego.
Operację usuwania z drzew czerwono-czarnych także można podzielić na
dwa etapy: w pierwszym usuwamy element z drzewa poszukiwań, a w drugim
wykonujemy co najwyżej trzy rotacje, bez żadnych innych zmian w strukturze
drzewa (patrz pod.rozdz. 14.4). W pierwszym etapie usunięty zostaje z drzewa
węzeł y. W celu zaktualizowania rozmiarów poddrzew wystarczy po prostu
przejść po ścieżce od węzła y do korzenia, odejmując 1 od pola size każdego
węzła na tej ścieżce. Długość tej ścieżki nie przekracza O(lgn) w drzewie czer-
wono-czarnym o n węzłach, dodatkowy czas potrzebny na aktualizację pól size
w pierwszym etapie wynosi więc O(lgn). Zmiany wprowadzone przez stałą
liczbę rotacji w drugim etapie można naprawić podobnie jak w przypadku

329
ROZDZIAŁ 15. WZBOGACANIE STRUKTUR DANYCH

wstawiania. Wykazaliśmy więc, ze zarówno wstawianie, jak i usuwanie, włą­


czając aktualizację pól size, działają w czasie O(lg n) na drzewie statystyk pozy-
cyjnych o n węzłach.

ZADANIA

15.1-1. Opisz działanie procedury OS-SELECT(T, 10) na drzewie czerwono-


-czarnym Tz rys. 15.1.
15.1-2. Opisz działanie procedury OS-RANK(T, x) na drzewie czerwono-c.zar-
nym z rys. 15.2, gdzie x jest takie, że key[x] = 35.
15.1-3. Napisz nierekurencyjną wersję procedury OS-SELECT.
15.1-4. Napisz rekurencyjną procedurę OS-KEY-RANK(T, k), która dla dane-
go drzewa statystyk pozycyjnych T oraz klucza k wyznaci.a rangę
kw zbiorze dynamicznym reprezentowanym przez T. Możesz przyjąć zało­
żenie, że klucze w T są parami różne.
15.1-5. Jak wyznaczyć i-ty następnik zadanego węzła x w drzewie statystyk
pozycyjnych w czasie O(lgn), gdzie n oznacza rozmiar drzewa?
15.1-6. Zauważ, że ilekroć odnosimy się do pola size w procedurach OS-SE-
LECT lub OS-RANK jego wartość służy jedynie do obliczenia rangi
x w poddrzewie o korzeniu x. Załóżmy więc, że w każdym węźle pamięta­
my po prostu jego rangę w poddrzewie, którego jest korzeniem. Wyjaśnij,
jak aktualizować tę wielkość w czasie operacji wstawiania i usuwania ele-
mentów. (Pamiętaj, że te operacje mogą wymagać wykonania rotacji).
15.1-7. Jak użyć drzewa statystyk pozycyjnych do obliczenia liczby inwersji
(patrz problem 1-3) w tablicy o rozmiarze n w czasie O(nlgn).
* 15.1-8. Rozważmy n cięciw okręgu (każda z nich jest wyznaczona przez swoje
końce). Zaprojektuj algorytm działający w czasie O(n lg n) obliczający licz-
bę par cięciw, które przecinają się wewnątrz okręgu. (Jeśli na przykład
wszystkich n cięciw to średnice przecinające się w środku okręgu, to po-

prawną odpowiedzią jest(;)). Możesz pr.zyjąć, że żadne dwie cięciwy nie


mają tego samego końca.

15.2. Jak wzbogacać strukturę danych


Przy projektowaniu algorytmów dość często przeprowadza się wzbogacanie
prostej struktury danych w celu przystosowania jej do wykonywania dodat-
kowych zadań. Użyjemy tej metody w następnym podrozdziale, projektując
strukturę danych dla przedziałów. W tym podrozdziale prześledzimy czynno-
ści, jakie należy wykonać w procesie takiego wzbogacania. Udowodnimy także
twierdzenie, które w wielu sytuacjach ułatwia wzbogacanie drzew czerwono-
-czarnych.
=~-----------·--------------------
330
15.2. JAK WZBOGACAC STRUKTURĘ DANYCH

Wzbogacanie struktury danych można zrealizować w czterech krokach;


są to:
1. Wybranie podstawowej struktury danych.
2. Wyznaczenie pomocniczych informacji, jak.ie należy przechowywać w pod-
stawowej strukturze danych.
3. Sprawdzenie, czy dodatkowe informacje da się poprawnie aktualizować
w czasie wykonywania elementarnych operacji na podstawowej strukturze
danych.
4. Zaprojektowanie nowych operacji,
Jak w każdym tego rodzaju schemacie postępowania, nie zawsze należy ślepo
trzymać się przewidzianych kroków w ustalonej sztywno kolejności. Większość
prac projektowych opiera się po części na metodzie prób i błędów, a postępy
w każdym z kroków są osiągane zwykle mniej lub bardziej równolegle. Nie ma
na przykład sensu ustalanie pomocniczych informacji oraz projektowanie no-
wych operacji (krok.i 2 i 4), jeśli nie będziemy w stanie efektywnie aktualizować
dodatkowych danych. Tak czy inaczej, wykorzystując powyższy schemat zło­
żony z czterech kroków, można skupić wysiłki na istotnych aspektach wzboga-
cania struktury danych; jest to również dobra metoda na zgromadzenie doku-
mentacji na temat wzbogaconej struktury danych.
Projektując drzewa statystyk pozycyjnych w pod.rozdz. 15.1, postępowali­
śmy zgodnie z powyższym schematem. W kroku 1 jako podstawową strukturę
danych wybraliśmy drzewa czerwono-czarne. Argumentem za słusznością wy-
boru drzew czerwono-czarnych jest efektywność operacji, takich jak MINI-
MUM, MAXIMUM, SUCCESSORi PREDECESSOR,na zbiorach dynamicznych.
W kroku 2 wzbogaciliśmy każdy węzeł drzewa x o pole size zawierające
rozmiar poddrzewa o korzeniu w x. Pomocnicze informacje umożliwiają zwyk-
le bardziej optymalną implementację nowych operacji. Moglibyśmy na przy-
kład zaimplementować procedury OS-SELECTi OS-RANK, wykorzystując tyl-
ko klucze znajdujące się w drzewie, ale wtedy czasu ich działania nie można by
ograniczyć przez O(lgn). Czasami dodatkowe informacje stanowią wskaźniki
(patrz zad. 15.2-1).
W kroku 3 wykazaliśmy, że w czasie operacji wstawiania i usuwania może­
my aktualizować wartości pól size, nie zwiększając przy tym asymptotycznej
złożoności tych operacji (tj. O(lgn)). Należy tak projektować pomocnicze in-
formacje dodawane do struktury danych, aby zmiany potrzebne w czasie ich
aktualizacji były jak najmniejsze. Gdybyśmy na przykład w każdym węźle
przechowywali jego rangę w drzewie, to procedury OS-SELECT i OS-RANK
działałyby szybko, lecz wstawienie nowego elementu pociągałoby konieczność
aktualizacji w każdym węźle drzewa. Jeśli jednak zapamiętujemy w każdym
węźle rozmiary poddrzew, to wstawienie nowego elementu zmienia te wartości
tylko w O(lg n) węzłach.
---- ------------- ----------
331
ROZDZIAŁ 15. WZBOGACANIE STRUKTUR DANYCH

W kroku 4 zaprojektowaliśmy operacje OS-SELECTi OS-RANK. Po to


przecież trudziliśmy się wzbogacaniem struktury danych, aby uzyskać efektyw-
ne implementacje nowych operacji. Czasami, zamiast projektować nowe opera-
cje, używamy pomocniczych informacji, o które wzbogaciliśmy strukturę da-
nych do przyspieszenia działania wcześniej zaimplementowanych operacji
(patrz zad. 15.2-1).

Wzbogacanie drzew czerwono-czarnych


Dla wzbogaconych drzew czerwono-czarnych można udowodnić, że pewne ro-
dzaje dodatkowych informacji można za.wsze aktualizować efektywnie podczas
operacji wstawiania i usuwania, co znacznie upraszcza krok 3. W dowodzie
następującego twierdzenia stosuje się rozumowanie podobne do zastosowane-
go już w podrozdz. 15.1, gdzie wykazaliśmy, że pole size daje się efektywnie
aktualizować w drzewie statystyk pozycyjnych.

TwlERDZENIE 15.1. (Wzbogacanie drzewa czerwono-czarnego)


Niech f będzie dodatkowym polem w każdym z n węzłów drzewa czerwono-
-czarnego T. Załóżmy też, że wartość f w węźle x można obliczyć na podstawie
informacji zawartych w węzłach x, left[x] i right(x], włączając f[left[x]] oraz
f[right[x]J. Możemy wtedy aktualizować wartości f we wszystkich węzłach
drzewa T w trakcie wstawiania i usuwania, nie zwiększając asymptotycznej
złożoności czasowej O(lgn) tych operacji.

DOWÓD
Zasadnicza dla dowodu jest obserwacja, że ZID.ianawartości pola f w węźle
x może wpłynąć tylko na przodków x w drzewie. Oznacza to, że modyfikacja
/lx] może wymusić tylko aktualizacjęf(p{x]] i tak dalej w górę drzewa. Jeśli
ZID.ienionazostaje wartość firoot(T] J, to można zakończyć poprawki, ponie-
waż zawartość żadnego innego węzła nie zależy od nowej wartości w korzeniu.
Wysokość drzewa czerwono-czarnego wynosi O(lgn), zmiana wartości pola
f dowolnego węzła wymaga więc czasu O(Jgn} na akutalizację w węzłach, na
które ta zmiana może wpłynąć.
Wstawianie nowego węzła x do drzewa T można rozbić na dwa etapy
(patrz pod.rozdz. 14.3). W pierwszym etapie x zostaje wstawiony jako syn pew-
nego istniejącego węzła p(xJ. Wartośćfix] można obliczyć w czasie 0(1), ponie-
waż zgodnie z założeniem zależy ona tylko od wartości innych pól samego
elementu x oraz jego synów, ale x nie ma synów. Po obliczeniu flxJ należy
odnutować tę zmianę na ścieżce w górę drzewa. Całkowity czas działania
pierwszego etapu wstawiania wynosi więc O{lgn). Jedyne zmiany w strukturze
drzewa do jakich dochodzi w drugim etapie to rotacje. Rotacja modyfikuje
tylko dwa węzły, zatem calk:owity czas aktualizacji pól f po jednej rotacji wy-

332
15.2. JAK WZBOGACAC STRUKTURĘ DANYCH

nosi O(lgn). Przy wstawianiu wykonujemy co najwyżej dwie rotacje, wobec tego
sumaryczny czas działania operatji wstawiania można ograniczyć przez O(lgn).
Usuwanie można, podobnie jak wstawianie, podzielić na dwa etapy (patrz
podrozdz. 14.4). W pierwszym etapie zmiany mogą wystąpić, gdy usuwany
węzeł zostaje zastąpiony przez swój następnik, a potem gdy usuwany węzeł lub
jego następnik zostaje usunięty z drzewa. Aktualizację wszystkich pól/, na
które może wpłynąć taka zmiana, można wykonać w czasie O(lgn), ponieważ
zmiany w drzewie mają charakter lokalny. Poprawienie struktury drzewa czer-
wono-czarnego w drugim etapie wymaga co najwyżej trzech rotatji, a aktuali-
zację pól/po każdej rotacji można wykonać w czasie O(lgn). Stąd, podobnie
jak w przypadku wstawiania, sumaryczny czas działania operacji usuwania
można ograniczyć przez O(lgn).


W wielu przypadkach, takich jak aktualizatja pól size w drzewach statys-
tyk pozycyjnych, koszt „napraw" po wykonaniu rotatji można ograniczyć
przez 0(1), a nie tylko przez O(lgn), jak w twierdzeniu 15.1. Zadanie 15.2-4
stanowi przykład takiej sytuacji.
ZADANIA

15.2-1. Opisz, jak zaimplementować operacje na zbiorach dynamicznych: MI-


NIMUM,MAXIMUM,SUCCESSORoraz PREDECESSOR,aby na odpowiednio
wzbogaconym drzewie statystyk pozycyjnych ich czas działania wynosił
0(1). Asymptotyczna złożoność pozostałych operacji na drzewach statys-
tyk pozycyjnych nie powinna przy tym ulec zmianie.
15.2-2. Czy czarną wysokość węzłów w drzewie czerwono-czarnym można
utrzymywać jako pole w każdym z węzłów, nie zwiększając asymptotycz-
nej złożoności żadnej z operacji na drzewach czerwono-czarnych? Pokaż,
jak to zrobić lub uzasadnij dlaczego nie można tego zrobić.
15.2-3. Czy głębokość węzłów w drzewie czerwono-czarnym można efektywnie
utrzymywać jako wartość pola każdego z węzłów w drzewie? Pokaż, jak to
zrobić lub uzasadnij dlaczego nie można tego zrobić.
* 15.2-4. Niech ® będzie łączną operacją dwuargumentową, natomiast a do-
datkowym polem w każdym węźle drzewa czerwono-czarnego. Załóżmy,
że w każdym węźle x znajduje się dodatkowe pole / takie, że f1x] =
=a[x 1]®a[x 2 J® ... ®a[x,,J, gdzie x 1 , x 2 , ••• , x 111 to węzły poddrzewa
o korzeniu w x ustawione w porządku in order. Wykaż, że pola/ można
aktualizować w czasie 0(1) po wykonaniu rotacji. Wykorzystaj ten fakt do
uzasadnienia, że pola size po wykonaniu jednej rotacji w drzewie statystyk
pozycyjnych można zaktualizować w czasie 0(1).
* 15.2-5. Chcemy wzbogacić drzewa czerwono-czarne o operację RB-ENUME-
RATE(x, a, b), która wyznacza wszystkie klucze k w drzewie czerwono-

333
ROZDZIAŁ 15. WZBOGACANIE STRUKTUR DANYCH

-czarnym o kor7.eniu x tak.ie, że a~ k ~ b. Wskaż, jak zaimplementować


operację RB-ENUMERATE, aby jej czas działania wynosił E>(m+ lgn), gdzie
m jest liczbą kluczy leżących w zadanym prz.edziale, a n jest liczbą węzłów
wewnętrznych w drzewie. (Wskazówka: Nie potrzeba w tym celu dodawać
żadnych dodatkowych pól do węzłów drzewa czerwono-czarnego).

15.3. Drzewaprzedziałowe
W tym podrozdziale zajmiemy się takim wzbogaceniem drzew czerwono-czar-
nych, aby móc zaimplementować operacje na dynamicznych zbiorach prze-
działów. Przedział domknięty jest uporz.ądkowaną parą liczb rzeczywistych [t1 ,
t 2], gdzie t 1 ~ t 2 • Przedział [t 1 , t 2 ] reprezentuje zbiór {teR:t 1 ~ t ~ t 2 }. Prze-
działy otwarte i jednostronnie otwarte nie zawierają odpowiednio obu albo jed-
nego z końców zbioru. Na potrzeby tego podrozdziału przyjmiemy założenie,
że przedziały są domknięte; łatwo uogólnić wszystkie przedstawione tu wyniki
na przedziały otwarte i jednostronnie otwarte.
Przedziały dobrze nadają się do reprezentowania zdarzeń zachodzących
przez pewien ciągły odcinek czasu. Możemy na przyklad wysunąć zapytanie do
bazy danych zawierającej przedziały, jak.ie zdarzenia zaszły w zadanym prze-
dziale czasu. Struktura danych, którą przedstawimy w tym rozdziale, umoż­
liwia efektywne wykonywanie tego rodzaju operacji.
Przedział [t 1 , tz] można reprezentować jak.o obiekt i o polach /ow[i] = t 1

; ; ;
; . '
. ' ;' ;' '

(•)

; ;' .' ;
'
(b) (,)

Rys. 15.3. Trychotomia przedziałowa dla dwóch domkniętych przedziałów i oraz i'. (a) Jesli i oraz i'
zachodzą na siebie, to zachodzi jedna z czterech sytuacji; w ka Mej z nich spełnione są nierówności
low(i] ~ high(i'] oraz low[i'] ~ high[i]. (b) high[i] < low{i']. (c) high[i'J < /11w{i]

(lewy koniec) oraz high[i] = t 2 (prawy koniec). Dwa przedziały i oraz i' za-
chodzą na siebie, jeśli i n i' # 0, tj. jeśli /ow[i] ~ high[i'] oraz /ow[i'] ~ high[i].
Każde dwa przedziały i oraz i' spełniają dokładnie jeden z trzech następujących
warunków (trychotomia przedziałowa):

334
15.3. DRZEWA PRZEDZIAŁOWE

(1) i oraz i' zachodzą na siebie;


(2) h;gh[;J < low[;'];
(3) h;gh[;'] < low[;].

Na rysunku 15.3 są przedstawione wszystkie trzy możliwości.

Dri:ewo przedziałowe jest drzewem czerwono-czarnym, w którym każdy


węzeł x zawiera przedział int[x]. Na drzewach przedziałowych można wykony-
' . .
wac następujące operacJe.

INTERVAL-INSERT(T,x) dodaje do drzewa przedziałowego T element x, które-


go pole int zawiera pewien przedział.
INTERVAL-DELETE(T, x) usuwa element x z drzewa przedziałowego T
INTERVAL-SEARCH(T, i) wyznacza wskaźnik do takiego elementu x drzewa
przedziałowego T, że przedziały int[ x] oraz i zachodzą na siebie, lub
stalą NIL, jeśli nie ma takiego przedziału w zbiorze reprezentowanym
przez drzewo T.

Na rysunku 15.4 widać przykładowe drzewo przedziałowe reprezentujące


przedstawiony zbiór przedziałów. Do opisu konstrukcji i operacji na drzewach
przedziałowych użyjemy schematu opisanego w podrozdz. 15.2, czyli wykona-
my cztery wymienione tam kroki.

Krok 1: Podstawowa struktura danych


Wybieramy drzewo czerwono-czarne, w którym każdy węzeł x zawiera prze-
dział int[x]; kluczem węzła x jest lewy koniec przedziału, tj. low[int[x]].Po-
rządek inorder na węzłach drzewa odpowiada więc uporządkowaniu przedzia-
łów według lewego końca.

Krok 2: Dodatkowe informacje


Oprócz przedziałów każdy węzeł x zawiera także atrybut max[x], który jest
największą wartością końca przedziału spośród przedziałów znajdujących się
w poddrzewie o korzeniu w x. Prawy koniec każdego przedziału jest nie mniej-
szy niż jego lewy koniec, max[x] jest więc w istocie maksymalną wartością
prawego końca przedziału spośród przedziałów znajdujących się w poddrzewie
o korzeniu w x.

Krok 3: Aktualizacja dodatkowych informacji


Musimy sprawdzić, czy operacje wstawiania i usuwania z drzewa przedziało­
wego można tak zaimplementować, aby działały w czasie O(lgn) na drzewie
o n węzłach. Jeśli dany jest przedział int[x] oraz wartości max dla synów węzła
x, to max[x] można wyznaczyć w następujący sposób:

335
ROZDZIAŁ 15. WZBOGACANIE STRUKTUR DANYCH

max[x] ~ max(high[int[x]], max[left[x]], max[right[x]])

Z twierdzenia 15.1 wynika więc, że wstawianie i usuwanie działają w czasie


O(lgn). Co więcej, jak się można przekonać (patrz zad. 15.2-4 oraz 15.3-1)
aktualizację pól max po wykonaniu rotacji da się przeprowadzić w czasie 0(1).

Krok 4: Projektowanienowychoperacji
Jedyną nową operacją, jakiej potrzebujemy, jest INTERVAL-SEARCH(t, i), która
wyszukuje przedział w drzewie T zachodzący na przedział i lub zwraca NIL,
jeśli takiego przedziału nie ma.

lNTERVAL-SEARCH(T, i)
I x +-- root{t]
2 wbile x 'F-NIL oraz i nie zachodzi na int[x]

261 26
25 JO
I 9 H 20
17 19
16 ·~21
15 ---- s2J
8H9
6 10
5 8
o J
L~
o 5 10 15 20 25 JO
(a)

[8.0!
• · !25,30] '' :
.
1.\ _\(I

lt1Jj
• [6,101 119,20]
" . ., . •· .

Rys. 15.4. Drzewo przedziałowe. (a) Zbiór IO przedziałów, uporządkowany według lewego końca.
(b) Drzewo przedziałowe, które reprezentuje ten zbiór przedziałów. Porządek inorder węzłów tego
drzewa odpowiada upori.ą.dkowaniu przedziałów według ich lewego końca

336
15.3. DRZEWA PRZEDZIAŁOWE

3 do if /eji[x] cf, NIL i max[left[x]];,, low[,]


4 theo x +- /eft[x]
5 else x +- right[x]
6 return X

Na początku zmienna x wskazuje na korzeń, a następnie przebiega w dół


drzewa. Wykonywanie zostaje przerwane, jeśli znaleziony wstał przedział
zachodzący na i albo gdy x osiągnął wartość NIL. Każda iteracja głównej
pętli zajmuje czas 0(1), wysokość drzewa czerwono-czarnego o n węzłach
jest ograniczona przez O(lgn), procedura INTERVAL-SEARCH działa więc
w czasie O(lgn).
Zanim wykażemy poprawność procedury INTERVAL-SEARCH, przyjrzyjmy
się, jak. działa ona na drzewie przedziałowym z rys. 15.4. Załóżmy, że szukamy
przedziału zachodzącego na przedział i= [22, 25]. Na początku x wskazuje na
korzeń, w którym znajduje się przedział [16, 21] nie zachodzący na i. Ponieważ
max{left[x]] = 23 jest większe niż low[i] = 22, wykonywanie pętli zostaje więc
wznowione ze zmienną x wskazującą na lewego syna korzenia, tj. węzeł zawie-
rający przedział [8, 9], który również nie zachodzi na i. Teraz jednak
max[left[x]] = 10 jest mniejsze niż /ow[i] = 22, zatem wykonywanie pętli w-
staje wznowione ze zmienną x wskazującą na prawego syna dotychczasowego
x. Przedział [15, 23] znajdujący się w tym węźle zachodzi na i, wobec tego ten
węzeł zostaje przekaz.any jako wynik działania procedury.
Jak.o przykład wyszukiwania zakończonego porażką posłuży nam próba
znalezienia w drzewie z rys. 15.4 przedziału zachodzącego na i= [11, 14].
Ponownie zaczynamy ze zmienną x wskazującą na korzeń. Przedział znajdują­
cy się w korzeniu, tj. [16, 21], nie zachodzi na i, wobec tego skoro
max{left[x]] = 23 jest większe niż low[i] = 1I, to zmiennej x przypisujemy
wskaźnik na lewego syna x, tj. na wierzchołek zawierający przedział [8,9].
(Zwróćmy uwagę na to, że żaden przedział w prawym poddrzewie nie zachodzi
na i - przekonamy się o tym później). Przedział [8, 9] nie zachodzi na i oraz
max[/eft[x]] = 10 jest mniejsze niż low[i] = 11, wybieramy więc dalej prawe
poddrzewo x. (Zwróćmy uwagę, że żaden przedział w lewym poddrzewie nie
zachodzi na i). Przedział [15, 23] nie zachodzi na i, lewy syn rozpatrywanego
węzła jest równy NIL, wybieramy zatem prawe poddrzewo. Wykonywanie pętli
zostaje przerwane i zostaje wyznaczona wartość NIL.
Aby przekonać się o poprawności procedury INTERVAL-SEARCH, musimy
zrozumieć, dlaczego wystarczy przeanalizować tylko jedną ścieżkę z korzenia
w dół drzewa. Zasadnicza obserwacja polega na tym, że dla każdego węzła x,
jeśli int[x] nie zachodzi na i, to wyszukiwanie zawsze przebiega dalej w bez-
piecznym kierunku: przedział zachodzący na i na pewno wstanie odnaleziony,
jeśli tylko istnieje taki w drzewie. Następujące twierdzenie wyraża tę obserwa-
cję bardziej precyzyjnie.

337
ROZDZIAŁ 15. WZBOGACANIE STRUKTUR DANYCH

TwIERDZENIE 15.2.
Rozważmy dowolną iterację pętli while w czasie wykonywania procedury IN-
TERVAL-SEARCH(T, i).

l. Jeśli zostaje wykonana instrukcja w wierszu 4 (tj. wyszukiwanie kierujemy


w lewo), to lewe poddrzewo węzła x zawiera przedział zachodzący na i lub
żaden przedział w prawym poddrzewie x nie zachodzi na i.
2. Jeśli zostaje wykonana instrukcja w wierszu 5 (tj. wyszukiwanie kierujemy
w prawo), to lewe poddrzewo x nie zawiera żadnego przedziału zacho-
dzącego na i.

DOWÓD
Dowód obu przypadków opiera się na trychotomii przedziałowej. Udowod-
nimy najpierw przypadek 2, ponieważ jest łatwiejszy. Zauważmy, że jeśli zo-
staje wykonana instrukcja w wierszu 5, to z warunku w wierszu 3 wynika, że
left[x] = NJL lub max[/efąx]] < /ow[i]. Jeśli lefąx] = NJL, to poddrzewo o ko-
rzeniu w left{x] z pewnością nie zawiera przedziału zachodzącego na i, bo nie
ma w nim żadnych przedziałów. Załóżmy więc, że left[x] 'F NIL oraz
max[/efąx]] < iow[i]. Niech i' będzie dowolnym przedziałem z lewego poddrze-
wa węzła x (patrz rys. 15.Sa). Największym możliwym końcem prawego prze-
działu z lewego poddrzewa x jest max[left[x]], więc

high[i'] <; max[/eft[x]]


< /ow[i]
skąd wynika, żei' oraz i nie zachodzą na siebie, co kończy dowód przypadku 2.
Udowadniając przypadek J możemy założyć, że żaden przedział w lewym
poddrzewie nie zachodzi na i (bo jeśli jest taki przedział, to teza wynika na-

."
."
'

'
.
'
i' i" •

i' i i' •
'
(•) (b)

Rys. 15.5. Przedziały w dowodzie twierdzenia 15.2. Wartość max(/eft[x]J w obu przypadka.eh jest
oznaczona przerywaną linią. (a) Przypadek2: wyszukiwanie zostaje skierowane w prawo. żaden
przedział i' nie zachodzi na i. (b) Przypadek I: wyszukiwanie zostaje skierowane w lewo. Lewe
poddrzewo węzła x zawiera przedział zachodzący na i (sytuacja nie pokazana na rysunku) lub istnieje
przedział i' w lewym poddrz.ewiex, taki że high(i'J = max(left[x]]. Skoro inie zachodzi.na i', to tym
bardziej nie za.chodzina Zaden prmdział ,~ z prawego poddrzewa, ponieważ low(i'J "low(iPJ

338
15.3. DRZEWA PRZEDZIAŁOWE

tychmiast), pozostaje więc wykazać, że żaden przedział w prawym poddrzewie


x nie zachodzi na i przy powyż.uym założeniu. Zwróć uwagę, że jeśli będzie
wykonana instrukcja w wierszu 4, to z warunku w wierszu 3 wynika nierów-
ność max[left[x]] ~ low[i]. Co więcej, z definicji wartości pola max wynika, że
w lewym poddrzewie x jest taki przedział i', że

high[i'J - maxfleft[xJJ
~ low[i]
(Na rysunku 15.5b znajduje się odpowiednia ilustracja tej sytuacji). Przedziały
i oraz i' nie zachodzą na siebie, skoro więc nie jest prawdą, że highf..i']< low[i],
to z trychotomii przedziałowej wynika, że zachodzi high[i](low[i']. Kluczami
w drzewach przedziałowych są lewe końce przedziałów, wobec tego z własności
drzewa wyszukiwań wynika, że dla każdego przedziału i" z prawego poddrze-
wa węzła x zachodzi

high[iJ< low[i1
~ low[i"J
Z trychotomii przedziałowej wnioskujemy więc, że i oraz i" nie zachodzą
na siebie.


Twierdzenie 15.2 daje gwarancję, że jeśli w procedurze INTERVAL-SEARCH do
dalszych wyszukiwań będzie wybrany jeden z synów węzła x i w rezultacie nie
będzie znaleziony żaden przedział zachodzący na i, to wyszukiwanie w drugim
poddrzewie węzła x będzie równie bezowocne.

ZADANIA
15.3-1, Napisz procedurę LEFT-ROTATE działającą na węzłach drzewa prze-
działowego aktualizującą pola max w czasie 0(1 ).
15.3-2. Zmodyfikuj tak: procedurę INTERVAL-SEARCH, aby działała popraw-
nie, gdy wszystkie przedziały są otwarte.
15.3-3. Zaprojektuj efektywny algorytm, który dla danego przedziału i daje
w wyniku przedział na niego zachodzący o najmniejszym lewym końcu lub
NIL, jeśli taki przedział nie istnieje.
1S.34, Opisz, jak: dla danego drzewa przedziałowego T oraz pr7.edziału i wy-
znaczyć w czasie O(min(n, klgn)) wszystkie przedziały zachodzące na i,
gdzie k jest liczbą tych przedziałów. (Dodatkowo: Podaj rozwiązanie, które
nie wykonuje żadnych modyfikacji w drzewie).
15.3-S. Zaproponuj modyfikacje w procedurach działających na drzewach
przedziałowych umożliwiające wykonywanie operacji INTERVAL-

339
ROZDZIAŁ 15. WZBOGACANIE STRUKTUR DANYCH

-SEARCH-ExACTLY(t, i), która daje w wyniku wskaźnik do węzła


x w drzewie przedziałowym T, taki że /ow[int[x]] = low[i] oraz
high[int[x]] = high[i], lub NJL, jeśli w Tnie ma takiego węzła. Wszystkie
operacje (także nowa lNTERVAL-SEARCH-EXACTLY) powinny działać
w czasie O(lgn) na drzewie o n węzłach.
lS.3-6. Zaproponuj strukturę danych Q dla dynamicznych zbiorów liczb,
w której można wykonywać operację MIN-GAP wyznaczającą odległość
między dwoma najbliższymi sobie liczbami w Q. Jeśli na przykład Q = {l,
5, 9, 15, 18, 22}, to MIN"GAP(Q) daje w wyniku 18 - 15 = 3, ponieważ 15
i 18 są najbliżej siebie położonymi liczbami w zbiorze Q. Zaimplementuj
jak najefektywniej operacje INSERT, DELETE, SEARCH oraz MIN-GAP
i wykonaj analizę ich złożoności czasowej.
* 1S.3-7. W bazach danych o układach VLSI poszczególne podukłady są zwykle
reprezentowane przez prostokąty. Załóżmy, że każdy prostokąt ma boki
równoległe do osi układu współrządnych, można więc go jednoznacznie
opisać przez podanie minimalnych i maksymalnych współrzędnych pozio-
mych i pionowych. Zaprojektuj algorytm działający w czasie O(nlgn),
sprawdzający czy w danym zbiorze n prostokątów są dwa prostokąty za-
chodzące na siebie. Algorytm ten nie musi wyznaczać wszystkich par prze-
cinających się prostokątów, ale powinien wykrywać sytuacje, w których
jeden z prostokątów leży całkowicie wewnątrz innego prostokąta, nawet
jeśli brzegi tych dwóch prostokątów nie mają punku wspólnego. (Wska-
zówka: ,,Zamiataj" zbiór prostokątów od strony lewej do prawej za pomo-
cą prostej pionowej, tzw. ,,miotły").

Problemy
lS-1. Punkt o największej liczbie przecięć
Załóżmy, że w zbiorze przedziałów chcemy mieć dostęp do punktu o najwięk­
szej liczbie przecięć, tj. punktu w którym zachodzi na siebie największa liczba
przedziałów. Opisz, jak: można efektywnie aktualizować punkt o największej
liczbie przecięć podczas wstawiania i usuwania przedziałów.

15-2. PermutacjaJózefa
Problem Józefa definiuje się następująco. Niech n osób stoi w okręgu oraz niech
dana będzie liczba m ~ n. Rozpoczynając od wskazanej osoby, przebiegamy po
okręgu, usuwając co m-tą osobę. Po usunięciu każdej kolejnej osoby odliczanie
odbywa się w nowo powstałym okręgu. Proces ten postępuje, aż zostaną usu-
nięte wszystkie osoby. Porządek, w którym osoby stojące początkowo w okrę­
gu są z niego usuwane, definiuje permutację Józefa typu (n, m) liczb 1, 2, ... , n.
Na przykład permutacją Józefa typu (7, 3) jest (3, 6, 2, 7, 5, l, 4).

340
PROBLEMY

(a) Przyjmij, że m jest stałą. Opisz algorytm działający w czasie O(n), który dla
danej liczby n wypisuje permutację Józefa typu (n, m).
(b) Rozważ sytuację, w której mnie jest ustalone. Zaprojektuj algorytm dzia-
łający w czasie O(nlgn), który dla danych n oraz m wypisuje permutację
Józefa typu (n, m).

Uwagido rozdziału
W książce Preparaty i Shamosa [160} są opisane różne typy drzew przedziało­
wych występujące w literaturze. Do najważniejszych z teoretycznego punk.tu
widzenia należy zaliczyć drzewa wynalezione niezależnie przez H. Edelsbrun-
nera (w 1980 r.) i E. M. McCreighta (w 1981 r.), które w zbiorze n przedziałów
umożliwiają wypisanie w czasie O(k + lgn) wszystkich k przedziałów zacho-
dzących na dany przedział i.
_______ Część IV

Zaawansowane metody
konstruowan
i analizowania
algorytmów
Wprowadzenie
W tej części omówimy trzy ważne metody konstruowania i analizowania efek-
tywnych algorytmów: programowanie dynamiczne (ro7.d.z. 16), algorytmy za-
chłanne (rozdz. 17) oraz analizę kosztu zamortyzowanego (rozdz. 18). We wcześ­
niejszych częściach opisaliśmy inne powszecbnie stosowane metody, takie jak
.,dziel i zwyciężaj", algorytmy probabilistyczne i rozwiązywanie równań reku-
rencyjnych. Nowe metody są bardziej wyrafmowane, choć niejednokrotnie ich
zastosowanie jest niezbędne do uzyskania efektywnych algorytmów. Do zagad-
nień poruszanych w tej części będziemy wracać w dalszych partiach książki.
Programowanie dynamiczne jest metodą stosowaną zwykle w odniesieniu
do problemów optymalizacyjnych. Znalezienie optymalnego rozwiązania ta-
kiego problemu wymaga podejmowania różnych decyzji w obliczeniach. Takie
wybory prowadzą do pod.problemów tego samego typu. Zastosowanie progra-
mowania dynamicznego daje dobre rezultaty, jeśli różne ciągi wyborów mogą
doprowadzić do identycznych podproblemów. Można wtedy zapamiętywać
rozwiązania takich podproblemów, aby ich powtórnie nie obliczać, jeśli wy~
stąpią ponownie w trakcie obliczeń, W rozdziale 16 za pomocą tej prostej
metody algorytmy o złożoności wykładniczej są przekształcane w algorytmy
działające w czasie wielomianowym.
Algorytmy zachłanne, podobnie jak programowanie dynamiczne, są stoso~
wane do problemów optymalizacyjnych, w których osiągnięcie optymalnego
rozwiązania wymaga podejmowania wielu decyzji. W algorytmie zachłannym
są podejmowane decyzje „lokalnie" optymalne. Prostym przykładem takiego
podejścia jest wydawanie reszty: aby 7lllinimalizować liczbę monet składają~
cych się na określoną sumę pieniędzy, wystarczy wybierać za każdym razem
monetę o największym nominale, której dołożenie nie przekroczy wydawanej
sumy. Jest wiele takich problemów, w których metoda zachłanna prowadzi do
optymalnego rozwiązania znacznie szybciej niż rozwiązania oparte na progra~

344
WPROWADZENIE

mowaniu dynamicznym. Nie zawsze jednak łatwo jest stwierdzić, czy zastoso-
wanie algorytmu zachłannego jest rozwiązaniem poprawnym, tzn. czy otrzy-
mane rozwiązanie jest zawsze optymalne. W rozdziale 17 omówimy teorię ma-
troidów, która często jest pomocna przy określaniu poprawności algorytmów
zachłannych. .
Analiza zamortyzowanego kosztu algorytmów służy do szacowania kosztu
algorytmów, w których następują ciągi podobnych operacji. Zamiast oceniać
koszt ciągu operacji, ograniczając koszt każdej z nich z osobna, wykorzystując
analizę kosztu zamortyzowanego możemy lepiej oszacować faktyczny koszt
całego ciągu operacji. Podejście takie może dać istotnie lepsze jakościowo re-
zultaty, ponieważ niejednokrotnie faktyczny koszt wielu pojedynczych operacji
jest znacznie mniejszy niż ich koszt w najgorszym przypadku. Mimo że nie-
które operacje są kosztowne, większość pozostałych może być tania. Analiza
kosztu zamortyzowanego służy nie tylko do analizy algorytmów. Dzięki niej
można inaczej spojrzeć na metody konstruowania algorytmów; projektowanie
i analiza algorytmów są bowiem często ściśle ze sobą powiązane. W rozdziale
18 wprowadzimy trzy równoważne metody analizy kosztu zamortyzowanego
algorytmów.
Rozdział 16

Programowaniedynamiczne

Stosując programowanie dynamiczne, podobnie jak przy korzystaniu z metody


,,dziel i zwyciężaj", rozwiązujemy problemy przez odpowiednie złożenie roz-
wiązań pod.problemów. (.,Programowanie" oznacza w tym kontekście tabela-
ryczną metodę rozwiązywania problemów, a nie pisanie programów kompute-
rowych). Z rozdziału 1 wiemy, że w algorytmach typu „dziel i zwyciężaj" dzieli
się problem na nie7.ależne podproblemy, rozwiązuje je rekurencyjnie, a następ­
nie łączy się rozwiązania wszystkich podproblemów w celu utworzenia roz-
wiązania pierwotnego problemu. Programowanie dynamiczne można stosować
wtedy, kiedy pod.problemy nie są niezależne, tzn. kiedy podproblemy mogą
zawierać te same podpodproblemy. Wtedy algorytm typu „dziel i zwyciężaj"
wykonuje więcej pracy niż to w istocie jest konieczne, wielokrotnie bowiem
rozwiązuje ten sam pod.problem. W algorytmie opartym na programowaniu
dynamicznym rozwiązuje się każdy podproblem tylko raz, po czym zapamiętu­
je się wynik w odpowiedniej tabeli, unikając w ten sposób wielokrotnych ob-
liczeń dla tego samego pod.problemu.
Programowanie dynamiczne jest zwykle stosowane do problemówoptymali-
zacyjnych. W tego typu zagadnieniach możliwych jest wiele różnych rozwiązań.
Z każdym rozwiązaniem jest związana pewna liczba (koszt). Rozwiązanie opty-
malne to takie, które ma optymalny (minimalny lub maksymalny) koszt. Może
być wiele rozwiązań optymalnych, wszystkie o tym samym optymalnym koszcie.
Proces projektowania algorytmu opartego na programowaniu dynamicz-
nym można podzielić na cztery etapy.

1. Scharakteryzowanie struktury optymalnego rozwiązania.


2. Rekurencyjne zdefiniowanie kosztu optymalnego rozwiązania.
3. Obliczenie optymalnego kosztu metodą wstępującą t (ang. bottom-up).

t To maczy rozpoczynając od najmniejszych podproblem6w, rozwiązywać coraz większe,


wykorzystując zapamiętane rozwiązania mniejszych (przyp. tłum.).
16.1. MNOŻENIE CIĄGU MACIERZV

4. Konstruowanie optymalnego rozwiązania na podstawie wyników wcze-


śniejszych obliczeń.

Etapy 1-3 stanowią trzon rozwiązania problemu za pomocą programowa-


nia dynamicznego. Jeśli interesuje nas tylko koszt rozwiązania optymalnego, to
etap 4 można pominąć. Jeśli mimo wszystko wykonujemy etap 4, to często
wygodnie jest zapamiętywać dodatkowe informacje w etapie 3, co niejedno-
krotnie znacznie ułatwia zrekonstruowanie optymalnego rozwiązania.
W następnych podrozdziałach zastosujemy programowanie dynamiczne do
rozwiązania kilku problemów optymalizacyjnych. W podrozdziale 16.1 omówi-
my rozwiązanie problemu polegającego na wybraniu takiej kolejności mnożenia
macierzy, aby liczba potrzebnych mnożeń skalarów była jak najmniejsza. Na
podstawie tego przykładu w pod.rozdz. 16.2 przedstawimy dwie podstawowe
cechy, które musi mieć problem, aby można było go z powodzeniem rozwiązać
za pomocą programowania dynamicznego. W podrozdziale 16.3 opiszemy roz-
wiązanie problemu najdłuższego wspólnego podciągu dwóch ciągów, a w pod-
rozdz. 16.4 metodę programowania dynamicznego zastosujemy do rozwiązania
problemu optymalnej triangulacji wypukłego wielokąta, który jest zadziwiająco
podobny do problemu optymalnego mnożenia ciągu macierzy.

16.1. Mnożenie ciągu macierzy


Jako pierwszy przykład zastosowania programowania dynamicznego rozpa-
trzymy algorytm służący do rozwiązywania problemu optymalnego mnożenia
ciągu macierzy. Mamy dany ciąg n macierzy (A 1, A2 , ••• , An) i chcemy obliczyć
następujący iloczyn:

A,A, ... A, (16.1)


Możemy w tym celu użyć, jako podprogramu standardowego, algorytmu mno-
żenia par macierzy. Wcześniej musimy jednak ustalić, jak umieścić nawiasyt
w tym wielokrotnym iloczynie, aby określić kolejność wykonywania mnożeń.
Iloczyn macierzy ma ustalonenawiasowanie, jeśli jest pojedynczą macierzą albo
jeśli jest iloczynem dwóch iloczynów macierzy o ustalonym nawiasowaniu.
Mnożenie macierzy jest łączne, zatem wartość iloczynu nie zależy od sposobu
ustawienia nawiasów. Na przykład dla ciągu 4 macierzy: (A , A , A , A )
1 2
w iloczynie A A 2 A 3 A.inawiasowanie można ustalić na pięć różnych sposobów:
3 4
1

(A,(A,(A,AJ))
(A,((A,A,)A,))

1
Sposób wnieszczania nawiasów będziemy też określać mianem nawiasowania (przyp. red.).

347
ROZDZIAŁ 16. PROGRAMOWANIE DYNAMICZNE

((A,A,XA,A,))
((A,(A,A,))A,)
(((A,A,)A,)AJ

Sposób ustawienia nawiasów w ciągu macierzy może - jak się okazuje


- znacząco wpłynąć na koszt obliczenia ich iloczynu. Rozpat.Jzmy najpierw
koszt mnożenia dwóch macierzy. Poniższy pseudokod jest zapisem standar-
dowego algorytmu mnożenia macierzy. Atrybuty rows oraz columns oznaczają
odpowiednio liczbę wierszy i kolumn w macierzy.
MATRIX-MULTIPLY(A, B)
1 if columns[A] i, rows(B]
2 tben en-or „niezgodne rozmiary"
3 else for i+- 1 to rows[A]
4 do for j +- 1 to columns[B]
5 doC[i,1]-0
6 for k - 1 to co/umns[A]
7 do C[i,J]-C(i,J] +A[i, k]·B(k,J]
8 return C
Dwie macierze A i B można pomnożyć tylko wtedy, gdy liczba kolumn macie-
rzy A jest równa liczbie wierszy macierzy B. Jeśli A jest macierzą wymiaru
p x q, a B jest macierzą wymiaru q x r, to macierz C będąca wynikiem ich
mnożenia jest macierzą wymiaru p x r. Czas obliczania macierzy C jest z.domi-
nowany przez liczbę skalarnych mnożeń w wierszu 7, która wynosi pqr. Odtąd
czas działania algorytmów mnożenia macierzy będziemy mierzyć liczbą wyko-
nywanych mnożeń skalarnych.
Aby zilustrować, jak bardzo sposób ustawienia nawiasów może wpłynąć
na koszt mnożenia ciągu macierzy, rozważmy ciąg trzech macierzy (A 1, A2,
A3 ). Załóimy, że wymiary tych macierzy wynoszą odpowiednio: 10 x 100,
100 x 5 oraz 5 x 50. Jeśli pomnożymy macierze zgodnie z nawiasowaniem
((A,A,XA,)), to wykonamy 10 · 100 · 5 = 5000 mnożeń skalarnych, aby obliczyć
macierz A 1A2, oraz 10· 5·50 = 2500 mnożeń skalarnych, aby pomnożyć tę ma-
cierz przez A.3, co daje łącznie 7500 mnożeń skalarnych. Jeśli dla odmiany
pomnożymy macierze zgodnie z nawiasowaniem (A 1(A:zA 3)), to wykonamy
100 · 5 · 50 = 25 OOOmnożeń skalarnych, aby obliczyć macierz A 2A 3, oraz
IO· 100 · 50 = 50 OOOmnożeń skalarnych, aby pomnożyć A 1 przez tę macierz,
co daje łącznie 75 OOO mnożeń skalarnych. Obliczenie iloczynu zgodnie z pierw-
szym sposobem ustawienia nawiasów odbywa się zatem 10 razy szybciej.
Problem mnożenia ciągu macierzy można sformułować następująco: dla
danego ciągu n macierzy (A,, A.2, ••• , An>,gdzie dla i= 1, 2, ...• n macierz A; ma
wymiar P;- 1 x P;, należy znaleźć pełne nawiasowanie iloczynu A,A 2 ••• An, dla
którego liczba potrzebnych mnożeń skalarnych jest najmniejsza.

348
16.1. MNOŻENIE CIĄGU MACIERZV

Ile jest możliwych sposobów umieszczenia nawiasów?

Zanim rozwiążemy problem mnożenia ciągu macierzy i.a pomocą programo-


wania dynamicznego, upewnijmy się, że wyczerpujące sprawdzenie wszystkich
możliwych sposobów umieszczenia nawiasów nie stanowi efektywnego algoryt-
mu. Oznac2111yprzez P(n) liczbę różnych nawiasowań ciągu n macierzy. Może­
my podzielić ciąg n macierzy między k-tą a (k + 1)-szą macierzą dla dowolnego
k = 1, 2, ... , n - 1 i w sposób niezależny wstawić nawiasy w dwóch powstałych
podciągach, otrzymujemy więc następujący układ równań rekurencyjnych:

I dlan=l
P(n)- ·-'
L P(k)P(n - k) dla n~ 2
k"' 1

W zadaniu 134 należy wykazać, że rozwiązaniem tego układu równań reku-


rencyjnych jest ciąg liczb Catslana:

P(n) - C(n - I)
gdzie

C(n) - I
n+
(2")
1 n
- !l(4"/n 312 )
Liczba możliwych nawiasowań jest zatem określona i.ależnością wykładniczą
ze względu na n, wobec tego metoda wyczerpującego przeszukiwania wszyst-
kich rozwiązań jest skrajnie nieefektywna jak.o sposób obliczania optymalnego
nawiasowania iloczynu macierzy.

Struktura optymalnego nawiasowania


Pierwszym etapem w metodzie programowania dynamicznego jest scharaktery-
zowanie struktury optymalnego rozwią1-ania. Rozwiązując problem mnożenia
ciągu macierzy, możemy postąpić następująco. Dla wygody oznac7lD.y przez
Ai..j macierz otrzymaną przez wymnożenie macierzy AiA.1 + 1 ... Ap Przy opty-
malnym nawiasowaniu iloczyn A 1A 2 ••• An jest dzielony między Ai: a A1:+1 dla
pewnego całkowitego k z przedziału 1 :=;:;;k < n. Oznacza to, że dla pewnego
k najpierw obliczamy macierze A 1.•k oraz Ak+ i .•n•a następnie mnożymy je przez
siebie, otrzymując Ai..n· Koszt tego optymalnego nawiasowania jest zatem su-
mą kosztu obliczenia macierzy A 1..1:i A1:+1..n oraz kosztu ich mnożenia.
Istotna obserwacja polega na tym, że sposób umieszczenia nawiasów
w podciągu A 1A2 ••. At w optymalnym nawiasowaniu dla A 1A 2 ••• An musi być
optymalnym nawiasowaniem. ciągu A 1A2 .•• At. Dlaczego? Gdyby bowiem ist-

349
ROZDZIAŁ 16. PROGRAMOWANIE DYNAMICZNE

nial sposób umieszczenia nawiasów w ciągu A 1A 2 ... Ak o mniejszym koszcie, to


w połączeniu z optymalnym nawiasowaniem dla A 1A 2 ••• A,, otrzymalibyśmy
nawiasowanie dla A 1A 2 ••• An o koszcie mniejszym niż optymalny - sprzecz-
ność. Podobne rozumowanie prowadzi do wniosku, że nawiasowanie podciągu
Ak + 1Ak + 2 ••• An w optymalnym nawiasowaniu dla A 1A 2 ••• A" jest optymalnym
nawiasowaniem ciągu A.,,.+1Ak+ 2 ••• An.
Optymalne rozwiązanie problemu nawiasowania iloczynu macierzy zawie-
ra więc optymalne rozwiązania pod.problemów tego samego typu. Optymalna
.,pod.struktura" rozwiązania optymalnego jest jednym z koniecznych warun-
ków stosowalności metody programowania dynamicznego, o czym przekona-
my się w pod.rozdz. 16.2.

Rozwiązanie rekurencyjne
Drugim etapem w metodzie programowania dynamicznego jest zdefiniowanie
kosztu rozwiązania optymalnego jako funkcji optymalnych rozwiązań podpro-
blemów. W przypadku problemu nawiasowania iloczynu macierzy jako pod-
problemy występują problemy wyznaczenia optymalnego nawiasowania dla
iloczynów A;A. i ,:::;;j~n.Niech m[i, 11 będzie minimalną
1 + 1 ... A.,. gdzie 1,:::;;
liczbą mnożeń skalarnych, niezbędnych do obliczenia macierzy A, ..1• NajniiSZy
możliwy koszt obliczenia Ai..,. wynosi zatem m[l, n].
Możemy zdefiniować m[i, 11 następująco. Jeśli i= j, to ciąg składa się
z tylko jednej macierzy A 1•.1 = A;, nie trzeba więc wykonywać żadnych dodat-
kowych mnożeń skalarnych. Dlatego m[i, i] = O dla i= 1, 2, ... , n. Aby ob-
liczyć m[i,11 dla i <j, należy wykorzystać strukturę optymalnego rozwiązania
scharakteryzowaną w etapie 1. Za.łóżmy, że optymalne nawiasowanie iloczynu
A,A1+ 1 ... A1 dzieli go między Ak a A.t+ 1, gdzie i~ k <j. Wtedy m[i, 11 jest
równe sumie minimalnych kosztów obliczenia iloczynów A 1•.k i At+ 1..J oraz
pomnożenia ich przez siebie. Ponieważ obliczenie iloczynu macierzy AL.t
i A.,,.+1..J kosztuje Ps-iPkPJskalarnych mnożeń, otrzymujemy następujący wzór:

m[i,j] - m[i, kJ+ m[k + l,J1 + p,_JJ,PJ


W tym równaniu rekurencyjnym. zakładamy, że znamy wartość k, lecz w istocie
nie wiemy, które kjest właściwe. Jest jednak tylkoj- i możliwych wartości k,
a mianowicie k = i, i+ 1, ..., j - 1. Któraś z tych wartości odpowiada op-
tymalnemu nawiasowaniu, wystarczy więc sprawdzić wszystkie i wybrać naj~
lepszą. Otrzymujemy w ten sposób następujący układ równań rekurencyjnych
na minimalny koszt obliczenia iloczynu A 1A 1+ 1 ... A1 :

o dlai=j
(16.2)
m[i,j] - min {m[i, kJ+ m[k + 1, Jl+ p,_JJ,PJ) dla i <j
ł.r;;k<J

350
16.1. MNOŻENIE CIĄGU MACIERZV

Wartości m{i, 11 są kosztami optymalnych rozwiązań pod.problemów. Aby


uprościć rozumowanie, 7.defmiujemy s[i, J1 jak.o tę wartość k, dla której podział
iloczynu AiA-1+ 1 ••• A1 prowadzi do jego optymalnego nawiasowania. Mamy
więc, że s[i, J1 jest równe takiemu k, dla którego zachodzi równość m[i, JJ=
- m[i, kJ + m[k + I, j] + p,_,P,JJt

Obliczanieoptymalnegokosztu
Teraz możemy już łatwo napisać rekurencyjny algorytm oparty na równaniu
(16.2), służący do obliczania minimalnego kosztu m[l, n] mnożenia A 1A2 ... A".
Jak się jednak przekonamy w pod.rozdz. 16.2, ten rekurencyjny algorytm działa
w czasie wykładniczym, nie jest więc wiele lepszy niż algorytm wyczerpującego
sprawdzania wszystkich możliwości nawiasowania iloczynu.
Zauważmy, że - co jest bardzo istotne - mamy tutaj stosunkowo niewiele
pod.problemów: dokładnie jeden podproblem dla każdego wyboru i oraz} ta-

kich, że 1 " i "j " n, czyli w sumie (;) + n = 0(n 2) podproblemów. Algo-
rytm rekurencyjny może napotkać każdy podproblem wielokrotnie w różnych
gałęziach drzewa rekursji. Własność wspólnych podproblemów jest drugim
niezbędnym warunkiem stosowalności programowania dynamicznego.
Zamiast obliczać rekurencyjnie rozwiązanie zależności (16.2), należy
przejść do trzeciego etapu metody programowania dynamicznego i obliczyć
optymalny koszt w sposób następujący. W następującej procedurze zakłada­
my, że macierz A 1 ma wymiar p,_ 1 x p 1, dla i= 1, 2, ... , n. Dane wejściowe
stanowi ciąg (p 0, p 1, ... , Pn>,gdzie /ength[p] = n + 1. W procedurze MATRIX-
-CHAIN-ORDER są używane pomocnicze tablice: m[l „ n, 1 .. n] do zapamięty­
wania kosztów m[i, J] oraz s[l .. n, I .. n] do zapamiętywania odpowiednich
indeksów k, dających optymalny podział przy obliczaniu m[i, j].

MATRIX-CHAIN-0RDER(p)
1 n+- length[p] - l
2 fori+-1 ton
3 do m[i, 11+- O
4 forl+-2ton
5 dofori+-lton-l+l
6 doj+-i+l- l
7 m[i, j] +- oo
8 fork+-itoj-1
9 do q+-m[i, k] +m[k+ l,J1 + Pi-1PkPi
10 if q < m[i,j]
11 then m[i, 11+- q

351
ROZDZIAŁ 16. PROGRAMOWANIE DYNAMICZNE•

12 s[i,11-k
13 return m oraz s

Algorytm ten powoduje wypełnienie tablicy m, rozwiązując problem op-


tymalnego nawiasowania dla coraz dłuższych podciągów oryginalnego ciągu
macierzy. Z równania (16.2) wynika, że m[i,J1, czyli minimalny koszt oblicze-
nia iloczynu j - j + 1 macierzy, x.aleźy tylko od kosztów oblic:zeniailoczynów
ciągów macierzy o długości mniejszej niż j - i + 1. Jest tak, ponieważ dla
k = i, i+ 1, ..., j- 1 macierz A1..kjest iloczynem k - i+ 1 <j - i+ 1 macie-
rzy, a macierz Ak+ 1•.J jest iloczynemj - k <j - i+ 1 macierzy.
W wierszach 2-3 są wykonywane instrukcje m[i, 11 - O dla i= 1, 2, ..., n
(minimalny koszt dla ciągów długości 1). Następnie w trakcie pierwszego wy-

I I I

Rys. 16.1. Tablice mi :sobliczone za pomocą procedury MATRIX-CHAIN-OłlnER dla n = 6 i macierzy


o następujących wymiarach:
Macierz Wymiar
A, 30 X 35
A, 35 X 15
A, 15 X 5
A, 5 X 10
A, 10 X 20
A, 20 X 25
Tablice zostały tak obrócone, aby główna przekątna leżała w poziomie. W tablicy m jest użyta
tylko górna połowa oraz główna pr:zekątna, a w tablicy :stylko górna połowa. Minimalna liczba
mnożen skalarów potrzebna do wymnożenia 6 macierzy wynosi m[l, 6] = 15125. Jednak.owo
pocieniowane pary jasnych pól tablicy są wykorzystywane w wierszu 9 do obliczenia

m[2, 2]+m[3, S]+PHs = 0+2500+35·16·20 = 13 OOO


m[2, 5] = min m(2, 3) + m[4, 5] + PiP:iPi = 2625 + 1000 + 35 · S · 20 = 7125
m[2, 4]+m[5, S]+PiP'-°s = 4375+0+35·10·20 = Il 375

= 7125

352
16.1. MNOŻENIE CIĄGU MACIERZY

konania pętli w wierszach 4-12jest użyty wzór (16.2) do obliczenia m[i, i+ I]


dla i = 1, 2, ... , n - 1 (minimalny koszt dla ciągów długości / = 2). Drugie
wykonanie tej pętli powoduje obliczenie m[i, i+ 2] dla i= I, 2, ... , n - 2 (mi-
nimalny koszt dla ciągów długości / = 3) i tak dalej. W każdym kroku koszt
m[i,J1 obliczany w wierszach 9-12 zależy tylko od wartości m[i, k] i m[k + 1,j],
które zostały wcześniej obliczone.
Na rysunku 16.l widać wyniki działania tego algorytmu na przykładowym
ciągu 6 macierzy. Ponieważ m[i, )] zdefiniowaliśmy tylko dla i :s;; ), obliczone
wartości zajmują tylko część tablicy powyżej głównej przekątnej. Tablica na
rysunku została tak obrócona, aby główna przekątna znajdowała się w po-
ziomie. Ciąg macierzy znajduje się na dole ilustracji. Minimalny koszt m[i, j]
obliczenia iloczynu podciągu AiA-1+ 1 ••• A1 macierzy można odczytać na prze-
cięciu linii biegnącej w prawo do góry z A 1 oraz linii biegnącej w lewo do
góry z AJ' Każdy poziomy wiersz w tablicy na rysunku zawiera koszty od-
powiadające ciągom macierzy o tej samej długości. Procedura MATRIX-
-CłlAIN-ORDER oblicza wartości wierszami od dołu do góry, a w każdym
wierszu od strony lewej do prawej. Wartość m[i,J] jest obliczana na podstawie
iloczynów p 1_ 1pkpi dla k = i, i+ 1, ... , j - I oraz wszystkich wartości w lewo
i w prawo w dół od m[i, j].
Z prostej analizy struktury pętli zagnieżdżonych występujących w proce-
durze MATRIX-CHAIN-ORDER wynika, że algorytm ten działa w czasie O(nl).
Głębokość zagnieżdżenia pętli wynosi 3, a zmienna sterująca każdej pętli (/, i
oraz k) może przyjmować co najwyżej n różnych wartości. W istocie czas dzia-
łania tego algorytmu można także ograniczyć z dołu przez O(n 3 ) (zad. 16.1-3).
Tablice m i s wymagają O(n 2 ) pamięci. Algorytm MATRIX-CHAIN-ORDER jest
więc o wiele bardziej efektywny niż wykładniczy algorytm generujący i spraw-
dzający wszystkie możliwe nawiasowania.

optymalnegorozwiązania
Konstruowanie
Chociaż procedura MATRIX-CHAIN-ORDBR wyznacza optymalną liczbę mno-
żeń skalarnych potrzebnych do policzenia iloczynu ciągu macierzy, jednak nie
podaje jawnie kolejności mnożeń, która pozwala to minimum osiągnąć. Etap
4 metody programowania dynamicznego to konstruowanie optymalnego roz-
wiązania na podstawie wcześniejszych obliczeń.
Do wyznaczenia najlepszej kolejności mnożenia macierzy użyjemy tablicy
s[l .. n, I .. n]. Każde pole s[i,j] zawiera taką wartość k, że optymalne nawiaso-
wanie dla AiA-1+1 ••• AJ dzieli iloczyn między Ak a Ak+i· Stąd wiadomo, że
ostatnim mnożeniem pary macierzy w czasie optymalnego obliczania A 1 n po- „

winno być A 1 „s[l, 111As[I,111+ J ••11• Wcześniejsze mnożenia mogą być odtworzone
rekurencyjnie, ponieważ s[l, s[l, n]] wyznacza ostatnie mnożenie w czasie ob-
liczania A 1 „s[l, li]' a s[s[l, n]+ 1, n] wyznacza ostatnie mnożenie w czasie

353
ROZDZIAŁ 16. PROGRAMOWANIE DYNAMICZNE

obliczania As[I, nl+l .. n· Następująca procedura rekurencyjna oblicza iloczyn


A1..J dla danego ciągu macierzy A= (A 1, A 2, ••• , A,.), tablicy s obliczonej
przez MATRIX-CHAIN-ORDER i indeksów i orazj. Aby obliczyć iloczyn A 1A 2
... A,., należy wywołać tę procedurę następująco: MATRIX-CHAIN-MULTI-
PLY(A,.v, I, n).

MATRIX-CHAIN-MULTIPLY(A,s, i,J)
1 ifj>i
2 then X +-MATRIX-CHAIN-MULTIPLY(A, s, i, s[i, jD
3 Y+-MATRIX-CHAIN-MULTIPLY(A, s, s[i,j] + l,;)
4 return MATRIX-MULTIPLY(X, Y)
5 else return A 1

W przykładzie z rys. 16.1 wywołanie MATRIX-CHAIN-MULTIPLY(A,s, 1, 6)


powoduje obliczenie iloczynu ciągu macierzy zgodnie z nawiasowaniem

((A,(A,A,))((A,A,)A,)) (16.3)

ZADANIA
16.1-1. Wyzna.c:z optymalne nawiasowanie iloczynu ciągu macierzy, których
wymiary stanowią ciąg (5, IO, 3, 12, 5, 50, 6).
16.1-2. Napisz szybki algorytm PRINT-0PTIMAL-PARENSwypisujący optymalne
nawiasowanie iloczynu ciągu macierzy, mając daną tablicę s obliczoną przez
procedurę MATRIX-CHAIN-ORDER.Przeprowadź analizę swego algorytmu.
16.1-3. Niech R(i, j) będzie liczbą odwołań do elementu m[i, j] tablicy m
w procedurze MATRIX-CHAIN-ORDERpodczas obliczania wartości innych
pól tej tablicy. Wykaż, że całkowita liczba odwołań do tablicy m wynosi

" n nl - n
L L R(i,J)- 3
i"'l}=I

(Wskazówka: Możesz skorzystać z następującej tożsamości: L" i2 = n(n +


j= l

+ IX2n + I)/6).
16.1-4. Wykaż, że pełne nawiasowanie n-elementowego wyrażenia zawiera do-
kładnie n - I par nawiasów.

16.2. Podstawymetody programowaniadynamicznego


Przeanalizowaliśmy już szczegółowo przykład zastosowania metody progra-
mowania dynamicznego, Zajmiemy się teraz warunkami, które muszą być speł­
nione, aby metoda ta dawała oczekiwane rezultaty. Z inżynierskiego punk.tu

354
16.2. PODSTAWY METODY PROGRAMOWANIA DYNAMICZNEGO

widzenia jest interesujące, dla jakiego rodzaju problemów programowanie dy-


namiczne jest obiecującą metodą uzyskania rozwiązania w postaci poprawnego
i efektywnego algorytmu, W tym podroz.dziale przedyskutujemy dwie podsta-
wowe cechy, jakie musi mieć problem optymalizacyjny, aby rokował nadzieje
na rozwiązanie go za pomocą programowania dynamicznego: optymalną pod-
strukturę oraz wspólne podproblemy. Zajmiemy się także innym wariantem
ogólnej metody, zwanym spamiętywaniem, w którym wykorzystuje się włas­
ność wspólnych podproblemów.

Optymalna podstruktura
Pierwszym etapem w metodzie projektowania algorytmów dla problemów op-
tymalizacyjnych za pomocą programowania dynamicznego jest scharakteryzo-
wanie struktury optymalnego rozwiązania, Powiemy, że problem wykazuje op-
tymalną podstrukturę, jeśli jego optymalne rozwiązanie jest funkcją optymal-
nych rozwiązań podproblemów. Jeżeli problem ma własność optymalnej pod-
struktury, to można się zwykle spodziewać, że za pomocą metody programo-
wania dynamicznego można będzie znaleźć algorytm do rozwiązania tego pro-
blemu. (Może to także czasem oznaczać, że daje się stosować strategia zachłan­
na. O algorytmach zachłannych trak.tuje rozdz. 17).
W podrozdziale 16.1 stwierdziliśmy, że problem optymalnego nawiasowa-
nia iloczynu ciągu macierzy ma własność optymalnej podstruktury. Zauważyli­
śmy, że optymalne nawiasowanie ciągu A 1A 2 ••• An, które dzieli ten iloczyn
między A;; a AJ:+ 1, zawiera optymalne nawiasowania dla iloczynów A 1A2 ••• A;;
oraz AA:+1AJ:+ 2 ••• An. Metoda, której użyliśmy do pokazania, że rozwiązania
podproblemów są optymalne, jest dość ogólna. Zakładamy najpierw, że ist-
nieje lepsze rozwiązanie podproblemu, po czym pokazujemy, iż to założenie
zaprzecza optymalności rozwiązania całego problemu.
Optymalna pod.struktura problemu sugeruje często odpowiednią prze-
strzeń podproblemów, na której działa programowanie dynamiczne. Zwykle
jest wiele klas podproblemów, które wydają się „naturalne" dla problemu. Na
przykład przestrzenią podproblemów, którą rozpatrywaliśmy dla optymalnego
nawiasowania iloczynu macierzy, były wszystkie spójne podciągi wejściowego
ciągu macierzy. Mogliśmy równie dobrze brać pod uwagę dowolne podciągi
macierzy z ciągu wejściowego, lecz ta przestrzeń podproblemów jest niepo-
trzebnie wielka. Algorytm zbudowany za pomocą metody programowania dy-
namicznego działający w tej przestrzeni podproblemów wykonuje więcej ob-
liczeń, niZ jest to naprawdę potrzebne.
Zbadanie optymalnej podstruktury problemu, przez przeliczenie kilku
przykładów, mo:Ze czasami znacznie ułatwić dobranie odpowiedniej przestrzeni
pod.problemów dla programowania dynamicznego. Na przykład zbadanie opty-
malnej podstruktury problemu optymalnego nawiasowania iloczynu macierzy
ROZDZIAŁ 16. PROGRAMOWANIE DYNAMICZNE

oraz struktury jego podproblemów, podpodproblemów itd. prowadzi do ob-


serwacji, że wszystkie pod.problemy składają się ze sp6jnych podciągów ciągu
(Ap A1, ... , An>· Stąd wybór zbioru ciągów postaci (A;, A 1+ 1, ••• , A1) dla
1 ~ i ~j ~ n daje naturalną, a zarazem rozsądnie małą przestrzeń pod.prob-
lemów.

Wspólne podproblemy
Drugą właściwością problemu optymalizacyjnego wymaganą z punktu widze-
nia stosowalności metody programowania dynamicznego jest właśnie „rozsąd­
nie mała" przestrzeń istotnie różnych pod.problemów. Zwykle liczba wszyst-
kich takich podproblemów jest wielomianowa ze względu na ro2llliar danych
wejściowych. Jeśli algorytm rekurencyjny wielokrotnie oblicza rozwiązanie te-
go samego pod.problemu, to mówimy że problem optymalizacyjny ma włas­
ność wspólnychpod.problemów. Przeciwnie, problemy, dla których właściwe jest
podejście „dziel i zwyciężaj", generują istotnie różne podproblemy w każdym
kroku rekursji. Algorytmy oparte na programowaniu dynamicznym wykorzys-
tują własność wspólnych pod problemów, rozwiązując każdy podproblem tylko
raz i zapamiętując gotowe rozwiązania, które wystarczy później tylko odczytać
w stałym czasie, jeśli podproblem pojawia się w obliczeniach wielokrotnie.
Aby zilustrować własność wspólnych podproblemów, wróćmy raz jeszcze
do problemu optymalnego nawiasowania iloczynu macierzy. Na rysunku 16.l
łatwo zaobserwować, że procedura MATRIX-CHAIN-ORDER wielokrotnie ko-
rzysta z rozwiązań podproblemów w dolnych wierszach do rozwiązania pod-
problemów w wyższych wierszach. Na przykład wartość m[3, 4] jest wykorzys-
tana 4 razy: do obliczenia m[3, 4], m[l, 4], m[3, 5] oraz m[3, 6]. Jeśli m[3, 4]
byłoby obliczane za każdym razem od nowa, to znacznie wzrósłby czas działa­
nia algorytmu. Aby się o tym przekonać, rozważmy następującą (nieefektyw-
ną) procedurę rekurencyjną, obliczającą m[i,J1, czyli minimalną liczbę mnożeń
skalarnych potrzebną do obliczenia iloczynu ciągu macierzy A1..1 = AiA 1 + 1...
... A . Procedura ta jest oparta bezpośrednio na wzorze (16.2).
1

RECURSIVE-MATRIX-CHAIN(p, i, J)
I ifi=j
2 then return O
3 m[i, j] +- oo
4 fork+-itoj-1
5 do q+-RECURSIVE-MATRIX-CHAIN(p, i, k)
+ RECURSIVE-MATRIX-CHAIN(p, k + 1,)) + P1- 1P1<PJ
6 if q < m[i,j]
7 tben m[i, j] +- q
8 returnm[i, j]

356
16.2. PODSTAWY METODY PROGRAMOWANIA DYNAMICZNEGO

1..4

1.,I 2..4 I. .3 4 ..4

2„2 3„4 2..3 4„4 1..1 2..2 3.3 4„4 1..1 2„3 1..2 3 ..3

/1
3..3 4„4
~
2..2 3..3
/1 ~
2..2 3 ..3 1•.1 2..2
Rys. 16.2. Drzewo rekursji dla procedury RECURSIVE-MATRIX-CHAIN(p, I, 4). Każdy węzeł drzewa
jest oznaczony przez parę parametrów i oraz j. Obliczenia wykonywane w zacieniowanych gałę­
ziach drzewa są w wersji ze spamięlywaniem MEMOIZEO-MATRIX-CHAIN(p, I, 4) zastąpione prze2;
odczytanie odpowiedniej wartości z tablicy

Na rysunku 16.2 widać drzewo rekursji powstałe w wyniku wywołań proce-


dury RECURSIVE-MATRIX-CHAIN(p, 1, 4). Każdy węzeł drzewa jest oznaczony
parą parametrów i oraz). Zauważmy że niektóre pary występują wielokrotnie.
W rzeczywistości można pokazać, że czas T(n) potrzebny do obliczenia
m[i, j] przez tę rekurencyjną procedurę jest co najmniej wykładniczy ze wzglę­
du na n. Załóżmy, że wykonanie instrukcji w wierszach 1-2 oraz wierszach 6-7
zajmuje co najmniej jednostkę czasu. Analiza tej procedury prowadzi do na-
stępujących zależności rekurencyjnych:

7\1);, I

T\n);, I + L ·-·
k "' 1
(T\k) + T(n - k) + I) dla n> I

Jeśli zauważymy, że dla i= I, 2, ... , n - 1 każdy składnik T(i) występuje raz


jako T(k) i raz jako T(n - k) oraz wyciągniemy przed znak sumy wszystkie
n - l jedynek, to możemy zapisać powyższą zależność w następujący sposób:
n ... 1
T\n) ;, 2 L T(l) + n (16.4)
I"" 1

Udowodnimy teraz przez indukcję, że T(n) = 0(2"). Pokażemy mianowicie,


że T(n) ~ 211- 1 dla każdego n~ 1. Dla n= 1 ta nierówność oczywiście zacho-
dzi, ponieważ T(l) ~ 1 = 2°. Korzystając z założenia indukcyjnego, mamy dla
n~ 2:

T(n) ;,
·-'
2 L 2•-' +n
i= 1
_________________________ ,,, ___ _
357
ROZDZIAŁ 16. PROGRAMOWANIE DYNAMICZNE

n"" 2
=2I2'+n
I ""O
= 2(2'~, - l) +n
= (2' -2) +n
~ 2n~1

co kończy dowód. Stąd łączny czas wykonywania procedury RECURSIVE-MA-


TRIX-CHAIN(p, 1, n) jest co najmniej wykładniczy ze względu na n.
Porównajmy teraz rekurencyjny algorytm rozwiązujący problem w sposób
zstępujący z algorytmem opartym na programowaniu dynamicznym rozwiązu­
jącym problem w sposób wstępujący. Ten drugi jest efektywniejszy, ponieważ
wykorzystuje własność wspólnych podproblemów. Jest tylko 0(n 2 ) istotnie
różnych podproblemów i algorytm oparty na programowaniu dynamicznym
rozwiązuje każdy z nich dokładnie jeden raz. Z kolei algorytm rekurencyjny
wielokrotnie oblicza rozwiązanie tego samego podproblemu - za każdym ra-
zem, gdy ten podproblem pojawia się w drzewie rekursji. Dlatego zawsze, gdy
drzewo rekursji naturalnego rekurencyjnego algorytmu zawiera wielokrotne
wystąpienia tych samych podproblemów oraz gdy łączna liczba istotnych pod-
problemów jest niewielka, warto spróbować, czy daje się stosować metoda
programowania dynamicznego.

Spamiętywanie

Istnieje odmiana metody programowania dynamicznego, która zapewnia efek-


tywność tej metody przy wykorzystaniu w niej strategii zstępującej. Pomysł
polega na uzupełnieniu naturalnego, choć nieefektywnego, algorytmu rekuren-
cyjnego mechanizmem spamiętywania (ang. memoization). Podobnie jak
w zwyczajnym programowaniu dynamicznym, używamy tu tablicy do zapa-
miętywania rozwiązań podproblemów, lecz zapełniani anie tej tablicy jest wbu-
dowane w algorytm rekurencyjny.
Algorytm rekurencyjny ze spamiętywaniem korzysta z tablicy, w której
przechowuje rozwiązania podproblemów. Każde pole tej tablicy zawiera po-
czątkowo specjalną wartość oznaczającą, że odpowiadający mu podproblem
nie byłjeszc:,.e rozwiązywany. Gdy pod.problem pojawia się w trakcie obliczeń
po raz pierwszy, obliczone rozwiązanie zostaje zapamiętane w odpowiednim
polu tablicy. Każde kolejne wystąpienie tego samego pod.problemu nie wyma-
ga ponownych obliczeń; wystarczy odczytać odpowiednią wartość z tablicy
rozwiązań podproblemów t).

I) Talcie podejście wymaga założenia, że znane są wszystkie parametry podproblemów i jest


uslalona odpowiedniość między polami lablicy a podproblemam.i. Innym rozwiązaniem jest użycie
haszowania z parametrami podprob!emów w roli kluczy.

358
16.2. PODSTAWY METODY PROGRAMOWANIA DYNAMICZNEGO

Następująca
procedura jest wersją procedury RECURSIVE-MATRIX-CHAIN
z wbudowanym mechanizmem spamiętywania.

MEMOIZED-MATRIX-CHAIN(p}
l n+--lengthfp] - 1
2 fori+--lton
3 doforj+-iton
4 do m[i, j] +--oo
5 return LOOKUP-CHAIN(p, 1, n)

LOOKUP-CHAIN(p, i, 1)
I if m[i,JJ < oo
2 then return m[i, j]
3 il i= j
4 tben m[i, j] +--O
5 elsefork+--itoj-1
6 do q +-- LOOKUP-CHAIN(p,i, k)
+ LOOKUP-CHAIN(p, k + 1,1) + P;-1PkPJ
7 if q < m[i,JJ
8 tbenm[i,j]+--q
9 return m[i, j]

Procedura MEMOIZED-MATRIX-CHAIN, podobnie jak MATRIX-CHAIN-


-ORDER, korzysta z tablicy m[l .. n, 1 .. n], w której są zapamiętywane minimal-
ne liczby mnożeń skalarów m[i,j] niezbędne do obliczenia macierzy A1..p Każ­
de pole tej tablicy zawiera początkowo wartość oo, w celu oznaczenia, ż.e właś­
ciwa wartość tego pola nie została jeszcze obliczona. Gdy wywołamy proce-
durę LOOKUP-CHAIN(p, i, 1), wtedy jeśli w wierszu 2 jest spełniony warunek
m[i, j] < oo, to otrzymamy poprzednio obliczony koszt m[i, 11(wiersz 2).
W przeciwnym razie koszt zostaje obliczony podobnie jak w procedurze RECU-
RSIVE-MATRIX-CHAIN,a następnie zapamiętany w polu m[i,j]. (Dogodnie jest
tutaj użyć wartości co do oznaczania nie obliczonych jeszcze elementów, ponie-
waż służy ona jednocześnie do inicjowania elementów m[i, }] w wierszu 3
procedury RECURSIVE-MATRIX-CHAIN). Dzięki temu wywołanie LOOKUP-
-CHAIN(p, i, 1) wyznacza zawsze wartość m[i, j], choć jest ona obliczana tylko
przy pierwszym wywołaniu LOOKUP-CHAINz argumentami i oraz}.
Na rysunku 16.2 widać, ż.e procedura MEMOIZED-MATRIX-CHAINszyb-
ciej wyznacza poszukiwaną wartość niż RECURSIVE-MATRIX-CHAIN,Ozna-
czone szarym kolorem poddrzewa zawierają wartości, których nie trzeba ob-
liczać - wystarczy je tylko odczytać z tablicy.
Podobnie jak algorytm oparty na programowaniu dynamicznym, procedu-
ra MEMOIZED-MATRIX~CHAINdziała w czasie O(n 3). Każde z 0(n 2 ) pól tabli~
cy m zostaje raz zainicjowane w wierszu 4, a następnie raz zmodyfikowane
---··"' ···------------
359
ROZDZIAŁ 16. PROGRAMOWANIE DYNAMICZNE

2
przez jedno wywołanie procedury LOOKUP-CHAIN. Każde z tych @(n ) wywo-
łań LoOKUP-CHAIN zajmuje O(n) jednostek czasu, nie wliczając czasu prze-
znaczonego na obliczanie innych pól tablicy, łączny czas działania wynosi więc
O(n 3). Dzięki spamiętywaniu można miniejszyć złożoność czasową algorytmu
z 0(2") do O(n').
Podsumowując możemy stwierdzić, że problem optymalnego nawiasowa-
nia iloczynu ciągu macierzy można rozwiązać w czasie O(n ) zarówno w spo-
3

sób zstępujący za pomocą algorytmu ze spamiętywaniem, jak i w sposób wstę­


pujący dzięki zastosowaniu algorytmu opartego na programowaniu dynamicz-
nym. W obu podejściach jest wykorzystywana własność wspólnych podprob-
lemów. W sumie jest tylko 0(n 2) różnych podproblemów i oba powyższe al-
gorytmy obliczają rozwiązanie każdego podproblemu co najwyżej jeden raz.
Zwykły algorytm rekurencyjny, nie stosujący spamiętywania, działa w czasie
wykładniczym, ponieważ wielokrotnie rozwiązuje te same podproblemy.
W praktyce, jeśli wszystkie podproblemy muszą być rozwiązane co naj-
mniej jeden raz, to wstępujący algorytm oparty na programowaniu dynamicz-
nym jest zwykle efektywniejszy o stały czynnik od zstępującego algorytmu
rekurencyjnego ze spamiętywaniem, ponieważ odpada dodatkowy koszt zwią­
zany z realizacją rekursji, a koszty obsługi tablicy z rozwiązaniami podprob-
lemów są mniejsze. Jeśli jednak niektóre podproblemy w przestrzeni podprob-
lemów nie muszą być nigdy rozwiązane, to algorytm ze spamiętywaniem może
okazać się szybszy, bo oblicza tylko to, co jest konieczne.

ZADANIA
16.2-1. Porównaj równanie rekurencyjne (16.4) z równaniem (8.4), które wyni-
kło przy analizie średniego czasu wykonania algorytmu quicksort. Wyjaś­
nij intuicyjnie, dlaczego rozwiązania tych równań różnią się tak znacznie.
16.2-2. Który z następujących sposobów obliczania optymalnego nawiasowa-
nia iloczynu ciągu macierzy jest efektywniejszy: wygenerowanie wszystkich
poprawnych nawiasowań iloczynu i obliczenie liczby mnożeń skalarów
potrzebnych w każdym z nich czy wywołanie procedury RECURSIVB-MAT-
RJX-CHAIN? Odpowiedź uzasadnij.
16.2-3. Narysuj drzewo rekursji dla procedury MERGE-SORTz podrozdz. 1.3.1
działającej na tablicy z 16 elementami. Wyjaśnij dlaczego spamiętywanie
nie pomaga przyspieszyć dobrego algorytmu typu „dziel i zwyciężaj", ta-
kiego jak MERGE-SORT.

16.3. Najdłuższy wspólny podciąg


Zajmiemy się teraz problemem najdłuższego wspólnego podciągu. Każdy pod-
ciąg danego ciągu można otrzymać przez usunięcie zeń niektórych elementów

360
16.3. NAJDŁUŻSZY WSPÓLNY PODCIĄG

(albo żadnego). Bardziej formalnie, dla danego ciągu X= (xi, x 2, ••• , xm> inny
ciąg Z= (z 1, z2, ••• , z.,) jest podciągiem X, jeśli istnieje ściśle rosnący ciąg
indeksów (i 1, i2 , ••• , im) taki, że dla wszystkichj = 1, 2, ... , k zachodzi równość
x,i = z1. Na przykład Z= (B, C, D, B) jest podciągiem ciągu X= (A, B, C, B,
D, A, B), a odpowiadający mu ciąg indeksów to (2, 3, 5, 7).
Mówimy, że ciąg Z jest wspólnym podciągiem ciągów X i Y, jeśli Z jest
zarówno podciągiem X, jak i Y. Na przykład dla danych ciągów X= (A, B, C,
B, D, A, B) i Y - (B, D, C, A, B, A) ciąg (B, C, A) jest wspólnym pod-
ciągiem X i Y. Ciąg (B, C, A) nie jest jednak najdłuższym wspólnym pod-
ciągiem (NWP) ciągów X i Y, ponieważ ma długość 3, a ciąg (B, C, B, A)
o długości 4 jest również wspólnym podciągiem ciągów X i Y. Podciągi (B, C,
B, A) oraz (B, D, A, B) są najdłuższymi wspólnymi podciągami ciągów X i Y,
ponieważ nie istnieje wspólny podciąg X i Yo długości 5 lub większej.
Danymi wejściowymi dla problemu najdłuższego wspólnego podciągu
(w skrócie: problemu NWP) są dwa ciągi X= (x 1, x 2, ••• , xm) i Y = (y 1, Y2,
..., Yn>· Zadanie polega na znalezieniu ich najdłuższego wspólnego podciągu.
W tym podrozdziale omawiamy efektywny algorytm służący do rozwiązywania
tego problemu oparty na programowaniu dynamicznym.

Charakterystyka najdłuższego wspólnego podciągu


Algorytm wyczerpującego przeszukiwania dla problemu NWP polega na gene-
rowaniu wszystkich podciągów ciągu X i sprawdzaniu dla każdego z nich, czy
jest też podciągiem ciągu Y, zapamiętując przy tym najdłuższy wspólny pod-
ciąg dotychczas odnaleziony. Każdy podciąg ciągu X odpowiada jednoznacz-
nie podzbiorowi {I, 2, ... , m} indeksów ciągu X. Istnieje zatem 2"' podciągów
X; czas działania tego algorytmu jest więc wykładniczy, co dyskwalifikuje go
dla długich ciągów.
Problem NWP ma własność optymalnej podstruktury. Jak wynika z twier-
dzenia 16.l naturalna przestrzeń pod problemów odpowiada w tym przypadku
parom „prefiksów" ciągów wejściowych. Mówiąc ściślej, dla danego ciągu
X= (x 1, x 2, .•• , xm) definiujemy i-ty prefiks ciągu X, dla i= O, I, ... , m, jako
X;= (x 1, x 2, ••• , x 1). Dla przykładu, jeśli X= (A, B, C, B, D, A, B), to
X 4 = (A, B, C, B), a X0 jest ciągiem pustym.

TWIERDZENIE 16.1. (0 optymalnej podstrukturze NWP)


Niech X= (x 1, x 2, ••• , xm) i Y = (y 1, y 2 , ••• , Yn) będą ciągami, a Z=
= (z 1, z2, ••• , z.,) dowolnym NWP ciągów X i Y.

I. Jeśli xm = Yn, to z.,= x,.. = Yn, a z.,_1 stanowi NWP ciągów Xm-i i Yn-i·
2. Jeśli xm #, Yn i z.,#, xm, to Z stanowi NWP ciągów Xm-i i Y.
3. Jeśli Xm #, Yn i Z;, "FYn to Z stanowi NWP ciągów X i Yn-I·

361
ROZDZIAŁ 16. PAOGAAMOWANlE DYNAMICZNE

DOWÓD
(I) Jeśli zk =ftx,,,, to moglibyśmy dołączyć x,,, = y 11 do Z, uzyskując wspólny
podciąg X i Yo długości k + 1, co przeczy założeniu, że Z jest najdłuższym
podciągiem X i Y. Muszą więc zachodzić równości zk = x,,, = y 11 . Prefiks
Zk-t długości k - I jest z kolei wspólnym podciągiem ciągów X,,,_1 i Y11_ 1•
Pokażemy teraz, że jest to NWP. Załóżmy przeciwnie, że istnieje wspólny
podciąg W ciągów X,,,_1 i Y11•• 1 o długości większej niż k - l. Wtedy, doda-
jąc do W element x,,, = y 11, otrzymujemy wspólny podciąg ciągów
X i Y o długości większej niż k - sprzeczność.
(2) Jeśli zk =Fx,,,, to Z jest wspólnym podciągiem ciągów X,,,_1 i Y. Gdyby
istniał wspólny podciąg W ciągów X,,,_1 i Yo długości większej niż k,
wtedy W byłby jednocześnie podciągiem. X,,, i Y, co jest w sprzeczności
z założeniem, że Z stanowi NWP ciągów X i Y.
(3) Dowód jest analogiczny do tego z przypadku (2).

Charakterystyka, którą daje twierdzenie 16.1, pozwala stwierdzić, że prob-
lem NWP ma własność optymalnej pod struktury. W twierdzeniu tym jest za-
warta obserwacja, że NWP dwóch ciągów zawiera NWP prefiksów tych cią­
gów. Jak. się wkrótce przekonamy, rekurencyjny algorytm dla tego problemu
również ma własność wspólnych podproblemów.

Rekurencyjny algorytm do rozwiązywania podproblemów


Z twierdzenia 16.1 wynika, że szukając NWP ciągów X= (x 1, x 2, ••• , x,,,)
oraz Y = (y 1, y 2, ••• , y 11), należy rozpatrzyć jeden lub dwa pod.problemy.
Jeżeli x,,, = y 11, to wystarczy znaleźć NWP ciągów X,,,_1 i Y11_p Dołączając
x,,,= y 11 do tego NWP, otrzymujemy NWP ciągów X i Y. Jeśli natomiast
, to musimy rozwiązać dwa pod.problemy: znaleźć NWP ciągów X,,,_1
x,,, 'F y 11
i Y oraz znaleźć NWP ciągów X i Y11 __1• Dłuższy spośród nich stanowi NWP
ciągów X i Y.
Jest dość oczywiste, że problem NWP ma własność wspólnych podprob-
lemów. Aby znaleźć NWP ciągów X i Y, możemy potrzebować NWP ciągów
X,,,_1 i Y oraz NWP ciągów X i Y11_ 1• Oba te podproblemy zawierają wspólny
podpodproblem znalezienia NWP ciągów X,,,_1 i Yn-i· Wiele innych podprob-
lemów obejmuje wspólne pod.pod.problemy.
Podobnie jak w przypadku problemu optymalnego nawiasowania iloczynu
macierzy, rekurencyjne rozwiązanie problem.u NWP wymaga zapisania reku-
rencyjnego wzoru na koszt optymalnego rozwiązania. Zdefiniujmy c[i, j] jako
długość NWP ciągów X; i Yj.Jeśli i= O lub j = O, to jeden z ciągów ma długość
O, ich NWP ma więc długość O. Z optymalnej podstruktury problemu NWP
wynika następująca zależność rekurencyjna:

362
16.3. NAJDŁUŻS2Y WSPÓLNY PODCIĄG

o, jeśli i= O lub j =O
c[i,J]= c[i-1,j-1]+1, jeśli i, j > Oi XI= Y1 (16.5)
max (c[i, j - I], c[i - I), J], jeśli i, j > O i xJ of. Y1

Obliczanie długości NWP


Nietrudno napisać rekurencyjny algorytm o wykładniczej złożoności czasowej
oparty na równaniu (16.5), obliczający długość NWP dwóch ciągów. Ponieważ
jednak jest tylko 9(mn) różnych podproblemów, możemy użyć programowa-
nia dynamicznego do obliczania ich rozwiązań metodą wstępującą.
Procedura LCS-LENGTH dla danych ciągów X= (x 1, x 2, ••• , xm>
i Y = (},1, y 2, ••• , Yn>oblicza wartości c[i, j] i zapamiętuje je w tablicy c[O .. m,
O.. n]. Obliczenia te są wykonywane wzdłuż wierszy, a w każdym wierszu od
strony lewej do prawej. Tworzona jest także tablica b(l „ m, 1 „ n], która ułat­
wia później konstrukcję optymalnego rozwiązania. Intuicyjnie, wartość b[i, j]
wskazuje na pole w tablicy c, odpowiadające wybranemu podczas obliczania
c[i, j] optymalnemu rozwiązaniu podproblemu. Procedura LCS-LENGTH obli-
cza tablice bi c; pole c[m, n] zawiera długość NWP ciągów X i Y.
LCS-LENGTf!(X, Y)
1 m +- length[X]
2 n +-length[Y]
3 fori+-1 tom
4 do c[i, OJ- O
5 forj+-Oton
6 do c[O,J]-0
7 fori+-1 tom
8 dofor}+-1 ton
9 doif x,=yi
IO fuenc[i,J]-c[i-1,j-l]+l
11 b[i,j] +-,, '\"
12 else if c[i-1,J] ;> c[i,j-1]
13 tben c[i,j] +- c[i-1,j]
14 b[i,J]-,,i"
15 else c[i,J]-c[i,j-1]
16 b[i,J]+-,,-"
17 returncib
Na rysunku 16.3 widać tablice obliczone przez procedurę LCS-LENGTł-I
dla ciągów X= (A, B, C, B, D, A, B) oraz Y = (B, D, (,', A, B, A). Czas
działania tej procedury wynosi O(nm), ponieważ obliczenie wartości każdego
z pól tablic ci b zajmuje 0(1) jednostek czasu.

363
ROZDZ1AŁ 16. PROGRAMOWANIE DYNAMICZNE

10123456

1 ~ B D C A B A
- .

o o o o o o o o
''
1 A 1
o o o
1 1
' '-,
1 -1 ""
1...

' 1
2

3
B
C
o 1- -1
1 1
1 2
1 1
o 1 1 2 -.1 2 2
'
4 B 1 1 11,
'
o 1 1 2 2 3
1 1 1 t 1
-,
5

6
D

A,
o 1 2 2 2
1 1 1
3

- o 1 2 21 ' 3 3 4
'
1 1 1 t
7 B
o
' 1 2 2 3
' 4 4
Rys. 16.3. Tablice ci b obliczone pr:rez procedurę LCS-LENOTH dla ciągów X= (A, B, C, B, D, A,
=
B) oraz Y (B, D, C, A, B, A). Kwadrat w wierszu i oraz kolumnie j zawiera wartość c[i, 11,
a także odpowiednią strzałkę będącą. wartością pola b(i,J1· Wartość 4 w c[7, 61- prawym dolnym
narożniku tablicy - jest długoicią NWP (B, C, B, A) ciągów X i Y. Dla i, j > O wartość c(i, j]
zależy tylko od tego, czy x 1 = Yp oraz od wartości c{i - l, 11, c[i, j - l] i c[i - I, j - l], które są
obliczane wcześniej niż c(i, Jl W celu skonstruowania NWP wystarczy podążać zgodnie ze strzał­
kami w tablicy b, począwszy od prawego dolnego narożnika; ta ścieżka została zacieniowana,
Ka:Wa strzałka typu,,," na tej ścieżce odpowiada pozycji, dla której x 1 = y1jest elementem NWP

Konstrukcja NWP
Ko12ystając z tablicy b obliczonej przez LCS-LENGTH, można szybko obliczyć
NWP ciągów X= (xi, x 1, ... , x,,.) i Y = (y 1, y 2 , ••• , Y~>·Wystarczy rozpocząć
od b[m, n], a następnie kierować się zgodnie ze strzałkami w tablicy b. Każda
strzałka typu ., '\" w polu b[i, 11oznacza, że x 1 = YJnależy do NWP. Postępu­
jąc w ten sposób, otrzymujemy elementy NWP w odwrotnej kolejności. Na-
stępująca procedura rekurencyjna wypisuje NWP ciągów X i Y we właściwej
kolejności. W tym celu należy ją wywołać następująco: PRINT-LCS(b, X,
length[X], length[Y].

PRINT-LCS(b, X, Y, i, J)
I ifi=Olubj=O
2 tben return
3 ifb[i,J1=,,1'"
4 then PRINT-LCS(b, X, i- 1,j- 1)
5 wypisz X;
6 else if b[i, 11 = ,,1"

364
16.3. NAJDŁUŻSZY WSPÓLNY PODCIĄG

7 lhen PRINT-LCS(b, X,; - l,j)


8 else PRJNT-LCS(b, X,;, j - 1)

Dla tablicy b z rys. 16.3 procedura ta wypisuje „BCBA". Czas jej działania
wynosi O(m + n), ponieważ co najmniej jedna z wartości i lub j jest zmniejsza-
na w każdym kroku rekurencyjnym.

Ulepszanie algorytmu
Algorytm zaprojektowany według ogólnych metod można często ulepszyć za-
równo pod względem złożoności czasowej, jak i pamięciowej. Jest to bardzo
powszechne zjawisko w przypadku narzucających się rozwiązań opartych na
programowaniu dynamicznym. Niektóre zmiany mogą uprościć algorytm i spo-
wodować zmniejszenie stałych czynników, lecz nie są w stanie poprawić złożono­
ści asymptotycznej. Pewne ulepszenia mogą jednak dać w rezultacie znaczne
oszczędności asymptotyczne, jeśli chodzi o zajmowaną pamięć lub czas obliczeń.
Możemy na przykład zupełnie wyeliminować tablicę b. Wartość każdego
pola c[i, j] zależy tylko od co najwyżej trzech innych pól tablicy c: c[i - 1,
j - 1], c{i - 1, J1oraz c[i, j - 1]. Mając dane c{i, j], możemy w czasie 0(1)
ustalić bez odwoływania się do tablicy b, która z tych trzech wartości została
użyta do obliczenia c[i, j]. Dzięki temu możemy zrekonstruować NWP przy
użyciu procedury podobnej do PRINT-LCS w czasie O(m + n). (Zadanie 16.3-2
polega na implementacji tej procedury). Mimo że oszczędzamy w ten sposób
E>(mn)pamięci, pomocnicza pamięć potrzebna do obliczenia NWP nie zmniej-
sza się dzięki temu asymptotycznie, ponieważ nadal jest potrzebne E>(mn) pa-
mięci na tablicę c.
Okazuje się jednak, że możemy mimo wszystko zmniejszyć asymptotyczną
złożoność pamięciową procedury LCS-LENGTH, gdyż wystarczają zawsze tyl-
ko dwa wiersze tablicy c: wiersz właśnie obliczany oraz wiersz bezpośrednio go
poprzedzający. (W rreczywistości do obliczenia długości NWP trzeba wykorzy-
stać tylko odrobinę więcej pamięci niż jeden wiersz tablicy c. Patrz zad. 16.3-4).
To ulepszenie działa jedynie wtedy, kiedy potrzeba podać tylko długość NWP.
Jeśli musimy także zrekonstruować elementy NWP, to mniejsza tablica nie
zawiera dość informacji do odtworzenia rozwiązania w czasie O(m + n).

ZADANIA

16.3-1. Wymar:z. NWP ciągów (1, O, O, 1, O, 1, O, 1) i (O, 1, O, 1, 1, O, 1, 1, O).


16.3-2. Pokaż, jak zrekonstruować NWP na podstawie obliczonej tablicy
coraz wejściowych ciągów X= (x 1, x 2, ••• , xm) i Y = (y 1, Y2 , ••• , Yn>w cza-
sie O(m + n) bez użycia tablicy b.
16.3-3. Podaj wersję ze spamiętywaniem procedury LCS-LENGTH, działającą
w czasie O(mn).

365
ROZDZIAŁ 16. PROGRAMOWANIE DYNAMICZNE

16.3-4. Pokaż, jak obliczyć długość NWP, używając tylko 2min(m, n} elementów
tablicy coraz 0(1} dodatkowej pamięci. Następnie uzasadnij, że w rzeczywiff
stości wystarczy min(m, n) pól w tablicy oraz 0(1} dodatkowej pamięci.
16.J..5. Podaj algorytm znajdujący w czasie O(n 2} najdłuższy monotonicznie
rosnący podciąg danego ciągu n liczb.
* 16.3-6. Podaj algorytm znajdujący w czasie O(nlogn} najdłuższy monotonicz~
nie rosnący podciąg danego ciągu n liczb. (Wskazówka: Zauważ, że ostatni
element kandydata na najdłuższy podciąg długości i jest nie mniejszy
niż ostatni element pewnego kandydata na najdłuższy podciąg długości
i - 1. Przechowuj informacje o takich kandydujących podciągach w osobff
nej tablicy).

16.4. Optymalnatriangulacjawielokąta
W tym podrozdziale poddamy analizie problem optymalnej triangulacji wieloff
kąta wypukłego. Mimo że pozornie tak różny od dotychczas rozważanych
zagadnień, ten geometryczny problem okaże się zaskakująco podobny do pro~
blemu optymalnego nawiasowania iloczynu ciągu macierzy.
Wielokąt to płaska figura geometryczna ograniczona łamaną z.amkniętą,
czyli krzywą mającą początek i koniec w tym samym punkcie i złożoną z od~
cinków, zwanych bokami wielokąta. Punkty wspólne dwóch sąsiednich boków
wielokąta nazywamy jego wierzchołkami. Zbiór punktów na płaszczyźnie za~
mknięty przez wielokąt nazywamy jego wnętrzem. Punk.ty leżące na krzywej
wielokąta tworzą jego bneg, a zbiór punktów otaczających wielokąt stanowi
jego zewnętrze. Wielokąt jest wypukły, jeśli jest spełniony następujący warunek:
dla dowolnej pary punktów leżących na jego brzegu lub we wnętrzu wszystkie
punk.ty na odcinku łączącym tę parę punktów należą do brzegu lub do wnętrza
wielokąta.
Każdy wielokąt wypukły możemy reprezentować za pomocą ciągu jego
wierzchołków, uporządkowanego przeciwnie do ruchu wskazówek zegara.
Zgodnie z tą umową P = (v 0, v1, ••• , vn_1) reprezentuje wielokąt wypukły
o n bokach V0v;, v1vz, ..., v,,._1vn, gdzie vn utożsamiamy z v0 • (Ogólnie będziemy
zakładać, że arytmetyka na indeksach wierzchołków będzie arytmetyką moduff
Io liczba wierzchołków).
Dla dowolnych nie sąsiadujących wierzchołków v1 i v1 odcinek v1v1 nazywaff
my przekątną wielokąta. Przekątna vpi dzieli wielokąt na dwa wielokąty:
(v 1, v1+ 1, ••• , v1) oraz (v 1, v1 + u ... , v1). Triangulacja wielokąta to tak.i zbiór
T jego przekątnych, który dzieli wielokąt na rozłączne trójkąty (wielokąty
o trzech bokach}. Na rysunku 16.4 widać dwie triangulacje siedmiokąta (wiele~
kąta o 7 bokach}. W triangulacji wielokąta nie ma przecinających się przekątff
nych (poza punktami końcowymi}; zbiór T jest też maksymalny: każda prze-

366
16.4. OPTYMALNA TRIANGULACJA WIELOKĄTA

'
'''
''
''
...•' ' ' --------------------~
•• .
''
' ''' ..' ''
..
'' '
'
..• .
''
' '
'''
'
..... ''
'' ,,
''
'
'' ...
''
.,'
.. ..
' ' '
' '\
.' ,
-- ,' -,,"'s
'' ''
'' '' ,'
'' '''
, ' , .. '
\
''
.--.,
, ,
-·---- ,
,,

•.
'' ''. ;
\
' ;•,
,' ,,-

,,' '• ,,
(>) (b)

Rys. 16.4. Dwie tńangulacje siedmiokąta wypukłego. Każda triangulacja siedmiokąta ma 7 - 3 = 4


przekątne i dzieli go na 7 - 2 = 5 trójkątów

kątna nie należąca do T przecina pewną przekątną ze zbioru T. Boki trójkątów


powstałych przez triangulację są albo przekątnymi należącymi do zbioru T,
albo bokami wielokąta. W wyniku każdej triangulacji n-kąta wypukłego otrzy-
mujemy zbiór składający się z n - 3 przekątnych, a wielokąt jest podzielony na
n - 2 trójkąty.
W problemie optymalnej triangulacji (wielokąta) dane są: wielokąt wypukły
P = (v 0 , v1, ••• , v11_ 1) i funkcja wagi w, zdefiniowana na trójkątach zbudowa-
nych z boków i przekątnych wielokąta P. Zadanie polega na znalezieniu trian-
gulacji o najmniejszej sumie wag trójkątów wchodzących w jej skład. Jedną
z naturalnych funkcji wagi na trójkątach jest

gdzie /v1v) jest odległością euklidesową między punktami v, i vJ' Algorytm,


który utworzymy, będzie działał dla dowolnej funkcji wagi.

Związek triangulacji z nawiasowaniem

Między triangulacją wielokąta wypukłego a nawiasowaniem wyrażenia takiego


jak iloczyn ciągu macierzy istnieje zaskakująca analogia. Najłatwiej wyjaśnić ją
za pomocą drzew.
Pełne nawiasowanie wyrażenia odpowiada regularnemu drzewu binarne-
mu, nazywanemu czasem drzewem struktury (ang. parse tree) wyrażenia. Na
rysunku 16.5a widać drzewo struktury dla następującego nawiasowania iloczy-
• •
nu ciągu macierzy:

367
ROZDZIAŁ 16. PROGRAMOWANIEDYNAMICZNE

'o
A,
''
,, ''' ''
'
A, '' '' ,''
' ' A
' '
/ ' ''
'' '' ,,
'' ' '
'' '
I ''
j , , '
'
'''
'I ' '
''
j , I

A, '' '' ' '


' '' '
A, A,

(•) (b)

Rys. 16.5, Drzewa struktury. (a) Drzewo struktury ponawiasowanego iloczynu ((A.1(A0 1))
(A4 (A.sA~)))oraz triangulacji siedmiokąta wypukłego z rys. 16.4a. (b) Triangulacja wielokąta
z wpisanym drzewem struktury. Każda macierz A 1 odpowiada bokowi v,_1v1 dla i= 1, 2, ..., 6

((A,(A,A,) )(A,(A,A.))) (16,6)

Każdy liść drzewa struktury jest etykietowany atomowymi elementami


(tutaj macierzami) wyrażenia. Jeśli lewe poddrzewo pewnego węzła drzewa
reprezentuje wyrażenie W1>a prawe poddrzewo reprezentuje wyrażenie WP,to
drzewo o korzeniu w tym węźle reprezentuje wyrażenie ( W1 WP).Między drze-
wami struktury a w pełni ponawiasowanymi wyrażeniami o n elementach ato-
mowych istnieje wzajemnie jednoznaczna odpowiedniość.
Triangulacja wielokąta wypukłego (v 0 , v1, ... , v,,_1) może być również
przedstawiona za pomocą drzewa struktury. Na rysunku 16.5b znajduje się
drzewo struktury triangulacji wielokąta z rys. 16.5a. Wewnętrzne węzły drzewa
struktury są przekątnymi ze zbioru triangulacji, oprócz korzenia, którym jest
bok wielokąta i>0v6• W liściach znajdują się pozostałe boki wielokąta. Korzeń
V v jest jednym z boków trójkąta Av0 v3 v6• Pozostałe dwa boki są synami ko-
0 6
rzenia: jednym z nich jest przekątna v0v3, a drugim przekątna v3v;;. Zauważmy,
że ten trójkąt dzieli oryginalny wielokąt na trzy części: trójkąt Av 0 v1 v6, wielo-
kąt (v 0 , v1, ••• , v3) i wielokąt (v 3, v4 , ••• , v6 ). Co więcej, oba wielokąty składają
się z boków oryginalnego wielokąta oraz przekątnych v0v3 i v;v6 •
Wielokąt (v 0 , v 1, .. ,, v3) zawiera lewe poddrzewo korzenia drzewa struk-
tury, a wielokąt (v 3, v4, ... , v6) zawiera prawe poddrzewo.
Ogólnie, triangulacja n-kąta odpowiada drzewu struktury z n - 1 liśćmi.
Postępując odwrotnie, z drzewa struktury możemy otrzymać triangulację. Mię­
dzy drzewami struktury i triangulacjami istnieje więc wzajemnie jednoznaczna
odpowiedniość.

368
16.4. OPTYMALNA TRIANGULACJA WIELOKĄTA

W pełni ponawiasowany iloczyn n macierzy odpowiada drzewu struktury


o n liściach i jednocześnie odpowiada też triangulacji wielokąta wypukłego
o n + 1 wierzchołkach. Rysunki 16.5a i b ilustrują tę odpowiedniość. Każda
macierz A 1 w iloczynie A 1A 2 ••• An odpowiada bokowi v;~1v1 wielokąta wypuk-
łego o n+ 1 wierzchołkach. Przekątna D1v1~ dla i<}, odpowiada macierzy
A;+ 1 ••J obliczanej w trakcie mnożenia.
Problem optymalnego mnożenia ciągu macierzy jest w rzeczywistości
szczególnym przypadkiem problemu optymalnej triangulacji. Jest tak, ponie-
waż każdy egzemplarz problemu nawiasowania iloczynu macierzy można sfor-
mułować jako równoważny egzemplarz problemu optymalnej triangulacji t.
Dla danego iloczynu ciągu macierzy A 1A 2 ... An definiujemy wielokąt P =
= (v 0 , v1, ••• , vn>·Przy założeniu, że macierz A 1ma wymiar p 1_ 1 x p 1dla i= 1,
2, ..., n, definiujemy funkcję wagi dla problemu triangulacji jako

Optymalna triangulacja wielokąta P, zgodnie z tą funkcją wagi, jest równo-


ważna z optymalnym nawiasowaniem iloczynu A 1A 2 ..• An.
Mimo że nie da się przeprowadzić odwrotnej redukcji - problem optymal-
nej triangulacji nie jest szczególnym przypadkiem problemu optymalnego na-
wiasowania iloczynu ciągu macierzy - okazuje się jednak, że procedura MAT-
RIX-CHAIN-ORDERz podrozdz. 16.1, z niewielką zmianą, wystarczy do roz-
wiązania problemu optymalnej triangulacji wielokąta wypukłego o n + 1 wie-
rzchołkach. Wystarczy zastąpić ciąg (p 0, p 11 ••• , Pn) wymiarów macierzy cią­
giem (v 0 , v1, ..., vn>wierzchołków, zamienić wystąpienia p odniesieniami do
v oraz zastąpić wiersz 9 następującym:

9 do q- m[i, k] + m[k + 1,J1 + w(L\.v1..1v1,.v


1)
Po wykonaniu tego algorytmu pole m[I, n] zawiera wagę optymalnej trian-
gulacji. Zajmiemy się teraz uzasadnieniem jego poprawności.

Podstruktura optymalnej triangulacji


Rozważmy optymalną triangulację T dla wielokąta wypukłego o n + 1 wierz-
chołkach P = (v 0, Vi, ..., v~>,zawierającą trójkąt .Av0vkvndla pewnego k, takie-
go że 1 ~ k ~ n -1. Waga zbioru Tjest sumą wag trójkąta .Av0v.1:-vn oraz trój-
kątów z triangulacji dwu wielokątów (v 0, v1, ... , V.1:)i (v.1:,vk+1, ... , vn>·Obie
triangulacje tych „podwielokątów" muszą być optymalne, ponieważ ist-

t Równoważny oznac7.3.tutaj laki, :rez rozwiązania nowego - równoważnego - problemu,


można łatwo odczytać rozwiązanie pierwotnego problemu (przyp. tłum.).

369
ROZDZIAŁ 16. PROGR.A.MOW.A.NłE DYNAMICZNE

nienie triangulacji o mniejszej wadze dla dowolnego z nich prowadzi do sprze-


czności z założeniem o optymalności zbioru T.

Rozwiązanie rekurencyjne
Podobnie jak m[i, ;1 oznaczało minimalny koszt obliczenia iloczynu podciągu
macierzy A;A; + 1 ••• Ap tak przez t[i, j] dla 1 ~ i~ n będziemy oznaczać wagę
optymalnej triangulacji wielokąta (v;_ 1, vl" ... , v1). Dla wygody przyjmijmy, że
zdegenerowany wielokąt (v 1_ 1, vj) ma wagę O. Waga optymalnej triangulacji
wielokąta P jest równa t[l, n].
Zdefiniujemy teraz wartość t[i, j] za pomocą tożsamości rekurencyjnej.
Warunek brzegowy dotyczy wielokątów zdegenerowanych (2-kątów): t[i, i] =
= Odla i= I, 2, ... , n. Jeślij - i;;,-1, to mamy do czynienia z wielokątem (v;_ 1,
V;, ... , v ) o co najmniej 3 wierzchołkach. Musimy teraz zminimalizować po
1
wszystkich wierzchołkach vk> dla k = i, i+ 1, ..., j - 1, sumę wag trójkąta
.1.v_ vkv oraz optymalnych triangulacji wielokątów (v;_ 1, V;, ..., vk) i (vk,
11 1
vk+ 1, ••• , v1). Oto odpowiednia zależność rekurencyjna:

o dla i=j
dla i <J (16.7)
l[i, Jl - min {t[i, kJ + l[k + 1, Jl + w(av,_, v,v1))
ł,o;;t<!;J-1

Porównajmy ten wzór z zależnością (16.2), którą uzyskaliśmy dla minimalnej


liczby m[i,J1 mnożeń skalarów potrzebnych do obliczenia A;A,+ 1 ••• Ai. Oprócz
funkcji wagi oba wzory są identyczne, wobec tego drobne zmiany w kodzie
wspomniane wcześniej wystarczą, by procedura MATRIX-CHAIN-ORDER ob-
liczała poprawnie wagę optymalnej triangulacji. Podobnie jak MATRlX-
-CHAIN-ORDER, procedura obliczająca wagę optymalnej triangulacji działa
w czasie 0(n 3 ) i wymaga 0(n 2 ) pamięci.

ZADANIA
16.4-1. Udowodnij, że każda triangulacja n-wierzchołkowego wielokąta wypu-
kłego zawiera n - 3 przekątne i dzieli wielokąt na n - 2 trójkąty.
16.4-2. Profesor Guinevere wysunął hipotezę, że istnieje szybszy algorytm dla
szczególnego przypadku problemu optymalnej triangulacji, w którym
funkcja wagi trójkąta jest jego polem powierzchni. Czy profesor ma rację'}
16.4-3. Przyjmijmy, że funkcja wagi w została zdefiniowana na przekątnych
triangulacji, a nie na jej trójkątach. Waga triangulacji względem w jest
w tym wypadku sumą wag jej przekątnych. Wykaż, że ta wersja problemu
optymalnej triangulacji jest szczególnym przypadkiem problemu optymal-
nej triangulacji z wagą określoną na trójkątach.
16.4-4. Wym.acz optymalną triangulację ośmiokąta foremnego o boku długo­
ści jednostkowej. Użyj następującej funkcji wagi:

370
PROBLEMY

11jest odległością euklidesową między wierzchołkami v1i vl'(Wielo-


gdzie lv,.v
kąt foremny ma wszystkie boki równe i wszystkie kąty wewnętrzne równe).

Problemy
16-1. Bitoniczny problem komiwojażera
Enklidesowy problem komiwojażera polega na wyznaczeniu najkrótszej za-
mkniętej ścieżki, która łączy zbiór n punktów na płaszczyźnie. Na rysunku
16.6a widać rozwiązanie dla 7 punktów. Ogólny problem jest NP-zupełny, co
w przekonaniu wielu informatyków oznacza, że raczej nie istnieje algorytm
działający w czasie wielomianowym (patrz rozdz. 36).

<•> (b)

Rys. 16.6. Siedem punktów na płaszczyźnie, UI.Zllaczonychna siatce. (a) Najkrótsz.a zamknięta ścież­
ka o długości 24,88 ... Ta ścieżka nie jest bitoniczna. {b) Najkrótsza ścieżka bitoniczna dla tego
samego zbioru punktów. Jej długość wynosi 25,58 ...

J.L. Bentley zauważył, że jeśli uprościmy problem, ograniczając się tylko


do ścieiek bitonicznych, to istnieje rozwiązanie działające w czasie wielomiano-
wym. Ścieżka bitoniczna zaczyna się w punkcie wysuniętym najbardziej na
lewo, biegnie następnie ciągle w prawo aż do punktu wysuniętego najbardziej
na prawo, po czym przebiega w lewo do punktu początkowego. Na rysunku
16.6b jest pokazana najkrótsza ścieżka bitoniczna dla tych samych 7 punktów.
Zaprojektuj algorytm znajdowania najkrótszej ścieżki bitonicznej, działający
w czasie O(n 2 ). Możesz przyjąć upraszczające założenie, że żadne dwa punkty
nie mają tej samej współrzędnej x. (W.vkazówka:Przebiegaj zbiór punktów od
strony lewej do prawej, zapamiętując optymalne wybory dla obu części ścieżek).

16-2. Estetyczny wydruk


Rozważmy problem estetycznego wydrukowania akapitu tekstu. Tekst wej-
ściowy składa się z ciągu n słów długości odpowiednio / 1, / 2 , ... , In,mierzonej

--------------------~--··----~
371
ROZDZIAŁ 16. PROGRAMOWANIE DYNAMICZNE

liczbą znaków. Chcemy estetycznie wydruk.ować ten akapit tekstu w wierszach,


które mogą zawierać nie więcej niż M znak.ów każdy. Oto nasze kryterium
estetycznego wydruk.u. Jeśli w wierszu znajdują się słowa o numerach od i do
j oraz stawiamy między słowami po jednym znak.u odstępu, to liczba zbędnych
;
znaków odstępu na końcu tego wiersza wynosi M - j + i - L lk. Zadanie po-
t"' J
lega na zminimalizowaniu sumy (po wszystkich wierszach oprócz ostatniego)
sześcianów liczb zbędnych znak.ów odstępu na końcach wierszy. Zaprojektuj
za pomocą metody programowania dynamicznego algorytm estetycznego dru-
kowania akapitu. Przeprowadź analizę złożoności czasowej i pamięciowej tego
algorytmu.

1~3. Odległość redakcyjna


Zastąpienie „źródłowego" napisu x[l .. m] ,.docelowym" napisem y[l .. n] moż­
na wykonać na wiele różnych sposobów przy użyciu następujących operacji
elementarnych: usunięcia pojedynczego znaku z napisu źródłowego, zastąpie­
nia go innym znakiem, skopiowania do napisu docelowego, wstawienia nowe-
go znaku, zamiany kolejności dwu sąsiednich znaków napisu źródłowego pod-
czas kopiowania do napisu docelowego. Po wykonaniu ciągu takich operacji
można usunąć cały sufiks napisu źródłowego za pomocą operacji „odetnij".
Przykładowo, następujący ciąg operacji zamienia napis źródłowy algorytmy
na napis docelowy altruisty:
Operacja Napis docelowy Napis źródłowy
kopiuj a a lgorytmy
kopiuj I al gorytmy
zastąp g przez t alt orytmy
usuń o alt rytmy
kopiuj r altr ytmy
wstaw u altru ytmy
wstaw i altrui ytmy
wstaw s altruis ytmy
zamień yt na ty altruisty my
odetnij my altruisty
Jest wiele innych ciągów operacji elementarnych, które dają ten sam wynik.
Każda z operacji usuń, zastąp, kopiuj, wstaw, zamień i odetnij ma pewien
ustalony koszt. (Koszt zastąpienia znaku innym znakiem powinien być mniej-
szy niż suma kosztów usunięcia i wstawienia; w przeciwnym razie użycie opera-
cji zastąp nie miałoby sensu). Koszt ciągu operacji „redakcyjnych" (edycyj-
nych) jest sumą kosztów pojedynczych operacji wchodzących w skład tego
ciągu. Na przykład koszt powyższego ciągu operacji zamieniających napis al-
gorytmy na napis altruisty wynosi

372
PROBLEMY

+ koszt(zastąp) + koszt(usuń) + (3 · koszt(wstaw))


(3 · koszt(kopiuj))
+ koszt(zamień) + koszt(odetnij)
Dla danych napisów x[l .. m] i y[l .. n] oraz zbioru kosztów operacji odle-
głość redakcyjna (edycyjna) napisów x i y jest kosztem najtańszego ciągu opera-
cji, który zamienia napis x na napis y. Zaprojektuj algorytm oparty na pro-
gramowaniu dynamicznym znajdujący odległość redakcyjną napisów x[l .. m]
i y[l .. n] oraz wypisujący optymalny ciąg operacji. Przeprowadź analizę złożo­
ności czasowej i pamięciowej tego algorytmu.

16-4. Planowanie bankietu w firmie


Profesor McKenzie jest konsultantem szefa firmy A.-B., który planuje zor-
ganizowanie okolicznościowego bankietu dla pracowników. Firma ma hierar-
chiczną strukturę, tzn. relacja przełożony-podwładny jest drzewem z szefem
firmy jako korzeniem. Dział personalny firmy wyznaczył „współczynnik towa-
rzyskości" każdego pracownika, będący liczbą rzeczywistą. Aby sytuacja nie
krępowała żadnego z uczestników bankietu, szef firmy postanowił, że nie mogą
zostać zaproszeni jednocześnie pracownik i jego bezpośredni przełożony.

(a) Opisz algorytm tworzą.cy listę zaproszonych gości w ten sposób, aby zmak-
symalizować sumę ich „współczynników towarzyskości". Oszacuj czas
działania tego algorytmu.
(b) Jak profesor może zagwarantować, że szef firmy zostanie zaproszony na
organizowany przez siebie bankiet?

16-5. Algorytm Viterbiego


Można użyć programowania dynamicznego na grafie skierowanym G = (V, E)
do rozpoznawania mowy. Każda krawędź (u, v)EE jest etykietowana zna-
kiem a{u, v) ze skończonego zbioru „dźwięków" 1:. Graf etykietowany jest
formalnym modelem człowieka mówiącego w ograniczonym języku. Każda
ścieżka w grafie rozpoczynająca się w wyróżnionym wierzchołku v0 EE od-
powiada możliwemu ciągowi dźwięków, jakie może wytworzyć model. Etykietę
skierowanej ścieżki definiujemy jako konkatenację etykiet krawędzi leżących
na tej ścieżce.

(a) Zaprojektuj efektywny algorytm, który dla danego grafu G z etykietowa-


nymi krawędziami i wyróżnionym wierzchołkiem v0 oraz danego ciągu
s = (u 1, u 2, ... , uk) znaków ze zbioru 1: wyznacza ścieżkę w G, zaczynającą
się w wierzchołku v0 o etykiecie .v,jeśli taka ścieżka istnieje. W przeciwnym
razie algorytm powinien wypisać komunikat NIE-MA-TAKIEJ-ŚCIEŻKI.
Oszacuj czas działania tego algorytmu. (Wskazówka: Mogą przydać się
koncepcje przedstawione w rozdz. 23).
------- -------""""""--
373
ROZDZIAŁ 16. PROGRAMOWANIE DYNAMICZNE

Przyjmijmy teraz, ze z każdą krawędzią (u, v)E E jest związane nieujemne


prawdopodobieństwo p(u, v) przejścia krawędzi (u, v) z wierzchołka u do
v i wygenerowania odpowiedniego dźwięku, Suma prawdopodobieństw krawę­
dzi wychodzących z każdego wierzchołka jest równa 1. Prawdopodobieństwo
przejścia ścieżki defmiujemy jako iloczyn prawdopodobieństw przejść krawędzi
leżących na tej ścieżce. Prawdopodobieństwo przejścia ścieżki o początku w v0
można traktować jako prawdopodobieństwo, ze „błądzenie losowe" o począt­
ku w v0 przebiegnie po tej ścieżce, o ile przyjmiemy zalozenie, Ze wybór następ­
nego wierzchołka w wierzchołku u jest losowy, zgodny z prawdopodobieństwa­
mi .krawędzi wychodzących z u.

(b) Ulepsz swoje rozwiązanie części (a), aby algorytm wyznaczał zawsze naj-
bardziej prawdopodobną ścieżkę o początku v0 i etykiecie s. Oszacuj czas
działania tego algorytmu.

Uwagido rozdziału
Systematyczne badanie metody programowania dynamicznego rozpoczął
R. Bellman w 1955 r. Słowo „programowanie" zarówno tutaj, jak i w pro-
gramowaniu liniowym odnosi się do metody tabelarycznej rozwiązywania pro-
blemów. Mimo ze metody optymalizacyjne o cechach programowania dyna-
micznego były znane już wcześniej, Bellman zbudował solidne podstawy mate-
matyczne tej metody [21]. Hu i Sbing [106] podali algorytm dla problemu
optymalnego nawiasowania iloczynu ciągu macierzy działający w czasie
O(nlogn). Zauważyli też bliski związek problemu optymalnej triangulacji wie-
lokąta z problemem optymalnego nawiasowania.
Algorytm wyszukiwania najdłuższego wspólnego podciągu działający
w czasie O(mn) był powszechnie znany od dawna. Knuth [43] postawił pytanie,
czy istnieje algorytm dla problemu NWP o złożoności mniejszej niż kwadrato-
wa. Pozytywnej odpowiedzi na to pytanie udzielili Masek i Paterson [143],
podając algorytm działający w czasie O(mnjlogn), gdzie n~ m, a ciągi należą
do zbioru o ograniczonym rozmiarze. Dla szczególnego przypadku, w którym
żaden element nie występuje wielokrotnie w ciągu wejściowym, Szymanski
[184] poda! algorytm działający w czasie O{{n + m)log(n + m)). Wiele z tych
rezultatów daje się uogólnić do problemu obliczania odległości redakcyjnej
między napisami (problem 16-3).
Rozdział 17

Algorytmy zachłanne

Algorytmy służące do rozwiązywania problemów optymalizacyjnych polegają


zwykle na podejmowaniu ciągu decyzji -w każdym kroku należy wybrać jedną
z wielu możliwości. Dla wielu takich problemów stosowanie programowania
dynamicznego jest grubą przesadą; istnieją dla nich prostsze i bardziej efektyw-
ne algorytmy. Algorytm zachłanny (ang. greedy algorithm) wykonuje zawsze
działanie, które wydaje się w danej chwili najkorzystniejsze. Wybiera zatem
lokalnie optymalną możliwość w nadziei, że doprowadzi ona do globalnie op-
tymalnego rozwiązania. W tym rozdziale zajmiemy się problemami, dla któ-
rych istnieją poprawne algorytmy zachłanne.
Algorytmy zachłanne nie zawsze prowadzą do optymalnych rozwiązań,
choć dla wielu problemów są wystarczające. Zbadamy najpierw w pod-
rozdz. 17.1 prosty, lecz nietrywialny problem wyboru zajęć, dla którego ist-
nieje efektywny i poprawny algorytm zachłanny. W podrozdziale 17.2 pod-
sumujemy podstawowe składniki metody algorytmów zachłannych, a w pod-
rozdz. 17.3 omówimy ważny przykład zastosowania strategii zachłannej: kon-
strukcję kodów lluffmana do kompresji danych. W podrozdziale 17.4 przed-
stawimy podstawy teorii obiektów kombinatorycznych zwanych „matroida-
mi", dla których algorytm zachłanny zawsze generuje optymalne rozwiązanie.
Na koniec, w podrozdz. 17.5, zilustrujemy zastosowanie matroidów do prob-
lemu szeregowania zadań o jednostkowym czasie trwania z karami za prze-
kroczenie terminu wykonania.
Algorytmy zachłanne są dość skutecwe i dają dobre rezultaty dla szerokiej
gamy problemów. W dalszych rozdziałach opisujemy wiele algorytmów, które
można traktować jak.o zastosowania metody zachłannej. Należą do nich: al-
gorytm wyznaczania minimalnego drzewa rozpinającego (rozdz. 24), algorytm
Dijkstry znajdowania najkrótszych ścieżek z ustalonego wierzchołka w grafie
(rozdz. 25) oraz heurystyczny algorytm zachłanny Chvitala dla problemu

375
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

pokrycia zbioru (rozdz. 37). Algorytm konstruowania minimalnego drzewa


rozpinającego jest klasycznym przykładem zastosowania metody zachłannej.
Chociaż ten rozdział oraz rozdział 24 mogą być czytane niezależnie, dobrze jest
zapoznać się z nimi jednocześnie.

17.1. Problemwyboru zajęć


Nasz pierwszy przykład dotyczy problemu przydzielania dostępu do zasobu
wykorzystywanego podczas wykonywania pewnych zajęć. Przekonamy się, że
algorytm zachłanny stanowi prostą a zarazem elegancką metodę znajdowania
największego zbioru wzajemnie zgodnych (nie zakłócających się) czynności.
Niech będzie dany zbiór S = {l, 2, ... , n} składający się z n proponowa-
nych zajęć, do których mają być przydzielone zasoby, takie jak na przykład
sala wykładowa, w której może się odbywać w danej chwili tylko jedno z tych
zajęć. Każde zajęcie ma swój czas rozpoczęcia s1 oraz czas zakończenia fi, takie
że s1 ~J;. Jeśli zajęcie o numerze i zostanie wytypowane, to zajmuje zasób
przez prawostronnie otwarty przedział czasu [s1,J;). Zajęcia o numerach i oraz
j są zgodne (nie zakłócają się), jeśli przedziały [s;,Ji) oraz [s1, Jj) nie zachodzą na
siebie (tzn. i oraz j są zgodne, jeśli s1 ;;==
Jj lub si;;==fi). Problem wyboru zajęć
polega na wyborze największego podzbioru parami zgodnych zajęć.
Poniższy pseudokod jest zapisem algorytmu zachłannego dla problemu
wyboru zajęć. Bez utraty ogólności zakładamy, że zajęcia są uporządkowane ze
względu na czas zakończenia:

(17.l)

W przeciwnym razie można najpierw uporządkować je w takiej kolejności


w czasie O(nlog n). W poniższej procedurze zakładamy, że s i f są reprezen-
towane jako tablice.

GREEDY-ACTIVITY-SELECTOR(s,.f)
1 n +- length [s]
2 A-{l}
3 j +-1
4 fori+-2ton
5 doifs 1;;=:Jj
6 thenA-Au{i}
7 j +- i
8 return A

Działanie
tego algorytmu jest zilustrowane na rys. 17. I. W zbiorze A są
gromadzone wybrane zajęcia. Zmiennaj zawiera ostatnio dodane do A zajęcie.

376
17.1. PROBLEM WYBORU ZAJĘC

' s, !,
I I 4

2 3 5 ~-,
' '

1 'j
3 o 6 b 3 1
1

4 5 7 4
I

5 3 8 b 5
1 4 '
7

6 5 9 6 :_____J
1 4
'
7 6 IO 7
1 f''l ' ----1
'
-
~
8 8 II 8
1 I 4
'
'
' '-
9 8 12
1 4' f 8
~
9
I

J
IO 2 I3 IO
E--··
1 4 I
'
II 12 14
1 4 I 8 v II I

I 4 8 li

--~--~--·:
O 1 2 J 4
--=-----c--:----:---:-------:::-----:
5 6 7 R 9 IO l l
----:::---:~---:::~
12 13 14
c,~
Rys. 17.1. Działanie procedury GREEDY-ACTMTY-SELECTOR na 11-eJementowym zbione zajęć
przedstawionym po lewej stronie rysunku. Każdy poziomy rząd na rysunku odpowiada jednej
iteracji pętli for w wierszach 4-7. Zajęcia włączone do zbioru A zostały zacieniowane, a zajęcie
i (białe na rysunku) jest aktualnie rozpatrywane. Jeśli czas rozpoczęcia s1 zajęcia i jest wcześniejszy
niż czas zakończenia!, zajęcia ostatnio dcxianego do A (strzałka między nimi wskazuje na lewo), to
zostaje ono odrzucone. W przeciwnym razie (strzałka wskazuje do góry lub w prawo) zostaje ono
wybrane i dodane do zbioru A
ROZDZIAŁ 17, ALGORYTMY ZACHŁANNE

Ponieważ zajęcia są rozpatrywane w porządku rosnącego czasu zakończe­


nia,Jj jest zawsze największym czasem zakończenia zajęcia należącego do A, tj.

fi- max{[,: kEA) (17.2)

W wierszach 2-3 jest wybierane zajęcie 1, jednoelementowy zbiór {1} staje się
wartością zmiennej A, a zmiennej j zostaje przypisany numer tego zajęcia.
W wierszach 4-7 są kolejno rozpatrywane wszystkie zajęcia i; każde z nich
zostaje dołączone, jeżeli jest zgodne ze wszystkimi dotychczas dołączonymi
zajęciami. Aby stwierdzić, czy zajęcie i jest zgodne z każdym zajęciem ze zbioru
A, wystarczy zgodnie z równaniem (17 .2) sprawdzić (wiersz 5), czy jego czas
rozpoczęcia s; nie jest wcześniejszy niż czas zakończenia /j zajęcia ostatnio
dodanego do A. Jeśli zajęcie i jest zgodne, to w wierszach 6-7 zostaje ono
dodane do zbioru A oraz jest aktualizowana wartość j. Procedura GREEDY-
-ACTIVITY-SELECTOR jest dość efektywna. Zakładając, że dane wejściowe są
uporządkowane rosnąco według czasów zakończenia zajęcia, GREEDY-ACTIVI-
TY-SELECTORwyznacza maksymalny podzbiór zajęć z n-elementowego zbioru
S w czasie E>(n).
Zajęcie wybierane przez GREEDY-ACTIVITY-SELECTOR ma zawsze najwcze-
śniejszy czas zakończenia wśród zajęć, które mogą być dołączone bez zakłócenia
zgodności zbioru A. Ten wybór jest „zachłanny" w tym sensie, 7.epozostawia
intuicyjnie możliwie najwięcej swobody przy wyborze pozostałych zajęć. Jest tak,
bo wybór tak.i maksymalizuje ilość nie zajętego czasu po jego dokonaniu.

Dowód poprawności algorytmu zachłannego


Algorytmy zachłanne nie zawsze generują optymalne rozwiązania. Okazuje
się jednak, że GREEDY-ACTIVITY-SELECTOR zawsze znajduje optymalny wy-
bór zajęć.

TWIERDZENIE 17.1.
Algorytm GREEDY-ACTMTY-SELECTORgeneruje rozwiązanie problemu wy-
boru zajęć o największym rozmiarze.

DOWÓD
Niech S = {1, 2, ... , n} będzie zbiorem zajęć. Ponieważ zakładaliśmy, że zajęcia
są uporządkowane według czasu zakończenia, zajęcie 1 ma najwcześniejszy
czas zakończenia. Wykażemy, że istnieje optymalne rozwiązanie, które można
rozpocząć od wyboru zachłannego, tj. od wybrania zajęcia 1.
Załóżmy, że A s; Sjest optymalnym rozwiązaniem. Niech elementy A bę­
dą uporządkowane ze względu na czas zakończenia. Przyjmijmy też, że pierw-
szym zajęciem należącym do A jest zajęcie o numerze k. Jeśli k = 1, to tworze-

378
17.1. PROBLEM WYBORU ZA.JĘC

nie rozwiązania A można zacząć od podjęcia decyzji zachłannej. Jeżeli nato-


miast k # 1, to wykazeDly, że istnieje inne optymalne rozwiązanie B c S, któ-
rego konstrukcję można zacząć od zachłannego wyboru, tj. od wyboru zajęcia
1. Niech B = A - {k} u {l}. Wiadomo, że/1 ~ft, zajęcia w B są więc zgodne.
Ponieważ B ma tyle samo zajęć co A, jest więc także rozwiązaniem optymal-
nym. Pokazaliśmy w ten sposób, że zawsze istnieje optymalne rozwiązanie,
którego konstrukcję można zacząć od wyboru zachłannego.
Co więcej, gdy już dokonaliśmy zachłannego wyboru zajęcia I, problem
sprowadza się do znalezienia optymalnego rozwiązania problemu wyboru za-
jęć dla zbioru tych zajęć z S, które są zgodne z zajęciem 1. Jeśli więc A jest
optymalnym rozwiązaniem całego problemu S, to A' = A - {1} jest optymal-
nym rozwiązaniem problemu optymalnego wyboru zajęć dla zbioru S' =
= {iE S: s1 ~ / 1}. Dlaczego? Jeśli moglibyśmy znaleźć rozwiązanie B' problemu
S' o większej liczbie zajęć niż A', to dodając zajęcie I do B', otrzymalibyśmy
rozwiązanie B problemu S o większej liczbie zajęć niż A, co przeczyłoby op-
tymalności A. Widać więc, że po każdym wyborze zachłannym pozostaje do
rozwiązania problem optymalizacyjny tego samego typu co początkowo. Ko-
rzystając z indukcji względem liczby podjętych decyzji i dokonując zachłan­
nego wyboru w każdym kroku, otrzymamy optymalne rozwiązanie.


ZADANIA
17.1-1. Podaj algorytm optymalnego wyboru zajęć oparty na programowaniu
dynamicznym, obliczający iteracyjnie wartość m1 dla i= 1, 2, ... , n, gdzie
m; jest rozmiarem największego zgodnego podzbioru zbioru {1, 2, ... , i}.
Przyjmij założenie, że czynności na wejściu zostały uporządkowane tak, by
spełniały zależność (17.1). Porównaj czas działania swojego rozwiązania
z czasem działania procedury GREEDY-ACTIVITY-SELECTOR.
17.1-2. Mamy dany zbiór zajęć, które mają się odbywać w pewnej liczbie sal
wykładowych. Chcemy użyć do tego celu możliwie najmniejszej liczby sal.
Podaj efektywny algorytm zachłanny wyznaczający przydział zajęć do sal.
(Problem ten jest również znany jako kolorowanie grafu przedziałów. Graf
przedziałów tworzymy, traktując zajęcia jako wierzchołki i łącząc krawę­
dziaini wzajemnie kolidujące zajęcia. Najmniejsza liczba kolorów potrzebna
do pokolorowania wszystkich wierzchołków, tak aby żadna para sąsiednich
wierzchołków nie miała tego samego koloru, odpowiada najmniejszej liczbie
sal wykładowych potrzebnych do odbywania się wszystkich zajęć).
17.1-3. Nie każde zachłanne podejście do problemu wyboru zajęć daje największy
zgodny zbiór zajęć. Podaj odpowiedni kontrprzykład dla strategii polegającej
na wyborze zajęcia o najmniejszym czasie trwania spośród zajęć zgodnych
z dotychczasowo wybranymi. Zrób to samo dla strategii opartej na wyborze
zajęcia, które koliduje z najmniejszą liczbą zajęć pozostałych do rozpatrzenia.

379
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

17.2. Podstawystrategiizachłannej
Algorytm zachłanny dochodzi do optymalnego rozwiązania przez podejmowa-
nie ciągu decyzji. Za każdym razem jest podejmowana decyzja, która wydaje
się w tej chwili najlepsza. Stosując taką heurystyczną strategię, nie zawsze
otrzymuje się optymalne rozwiązania, lecz jak się przekonaliśmy na przykła­
dzie problemu wyboru czynności, dla niektórych problemów jest to w pełni
uzasadnione. W tym podrozdziale omówimy ogólne własności metody za-
chłannej.
Jak przekonać się, czy algorytm zachłanny poprawnie rozwiązuje dany
problem optymalizacyjny? Nie ma niestety żadnej ogólnej metody, lecz dwie
cechy są charakterystyczne dla większości problemów poddających się strategii
zachłannej: własność wyboru zachłannego oraz optymalna podstruktura.

Własność wyboru zachłannego


Pierwsza podstawowa własność to własność wyboruzachłannego: za pomocą
lokalnie optymalnych (zachłannych) wyborów można uzyskać globalnie op-
tymalne rozwiązanie. Cecha ta istotnie odróżnia algorytmy zachłanne od pro-
gramowania dynamicznego. W programowaniu dynamicznym w każdym kro-
ku są podejmowane decyzje, lecz właściwy wybór może zależeć od rozwiązań
podproblemów. W algorytmie zachłannym dokonujemy wyboru, który wydaje
się być najlepszy w danej chwili, a następnie rozwiązujemy pod.problemy, które
wynikają z podjętej decyzji. Wybory podejmowane w algorytmie zachłannym
mogą zależeć od dotychczasowych decyzji, lecz nie mogą być uzależnione od
przyszłych wyborów lub od rozwiązań pod.problemów. Sprawia to, że w prze-
ciwieństwie do algorytmów opartych na programowaniu dynamicznym, roz-
'Niązujących problem w sposób wstępujący, algorytmy zachłanne znajdują roz-
wiązanie w sposób zstępujący, podejmując kolejno decyzje zachłanne, stop-
niowo redukując podproblemy do coraz mniejszych.
Musimy oczywiście udowodnić, że wybór zachłanny w każdym kroku pro-
wadzi do globalnie optymalnego rozwiązania, niezbędna jest więc ludzka in-
wencja i pomysłowość. Podobnie jak w przypadku twierdzenia 17.1, dowód
polega na sprawdzeniu pewnego globalnie optymalnego rozwiązania. Wykazu-
je się zwykle, że można je sprowadzić do rozwiązania, którego początkiem jest
podjęcie decyzji zachłannej w pierwszym kroku, oraz wykazuje się, że ten wy-
bór redukuje problem do podobnego, ale o mniejszym rozmiarze. Aby następ­
nie uzasadnić, że strategię zachłanną można stosować w każdym następnym
kroku, wystarczy użyć indukcji. Jeśli wykażemy, że wybór zachłanny sprowa-
dza problem do podobnego o mniejszym rozmiarze, to dowód poprawności
algorytmu sprowadza się do uzasadnienia optymalnej podstruktury optymal-
nego rozwiązania.

380
17.2. PODSTAWY STRATEGII ZACHŁANNEJ

Optymalna podstruktura

Problem wykazuje optymalną podstrukturę, jeśli optymalne rozwiązanie jest


funkcją optymalnych rozwiązań podproblemów. 'fa własność jest zasadnicza
nie tylko dla stosowalności metody programowania dynamicznego, ale także
i algorytmów zachłannych. Jako przykład optymalnej podstruktury przypo-
mnijmy twierdzenie 17,l. Wynika z niego, 7.e jeśli optymalne rozwiązanie
A problemu wyboru zajęć rozpoczyna się od zajęcia I, to A' = A - { 1} jest
optymalnym rozwiązaniem problemu optymalnego wyboru zajęć dla zbioru
S'={iES:s 1 ~/ 1}.

Porównanie strategii zachłannych z programowaniem dynamicznym


Ponieważ własność optymalnej podstruktury jest wykorzystywana zarówno
w strategiach 7..achłannych, jak i programowaniu dynamicznym, pojawia się
czasem chęć użycia programowania dynamicznego tam, gdzie wystarczyłaby
jakaś strategia zachłanna. Można też niekiedy błędnie przypuszczać, że wystar-
czająca jest strategia zachłanna, podczas gdy niezbędne jest użycie programo-
wania dynamicznego. Aby zilustrować subtelne różnice między tymi dwoma
metodami, zajmiemy się teraz zbadaniem dwóch wersji klasycznego problemu
optymalizacyjnego.
Dyskretny problem plecak.owy (ang. 0-1 knapsack problem) można sformu-
łować następująco. Złodziej rabujący sklep znalazł n przedmiotów; i-ty przed-
miot jest wart c; złotych i waży w1 kilogramów, gdzie C; oraz w1 są nieujemnymi
liczbami całkowitymi. Dąży on do zabrania re sobą jak najwartościowsrego
łupu, lecz nie może wziąć do swego plecaka więcej niż W kilogramów. Jakie
przedmioty powinien zabrać ze sobą złodziej? (Problem ten nazywa się dys-
kretnym problemem plecakowym, ponieważ każdy prredmiot musi być albo
zabrany, albo pozostawiony; złodziej nie może zabrać ułamkowej części przed-
miotu ani wielokrotności żadnego z nich).
Ciągły problem plecakowy formułuje się podobnie, lecz złodziej nie musi
podejmować dramatycznych decyzji i może zabierać ułamkowe części przed-
miotów (w tej sytuacji dogodniej jest mówić o „substancjach", a nie „prred-
miotach").
Obie wersje problemu plecakowego wykazują własność optymalnej pod-
struktury. Rozwa·iroy najwartościowszy ładunek o masie nie większej niż W,
dla dyskretnego problemu plecakowego. Jeśli usuniemy z tego ładunku przed~
miot j, to pozostający ładunek musi być najwartościowszym zbiorem przed-
miotów o wadze nie przekraczającej W - w1, jakie złodziej może wybrać
z n - 1 oryginalnych przedmiotów z wyjątkiem j. Dla analogicznego problemu
ciągłego, jeśli usuniemy z optymalnego ładunku w kilogramów pewnej substan-
cji j, to pozostający ładunek powinien być najwartościowszym ładunkiem

381
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

o wadze co najwyżej W - w, który złodziej może skompletować z n - 1 orygi-


nalnych substancji, plus w1 - w kilogramów substancji j.
Mimo że problemy są do siebie podobne, ciągły problem plecakowy pod-
daje się strategii zachłannej, a problem dyskretny nie! Aby rozwiązać ciągły
problem plecak.owy, należy najpierw obliczyć wartość masy jednostkowej vJw1
każdej substancji. Kierując się strategią zachłanną, złodziej wybiera najpierw
największą możliwą ilość najbardziej wartościowej substancji. Jeśli zapas tej
substancji się wyczerpał, a w plecaku jest ciągle jes:zcze wolne miejsce, złodziej
wybiera następną pod względem ceny za jednostkę masy substancję i wypełnia
nią plecak, i postępuje tak dopóty, dopóki plecak nie zostanie wypełniony
całkowicie. Podejście to wymaga posortowania „substancji" według wartości
jednostki masy, algorytm zachłanny działa więc w czasie O(n log n). Dowód, że
ciągły problem plecak.owy ma własność wyboru zachłannego pozostawiamy
czytelnikowi (zad. 17.2-1).
Aby przekonać się, Ze ta strategia zachłanna nie jest poprawna dla dyskret-
nego problemu plecakowego, rozważmy przykład z rys. 17.2a. Są tam do wy-
boru 3 przedmioty, a plecak moze pomieścić do 25 kg. Przedmiot 1 waży 5 kg
i jest wart 60 zł. Przedmiot 2 waży 10 kg i jest wart 100 zł. Przedmiot 3 waży
15 kg i jest wart 120 zł. Cena jednostkowa prze.dmiotu I wynosi 12 zł/kg, jest
więc większa od ceny za jednostkę masy zarówno przedmiotu 2 (10 zł/kg), jak
i przedmiotu 3 (8 zł/kg). Strategia zachłanna doprowadziłaby więc do wyboru
przedmiotu 1 na samym początku. Jak jednak wynika z analizy zilustrowanej
na rys. 17.2b, w optymalnym rozwiązaniu zostaną wybrane przedmioty 2 oraz
3. Oba rozwiązania, w których jest wybrany przedmiot 1, nie są optymalne.
W przypadku analogicznego problemu ciągłego strategia zachłanna, która
prowadzi do wyboru najpierw przedmiotu 1, powoduje wybranie oczywiście

80 ,I
Przedmiot 3 30 120 zł
+
Przedmiot 2 + 30 120 zł
20 100 zł 20 100 ,I
Przedmiot J 30 + +

~
20 100
20 60 ,I 60 ,I
60 zł 100 zł 120 zł Plecak =220 zł "'160 zł =IROzl =240 zł
(a) (b) (c)

Rys. 17.2, Sl.ralegia zachłanna nie jest poprawna dla dyskretnego problemu plecak.owego. (a) 710-
dziej może wybrać podzbiór trzech pr:redmiotów, którego waga nie przekracza 50 kg. (b) Optymal-
ny podzbiór składa się z prt.edmiotów 2 i 3. Żadne rozwiązanie zawierające przedmiot I nie jest
optymalne, mimo że ma on najwięksZ\ wartość na jednostkę masy. (c) Wybór substancji w kolej-
ności ich wartości na kilogram masy daje optymalne rozwiązanie ciągłego problemu plecak.owego

382
17.3. KODY HUFFMANA

optymalnego rozwiązania, jak widać na rys. 17.2c. Wybierając przedmiot


1 w przypadku problemu dyskretnego, złodziej nie jest później w stanie wypeł­
nić swego plecaka do jego całkowitej pojemności i pozostająca wolna prze-
strzeń obniża efektywną wartość przypadającą na kilogram zabranego ładun­
ku. W dyskretnym problemie plecakowym, zanim podejmiemy decyzję, czy
należy zabrać przedmiot, musimy porównać rozwiązanie podproblemu, w któ-
rym ten przedmiot występuje, z rozwiązaniem podproblemu, w którym nie jest
on brany pod uwagę. Takie ujęcie problemu daje w efekcie wiele wspólnych
podproblemów - własność charakterystyczna dla programowania dynamicz-
nego; nie jest więc zaskoczeniem, że istnieje rozwiązanie dyskretnego problemu
plecakowego za pomocą programowania dynamicznego (patrz zad. 17.2-2).
ZADANlA

17.2-1. Wykaż, że ciągły problem plecakowy ma własność wyboru zachłannego.


17.2-2. Podaj rozwiązanie dyskretnego problemu plecakowego oparte na pro-
gramowaniu dynamicznym, działające w czasie O(nJf), gdzie n jest liczbą
przedmiotów, a W maksymalnym dopuszczalnym ciężarem przedmiotów,
które złodziej może włożyć do plecaka.
17.2-3. Przypuśćmy, że w dyskretnym problemie plecakowym kolejność przed-
miotów uporządkowanych rosnąco według ciężaru jest taka sama, jak
przy uporządkowaniu malejącym według wartości. Podaj efektywny algo-
rytm znajdujący optymalne rozwiązanie dla tej wersji problemu plecako-
wego i uzasadnij jego poprawność.
17.2-4. Profesor Midas jedzie samochodem z Newark do Reno. Bak pełen
benzyny w jego pojeździe wystarcza na przejechanie n km, a na jego mapie
są zaznaczone odległości między wszystkimi stacjami benzynowymi na tra-
sie. Profesor ma zamiar tankować jak najmniejszą liczbę razy w trakcie
podróży. Podaj efektywną metodę, za pomocą której profesor Midas może
ustalić, na których stacjach powinien tankować, oraz udowodnij, że strate-
gia ta prowadzi zawsze do optymalnego rozwiązania.
17.2-5. Zaprojektuj efektywny algorytm, który dla danego zbioru {x 1 , x 2 ,
... , x,.} punktów na prostej wyznacza najmniejszy zbiór przedziałów do-
mkniętych o długości jednostkowej, których suma zawiera wszystkie dane
punk.ty. Uzasadnij poprawność swojego algorytmu.
* 17.2-6. Wykaż, jak rozwiązać dyskretny problem plecakowy w czasie O(n).
Przyjmij, że znane jest rozwiązanie problemu 10-2.

17.3. Kody Huffmana


Kody Huffmana są powszechnie stosowaną i bardzo efektywną metodą kompre-
sji danych; w zależności od typu kompresowanego pliku osiąga się oszczędności

----~----~ -----"------"-·- -=
383
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

od 20% nawet do 90%. Za pomocą zachłannego algorytmu Huffmana tworzy


się optymalny sposób reprezentacji znaków za pomocą ciągów bitów, wykorzys-
tując tablicę częstości występowania znaków.
Przyjmijmy, że chcemy skompresować plik o długości 100000 znaków;
częstości wystąpień znaków w tym pliku są podane na rys. 17.3. Występuje
w nim więc tylko 6 różnych znaków, a znak a ma 45 OOOwystąpień.

• b
' d • t
Częstość (w ty&iącach) 4S 13 12 16 9 S
Słowo kodowe o ustalonej długości OOO 001 010 011 100 101
Słowo kodowe o zmiennej długości O 101 100 111 1101 1100

Rys. 17.3. Problem kodowania maków. W pliku o długości 100000 występują tylko znaki a-t,
z podanymi częstościami. Jeśli każdemu makowi przypiszemy 3-bitowykod, można ten plik zapisać
za pomocą, 300000 bitów. Używając kodów o zmiennej długości, można zmniejszyć tę liczbę do
224OOObitów

Tak.i plik można reprezentować na wiele różnych sposobów. Rozważmy


problem zaprojektowania kodu binarnego (lub po prostu kodu), w którym każ­
dy znak jest reprezentowany przez pewien ustalony ciąg bitów. Jeśli używamy
kodu o ustalonej długości, to do reprezentacji 6 znak.ów potrzeba nam 3 bitów:
a= OOO,b = 001, ... , f = 101. Nasz plik zapisany przy użyciu tej metody zaj-
muje aż 300 OOObitów. Czy da się go reprei.entować w bardziej zwarty sposób?
Kody o zmiennej długości odznaczają się zn8crnie lepszymi właściwościami
niż kody o stałej długości, ponieważ częściej występujące znaki są wtedy re-
prezentowane za pomocą krótszych słów kodowych kosztem znak.ów o mniej-
szej częstości występowania, które mają kod dłuższy. Na rysunku 17.3 widać
taki kod; jeden bit O reprezentuje w nim mak a, a 4-bitowy ciąg 1100 reprezen-
tuje znak f. Do reprezentacji naszego pliku przy użyciu tego kodu potrzeba
(45· l + 13·3 + 12·3 + 16·3 + 9·4 + 5·4)· 1000 - 224000 bitów
co daje oszczędność około 25%. W istocie, jak się pri.ekonamy, jest to op-
tymalny kod dla tego pliku.

Kody prefiksowe
Będziemy teraz rozważać tylko takie kody, w których kod żadnego znaku nie
jest prefiksem kodu innego znaku. Takie kody nazywa się kodami prefiksowy-
mi. Można pokazać (choć nie udowodnimy tutaj tego faktu), że za pomocą
kodów prefiksowych można uzyskać maksymalny stopień kompresji, osiągal­
ny za pomocą kodów przypisanych znakom na stałe. Dzięki temu, rozpatrując
tylko kody preftksowe, nie tracimy ogólności w naszych poszukiwaniach op-
tymalnych kodów.

384
17.3. KODY HUFFMANA

Kody prefiksowe są wygodne, ponieważ upraszczają kodowanie (kompre-


sję) i dekodowanie. Kodowanie za pomocą kodów binarnych jest bardzo łat­
we; wystarczy skonkatenować kody kolejnych znaków w pliku. Na przykład,
używając kodu o zmiennej długości z rys. 17.3, plik zawierający trzy znaki abc
reprezentujemy za pomocą ciągu bitów O· 101 · 100 = 0101100, gdzie znak ,, ·"
oznacza operację konkatenacji (czyli łączenia) ciągów znaków.
Dekodowanie jest także stosunkowo proste w przypadku kodów prefik-
sowych. Pierwszy kod w pliku jest wtedy wyznaczony jednoznacznie, bo żaden
kod nie jest preflksem innego kodu. Wystarczy wyznaczyć pierwszy kod w pli-
ku, przetłumaczyć go na odpowiadający znak, usunąć z zakodowanego pliku
i powtórzyć procedurę dekodującą dla reszty pliku. W naszym przykładzie ciąg
001O11101 rozkłada się jednoznacznie na O· O· 1Ol · 1101, co daje słowo aabe.
Aby móc łatwo rozpoznawać jednoznaczne kody początkowe, należy od-
powiednio reprezentować kod prefiksowy. Taką dogodną reprezentacją jest
drzewo binarne, którego liście odpowiadają zakodowanym znakom. Słowo bi-
towe traktujemy w tej reprezentacji jako ścieżkę od korzenia do znaku, przyj-
mując umownie, że O oznacza „przejście do lewego syna", a 1 „przejście do
prawego syna" w drzewie. Na rysunku 17.4 widać drzewa odpowiadające ko-
dom z naszego przykładu. Należy tutaj zaznaczyć, że nie są to drzewa po-
szukiwań binarnych, ponieważ liście nie muszą być uporządkowane, a węzły
wewnętrzne nie zawierają kluczy znak.ów.

100 100
o 1 o
a:45
Il
14

(a) (bi

Rys. 17.4, Drzewa odpowiadające kodom z rys. 17.3. Kai.dy liść jesl etykielowany znakiem i liczbą
jego wystąpień w pliku. Każ.dy węzeł wewnętrmy jest etykielowany sumą wag liści w poddrzewie,
którego jest korzeniem. (a) Drzewo odpowiadające kodowi o sWej długości 11= OOO,..., f = !Ol.
(b) Orz.ewo odpowiadające optymalnemu kodowi prefiksowemu 11 = O, b = 101, ... , f = 1100

Optymalny kod jest zawsze reprezentowany przez regularne drzewo binar-


ne, w którym każdy węzeł wewnętrzny ma dwóch synów (patrz zad. 17.3-1).
Kod o ustalonej długości z naszego przykładu nie jest optymalny, bo jego
drzewo, przedstawione na rys. 17.4a, nie jest regularnym drzewem binarnym:

385
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

są kody rozpoczynające się od 10... , lecz nie ma kodu o początku 11... Możemy
się, bez zmniejszenia ogólności, ograniczyć do regularnych drzew binarnych,
wobec tego jeśli bierzemy pod uwagę znaki ze zbioru (alfabetu) C, to drzewo
optymalnego kodu prefiksowego ma dokładnie ]Clliści oraz dokładnie ICI- 1
węzłów wewnętrznych.
Mając dane drzewo T odpowiadające kodowi prefiksowemu, łatwo jest
obliczyć liczbę bitów potrzebnych do zakodowania pliku. Niech dla każdego
znaku c z alfabetu C liczba /(c) będzie liczbą występień znaku c w pliku,
a dr(c) długością kodu znaku c. Liczba bitów potrzebnych do zakodowania
pliku jest więc równa

B(1) - 'i,J(c)dT(c) (17.3)


~,
Liczbę tę nazywamy także kosztem drzewa T.

Tworzeniekodu Huffmana
Huffman wynalazł algorytm zachłanny, za pomocą którego jest tworzony op-
tymalny kod prefiksowy, nazywany na jego cześć kodem Huffmana. Algorytm
polega na budowaniu w sposób wstępujący drzewa T odpowiadającego op-
tymalnemu kodowi. Zaczyna się od zbioru ICI liści, a następnie wykonuje się
ICI- 1 operacji „scalania", które dają w efekcie jedno drzewo.
W następującej procedurze przyjmujemy, że C jest zbiorem n znaków i że
każdemu znakowi ce C odpowiada jego liczba wystąpień/{c}. Kolejka priory-
tetowa Q z atrybutami/ w roli kluczy została użyta do wyznaczania dwóch
obiektów o najmniejszej liczbie wystąpień, które należy scalić. Wynikiem scale-
nia dwóch obiektów jest nowy obiekt, którego liczba wystąpień jest sumą licz-
by wystąpień jego składowych.

HUFFMAN(C)
1 n~1c1
2 Q~c
3 fori+-1 ton-I
4 do z +- AL LOCATE-N ODEQ
5 x~ /eft[z] ~ EXTRACT-MIN(Q)
6 y +- right[z] +- EXTRACT-MIN(Q)
7 /[z]~ /[x] +f[y]
8 INSERT(Q, z)
9 return EXTRACT-MIN(Q)

Działaniealgorytmu Huffmana dla naszego wcześniejszego przykładu jest po-


kazane na rys. 17.5. Alfabet C jest 6-literowy, początkowy rozmiar kolejki

386
17.3. KODY HUFFMANA

(b) lc:12] lb:131 14


o )

,,, 14 (d)
'
25 30
o I o I
1c:121 1b:IJ1 14 ld:16
o I
lf:511•:91

(e} la:45j ,,, (fi


o I
25 3-0 a:45
o I o I
lc:121 b:13i 14 ld:16 25 30
o I o
1f:S11•:91 14
o I

Rys. 17.5. Kroki algorytmu Huffmana dla częstości wystąpień znaków z rys. 17.3. Każda część
przedstawia zawartość kolejki uponądkowaną według częstości wystąpień. W każdym kroku dwa
drzewa o najmniejszej liczbie wystąpień zostają sca..lone.Liście są pnedstawione jako prostokąty
zawierające znak i częstość jego wystąpień. Węzły wewnętrzne są reprezentowane przez kółka
zawierające sumę częstości wystąpień ich dzieci. Krawędż etykietowana O łączy węzeł wewnętrzny
z jego lewym synem, a etykietowana I - z prawym. Kod litery jest ciągiem etykiet krawędzi na
ścieżce cxl korzenia do liścia etykietowanego tą literą. (•) Początkowy zbiór n = 6 liści, po jednym
dla każdej litery. (bKe) Fazy przejściowe. (0 Końcowe drr.ewo

Q wynosi więc n = 6, a budowa drzewa wymaga 5 scaleń. Ostatnie drzewo


odpowiada optymalnemu kodowi prefiksowemu. Kod litery jest ciągiem ety-
kiet krawędzi na ścieżce od korzenia do liścia etykietowanego tą literą.
W wierszu 2 do kolejki Q zostają wstawione znaki u zbioru C. W pętli for,
w wierszach 3-8, są cyklicznie usuwane dwa węzły o najmniejsrej liczbie wy-
stąpień, a następnie zastępowane w kolejce Q przez węzeł z, powstały przez ich
scalenie. Jako liczbę wystąpień z traktuje się sumę liczb wystąpień x oraz
y (wiersz 7). Węzły x i y stają się odpowiednio lewym i prawym synem węzła z.
(fen porządek jest dowolny; zamiana lewego i prawego syna daje inny kod
o tym samym koszcie). Po n - 1 scaleniach w kolejce jest już tylko jeden węzeł
- korzeń drzewa kodu.

387
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

W analizie czasu działania algorytmu Huffmana zakładamy, że kolejka


Q jest zaimplementowana jako kopiec binarny (patrz rozdz. 7). Dla zbioru
Q zawierającego n znaków inicjowanie Q w wierszu 2 kosztuje O(n) jednostek
czasu, o ile zastosujemy procedurę BUILD-HEAP z pod.rozdz. 7 .3. Pętla for
w wierszach 3-8 jest wykonywana dokładnie n - 1 razy, a ponieważ każda
operacja na kopcu wymaga O(lgn) czasu, więc w sumie czas jej wykonania
można ograniczyć przez O(n lgn). Czas działania procedury HUFFMAN wynosi
zatem O(nlgn).

Poprawność algorytmu Huffmana

Aby wykazać poprawność zachłannego algorytmu Huffmana, pokażemy, że


problem wyznaczania optymalnego kodu prefiksowego ma zarówno własność
wyboru zachłannego, jak i optymalną podstrukturę. Następujący lemat mówi,
że zachodzi własność wyboru zachłannego.

LEMAT17.2.
Niech C będzie alfabetem, a każdy znak ce C występuje J[c] razy. Niech
x i y będą parą znaków z C o najmniejszej liczbie wystąpień. Istnieje wtedy
optymalny kod prefiksowy dla C, w którym kody dla x i y mają tę samą
długość i różnią się tylko na ostatnim bicie.

DOWÓD
Idea dowodu polega na zmodyfikowaniu drzewa T reprezentującego dowolny
optymalny kod prefiksowy, aby odpowiadało ono innemu optymalnemu ko-
dowi prefiksowemu o tej własności, że znaki x i y są reprezentowane przez
bliźniacze liście o największej głębokości w drzewie. Jeśli uda się nam wykonać
taką operację, to kody x i y będą rzeczywiście miały równą długość i będą się
różnić tylko na ostatnim bicie.

T' T"
T"
- /-
b
-b
y

' • ' y

Rys. 17.6. llustraeja kluczowego kroku w dowodzie lematu 17.2. W optymalnym drzewie T liście
bi c są najgłębszymi liśćmi i slanowią rodzeństwo. Liście .:ci y są liśćmi, które algorytm Huffma-
na scala w pierw&zym kroku; znajdują się one na dowolnych pozycjach w T. Liście b oraz
x zostają rnmienione miejscami, przez co otrzymujemy drzewo r. Następnie liściec oraz y zo-
stają zamienione miejscami, w wyniku czego otrzymujemy drzewo T». Ponieważ iadna zamiana
nie powiększa kosztu, wynikowe drzewo T" jest również optymalne

3~8~8-----------------------
17.3. KODY HUFFMANA

Niech b i c będą bliźniaczymi znakami o największej głębokości w drzewie


T. Nie zmniejszając ogólności, możemy założyć, że/[b] ~/[c] oraz/[x] ~f[y].
Ponieważ f[x] i f[y] są najmniejszymi liczbami wystąpień dla liści, zachodzą
więc nierówności/[x] ~/[b) oraz/[y] ~/[c]. Jak widać na rys. 17.6, w Tza-
mieniamy miejscami liście bi x, otrzymując drzewo T', a następnie w T' zamie-
niamy miejscami liście c i y, otrzymując drzewo T". Zgodnie z równaniem
(17 .3) różnica w koszcie między Ta T' wynosi

B(T) - B(T') ~ 2,/(c)d,(c) - 2,/(c)d,,(c)

~ f[x]d,(x) + f[b]d,.(b) - f[x]d,,(x) - f[b]d,,(b)


~ f[x]d,(x) +f[b]d,(b) - f[x]d,(b) - f[b]d,.(x)
~ (f[b] - f[x])(d,(b) - d,(x))
;,,o
ponieważ zarówno f[b] - f[x], jak i di{b) - dr(x) są nieujemne. Dokładniej,
f[b] - f[x] jest nieujemne, ponieważ x jest liściem o najmniejszej liczbie wy-
stąpień, a dr(b) - dr(x) jest nieujemne, bo b jest liściem o maksymalnej głębo­
kości w T. Podobne rozumowanie (zamiana y i c nie powiększa kosztu) po-
zwala wykazać, że B(T') - B(T") jest nieujemne. Dlatego B(T") ~ B(T), a po-
nieważ Tjest optymalne, tj. B(T) <; B(T"), więc B{T") ~ B{T). Stąd wynika, że
T" jest optymalnym drzewem, w którym x i y są bliźniaczymi liśćmi o najwięk­
szej głębokości, co pociąga za sobą tezę lematu.

Z lematu 17.2 wynika, że budowanie optymalnego drzewa przez scalanie
może bez utraty ogólności być rozpoczęte od wyboru zachłannego, tj. scalenia
dwóch znaków o najmniejszej liczbie wystąpień. N a czym polega zachłanność
takiego wyboru? Możemy traktować koszt scalenia jako sumę liczb wystąpień
scalanych obiektów. W zadaniu 17,3-3 wykazujemy, że sumaryczny koszt drze-
wa jest równy sumie kosztów scaleń wykonywanych w czasie jego budowy.
Spośród wszystkich możliwych w każdym kroku scaleń procedura HUFFMAN
wybiera to, którego koszt jest najmniejszy.
Kolejny lemat pokazuje, że problem konstruowania optymalnych kodów
prefiksowych ma własność optymalnej podstruktury.

LEMAT17.3.
Niech T będzie regularnym drzewem binarnym odpowiadającym optymalne-
mu kodowi prefiksowemu nad alfabetem C. Dla każdego znaku ce C definiuje-
my /[c] jako liczbę jego wystąpień. Załóimy, że znaki x oraz y występują
w T jako bracia i niech z będzie ich ojcem. Wtedy, traktując z jako znak

389
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

o liczbie wystąpień f[z] = f[x] + f[y], drzewo T' = T- {x, y} reprezentuje


optymalny kod prefiksowy dla alfabetu C' = C - {x, y} u {z}.

DOWÓD
Wykażemy najpierw, że koszt B(T) drzewa T można wyrazić w kategoriach
kosztu B(T') drzewa T', biorąc pod uwagę składniki kosztu w równaniu 17.3.
Dla każdego ccC- {x, y} mamy d,(c) = d,,(c), więc też i f[c]dr(c) =
= f[y]dT,(c). Ponieważ dT(x) = dT(y) = dT,(z) + 1, zachodzą więc równości

f[x]d,(x) + f[y]d,(y) = (f[x] + f[y])(d,,(z) + 1)


= f[z]d,,(z) + (f[x] + f[y])
skąd wynika, że

B(T) = B(T') + f[x] + f[y]


Jeśli założymy, że T' reprezentuje nieoptymalny kod prefiksowy dla alfabetu
C', to istnieje drzewo T", którego liście są znak.ami z C', oraz B(T") < B(T').
Ponieważ z traktujemy jako mak w C', wobec tego w T" występuje on jak.o liść.
Jeśli dodamy x i y jako synów węzła z w drzewie T", to otrzymamy w ten sposób
kod prefiksowy dla C o koszcie B(T") +f[x] + f[y] < B(T), co jest sprzeczoe
z założeniem o optymalności T. Stąd T' musi być optymalne dla alfabetu C' .

TwlERDZENIE 17.4.

Procedura HUFFMANgeneruje optymalny kod prefiksowy.

DOWÓD
Natychmiastowy z lematów 17.2 i 17.3.

ZADANIA

17.3-1. Udowodnij, że drzewo binarne, które nie jest regularne, nie może od-
powiadać optymalnemu kodowi preftk:sowemu.
17.3-2. Jaki jest optymalny kod Huffinana dla następującego zbioru częstości
wystąpień liter opartego na początkowych 8 liczbach Fibonacciego?

a:1 b:l c:2 d:3 e:5 f:8 g:13 h:21

Uogólnij swoją odpowiedź na przypadek, gdy częstości wystąpień stano-


wi n początkowych liczb Fibonacciego.

390
* 17.4. TEORETYCZNE PODSTAWY STRATEGII ZACHŁANNYCH
17.3-3. Udowodnij, że koszt całego
drzewa kodu można obliczyć jako sumę, po
wszystkich węzłach wewnętrznych, sum częstości wystąpień ich potomków.
17.3-4. Udowodnij, że dla optymalnego kodu i ciągu znaków o nierosnących
częstościach wystąpień odpowiedni ciąg długości ich kodów jest niemalejący.
17.3-5. Niech C = {O, 1, ..., n -1} będzie zbiorem znak.ów. Udowodnij, że
każdy optymalny kod prefiksowy dla C można przedstawić za pomocą

ciągu

2n-l +n 1Ignl
bitów. (Wskaz6wka: Użyj 2n - 1 bitów do reprezentacji drzewa).
17.3-6. Uogólnij algorytm Huffmana do kodów trójkowych (tzn. kodów uży~
wających symboli O, 1 i 2) i udowodnij, że generuje on optymalne kody
trójkowe.
17.3-7. Załóżmy, że plik danych zawiera 8-bitowe znaki i wszystkich 256 zna-
ków występuje w przybliżeniu równie często: maksymalna częstość wystą­
pienia znak.u jest co najwyżej dwa razy większa od najmniejszej częstości
wystąpienia innego znaku. Udowodnij, że kody Huffmana nie dają w ta-
kiej sytuacji żadnego zysku w porównaniu ze zwykłym 8-bitowym kodem.
17.3-8. Wykaż, że żadna metoda kompresji nie może zagwarantować zmniej-
szenia pliku losowo wybranych 8-bitowych znaków nawet o jeden bit.
(Wskazówka: Porównaj liczbę plików z liczbą potencjalnych plików skom-
presowanych).

*17.4. Teoretycznepodstawystrategiizachłannych
W tym podrozdziale przedstawiamy teorię związaną z algorytmami zachłan­
nymi. "feoria ta bywa użyteczna w określaniu, w jakich sytuacjach strategia
zachłanna prowadzi do optymalnych rozwiązań. Dotyczy ona obiektów kom-
binatorycznych zwanych „matroidami". Mimo że teoria matroidów nie obej-
muje wszystkich przypadków stosowania metody zachłannej (w szczególności
nie daje się zastosować do problemu wyboru zajęć z podrozdz. 17.1 lub prob-
lemu kodów Huffmana z podrozdz. 17.3), jednak znajduje wiele praktycznych
zastosowań. Co więcej, teoria ta gwałtownie się rozwinęła i znalazła wiele róż­
norodnych zastosowań; w uwagach na końcu tego rozdziału moi-na znaleźć
odpowiednie odnośniki do literatury.

17.4.1. Matroidy
Matroid jest parą uporządkowaną M = (S, Jf) spełniającą następujące warunki:

1. Sjest skończonym niepustym zbiorem.

391
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

2. J to taka niepusta rodzina podzbiorów S, zwana rodziną niezależnych pod-


zbiorów S, że jeśli BEJ oraz Ac B, to AEJ. Mówimy czasem, że J jest
dziedziczne, jeśli ma tę własność. Zauważmy, że zbiór pusty 0 jest zawsze
elementem J.
3. Jeśli AEJ, BEJ i )Al<IB!, to istnieje taki element xEB-A, że
A u {x}E..f. Mówimy wtedy, że Mma własność wymiany.

Słowo „matroid" zostało wprowadzone przez Hasslera Whitneya. Zajmo-


wał się on matroidami macierzowymi, w których elementami zbioru S były
wiersze pewnej macierzy. Zbiór wierszy jest w tym kontekście niezależny, jeśli
jest liniowo niezależny w zwyczajnym sensie. Łatwo jest wykazać, że taka stru-
ktura rzeczywiście definiuje matroid w powyższym sensie (patrz zad. 17.4-2).
Innym przykładem matroidu jest matroid grafowy MG = (SG, JG), zdefi-
niowany na grafie nieskierowanym G = (V, E) w następujący sposób:
• SG = E (zbiór krawędzi G).
• Jeśli A jest podzbiorem E, to AE.J'G, wtedy i tylko wtedy, gdy A jest
acykliczny (tzn. zbiór krawędzi jest niezależny wtedy i tylko wtedy, gdy
tworzy las).
Matroid grafowy MG jest ściśle związany z problemem minimalnego drze-
wa rozpinającego, który szczegółowo omówimy w rozdz. 24.

TwlERDZENIE17.5.
Jeśli G jest grafem nieskierowanym, to MG = (SG, JG) jest matroidem.

DOWÓD
Oczywiście SG = E jest zbiorem skończonym. Zbiór Jo jest dziedziczny, ponie-
waż podzbiór lasu jest też lasem. Inaczej mówiąc, usuwając krawędzie z acyk-
licznego zbioru krawędzi, nie można utworzyć nowego cyklu.
Pozostaje zatem wykazać, że MG ma własność wymiany. Załóżmy, że
A i B są lasami w G oraz że IBI> IAI,tzn. A oraz B są acyklicznymi zbiorami
krawędzi, przy czym B zawiera więcej krawędzi niż A.
Z twierdzenia 5.2 wynika, że las zawierający k krawędzi składa się z do-
kładnie IV]- k drzew. (Oto inne uzasadnienie: rozpoczynamy od IVIdrzew
i żadnych krawędzi. Dodanie do lasu każdej nowej krawędzi miniejsza liczbę
drzew o 1). Stąd wnioskujemy, że las A składa się z IVI- IAIdrzew, a las
B składa się z IV]- IBJdrzew.
Las B zawiera mniej drzew niż las A, musi więc zawierać pewne drzewo T,
którego wierzchołki leżą w dwóch różnych drzewach lasu A. Co więcej, Tmusi
zawierać taką krawędź (u, v), że wierzchołki u oraz v znajdują się w różnych
drzewach lasu A, ponieważ T jest spójne. Krawędź (u, v) łączy wierzchołki
w dwóch różnych drzewach w lesie A, może więc ona zostać dołączona do A,

392
* 17.4. TEORETYCZNE PODSTAWY STRATEGI! ZACHŁANNYCH

nie tworząc cyklu. Pokazaliśmy w ten sposób, że MG spełnia własność wymia-


ny, co kończy dowód, iż MG jest matroidem. +
Dla danego matroidu M = (S, J) element xf:A nazywamy rozszerzeniem
AE J, jeśli x można dodać do A, zachowując niezależność; mówiąc inaczej
x jest rozszerzeniem A, jeśli A u {x} EJ. Rozważmy dla przykładu matroid
grafowy MG· Jeśli A jest niezależnym zbiorem krawędzi, to krawędź e jest
rozszerzeniem A wtedy i tylko wtedy, gdy e nie należy do A oraz gdy dodanie
x do A nie powoduje powstania cyklu.
Jeśli A jest niezależnym zbiorem matroidu M, to mówimy, że zbiór A jest
maksymalny,jeśli nie ma rozszerzeń. Inaczej mówiąc, A jest maksymalny, jeżeli
nie zawiera się w żadnym większym, niezależnym podzbiorze M. Często korzy-
sta się z następującej własności.

TwlERDZENIE 17.6.
Wszystkie maksymalne niezależne podzbiory matroidu mają ten sam rozmiar.

DOWÓD
Załóżmy przeciwnie, że A jest maksymalnym niezależnym podzbiorem M oraz
że istnieje inny, większy, maksymalny niezależny podzbiór B matroidu M.
Wtedy z własności wymiany wynika, że A można rozszerzyć do większego
zbioru niezależnego Au{x} dla pewnego xEB-A, co przeczy założeniu
o maksymalności A. +
Jako ilustrację tego twierdzenia rozpat..t2llly matroid grafowy MG dla spój-
nego grafu nieskierowanego G. Każdy maksymalny niezależny podzbiór MG
musi być drzewem o dokładnie IVl- I krawędziach, które łączą wszystkie
wierzchołki grafu G. Takie drzewo jest nazywane drzewemrozpinającym (ang.
spanning tree) grafu G.
Mówimy, że matroid M = (S, J) jest ważony, jeśli istnieje związana z nim
funkcja wagi w, która przypisuje dodatnią wagę w(x) każdemu elementowi
xES. Funkcja wagi w rozszerza się do podzbiorów Sza pomocą sumowania
w(A) ~ L w(x)
~,
po dowolnym zbiorze A c S. Jeśli na przykład w(e) oznacza długość krawędzi
e wmatroidzie grafowym MG, to w(A) jest sumą długości krawędzi ze zbioru A.

17.4.2. Algorytmy zachłanne na matroidzie ważonym


Wiele problemów, dla których strategia zacWanna daje optymalne rozwiąza­
nia, można sformułować w kategoriach wyznaczania niezależnego zbioru

393
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

o największej wadze w ważonym matroidzie. Inaczej mówiąc, dla danego wa-


żonego matroidu M = (S, J), szukamy takiego zbioru niezależnego AeJ, że
w(A) jest największe. Taki niezależny podzbiór o maksymalnej wadze nazywa-
my optymalnym podzbioren1 matroidu. Waga w(x) każdego elementu x e Sjest
dodatnia, optymalny podzbiór musi więc być maksymalnym zbiorem niezależ­
nym - dzięki temu założeniu można zawsze wybierać A jak największe.
Na przykład w problemie minimalnego dnewa rozpinającego jest dany graf
nieskierowany G = (V, E) oraz funkcja długości w taka, że w(e) jest (dodatnią)
długością krawędzi e. (Używamy tutaj tenninu „długość" w odniesieniu do
zwyczajowych „wag" krawędzi w grafie, ograniczając użycie słowa „waga" do
związanego z nim matroidu). Zadanie polega na znalezieniu podzbioru krawędzi
łączących wszystkie wierzchołki o minimalnej sumie długości. Aby sformułować
ten problem w kategoriach optymalnego podzbioru matroidu, rozważmy ważo­
ny matroid Me z funkcją wagi w', gdzie w'(e) = w0 - w(e), a w0 jest większe niż
długość każdej krawędzi. W tym matroidzie ważonym wszystkie wagi są dodat-
nie, a podzbiór optymalny stanowi drzewo rozpinające pierwotnego grafu o mi-
nimalnej sumie długości. Mówiąc dokładniej, każdy maksymalny niezależny
podzbiór A odpowiada pewnemu drzewu rozpinającemu, a ponieważ

w'(A)- (IJ/1- l)w, - w(A)

dla każdego maksymalnego niezależnego podzbioru A, więc niezależny podzbiór,


który maksymalizuje w'(A), musi minimalizować w(A). Dzięki tej obserwacji
wiemy, że dowolny algorytm znajdujący optymalny podzbiór A w matroidzie
może posłużyć do rozwią:zania problemu minimalnego drzewa rozpinającego.
W rozdziale 24 opiszemy algorytm służący do rozwiązywania problemu
minimalnego drzewa rozpinającego; tutaj podajemy algorytm zachłanny, który
działa dla dowolnego matroidu ważonego. Dane wejściowe dla algorytmu sta-
nowi matroid ważony M = (S, J) wraz z dodatnią funkcją wagi w;za pomocą
algorytmu jest znajdowany optymalny podzbiór A. W naszej procedurze ozna-
czamy składniki matroidu M przez S[.M] oraz .l[M], a funkcję wagi przez
w. Algorytm jest zachłanny, ponieważ rozpatruje każdy element xeS w po-
rządku nierosnących wag i natychmiast dodaje x do zbioru A, jeśli A u {x}
jest niezależny.

GREEDY(M, w)
1 A.._0
2 uporządkuj S[.M] nierosnąco według wagi w
3 for xeS[.M], brane w porządku nierosnącym według wagi w(x)
4 do if A u {x}E.f[M]
5 thenA-Au{x}
6 return A

394
* 17.4. TEORETYCZNE PODSTAWY STRATEGII ZACHŁANNYCH

Elementy zbioru S są rozpatrywane kolejno w porządku malejącej wagi.


Jeśli właśnie rozważany element x może zostać dodany do A, nie wyprowadza-
jąc A poza klasę zbiorów niezależnych, to zostaje dodany. W przeciwnym razie
x zostaje odrzucony. Zbiór pusty jest niezależny z definicji matroidu; x jest
dodawany do A tylko wtedy, kiedy A u {x} jest niezależny, więc przez indukcję
wnioskujemy, że podzbiór A jest zawsze niezależny. Algorytm GREEDY wyzna-
cza zatem zawsze zbiór niezależny A. Przekonamy się za chwilę, że A jest
dodatkowo podzbiorem o maksymalnej możliwej wadze, jest więc w istocie
pozdbiorem optymalnym.
Czas działania algorytmu GREEDY łatwo jest oszacować. Niech n oznacza
ISI. Faza sortowania w algorytmie GREEDY zajmuje czas O(nlgn). Wiersz
4 jest wykonywany dokładnie n razy; raz dla każdego elementu zbioru S. Każ­
de wykonanie wiersza 4 wymaga sprawdzenia, czy zbiór A u {x} jest niezależ­
ny. Jeśli każde takie sprawdzenie wymaga czasu O(f(n)), to czas działania
całego algorytmu można ograniczyć przez O(nlgn + n/(n)).
Udowodnimy teraz, że procedura GREEDY wyznacza optymalny podzbiór.

LEMAT 17.7. (Matroidy mają własność zachłannego wyboru)


Załóżmy, że M = (S, J) jest matroidem ważonym z funkcją wagi w oraz że
Sjest uporządkowany nierosnąco według wag. Niech x będzie pierwszym ele-
mentem S takim, że {x} jest niezależny. Jeśli takie x istnieje, to wtedy istnieje
optymalny podzbiór A zbioru S zawierający x.

DOWÓD
Jeś1i nie istnieje takie x, to jedynym zbiorem niezależnym jest zbiór pusty i teza
jest trywialnie spełniona. W przeciwnym razie niech B będzie niepustym zbio-
rem optymalnym. Przypuśćmy, że xfB (w przeciwnym wypadku bierzemy
A = Bi teza znów wynika trywialnie).
Żaden element zbioru B nie ma wagi większej niż w(x). Aby się o tym
przekonać, wystarczy zauważyć, że jeśli y EB, to {y} jest niezależny, ponieważ
BEJ, a J jest dziedziczne. Nasz wybór x gwarantuje więc, że w(x) ;?!=w(y) dla
każdego y EB.
Tworzenie zbioru A przebiega następująco. Zaczynamy od A= {x}. Dzięki
wyborowi x zbiór A jest zbiorem niezależnym. Korzystając wielokrotnie z włas­
ności wymiany, dodajemy do A pewne elementy B, zachowując niezależność A,
aż nie osiągniemy IAI =IBI.Wtedy A= B - {y} u {x} dla pewnego yEB, więc

w(A) = w(B) - w(y) + w(x)


;, w(B)

Zbiór A jest zatem optymalny (bo B jest optymalny) oraz xEA, co kończy
dowód lematu. ł

395
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

Wykażemy teraz, że jeśli element nie może być początkowo dołączony, to


już nigdy nie będzie musiał być rozpatrywany.

LEMAT 17.8.
Niech M = (S, .I) będzie dowolnym matroidem. Jeśli xe S nie jest rozszerze-
niem zbioru 0, to x nie jest rozszerzeniem żadnego niezależnego zbioru A.

DOWÓD
Dowód przeprowadzamy przez doprowadzenie do sprzeczności, Załóżmy, że
x jest rozszerzeniem zbioru A, choć nie jest rozszerzeniem zbioru pustego 0.
Ponieważ x jest rozszerzeniem A, zbiór A u {x} jest więc niezależny. Ale z defi-
nicji matroidu wiadomo, że .I jest dziedziczny, zatem {x} jest zbiorem nieza-
leżnym, co jest sprzeczne z założeniem, że x nie jest rozszerzeniem 0.


Lemat 17.8 mówi, że jeśli elementu nie daje się użyć natychmiast, to na
zawsze pozostaje bezużyteczny. Dlatego nie może być błędem pomijanie w pro-
cedurze GREEDY elementów S, które nie są rozszerzeniem 0, bo i tak nie
należą do żadnego zbioru niezależnego.

LEMAT 17.9. (Matroidy wykazują własność optymalnej podstruktury)


Niech x będzie pierwszym elementem wybranym przez procedurę GREEDY
w matroidzie ważonym M = (S, .I). Pozostający problem znalezienia niezależ­
nego podzbioru o maksymalnej wadze zawierającego x sprowadza się do prob-
lemu znalezienia niezależnego podzbioru o maksymalnej wadze w matroidzie
ważonym M' = (S', J'), gdzie

S' - (yeS: (x, y}e.J'}

.J'' - (B c S- (x}:Bu (x}e.J'}

oraz funkcja wagi dla M' jest funkcją wagi dla M ograniczoną do S'. (Taki
matroid M' nazywamy kontrakcją Mo element x).

DOWÓD
Jeśli A jest niezależnym podzbiorem o maksymalnej wadze zawierającym x, to
A'= A - {x} jest niezależnym podzbiorem w M'. Odwrotnie, każdy niezależ­
ny podzbiór A' matroidu M' odpowiada niezależnemu podzbiorowi
A - A' u {x} matroidu M. W obu przypadkach w(A) - w(A') + w(x), zatem
rozwiązanie o maksymalnej wadze w matroidzie M zawierające x odpowiada
optymalnemu rozwiązaniu w M' i na odwrót.

396
* 17.4. TEORETYCZNE PODSTAWY STRATEGII ZACHŁANNYCH
TwIERDZENIE17.10. (Poprawność algorytmu zachłannego na matroidacb)
Jeśli M = (S, $) jest ważonym matroidem z funkcją wagi w, to w wyniku
wywołania procedury GREEDY(M, w) jest wyznaczany optymalny podzbiór.

DOWÓD
Lemat 17,8 daje gwarancję, że każdy element początkowo pominięty, ponieważ
nie jest rozszerzeniem 0, może być pominięty w dalszym postępowaniu, bo
i tak pozostanie bezużyteczny. Z kolei z lematu 17.7 wynika, że pierwszy wy-
brany element x można dodać do A, ponieważ istnieje optymalny zbiór zawie-
rający x. Wreszcie z lematu 17.9 wynika, że po wyborze elementu x problem
polega na znalezieniu optymalnego podzbioru w matroid:rie M', będącym
kontrakcją matroidu M o element x. Po zainicjowaniu zmiennej A jednoele-
mentowym zbiorem {x} działanie procedury GREEDY można interpretować
jako działanie na matroidzie M' = (S', $'), ponieważ B jest zbiorem niezależ­
nym w M' wtedy i tylko wtedy, gdy Bu {x} jest niezależny w M. Następne
kroki algorytmu GREEDYdoprowadzą zatem do znalezienia niezależnego pod-
zbioru w M' o maksymalnej wadze, a w ostatecznym rozrachunku w wyniku
wykonania całej procedury GREEDY zostanie wyznaczony podzbiór niezależny
matroidu M o maksymalnej wadze. +
ZADANIA

17.4-1. Wykaż, że (S, ~) jest matroidem., gdzie Sjest dowolnym skończonym


zbiorem, a $k jest zbiorem wszystkich podzbiorów S o rozmiarze co naj-
wyżej k, dla k <. ISJ.
* 17.4-2. Dla danej macierzy To wartościach rzeczywistych i wymiarze n x n
wykaż, że (S, $) jest matroidem, gdzie Sjest zbiorem kolumn macierzy
T, i AE$ wtedy i tylko wtedy, gdy kolumny należące do A są liniowo
niezależne.
* 17.4-3. Wykaż, że jeśli (S, J) jest matroidem, to matroidem jest także (S, $'),
gdzie J' = {A': S- A' zawiera pewien maksymalny AE$}. Z defmicji tej
wynika, że maksymalne niezależne podzbiory matroidu (S', $') są dopeł­
nieniami maksymalnych niezależnych podzbiorów matroidu (S, $).
* 17.4-4. Niech S będzie skończonym zbiore:tn, a S 1 , S 2 , ... , S„ podziałem. S na
niepuste rozłączne podzbiory. Zd.efmiujmy strukturę (S, $) za pomocą
warunku J - {A: IA u S,I <; I dla i - I, 2, ... , k). Wykaż, że (S, J) jest
matroidem, Inaczej mówiąc, rodzina wszystkich zbiorów A zawierających
po co najwyżej jednym elemencie z każdego bloku podziału wyznacza ro-
dzinę zbiorów niezależnych pewnego matroidu.
17.4-5. Jak należy przedefiniować funkcję wagi matroidu ważonego, aby zwy-
czajny algorytm znajdowania optymalnego zbioru w matroidzie ważonym
wyznaczał maksymalny zbiór niezależny o minimalnej wadze. Uzasadnij
dokładnie poprawność swojej konstrukcji.

397
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

*17.5. Problemszeregowaniazadań
Jednym z interesujących problemów, które można rozwiązać przy użyciu ma-
troidów, jest problem optymalnego szeregowania zadań o jednostkowym cza-
sie wykonywania z karami za przekroczenie terminu wykonania. Problem wy-
daje się dość skomplikowany, lecz daje się go rozwiązać zaskakująco łatwo za
pomocą algorytmu zachłannego.
Zadanie o jednostkowym czasie wykonania jest czynnością, taką jak pro-
gram działający na komputerze, której wykonanie wymaga jednostkowego
czasu. Dla danego zbioru zadań S ich uszeregowanie jest permutacją S od-
powiadającą kolejności ich wykonywania. Pierwsze zadanie w uszeregowaniu
zaczyna się w chwili O i kończy w chwili 1, drugie zaczyna w chwili I i kończy
w chwili 2 itd.
Problem szeregowania zadań o jednostkowym czułe wykonania z karami za
przekroczenie terminu wykonania ma następujące dane wejściowe:
• zbiór S = {1, 2, ... , n} zawierający n zadań o jednostkowym czasie wykonania;
• zbiór n dopuszczalnych terminów wykonania d 1 , d2 , ... , dn, takich że
1 ~ d1 ~ n, gdzie wykonanie zadania i ma zostać zakończone przed chwilą di;
• zbiór nieujemnych wag lub kar w1 , w2 , ••• , wn, takich że kara w1 zostaje
naliczona tylko wtedy, kiedy zadanie i nie jest zakończone przed chwilą d1•
Zadanie polega na znalezieniu uszeregowania zadań ze zbioru S, dla którego
suma naliczonych kar za niedotrzymanie terminu wykonania jest najmniejsza.
Rozważmy pewne uszeregowanie. Powiemy, że zadanie jest spóźnione
w tym uszeregowaniu, jeśli jego wykonanie kończy się po terminie. W przeciw-
nym razie mówimy, że zadanie jest terminowe. Dowolne uszeregowanie można
zawsze doprowadzić do terminowej postaci normalnej, w której terminowe za-
dania poprzedzają zadania spóźnione. Aby się o tym przekonać, wystarczy
zauważyć, że jeśli pewne spóźnione zadanie x poprzedza terminowe zadanie y,
to można zamienić je miejscami, po c-zym zadanie x nadal będzie spóźnione,
a y pozostanie terminowe.
Co więcej, przekonamy się, że każde uszeregowanie można sprowadzić do
postaci kanonicznej, w której terminowe zadania poprzedzają zadania spóźnio­
ne oraz wszystkie terminowe zadania są uporządkowane niemalejąco według
dopuszczalnych terminów wykonania. W tym celu sprowadzamy najpierw
uszeregowanie do terminowej postaci normalnej. Następnie, dopóki można
znależć terminowe zadania i oraz j, których wykonanie kończy się odpowied-
nio w chwilach ki k + 1, takie że di< tł,,, zamieniamy je miejscami w naszym
uszeregowaniu. Ponieważ zadanie j jest terminowe przed zamianą, więc
k + 1 ~ di. Stąd k + 1 < d1, czyli zadanie i po zamianie jest nadal terminowe.
Zadanie jw oczywisty sposób pozostaje nadal terminowe (zostanie teraz wyko-
nane jeszcze wcześniej).

398
* 17.5. PROBLEM SZEREGOWANIA ZADAŃ

Poszukiwanie optymalnego uszeregowania sprowadza się więc do wyzna-


czenia zbioru zadań A, które są terminowe w uszeregowaniu optymalnym.
Po wyznaczeniu A właściwe uszeregowanie tworzymy przez wypisanie elemen-
tów A uporządkowanych niemalejąco według dopuszczalnego terminu wyko-
nania, a następnie wypisanie zadań spóźnionych (tj. ze zbioru S - A) w do-
wolnym porządku. W ten sposób otrzymujemy kanoniczną postać optymat-

nego uszeregowama.
Mówimy, że zbiór zadań A jest niezależny, jeśli istnieje uszeregowanie tych
zadań, w którym żadne z nich nie jest spóźnione. Zbiór terminowych zadań
dowolnego uszeregowania jest oczywiście niezależny. Niech$ będzie rodziną
wszystkich niezależnych zbiorów zadań.
Rozważmy problem stwierdzania, czy dany zbiór zadań A jest niezależny.
Niech Ni(A) dla t = l, 2, ... , n, oznacza liczbę zadań w A, których dopuszczal-
ny termin wykonania jest wcześniejszy lub równy t.

LEMAT17.11.
Dla dowolnego zbioru zadań A są równoważne następujące warunki:

(I) zbiór A jest niezależny;


(2) dla t = l, 2, ... , n zachodzi nierówność N,(A) ~ t;
(3) jeśli zadania w A są uporządkowane niemalejąco według dopuszczalnego
terminu wykonania, to żadne zadanie nie jest spóźnione.

DOWÓD
Oczywiście, jeśli
Nr(A) > t dla pewnego t, to nie jest możliwe uszeregowanie dla
A bez spóźnionych zadań, ponieważ jest więcej niż t zadań, które należy wyko-
nać przed chwilą t. Dlatego (I) implikuje (2). Jeśli z kolei zachodzi (2), to już
wynika (3): skoro bowiem każdy i-ty w kolejności dopuszczalny termin wyko-
nania jest nie mniejszy od i, to szeregując zadania niemalejąco według tego
terminu, żadne zadanie nie jest spóźnione. Wreszcie z (3) trywialnie wynika (1) .

Używając własności (2) z lematu 17.11, łatwo możemy sprawdzić, czy dany
zbiór zadań jest niezależny (por. zad. 17.5-2).
Problem minimalizacji sumy kar za spóźnione zadania jest tożsamy z pro-
blemem maksymalizacji sumy kar odpowiadających terminowym zadaniom.
Następujące twierdzenie uzasadnia użycie algorytmu zachłannego do wyzna-
czania niezale7..nego zbioru zadań A o maksymalnej sumie kar.

TwlERDZENIE 17.12.
Jeśli
Sjest zbiorem zadań o jednostkowym czasie wykonania, a J jest rodziną
wszystkich niezależnych zbiorów zadań, to (S, $) jest matroidem.

399
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

DOWÓD
Każdy podzbiór niezależnego zbioru zadań jest też oczywiście niezależny. Aby
wykazać własność wymiany, załóżmy, że Bi A są zbiorami niezależnymi oraz
że ]BI > IAI. Niech k będzie największym takim t, że zachodzi Nr(B) ~ N 1(A).
Wiadomo, że N.(B) = IBI,N.(A) = IAIi [BI> IAI,więc k < n oraz dla każde­
go jz przedziału k + 1 ~j < n zachodzi N;(B) > Ni(A). Stąd B zawiera więcej
zadań niż A o dopuszczalnym terminie wykonania nie większym od k + 1.
Niech x będzie zadaniem w B - A o dopuszczalnym terminie nie większym od
k +I.Niech A'= A u {x}.
Korzystając z własności (2) z lematu 17.11, wykażemy teraz, że zbiór A'
musi być niezależny. Dla 1 ~ t ~ k mamy Nr(A') ~ Ni(A) ~ t, ponieważ A jest
niezależny. Dla k < t ~ n mamy Nt(A')::;;; Nr(B) ~ t, ponieważ B jest niezależ·
ny. Stąd A' jest niezależny, co kończy dowód, że (S, .I') jest matroidem.

Twierdzenie 17.10 uzasadnia użycie algorytmu zachłannego do znajdowa·
nia niezależnego zbioru zadań A o największej wadze. Możemy następnie łat.
wo utworzyć optymalne uszeregowanie, mając dany zbiór jego terminowych
zadań A. Metoda ta daje efektywny algorytm szeregowania zadań o jednow
stkowym czasie wykonania z karami za przekroczenie terminu wykonania.
Czas działania tego algorytmu wynosi O(n 2 ), ponieważ algorytm GREEDY wy-
konuje O(n) sprawdzeń, czy zbiór jest niezależny; każde takie sprawdzenie
wymaga czasu O(n) (patrz zad. 17.5-2). Szybsza implementacja jest opisana
w problemie 17-3.

Zadanie

I 2 3 4 5 6 7
d(4243146
w1 70 60 50 40 30 20 10

Rys. 17.7. Przykład problemu szeregowania zadań o jednostkowym czasie wykonania z karami za
przekroczenie terminu wykonania

N a rysunku 17.7 jest pokazany przykład problemu szeregowania zadań


o jednostkowym czasie wykonania z karami za przekroczenie terminu wykona-
nia. W tym przykładzie algorytm zachłanny wybiera zadania 1, 2, 3 i 4, następ­
nie odrzuca zadania 5 i 6, po czym dobiera zadanie 7. W efekcie otrzymujemy
optymalne uszeregowanie

(2, 4, 1, 3, 7, 5, 6)

którego suma kar wynosi w5 + w6 = 50.


400
PROBLEMY

Z4DANIA

17.5,,1. Rozwiąż problem szeregowania zadań z rys. 17.7 z każdą z kar w 1


:zamienioną na 80 - w1•
17.5,,2. Jak. użyć własności (2) z lematu 17.11 do stwierdzenia w czasie O(IAI),
C7.Yzbiór zadań A jest niezależny.

Problemy
17-1. Wydawaniereszty
Rozważmy problem wydawania reszty za pomocą jak najmniejszej liczby monet.

(a) Opisz algorytm zachłanny wydający resztę za pomocą monet o nominałach


1 gr, 2 gr, 5 gr, 10 gr, 20 gr i 50 gr. Udowodnij, że ten algorytm generuje
zawsze optymalne rozwiązanie.
(b) Przyjmij założenie, że monety mają nominały c0 , c 1 , ..• , ct dla pewnych
liczb całkowitych c > 1 oraz k ;;, I. Wykaż, że algorytm zachłanny daje
zawsze optymalne rozwiązanie.
(c) Podaj zbiór nominałów, dla którego algorytm zachłanny nie wyznacza op-
tymalnego rozwiązania.

17-2. Podgrafy acykliczne


(a) Niech G = (E, V) będzie grafem nieskierowanym. Opierając się na definicji
matroidu, wykaż, że (E, J) jest matroidem, jeżeli A e J, wtedy i tylko
wtedy, gdy A jest acykliC7.nym podzbiorem E.
(b) Macierz incydencji grafu nieskierowanego G = (V, E) jest macierzą
Mo wymiarre 111 x IEl taką, że M,. - I, jeśli krawędź e przylega do
wierzchołka v, i M,,,, = Ow przeciwnym razie. Udowodnij, że zbiór kolumn
macierzy M jest liniowo niezależny wtedy i tylko wtedy, gdy odpowiadają­
cy zbiór krawędzi jest acykliczny. Pcxiaj następnie alternatywny dowód, że
(E, J) z punktu (a) jest matroidem, opierając się na wyniku zad. 17.4-2.
(c) Załóżmy, że z każdą krawędzią e grafu nieskierowanego G = (V, E) jest
związana nieujemna waga w(e). Pcxiaj efektywny algorytm do wyznaczania
acyklic:znego podzbioru E o największej wadze.
(d) Niech G - (V, E) będzie dowolnym grafem skierowaoym i niech (E, .F)
będzie zdefiniowane tak, że AeJ wtedy i tylko wtedy, gdy A nie zawiera
żadnego cyklu skierowanego. Podaj przykład grafu skierowanego G, dla
którego struktura (E, J) nie jest matroidem. Określ, który warunek defini-
cji matroidu nie jest spełniony.
(e) Macierzą incydencji grafu skierowanego G = (V, E) jest macierz Mo wy-
miarze IVI x ]El,tak.a że Mp11 = -1, jeśli krawędź e wychodzi z wierzchołka
v, Mue = 1, jeśli krawędź e wchodzi do wierzchołka v, oraz MV/I= Ow prze-

401
ROZDZIAŁ 17. ALGORYTMY ZACHŁANNE

ciwnym razie. Udowodnij, że jeśli zbiór kolumn macierzy M jest liniowo


niezależny, to odpowiedni zbiór krawędzi nie zawiera cyklu skierowanego.
(ł) Z zadania 17.4-2 wiadomo, że rodzina liniowo niezależnych podzbiorów
kolumn dowolnej macierzy M jest matroidem. Wyjaśnij precyzyjnie, dla-
czego stwierdzenia zawarte w punktach (d) i (e) nie są. wzajemnie sprzeczne.
Gdzie załamuje się dokładna odpowiedniość między pojęciem acyklicznego
zbioru krawędzi a liniową niezależnością zbioru odpowiadających tym kra-
wędziom kolumn macierzy incydencji?

17-3. Inne metody szeregowania


Rozważ następujący algorytm dla problemu szeregowania zadań o jednostko-
wym czasie wykonania z karami za przekroczenie terminu. Początkowo wszys-
tkich n przedziałów czasu jest pustych (i-ty przedział czasu ma długość 1 i koń­
czy się w chwili 1). Rozpatrujemy zadania w kolejności malejących kar. Jeśli
rozpatrujemy zadanie j i istnieje pusty przedział czasu przed dopuszczalnym
terminem dla j, to zadanie j zajmuje najpóźniejszy taki przedział. Jeśli nato-
miast taki przedział nie istnieje, to j przypada najpóźniejszy spośród dotych-
czas nie zajętych przedziałów.

(a) Udowodnij, że ten algorytm wyznacza optymalne rozwiązanie.


(b) Użyj struktury danych dla zbiorów rozłącmych, opisanej w podro7.dz.
22.3, do efektywnej implementacji tego algorytmu. Przyjmij :założenie, że
zbiór zadań został wcześniej uporządkowany malejąco według kar za prze-
kroczenie dopuszczalnego terniinu wykonania. Oszacuj czas działania swo-
jej implementacji.

Uwagido rozdziału
Znacznie więcej informacji o algorytmach zachłannych i matroidach można
znaleźć w publikacjach Lawlera [132] oraz Papadimitriou i Steiglitza [154].
Algorytm zachłanny pojawił się po raz pierwszy w literaturze na temat
optymalizacji kombinatorycznej w artykule Edmondsa [62), choć teoria mat-
roidów jest znana od 1935 r., gdy swój artykuł na ten temat opublikował
Whitney [200].
Nasz dowód poprawności algorytmu zachłannego dla problemu wyboru
zajęć pochodzi od Gavrila [80]. Problem szeregowania zadań był studiowany
przez Lawlera [132], Horowitza i Sahniego [105] oraz Brassarda i Bratleya [33].
Kody Huffmana zostały wynalezione w 1952 r. [107]; w pracy Lelewera
i Hirchberga [136] znajduje się przegląd metod kompresji danych znanych
w 1987 r.
Teoria matroidów została rozszerzona do teorii greedoidów w pionierskich
pracach Korte'a i Lovasza [127, 128, 129, 130], którzy znacznie uogólnili teorię
przedstawioną w tym rozdziale.
Rozdział 18

Analizakosztu
zamortyzowanego

W analizie kosztu zamortyzowanego czas potrzebny na wykonanie ciągu opera-


cji na strukturze danych jest równo dzielony między wykonane operacje. Ana-
lizę kosztu zamortyzowanego można wykorzystać do wykazania, że średni
koszt operacji jest niewielki, jeśli wziąć pod uwagę cały ciąg operacji, mimo iż
pojedyncze operacje mogą być bardzo kosztowne. Analiza kosztu zamortyzo-
wanego różni się od analizy średniego kosztu tym, że nie polega na rozważa­
niach probabilistycznych. Koszt zamortyzowany operacji jest jej średnim kosz-
tem w najgorszym przypadku.
W pierwszych trzech podrozdziałach wprowadzimy trzy powszechnie uży­
wane metody analizy kosztu zamortyzowanego. W podrozdziale 18.1 omówi-
my metodę kosztu sumarycznego, w której należy określić górne ograniczenie
T(n) na całkowity koszt ciągu n operacji. Przez koszt ,:amortyzowany każdej
operacji rozumiemy wtedy T(n)/n.
W podrozdziale 18.2 opiszemy metodę księgowania (ang. accounting me-
thod), w której wyznaczamy koszt zamortyzowany każdej operacji. Jeśli mamy
do czynienia z różnymi rodzajami operacji, to każda z nich może mieć inny
koszt zamortyzowany. W metodzie księgowania zawyżamy koszt operacji znaj-
dujących się na pOC'lątku ciągu, wiążąc „nadpłaty" z pewnymi obiektami
w strukturze danych. Ten kredyt zostaje potem zużywany na „zapłacenie" za
operacje, których wkład jest mniejszy niż faktycmie poniesione koszty.
W podrozdziale 18.3 przedstawimy metodę potencjału, która - podobnie
jak metoda księgowania - umożliwia wyznaczanie kosztu zamortyzowanego
operacji i polega na przypisaniu większego kosztu wcześniejszym operacjom,
aby skompensować późniejsze nadmierne wydatki. W metodzie potencjału
,,kredyt" jest reprezentowany jak.o „energia potencjalna" całej struktury da-
nych i nie jest związana z pojedynczymi obiektami.

403
ROZDZIAŁ 18. ANALIZA KOSZTU ZAMORTYZOWANEGO

Do zilustrowania każdej z tych trzech metod użyjemy dwóch przykładów.


W pierwszym omówimy stos z dodatkową operacją MULTIPOP, która umo-
.zliwia zdjęcie ze stosu wielu elementów jednocześnie. W drugim przykładzie
przedstawimy licznik binarny zliczający od O za pomocą jedynej operacji
lNCREMENT.
Czytając ten rozdział, należy pamiętać, że kredyty przypisywane obiektom
struktury danych służą. tylko i wyłącz.nie analizie. Nie ma więc powodu, by
brać je pod uwagę przy implementacji algorytmów. Jeśli na przykład w meto-
dzie księgowania przypisujemy obiektowi x pewien kredyt, to nie ma potrzeby
przypisywać odpowiedniej wartości atrybutowi kredyt [x] w treści algorytmu.
Doświadczenia zdobyte przy analizie kosztu zamortyzowanego konkretnej
struktury danych mogą niejednokrotnie pomóc w jej ulepszeniu. W podroz-
dziale 18.4 wykorzystamy metodę potencjału do analizy tablicy o zmiennym

rozmiarze.

18.1. Metodakosztusumarycznego
W metodzie kosztu sUD1arycznego wykazujemy, że dla każdego n pesymistyczny
czas wykonania ciągu n operacji można ograniczyć przez T{n). W pesymistycz-
nym przypadku średni koszt lub koszt zamortyzowany pojedynczej operacji
wynosi wtedy 'I{n)/n. Należy zaznaczyć, że koszt zamortyzowany odnosi się
tutaj jednakowo do każdej operacji, nawet jeśli w ciągu pojawiają się operacje
różnych typów. Pozostałe dwie metody analizy kosztu zamortyzowanego (me-
toda księgowania i metoda potencjału) umożliwiają przypisywanie różnych ko-
sztów zamortyzowanych różnym rodzajom operacji.

Operacjena stosie
Pierwszy przykład zastosowania metody kosztu sumarycznego dotyczy stosów,
na których można wykonywać dodatkową operację MULTIPOP.W podrozdziale
11.l omówiliśmy dwie elementarne operacje na stosach, działające w czasie 0(1):

PUSH(S, x) - umożliwia włożenie elementu x na stos S,


POP(S) - umożliwia zdjęcie elementu ze stosu S.

Ponieważ każda z tych operacji działa w czasie 0(1 ), możemy przyjąć, i.e
jej koszt jest równy 1. Całkowity koszt ciągu n operacji PUSH i POP jest więc
równy n, a faktyczny czas działania n operacji wynosi 0(n).
Bardziej interesujący jest przypadek, kiedy dodamy operację MULTI-
POP(S, k), która usuwa k elementów z wierzchu stosu S lub opróżnia go, jeśli
na stosie było mniej niż k elementów. W następującej procedurze operacja

404
18.1. METODA KOSZTU SUMARYCZNEGO

SrACK~EMPTY daje w wyniku wartość TRUE, jeśli stos jest pusty, a wartość
FALSEw przeciwnym razie.

MULTIPOP(S,k)
I wbilenot STACK-EMPTY(S)i k 'F o
2 do POP(S)
3 k-k-1

Na rysunku 18.1 widać przykłady działania operacji MULTIPOP.

wieuchołek .... 23
17
6
39
IO wierzchołek .... I O
47 47

(•) (b) (,)

Rys. 18.1. Przykład działania procedury MULTIPOPna stosie S. (a) Sytuatja początkowa. (b) Stos
S po wykonaniu operacji MULTIPOP(S, 4), która usunęła 4 elementy z wierzchu stosu. (c) Stos S po
wykonaniu operacji MULTIPOP(S, 7) jest pusty, ponieważ na stosie majdowało się mniej niż 7 ele-
mentów

Jaki jest czas działania operacji MULTIPOP(S, k) na stosie os elementach?


Rzeczywisty czas działania jest proporcjonalny do liczby wykonanych faktycz-
nie operacji POP. Liczba iteracji pętli wbile jest równa liczbie min(s, k) obiek-
tów zdjętych ze stosu. Podczas każdej iteracji pętli procedura POP jest wywoły­
wana w wierszu 2. Całkowity koszt operacji MULTIPOPwynosi więc min(s, k),
a faktyczny czas działania jest proporcjonalny do tego kosztu.
Przeanalizujemy teraz ciąg n operacji PUSH, POP i MULTIPOP na począt­
kowo pustym stosie. Pesymistyczny czas działania operacji MULTIPOP w tym
ciągu można ograniczyć prZC'l O(n), ponieważ rozmiar stosu nie może prze-
kroczyć n. Analiza pesymistycznego kosztu n operacji prowadzi do ogranicze-
nia O(n2 ), gdyż w ciągu może być O(n) operacji MULTIPOP,a każda z nich ma
pesymistyczny koszt O(n). Mimo że ta analiza jest poprawna, ograniczenie
O(n2 ) uzyskane przez rozpatrywanie kosztu każdej operacji z osobna można
• • •
znaczme popraWIC.
Korzystając z metody kosztu sumarycznego, możemy uzyskać lepsze górne
ograniczenie przez analizę całego ciągu n operacji. W rzeczywistości łączny
koszt każdego ciągu n operacji PUSH, Pop i MULTIPOPna początkowo pustym
stosie wynosi co najwyżej O(n). Dlaczego? Każdy obiekt, po włożeniu go na
stos, może być z niego zdjęty co najwyżej jeden raz. Stąd liczba wywołań

405
ROZDZIAŁ 18. ANALIZA KOSZTU ZAMORTYZOWANEGO

procedury POP na niepustym stosie, włączając w to wywołania wewnątrz ope-


racji MULTIPOP,nie może być więksu niż liczba operacji PUSH,która nie jest
większa niż n. Dla dowolnego n łączny czas wykonania każdego ciągu n opera-
cji PuSH, POP i MULTIPOPna początkowo pustym stosie wynosi co najwyżej
O(n). Koszt zamortyzowany operacji jest zatem równy O(n)/n = 0(1).
Należy jeszcze raz podkreślić, że powyższe wyliczenia średniego kosztu
(a co za tym idzie C"Zasudziałania) operacji na stosie nie wymagały żadnych
rozważań o prawdopodobieństwie. Wykazaliśmy bowiem, że O(n) jest pesymis-
tycznym kosztem ciągu n operacji. Dzieląc ten całkowity koszt przez n, otrzy-
maliśmy średni koszt przypadający na operację, czyli koszt zamortyzowany.

Licznik binarny
Następnym przykładem użycia metody kosztu sumarycmego jest analiza dzia-
łania k-bitowego licznika binarnego, który może przyjmować nieujemne war-
tości całkowite. Licznik jest reprezentowany przez tablicę bitów A [O„ k - l],
gdzie length(A] = k. Najmniej znaczącym bitem liczby binarnej x, będącej war-
tością licznika, jest A {O], a najbardziej znac:zącym - A [le- l], więc
,-1
x= L A[i]·2 1• Początkowo x = O, więc A[i] = O dla i= O, I, ... , k- 1. Aby
i=O
zwiększyć wartość licznika o 1 (module 21), używamy następującej procedury:

lNCREMENT(A)
1 i+- O
2 wbllei< Iength[A] i A[i] = I
3 do A[i]-o
4 i+-i+l
5 H i < length [A]
6 thenA[i]-1

Ten algorytm jest zwykle realizowany spnętowo za pomocą liczników potoko-


wych (patrz podrozdz. 29.2.1). Na rysunku 18.2 widać stan licznika po wyko-
naniu każdej z 16 kolejnych operacji INCREMENTna początkowo wyzerowa-
nym liczniku. Na początku każdej iteracji pętli wbile, w wierszach 24, chcemy
dodać 1 na pozycji i. Jeśli A[i] = 1, to dodanie 1 powoduje zamianę bitu na
O i powstaje przeniesienie o wartości 1, tzn. w następnej iteracji pętli należy
dodać I na pozycji i + l. W pneciwnym razie wykonywanie pętli wbile zostaje
przerwane. Jeśli wtedy i< k. to wiemy, że A [i]= O, więc aby dodać 1 na
pozycji i, zamieniamy O na 1 w wierszu 6. Koszt każdej operacji INCREMBNT
jest równy liczbie zamienionych bitów.
Podobnie jak w przykładzie operacji na stosie, powierzchowna analiza
daje poprawne, ale nie najlepsu ogranie.zenie kosztu. Pojedyncze wykonanie

406
18.1. METODA KOSZI U SUMARYCZNEGO

Wartość ;::,~;:;-~:=;,;_;,:::;,s, Całkowity


licmika ~~~~~~~~ koszt
O 000000018' O
I OOOOOOłti4° I
2 0000001• 3
3 OOOOOlrll 4
4 0000010• 7
5 00000111,4, 8
6 OOOOO I I 8 IO
7 000011.1.,,t.J, li
8 O O OO I O OO 15
9 O O O O I O 8,1'. 16
IO OOOO!Olllc 18
11 000010.MII 19
12 O O O O I I O Il 22
13 O O O O I I lt'Pl 23
14 OOOO I I I O 25
15 O O O 11{.i;,<I.f,01 26
16 000100011; 31
Rys. 18.2. Stany licznika 8-bitowego po wykonaniu kolejnych 16 operacji INCREMENT.Bity, których
wartość uległa zmianie w trakcie operacji, zostały za.cieniowane. W prawej kolumnie znajduje się
sumarycmy koszt wykonanych dotychczas operacji. Zauważmy, że koszt ten nigdy nie jest większy
niż dwukrotność liczby dotychczasowych operacji INCREMENT

procedury INCREMENT może trwać 0(k) jednostek czasu w pesymistycznym


przypadku, w którym w tablicy A są same jedynki. Pesymistyczny czas działa­
nia ciągu n operacji INCREMBNT na początkowo wyzerowanym liczniku można
więc ograniczyć przez O(nk).
Można poprawić powyższ.ą analizę, uzyskując ograniczenie O(n) na koszt
ciągu n operacji INCREMENT. Należy w tym celu zaobserwować, że nie wszyst-
kie bity są modyfikowane przy każdym wywołaniu procedury INCRBMBNT.
Jak widać na rys. 18.2, bit A.[O]jest modyfikowany przy każdym wywołaniu
INCREMENT. Następny bit A [I] ulega modyfikacji tylko w co drugim wywoła­
niu: ciąg n operacji INCREMENT na początkowo wyzerowanym liczniku powo-
duje zmianę wartości bitu A [1] dokładnie Ln/2J razy. Podobnie bit A [21ulega
modyfikacji w co czwartym wywołaniu, czyli Ln/4J razy w ciągu n operacji
INCREMENT. Uogólniając, dla i= O, l, ... , llgnj bit A.[i] ulega modyfika-
cji Ln/2'Jrazy w ciągu n operacji INCREMENT wykonywanych na pocz.ątkowo
wyzerowanym liczniku. Dla i> UgnJ bit A[i] nigdy nie jest modyfikowany.
Sumaryczna liczba modyftk:acji bitów w tablicy A wynosi więc
LifnJ
I
l=O l•J
-1
2

L <n
J=O
"I'I
2

=2n

407
ROZDZIAŁ 1 8. ANALIZA KOSZTU ZAMORTYZOWANEGO

zgodnie z równaniem 3.4. Stąd wynika, że pesymistyczny czas wykonywania


ciągu n operacji INCRBMBNT na pocz.ątkowo wyzerowanym licznik.u jest ogra-
niczony przez O(n), zamortyzowany koszt każdej operacji jest więc równy
O(n)/n = 0(1).

ZADANIA
18.1-1. Czy ograniczenie 0(1) na koszt zamortyzowany operacji na stosie po-
zostanie w mocy, jeśli dopuścimy operację MULTIPUSH, która umożliwia
jednoczesne umieszczanie wielu elementów na stosie?
18.1-2. Uzasadnij, że jeśli dopuścimy operację DECREMENT, która zmniejsza
wartość k-bitowego licznika o 1, to ciąg n operacji może wymagać czasu
®(nk).
18.1-3. Wykonujemy ciąg n operacji na strukturze danych. Koszt i-tej operacji
jest równy i, jeśli i jest potęgą dwójki; w przeciwnym razie wynosi 1.
Dokonaj analizy kosztu zamortyzowanego za pomocą metody kosztu su-
marycznego.

18.2. Metodaksięgowania
Stosując do analizy kosztu zamortyzowanego metodę księgowania, możemy
przypisywać różne koszty zamortyzowane różnym rodzajom operacji. Niektóre
z nich są większe, inne mogą być mniejsze niż koszt faktyczny. Jeśli koszt
zamortyzowany operacji przewyższa jej koszt faktyczny, to różnica tych kosz-
tów jest przypisywana pewnym obiektom w strukturze danych Gest księgowa­
na) jak.o kredyt. Kredyt może być później wykorzystany na zapłacenie za ope-
racje, których faktyczny koszt jest większy niż ich koszt zamortyzowany. Moż­
na :zatem wyobrażać sobie, że koszt zamortyzowany operacji dzieli się na jej
koszt faktyczny oraz kredyt, który jest albo składany w depozyt, albo wykorzy-
stywany. Podejście takie różni się znacznie od metody kosztu sumaryczn.ego,
w której wszystkim operacjom przypisujemy ten sam koszt zamortyzowany.
Koszty zamortyzowane poszczególnych operacji należy dobierać z dużą
dozą ostrożności. Jeśli oczekujemy od analizy u pomocą kosztów zamortyzo-
wanych wykazania, że w najgorszym przypadku śrei:łni koszt operacji jest ma-
ły, to musimy zapewnić, że całkowity koszt zamortyzowany ciągu operacji
stanowi górne ograniczenie faktycznego kosztu tego ciągu. Co więcej, podob-
nie jak w metodzie kosztu sumarycznego, musimy udowodnić tę własność dla
wszystkich ciągów operacji. Dlatego suma kredytów związanych ze strukturą
da.Dych musi być przez cały czas nieujemna, ponieważ określa ona, o ile cał­
kowity koszt zamortyzowany ciągu operacji przekracza jego koszt faktyczny.
Jeśli dopuścimy do sytuacji, w której kredyt jest ujemny (rezultat zainkasowa-
nia zbyt małego kredytu od wcześniejszych operacji w nadziei, że później po-

408
18.2. METODA KSIĘGOWANIA

czyni się odpowiednie oszczędności), to całkowity koszt zamortyzowany nali-


czony do tej chwili będzie mniejszy niż koszt faktycznie wydatkowany. Dla
ciągu operacji od początku do tej właśnie chwili, całkowity koszt zamortyzo-
wany nie stanowi wtedy górnego ograniczenia kosztu faktycznego. Musimy
więc zadbać, aby suma kredytów w strukturze danych nigdy nie była ujemna.

Operacjena stosie
W celu zilustrowania metody księgowania powróćmy do przykładu ze stosem.
Przypomnijmy, że faktyczne koszty operacji na stosie są następujące:

PUSH I
POP I
MULTIPOP min(k, s)

gdzie k jest argumentem przekazywanym do procedury MULTIPOP, as wyso-


kością stosu w chwili jej wywołania. Przypiszmy teraz tym operacjom następu­
jące koszty zamortyzowane:

PuSH 2
POP O
MULTIPOP 0

Zauważmy, że koszt zamortyzowany operacji MULTIPOPjest stały (O), choć jej


koszt faktyczny jest zmienny. Wszystkie koszty zamortyzowane są w tym przy-
padku ograniC'Lone przez 0(1), lecz w ogólności koszty zamortyzowane rozpa-
trywanych operacji mogą się różnić asymptotycznie.
Wykażemy teraz, że jesteśmy w stanie zapłacić za każdy ciąg operacji na
stosie za pomocą zaksięgowanego kosztu zamortyzowanego. Wyobraźmy so-
bie, że kazdą jednostkę kosztu reprezentuje moneta 1 zł. Rozpoczynamy od
pustego stosu. Przypomnijmy sobie analogię z podrozdz. 11.1 między stosem
jako strukturą danych a stosem talerzy w restauracji. Jeśli kładziemy talerz na
stosie, to zużywamy 1 zł na zapłacenie za faktyczny koszt położenia talerza,
pozostaje nam więc moneta 1 zł (bo koszt zamortyzowany operacji PUSH wy-
nosi 2 zł), którą kładziemy na talerzu. W każdej chwili każdy talerz na stosie
ma na sobie 1 zł kredytu.
Gotówka leżąca na talerzu stanowi przedpłatę na koszt zdjęcia go ze stosu.
Za wykonanie operacji POP nie jest pobierana żadna oplata, bo jesteśmy w sta-
nie zapłacić za jej faktyczny koszt, używając kredytu złożonego na stosie. Aby
W.jąć talerz ze stosu, zdejmujemy z niego kredyt, którym opłacamy rzeczywisty
koszt operacji. Inkasując od operacji PUSH nieco więcej niż wynosi jej faktycz-
ny koszt, nie musimy już niczego inkasować od. operacji POP.

409
ROZDZIAŁ 18. ANALIZA KOSZTU ZAMORTYZOWANEGO

Co więcej,
nie musimy też obciążać żadnymi opiatami operacji MULTIFOP.
Aby zdjąć pierwszy talerz, wystarczy wziąć z niego 1 zł kredytu i zapłacić za
operację POP. W celu zdjęcia drugiego talerza znowu wystarczy wziąć z niego
1 zł kredytu i zapłacić za operację POP itd. Widać więc, że w każdej chwili
wystarczy uinkasowanych wcześniej pieniędzy na zapłacenie za następną ope-
rację MULTIPOP.Inaczej mówiąc, ponieważ na każdym talerzu znajduje się 1 zł
kredytu, a na stosie jest zawsze nieujemna liczba talerzy, kredyt jest więc za-
wsze wielkością nieujemną. Zagwarantowaliśmy w ten sposób, że dla każdego
ciągu n operacji PUSH, POP i MULTIPOP ich koszt zamortyzowany stanowi
górne ograniczenie na faktyczny koszt wykonania tych operacji. Ponieważ cał­
kowity koszt zamortyzowany jest ograniczony przez O(n), tym bardziej to
ograniczenie jest słuszne dla kosztu faktycznego.

Licznik binarny
Kolejną ilustracją zastosowania metody księgowania jest analiza operacji IN-
CREMENTna liczniku binarnym. Jak wcześniej zaobserwowaliśmy, czas dzia-
łania tej operacji jest proporcjonalny do liczby zmodyfikowanych bitów - mo-
żemy traktować ją jak.o miernik faktycznego kosztu. Użyjmy raz jeszcze mo-
nety 1 zł do reprezentacji jednostkowego kosztu (w naszym przykładzie mo-
dyfikacji bitu).
Dla celów analizy zwiążmy z operacją przypisania bitowi wartości 1 koszt
2 zł. Gdy przypisujemy bitowi wartość 1, używamy 1 zł (z zainkasowanych
2 zł) na zapłacenie za modyfikację bitu, a drugą monetę 1 zł „kładziemy" na
tym bicie jako kredyt. W każdej chwili każdy bit 1 w liczniku ma 1 zł kredytu,
nie musimy więc nic inkasować, aby wyzerować ten bit, bo możemy użyć kre-
dytu związanego z tym bitem.
Teraz możemy już wyznaczyć koszt zamortyzowany operacji INCREMENT.
Koszt zerowania bitów w pętli wbile pokryty zostaje przez złotówki związane
z zerowanymi bitami. Co najwyżej jednemu bitowi przypisujemy wartość
I w wierszu 6 procedury INCREMENT,więc jej koszt zamortyzowany wynosi co
najwyżej 2 zł. Liczba jedynek w liczniku nie jest nigdy ujemna, zatem i kredyt
jest zawsze nieujemny. Wnioskujemy stąd, że całkowity koszt mmortyzowany
ciągu n operacji INCREMENTwynosi O(n), co jest także ograniczeniem na cal~
kawi.ty koszt rzeczywisty tego ciągu.

ZADANIA
18.2-1. Na stosie, którego rozmiar nigdy nie przekracu k, jest wykonywany
ciąg operacji. Co każde k operacji jest wykonywana kopia bezpieczeństwa
całego stosu. Wykaż, że koszt n operacji, wliczając koszt kopiowania, jest
ograniczony przez O(n); przypisz w tym celu operacjom na stosie odpo-
wiednie koszty zamortyzowane.

410
18.3. METODA POTENCJAŁU

18.2-2. Rozwiąż zadanie 18.1-3 za pomocą metody księgowania.


18.2-3. Załóżmy, że oprócz operacji zwiększania możemy także zerować licz-
nik (tzn. zerować wszystkie jego bity) za pomocą operacji RESET. Pokaz,
jak zaimplementować licznik w postaci wektora bitów, aby czas działania
dowolnego ciągu n operacji lNCREMBNT i RESET, działających na począt­
kowo wyzerowanym. liczniku, wynosił O(n). (Wskazówka: Zapamiętuj
wskaźnik do następnej jedynki).

18.3. Metodapotencja/u
W metodzie potencjału zamiast reprezentować nadpłatę kosztu jak.o kredyt ściś­
le związany z pewnym.i obiektami w strukturze danych, trak.tuje się ją jako
,,energię potencjalną" (lub po prostu „potencjał"), która może być wyzwolo-
na, aby zapłacić za późniejsze operacje. Potencjał jest związany ze strukturą
danych jako całością, a nie z jej pojedynczymi obiektami.
Stosując metodę potencjału, postępujemy następująco. Na początku ma-
my strukturę danych D 0 , na której chcemy wykonać n operacji. Dla kaidego
i= 1, 2, ... , n niech c; oznacza faktyczny koszt i-tej operacji, a D 1 niech będzie
strukturą danych powstałą ze struktury D 1_ 1 po wykonaniu i-tej operacji.
Funkcja pot.encjalutl>przyporządkowuje każdej strukturze D 1 liczbę rzeczywi-
stą ll>(DJ, nazywaną pot.entjałem. struktury Di. Koszt zamortyzowany C1 dla i-tej
operacji względem funkcji potencjału tl>definiuje się jako

c1 = c, + ił>(D 1 ) - il>(D,_1) (18.1)

Koszt zamortyzowany każdej operacji jest więc sumą kosztu faktycznego


i przyrostu potencjału będącego wynik.iem wykonania tej operacji. Zgodnie
z równaniem (18.1) całkowity koszt zamortyzowany ciągu n operacji wynosi
' "
L c,= L (c, + ił>(D,) - ił>(D,_ 1 ))
i= l I= l

= L' c, + il>(D,) - il>(D,) (18.2)


i=l

Druga równość wynika z równania (3. 7), ponieważ tl>(D1) się redukują.
Jeśli zdefiniujemy funkcję potencjału tł> tak, że tl>(D11) ~ tl>(D0 ), to całkowi-

ty koszt zamortyzowany L' ć1 ogranicza z góry całkowity koszt faktyczny.


i= 1
W praktyce nie wiemy zwykle z góry, ile operacji zostanie wykonanych. Dlate-
go dopiero jeśli zapewnimy, że tl>{DJ ~ tl>(D0 ) dla każdego i, możemy mieć

411
ROZDZIAŁ 18. ANALIZA KOSZTU ZAMORTYZOWANEGO

gwarancję {podobnie jak w metodzie księgowania), że płacimy zawsze z góry.


Zwykle dla wygody definiuje się Clt{D 0 ) = O, po czym pozostaje wykazać, że
<D(DJ;;;i,O dla każdego i (patrz zad. 18.3-1, które daje odpowiedź, jak w łatwy
sposób poradzić sobie w przypadkach, gdy q)(D 0) # O).
Intuicyjnie, jeśli przyrost potencjału ~D 1) - <D(D1_ 1 ) przy i-tej operacji
jest dodatni, to koszt zamortyzowany ć 1 daje nadpłatę przy i-tej operacji, a po-
tencjał struktury danych wzrasta. Jeśli natomiast różnica potencjałów jest
ujemna, to koszt zamortyzowany i-tej operacji jest mniejszy niż jej koszt rze-
czywisty; ta niedopłata jest kompensowana przez spadek potencjału.
Koszt zamortyzowany zdefiniowany za pomocą równań (18.1) i (18.2) za-
leży od wyboru funkcji potencjału Cl».Wykorzystując różne funkcje potencjału,
można otrzymać różne koszty zamortyzowane i mimo wszystko otrzymać gór-
ne ograniczenia kosztu faktycznego. Wyboru funkcji potencjału dokonuje się
zwykle na drodze kompromisu; najlepsza funkcja potencjału zależy od ograni-
czenia, jakie chcemy wykazać.

Operacjena stosie
Aby zilustrować metodę potencjału, powróćmy jeszcze raz do przykładu ope-
racji na stosie: PUSH, POP i MULTIPOP. Zdefmiujmy funkcję potencjału Cl»na
stosie jako jego wysokość. Dla stosu pustego, od którego rozpoczynamy,
Cl>(D0 ) = O. Wysokość stosu jest zawsze nieujemna, więc

<!>(DJ;,, O

= q)(D,)
Całkowity koszt zamortyzowany ciągu n operacji ze względu na Cl»stanowi
więc górne ograniczenie faktycznego kosztu.
Obliczmy koszt zamortyzowany różnych operacji na stosie. Jeśli i-ta ope-
racja na stosie zawierającym s elementów jest operacją PUSH, to przyrost po-
tencjału wynosi

<i>(D
1) - q)(D,_ 1 ) = (s + 1) - s

=l
Z równania (18.1) wynika, że koszt zamortyzowany tej operacji PUSH jest
równy

c1 = c1 + q)(DJ- q)(D1_ 1)

=l+l
=2

412
18.3. METODA POTENCJAŁU

Przyjmijmy teraz, że i-tą operacją na stosie jest MULTIPOP(S,k) oraz że w efek-


cie jej wykonania zdjętych zostaje ze stosu k' = min(k, s) elementów. Faktycz-
ny koszt tej operacji wynosi k', natomiast przyrost potencjału jest równy

<P(D1) - <P(D,_1) - - k'

Koszt zamortyzowany operacji MULTIPOPwynosi więc

c,- c1 + <!>(DJ- <l>(D,_


1)

= k' - k'

Podobnie koszt zamortyzowany zwykłej operacji POPjest równy O.


Koszt zamortyzowany wszystkich trzech operacji jest ograniczony przez
0(1), całkowity koszt zamortyzowany całego ciągu n operacji jest więc równy
O(n). Stwierdziliśmy już wcześniej, że fl)(DJ ~ <ll(D0 ), zatem całkowity koszt
zamortyzowany n operacji na stosie stanowi górne ograniczenie ich faktycz-
nego kosztu. Stąd pesymistyczny koszt n operacji wynosi O(n).

Licznik binarny
Jako kolejny przykład zastosowania metody potencjału dokonamy jeszcze raz
analizy przykładu z licznikiem binarnym. Potencjał licznika po i-tym zwięk­
szeniu zdefiniujemy jako b1 - liczbę jedynek w liczniku po i-tej operacji.
Obliczymy teraz koszt z.amortyzowany operacji INCREMENT. Załó2my, że
i-ta operacja INCREMENT zeruje t1 bitów. Faktyczny koszt tej operacji jest więc
nie większy niż t1 + 1, ponieważ oprócz zerowania t 1 bitów może ona przypisać
wartość 1 co najwyżej jednemu bitowi. Liczba jedynek w liczniku po wykonaniu
i-tej operacji jest równa b1 ~ b;_ 1 - t 1 + 1, zatem przyrost potencjału wynosi
<l)(DJ- Cl>(D
1_ 1 ) ~ (b1_ 1 - t 1 + I) - b1_ 1

=I- t1
Stąd koszt zamortyzowany

c,- c1 + <l>(D1) - <l>(D,_,)


<;(t,+ l)+(l-tJ
-2

Jeśli 0 ) = O. Ponie-
zaczynamy zliczać za pomocą licznika od zera, to Cl>(D
waż Cl>(D
1) ~ Odla każdego i, całkowity koszt zamortyzowany ciągu n operacji

413
ROZDZIAŁ 18. ANALIZA KOSZTU ZAMORTYZOWANEGO

lNCRBMENT stanowi więc górne ograniczenie kosztu faktycznego, co daje pe-


symistyczny koszt ciągu n operacji INCREMENT równy O(n).
z.apomocą metody potencjału łatwo jest także dokonać analizy w przypa-
dku, gdy licznik nie startuje od zera. Na początku licznik zawiera b0 jedynek,
po n operacjach INCREMENT - b„ jedynek, gdzie O ~ b0, b,.~ k. Równanie
(18.2) możemy zapisać następująco:

" "
L c, - L c,+ ll>(D.) - ll>(D,) (18.3)
J='l 1="1

Wiadomo, że ć 1 ~ 2 dla 1 ~ i~ n. Ponieważ «l>(D = b,., cał­


0 ) = b0 oraz Cl>(D,.)
kowity faktyczny koszt n operacji spełnia zależność

"
Lei~ "
L2-h,. + ho
focl J,c,1

=2n-b,.+b 0

W szczególności
b0 ~ k, więc jeśli wykonamy co najmniej n= O(k) operacji
lNCREMENT, to ich faktyczny całkowity koszt wyniesie O(n), niezależnie od
początkowej wartości licznika.

ZADANIA
18.3-1. Niech dana będzie funkcja potencjału Cl>taka, że tl>(D,)~ fl>(D 0 ) dla
kaWego i, lecz Cl>(D0 ) #O.Wykaż. że istnieje funkcja potencjału Cl>'
spełnia­
jąca warunki tl>'(D0) = O,tl>'(Di}~ Odla i~ 1 oraz koszty zamortyzowane
operacji względem Cl>'są takie same jak koszty zamortyzowane względem tl>.
18.3-2. Rozwiąż zadanie 18.1-3 za pomocą metody potencjału.
18.3-3. Rozważ zwyczajny binarny n-elementowy kopiec, na którym są dopu-
szczalne operacje INSERT i EXTRACT-MIN, których pesymistyczny czas
działania wynosi O(lgn). Podaj funkcję potencjału Cl>,względem której
koszt zamortyzowany operacji INSERT wynosi O(lgn), a koszt z.amortyzo-
wany operacji EXTRACT-MIN wynosi 0(1 ).
18.3-4. Jak.ijest koszt wykonania na stosie n operacji PUSH,POPi MULTIPOP
przy założeniu, że na początku wysokość stosu jest równa s0 , a po n opera-
cjach wynosi s,..
18.3-5. Zakładając, że licznik zaczyna zliczać nie od zera, lecz od pewnej liczby
z b jedynkami w jej binarnej reprezentacji, wykaż, że koszt wykonania n
operacji INCREMENT jest równy O(n), jeśli n= O:(b).(Nie możesz przyj-
mować założenia, że b jest stałą).
18.3,-6.Pokaż, jak zaimplementować kolejkę za pomocą dwóch zwyczajnych
stosów (zad. 11.1~6),aby koszt zamortyzowany każdej operacji INSERT
i DELETE wynosił 0(1 ).

414
18.4. TABLICE DYNAMICZNE

18.4. Tablicedynamiczne

W wielu zastosowaniach nie wiemy z góry, ile elementów trzeba będzie zapa-
miętać w tablicy. Może dojść do sytuacji, że obszar pamięci zarezerwowany dla
tablicy okazuje się zbyt mały. Wtedy trzeba przydzielić tablicy większy obszar
pamięci, a wszystkie elementy zapamiętane w starym obszarze należy skopio-
wać do nowej, większej tablicy. Podobnie, jeśli bardzo wiele obiektów zostało
z tablicy usuniętych, to może się opłacać zmniejszyć rozmiar zajmowany przez
tablicę. W tym podrozdziale zajmiemy się problemem dynamicznego zwiększa­
nia i zmniejszania tablic. Za pomocą analizy kosztu zamortyzowanego wyka-
żemy, że średni koszt wstawiania i usuwania elementów z odpowiednio za-
projektowanej tablicy dynamicznej wynosi tylko 0(1), mimo że faktyczny
koszt operacji może być bardzo duży, jeśli w jej trakcie zajdzie potrzeba powię­
kszenia lub zmniejszenia tablicy. Co więcej, pokażemy, jak zagwarantować, że
nie wykorzystana pamięć w tablicy dynamicznej nigdy nie stanowi więcej niż
pewien ustalony ułamek zajmowanej pamięci.
Zakładamy, że na tablicy dynamicznej można wykonywać operacje TAB-
LE-INSERTi TABLE-DELETE. Operacja TABLE-INSERTumożliwia wstawienie
do tablicy elementu, który zajmuje wtedy jedną komórkę, tzn. pamięć prze-
maczoną na jeden element. Analogicznie TABLE-DELETEumożliwia usunięcie
elementu z tablicy, zwalniając zajmowaną przezeń komórkę. Szczegóły doty-
czące struktury danych użytej do reprezentacji tablicy są nieistotne; możemy
równie dobrze zastosować stos (pod.rozdz. 11.1), kopiec (podrozdz. 7.1) lub
tablicę z haszowaniem (rozdz. 12). Możemy także użyć w tym celu zwykłej
tablicy lub kilku tablic, podobnie jak to czyniliśmy w pod.rozdz. 11.3.
Dogodnie będzie użyć pojęcia, z którego korzystaliśmy przy analizie ha-
szowania (rozdz. 12). Zdefiniujmy współczynnik zapełnienia 1X(7)niepustej tab-
licy T jako iloraz liczby elementów zapamiętanych w tablicy i jej rozmiaru
(liczby komórek). Pustej tablicy (czyli nie zawierającej żadnych elementów)
przypisujemy rozmiar Oi współczynnik zapełnienia równy 1. Jeśli uda się nam
ograniczyć od dołu współczynnik zapełnienia, to będziemy mieli gwarancję, że
nie wykorzystana część tablicy nigdy nie stanowi więcej niż pewien ustalony
ułamek zajmowanej pamięci.
Rozpoczniemy od analizy tablicy dynamicznej, na której można wykony-
wać tylko operacje wstawiania. Następnie rozważymy ogólniejszy przypadek,
w którym będą taicie dopuszczalne operacje usuwania elementów z tablicy.

18.4.1. Powiększanie tablicy


Niech tablica składa się z ciągu komórek. Tablica zapełnia się, jeśli wszystkie
komórki zostają zajęte lub, równoważnie, jeśli współczynnik zapełnienia osią-

415
ROZDZIAŁ 18. ANALIZA KOSZTU ZAMORTYZOWANEGO

ga 10. W niektórych środowiskach programistycznych, jeśli podjęta zostanie


próba wstawienia elementu do pełnej tablicy, to pozostaje tylko przerwać wy-
konywanie programu z komunikatem o błędzie. Będziemy jednak zakładać, że
nasze środowisko, podobnie jak wiele nowoczesnych systemów programistycz-
nych, zawiera system zarządzania _pamięcią, umożliwiający przydzielanie i zwa-
lnianie bloków pamięci na żądanie. Jeśli więc dochodzi do próby wstawienia
nowego elementu do pełnej tablicy, to należy powiększyć tę tablicę, przydziela-
jąc jej obszar pamięci o większej liczbie komórek, oraz skopiować zawartość
starej tablicy do tego nowego obszaru.
Zwykle stosuje się heurystykę polegającą na przydziale dwa razy większe­
go obszaru niż zajmowany dotychczas przez wypełnioną tablicę. Jeśli wykony-
wane są tylko operacje wstawiania do tablicy, to współczynnik zapełnienia
tablicy jest dzięki temu zawsze nie mniejszy niż 1/2, więc ilość nie wykorzysta-
nej pamięci nigdy nie przekracza połowy pamięci zajmowanej przez tablicę.
W następującej procedurze zakładamy, że T reprezentuje tablicę dyna-
miczną. Pole table [T] zawiera wskaźnik do bloku pamięci, w którym tablica
jest przechowywana. Pole num (T] zawiera liczbę elementów znajdujących się
w tablicy, a pole size[T] - liczbę komórek wchodzących w jej skład. Począt­
kowo tablica jest pusta: num[M] = size[M] = O.

TABLB-lNSERT(T, x)
I if size[TJ - O
2 tben przydziel I komórkę dla table[TJ
3 size[T] +-1
4 if num [TJ - size [TJ
5 tben przydziel 2·size[TJ komórek dla new-table
6 wstaw wszystkie elementy z table{T] do new-table
7 zwolnij table[TJ
8 table [T] +- new-table
9 size [TJ - 2 · size [TJ
10 wstaw x do table[T]
li num[TJ-num[TJ + I

Zauważmy, że występują tutaj dwie różne procedury „wstawiania": proce-


dura TABLE-INSERT oraz elementarne wstawienie do tablicy w wierszach 6 i 10.
Czas działania procedury TABLE-INSERT będziemy wyrażać za pomocą liczby
elementarnych wstawień, wiążąc z każdym takim elementarnym wstawieniem
koszt jednostkowy. Faktyczny czas działania TABLE-INSERT jest proporcjo~

11 W pewnych sytuacjach, takich jak tablica z haszowaniem z wykorzystaniem adresowania


otwartego, wygodnie jest umać tablicę za mpełnioną, jeśli współczynnik zapełnienia pr:zełracza
pewną stałą mniejszą niż I (patrz md. 18.4-2).

416
18.4. TABLICE DYNAMICZNE

naJny do liczby wykonanych wstawień elementarnych, ponieważ narzut cza-


sowy związ.any z inicjowaniem tablicy w wierszu 2 można ograniczyć przez
stałą, a koszt przydzielania i zwalniania pamięci w wiersmch 5 i 7 jest zdo-
minowany przez koszt kopiowania elementów w wierszu 6. Jeśli zostają wy-
konane instrukcje po słowie then w wierszach 5-9, to mówimy, że tablica zo-
staje powiększona.
Dokonamy teraz analizy ciągu n operacji TABLE-INSERT na początkowo
pustej tablicy. Jaki jest koszt C; wykonania i-tej operacji? Jeśli w bieżącej tabli-
cy jest jeszcze wolne miejsce (lub wykonujemy pierwszą operację), to c1 = 1,
ponieważ musimy wykonać tylko jedno elementarne wstawienie w wierszu IO.
Jeśli jednak bieżąca tablica jest zapełniona, to trzeba ją powiększyć i wtedy
c1 = i. Wówczas kopiowanie i - 1 elementów ze starej tablicy do nowej w wier-
szu 6 kosztuje i - 1 plus jednostkowy koszt elementarnego wstawienia w wier-
szu 10. Jeśli wykonujemy w sumie n operacji, to pesymistyczny koszt pojedyn-
czej operacji wynosi O(n), co daje górne ograniczenie O(n2 ) na całkowity czas
działania ciągu n operacji.
Ograniczenie to nie jest ścisłe, ponieważ koszt związany z powiększaniem
tablicy w ciągu n operacji TABLE-INSERT nie jest naliczany zbyt c7.ęsto. Do-
kładnie rzecz biorąc, i-ta operacja wymusza powiększanie tablicy tylko wtedy,
gdy i - 1 jest całkowitą potęgą dwójki. Koszt zamortyzowany operacji TAB·
LE-INSERT jest w efekcie równy 0(1), co można wykazać za pomocą metody
kosztu sumarycznego. Koszt i-tej operacji wynosi

,, jeśli i - 1 jest całkowitą potęgą


c, = {
I, •
w przeciwnym •
razie
2

Stąd całkowity koszt n operacji TABLE-INSERT wyraża się jako


n Llgnj
[c,,s;n+ L 2'
l=l )"'-O

<n+2n
= 3n

bo jest co najwyżej n operacji o koszcie I, a koszty pozostałych tworzą szereg


geometryczny. Całkowity koszt n operacji jest nie większy niż 3n, koszt zamor-
tyzowany każdej z nich jest więc ograniczony przez 3.
Korzystając z metody księgowania, można podobnie intuicyjnie stwier-
dzić, dlaczego koszt zamortyzowany operacji TABLE-INSERT powinien wynosić
3. Każdy element płaci za trzy elementarne wstawienia: wstawienie siebie same-
go do bieżącej tablicy, przeniesienie się do nowej tablicy, gdy tablica jest po-
większana oraz przeniesienie innego elementu, który jest przenoszony po raz

417
ROZDZIAŁ 18. ANALIZA KOSZTU ZAMORTYZOWANEGO

kolejny z powodu powiększania tablicy. Przyjmijmy na przykład, że tablica


w chwili po powiększeniu ma rozmiar m. Liczba elementów w tablicy jest wtedy
równa m/2; jej kredyt wynosi O. Od każdego wstawienia inkasujemy 3 zł. Wsta-
wienie elementarne związane z każdą operacją wstawienia kosztuje 1 zł. Drugą
złotówkę „kładziemy" na wstawionym elemencie jak.o kredyt, a trzecia zasila
kredyt jednego z m/2 elementów znajdujących się wcześniej w tablicy. Aby
ponownie zapełnić tablicę, trzeba wykonać m/2 wstawień, po których tablica
zawieram elementów - jest pełna i na każdym elemencie znajduje się złotówka
na zapłatę za wstawienie go do nowej tablicy w czasie operacji powiększania.
Do analizy ciągu n operacji TABLE-INSERTmożna równie dobrze użyć
metody potencjału, co uczynimy w pod.rozdz. 18.4.2, gdzie za.projektujemy
także operację TABLE-DELETEo koszcie zamortyzowanym 0(1). Zdefiniujemy
najpierw funkcję potencjału cI>równą Opo każdym powiększeniu, która później
rośnie, osiągając wartość równą rozmiarowi tablicy, gdy ta jest pełna. Dzięki
temu kolejne powiększenie tablicy może zostać opłacone przez zgromadzony
potencjał. Jedną z możliwości jest funkcja

~1) -2·num[T] -size[T] (18.4)

W chwili po powiększeniu tablicy mamy nwn[T] = size[T]/2, więc-jak ocze-


kiwaliśmy - cI>(7)= O. Bezpośrednio przed powiększeniem mamy num [T] =
= size[T], zatem zgodnie z oczekiwaniami cI>(1)= num[T]. Początkowa war-
tość potencjału jest równa O, a ponieważ tablica jest zawsze wypełniona co
najmniej w połowie, spełniona jest nierówność num[T] ~ size[T]/2, co gwa-
rantuje, że wartość cI>(1)jest zawsze nieujemna. Stąd wynik.a, że suma kosztów
zamortyzowanych n operacji TABLE-INSERTstanowi górne ograniczenie na ich
faktyczny koszt.
Aby przeanalizować koszt zamortyzowany i-tej operacji TABLE-INSERT,
oznaczmy przez num; liczbę elementów znajdujących się w tablicy po i-tej ope-
racji, przez size1 całkowity rozmiar tablicy po i-tej operacji, a przez cI>
1 odpo-
wiedni potencjał tablicy. Początkowo mamy num0 = O, size0 = O oraz cI> 0 = O.
Jeśli i-ta operacja TABLE-INSERT nie wymusza powiększenia tablicy, to
size1 = size 1_ 1 , a koszt zamortyzowany operacji wynosi

c,= c, + cI>,- cI>l-1


= 1 + (2·num size;)-(2·num
1- 1_ 1 -size 1_ 1 )

= 1 + (2 · num1 - sizeJ - (2(numi - 1) - size1)


=3

Je.żeli natomiast i-ta operacja powoduje powiększenie tablicy, to sizeJ2 =


= size1_ 1 = num 1 - 1, koszt zamortyzowany jest więc równy

418
18.4. TABLICE DYNAMICZNE

Ć1 = C; + Cl>l- Cl>1-1
= num + (2 · num; - 1 sizeJ - (2 ·num 1_ 1 - size 1_ 1)

- num,+ (2·num, - (2·num, - 2))-(2(num,- 1) - (num, - 1))

= num; + 2 - (num 1 - 1)
-3

32
A •
••
24
size.
'
num1 / ''
/ '' '

'
16
/ '' '
d>. ,'
/::'
' ' '''
'
•' '' '' '
''
8 '' ''
' '' '' '' ''
'' '' '' '' ''
' ' '' ';' '
'
' '' '
' i
8 16 24 32
Rys. 18.3. Wynik działania ciągu n operacji TABLE-INSERT na liczby: num1 elementów w tablicy, size1
komórek należących do tablicy, oraz potencjału~. "" 2 · num1 - size1mierzonych po wykonaniu i-tej
operacji. Cienka linia ornacza numi, gruba linia pokazuje sizei, a linia przerywana potencjał ~j-
2.auważ, żena chwilę przed powiększ.eniem tablicy wartość potencjału jest równa liczbieelementów
w tablicy, więc możemy za jego pomocą opłacić koszt skopiowania wszystkichelementów do nowej
tablicy.Po tym kopiowaniu potencjał spadado O,leczjego wartość natychmiast przyrasta do 2, jako
efekt wykonania elementarnego wstawienia elementu, który wywołał powiększenie tablicy

Na rysunku 18.3 są pokazane wartości num 1, size 1 oraz Cl>


1 jako funkcje i.
Zwróć uwagę, jak jest „zużywany" potencjał na zapłacenie za operacje po-
większenia tablicy.

18.4.2. Powiększanie i zmniejszanie tablicy


W implementacji operacji TABLE-DELETEwystarczy usuwać podany element
z tablicy. Jeśli jednak współczynnik zapełnienia tablicy bardzo się zmniejszy,
dobrze będzie 2'lllniejszyć ro2'llliar tablicy, aby nie zawyżać nadmiernie obszaru
nie wykorzystanej, lecz zajętej pamięci. Zmniejszanie tablicy jest podobne do
jej powiększania: gdy liczba elementów maleje poniżej pewnej granicy, przy-
dzielamy tablicy nowy, mniejszy obszar pamięci i kopiujemy jej zawartość do

419
ROZDZIAŁ 18. ANALIZA KOSZTU ZAMORTYZOWANEGO

tego nowego obszaru. Pamięć zajmowana dotychczas przez tablicę zostaje


w ten sposób zwolniona i zwrócona do systemu zarządzania pamięcią. Będzie­
my dążyć do zachowania następujących dwóch własności:

• współczynnik zapełnienia tablicy dynamicznej jest ograniczony z dołu przez


pewną stałą,
• koszt zamortyzowany każdej operacji na tablicy jest ograniczony przez stałą.

Przyjmujemy, Ze koszt moZD.amierzyć za pomocą liczby elementarnych opera-


cji wstawienia lub usunięcia.
Naturalną strategią powiększania i zmniejszania tablicy jest podwojenie jej
rozmiaru, gdy próbujemy wstawić element do wypełnionej tablicy, oraz
mmiejszenie rozmiaru o połowę, jeśli usunięcie elementu wywoła zmniejszenie
współczynnika zapełnienia poniżej 1/2. Taka strategia gwarantuje, ze współ­
czynnik zapełnienia tablicy nie jest nigdy mniejszy niż 1/2, lecz niestety dopusz-
cza duZy koszt zamortyzowany operacji. Rozważmy następujący scenariusz.
Wykonujemy n operacji na tablicy T, gdzie n jest całkowitą potęgą 2. Pierw-
szych n/2 operacji stanowią wstawienia, których całkowity koszt (zgodnie z na-
szą wcześniejszą analizą) wynosi @(n). Po wykonaniu tych n/2 operacji mamy
nwnT = sizeT = n/2. Niech pozostałych n/2 operacji stanowi następujący ciąg:

I, D, D, I, I, D, D, I, I, ... ,

gdzie I oznacza wstawienie, a D usunięcie elementu. Pierwsze wstawienie po-


woduje powiększenie tablicy do rozmiaru n. Następne dwie operacje usunięcia
powodują zmniejszenie tablicy z powrotem do rozmiaru n/2. Dwa kolejne
wstawienia ponownie pociągają za sobą powiększenie tablicy itd. Koszt każ­
dego powiększenia i zmniejszenia wynosi 0(n). Wykonujemy w sumie 0(n)
tych operacji, zatem całkowity koszt powyZszego ciągu n operacji jest równy
0(n 2). Stąd koszt zamortyzowany operacji wynosi 0(n).
Wada tej strategii jest dość oczywista: po powiększeniu wykonujemy za
mało operacji usunięcia, aby zrekompensować koszty zmniejszenia. Podobnie
po zmniejszeniu, nie wykonujemy dość wstawień, aby wyrównać wydatki zwią­
zane z powiększaniem.
Mozemy poprawić tę strategię kosztem dopuszczenia sytuacji, w której
współczynnik zapełnienia maleje ponizej 1/2. Nadal będziemy podwajać roz-
miar tablicy w przypadku, gdy próbujemy wstawić element do pełnej tablicy.
Natomiast zmniejszenie rozmiaru o połowę będziemy wykonywać dopiero wte-
dy, kiedy współczynnik zapełnienia zmaleje poniżej 1/4. Współczynnik zapeł­
nienia tablicy nadal jest więc ograniczony z dołu przez stałą, lecz teraz będzie
to 1/4, a nie 1/2 jak poprzednio. Po wykonaniu powiększenia tablicy jej współ­
czynnik zapełnienia jest równy 1/2. Zanim będzie moZna w tej sytuacji wyko-

420
18.4. TABLICE DYNAMICZNE

nać operację 2lllniejszenia rozmiaru tablicy, trzeba będzie najpierw usunąć po-
łowę jej zawartości, bo 2lllniejszenie jest dozwolone dopiero wówczas, gdy
współczynnik zapełnienia maleje poniżej 1/4. Po zmniejszeniu rozmiaru tablicy
współczynnik zapełnienia jest równy 1/2. Zanim więc zostanie wykonane po-
większenie rozmiaru tablicy, trzeba podwoić liczbę jej elementów, ponieważ
operacja powiększania jest dopuszczalna tylko w sytuacji, w której współczyn­
nik zapełnienia przekroczy 1.
Nie podajemy tutaj implementacji operacji TABLE-DELETE, ponieważ jest
analogiczna do operacji TABLE-INSERT. Do celów analizy wygodnie będzie
przyjąć, że jeśli liczba elementów w tablicy maleje do O, to pamięć przydzielona
tablicy jest zwalniana, tzn. jeśli num[T] = O, to size[T] = O.
Użyjemy teraz metody potencjału do analizy kosztu ciągu n operacji TAB.
LE-INSERT i TABLE-DELETE. Zdefmiujemy najpierw funkcję potencjału et,rów-
ną O zaraz po wykonaniu operacji powiększenia lub zmniejszenia tablicy,
a przyrastającą, jeśli współczynnik zapełnienia wzrasta do l lub maleje do 1/4.
Oznaczmy współczynnik zapełnienia niepustej tablicy T przez ix(J) = nwn[T]/
/size[T]. Przyjęliśmy że dla pustej tablicy Tmamy num [T] = .vize[T] = Ooraz
ix(J) = 1, więc dla każdej tablicy Tzachodzi równość num[T] = ix(l)·size[T].
Zdefiniujemy funkcję potencjału następująco:

2 · num[T] - size [T], jeśli •(1);, 1/2


<D(1)= { (18.5)
size [T]/2 - num [T], jeśli •(1) < 1/2

Zauważmy, że potencjał pustej tablicy jest równy O oraz że potencjał jest za-
wsze nieujemny. Dlatego sumaryczny koszt zamortyzowany ciągu operacji ze
względu tł> stanowi górne ograniczenie ich faktycznego kosztu.
Zanim przejdziemy do ścisłejanalizy, przyjrzymy się własnościom funkcji
potencjału. Jeżeli współczynnik zapełnienia jest równy 1/2, to wartość poten-
cjału wynosi O. Kiedy współczynnik ten osiąga 1, zachodzi równość size[T] =
= nwn[T], potencjał jest więc wtedy równy cI>(7)= nwn{T], co wystarczy na
zapłacenie za koszty powiększenia tablicy, jeśli zajdzie taka potrzeba. Jeśli
z kolei współczynnik zapełnienia jest równy 1/4, to mamy size[T] =
= 4 · nwn [T], więc znów lf,(1) = num [T], czyli wystarczy potencjału na opła­
cenie wydatków na operację zmniejszenia tablicy. Na rysunku 18.4 widać
zmiany potencjału dla pewnego ciągu operacji.
Aby przeanalizować ciąg n operacji TABLE-INSERT i TABLE-DELETE,
wprowadźmy następujące oznaczenia: niech c; oznacza faktyczny koszt i-tej
operacji, C1 - będzie jej kosztem zamortyzowanym względem potencjału <I>,
num1 niech oznacza liczbę elementów znajdujących się w tablicy po i-tej opera-
cji, size 1 - liczbę komórek wchodzących wtedy w skład tablicy, IX; - jej współ­
czynnik zapełnienia po i-tej operacji, a <It1 - odpowiedni potencjał. Początkowo
num0 = O, size 0 = O, ix0 = O, a <Il0 = O.

421
ROZDZIAŁ 18. ANALIZA KOSZTU ZAMORTYZOWANEGO

32 ~

24
size;
~.

...
7f
~
16
um,
'
/ '' '' l
8
'' '•
.•• -
-
• ''
'' • '' ' : (J). ,0,,
' • • •
' '' •
'' '• , ' • ' ' '' ''
,' ' '
' ,· '
',' ' ' '1'
'
',, ,
,
'' ''
'' '• ' '
' •
' " ''
'' ''
' '' ;
8 16 24 32 40 48
Rys. 18.4. Wpływ driałanią ciągu Il operacji TABLE-INSERToraz TABLE-DELETEna liczby: 11Um1 ele-
mentów w tablicy, size1 komórek wchodzących w jej skład oraz potencjał
2 · nwn 1 - size1, jeśli a(1)~ l /2
'11,= {
sizeJ2 - num1, jeśli ~(1)< 1/2
mierzone po wykonaniu i-tej operacji. Cienką Hnią oznaczono num1, grubą - sizei, a przerywaną
- potencjał '11
1• Zauważ., h: w chwili przed powiększeniem tablicy wartość potencjału jest równa
liczbie elementów w tablicy, możemy więc z.ajego pomocą opłacić koszt skopiowania wszystkich
elementów do nowej tablicy. Podobnie, przed zmniejmmi.emtablicy potencjał zrównuje się z liczbą
jej elementów

Rozważmy najpierw przypadek, w którym i-tą operacją jest TABLE-


-INSERT. Jeśli cx1_ 1 ~ 1/2, to analiza pnebiega tak samo jak w podro:zdz.
18.4.1.Niezależnie od tego, czy dochodzi do powiększenia tablicy c:Ly nie, koszt
zamortyzowany C1 operacji nie jest większy niż 3. Jeżeli natomiast cx1_ 1 < 1/2, to
tablica nie może ulec powiększeniu, bo :zdarza się to tylko, gdy a 1_ 1 = 1. Jeśli
zachodzi również a1 < 1/2, to koszt zamortyzowany i-tej operacji wynosi

C;= C1 + cl>i-tl>1-1
=I+ (sizeJ2 - nwn 1) - (size1_ 1/2 - num 1_ 1)
= I + (sizeJ2 - num,) - (size,/2 - (num, - I))
=0
Jeżeli a 1_ 1 < 1/2, ale cx1 ~ 1/2, to

Ci= + tł>, - t,1)1-1


C1

= I + (2 · num1 - size 1) - (size 1_ 1 /2 - nwn;- 1)

422
18.4. TABLICE DYNAMICZNE

= 1 + (2 · (nwn 1_ 1 + 1) - size 1_ 1) - (size;_ 1/2 - nwn 1_ 1)

3 .
=3·nwn 1_ 1 - size 1_ 1 +3
2

3 3
< size 1_ 1 - size;_ 1 + 3
2 2

Koszt zamortyzowany operacji TABLE-INSERTnie przekracza więc 3.


Zajmijmy się teraz analizą sytuacji, w której i-tą operacją jest TABLE-
-DELETE. W tym przypadku num1 = num 1_ 1 -1. Jeśli a:1_ 1 < 1/2, to musimy
rozważyć, czy operacja powoduje zmniejszenie rozmiaru tablicy. Jeśli nie, to
size1 = size1_ 1 , a koszt zamortyzowany i-tej operacji wynosi

c1 = c, + Cl>i- Cl>1-1
=I+ (size1/2- nwni) -(size 1_ 1 /2 - num1_ 1 )
- 1 + (sizeJ2 - num,)- (size,/2- (num,+ I))
-2
Jeżeli natomiast a:1_ 1 < 1/2 oraz i-ta operacja powoduje zmniejszenie
rozmiaru tablicy, to jej faktyczny koszt wynosi c1 = nwn 1 + 1, ponieważ usu-
wamy jeden oraz kopiujemy num 1 elementów. Zachodzą przy tym równości
.vize;/2= size1_ 1 /4 = nwn 1 + 1, wobec tego koszt zamortyzowany i-tej operacji

wynosi

= (nwn 1 + 1) + (size1/2- numi)- (size 1_ 1 /2 - nwn 1_ 1)

- (num,+ I)+ ((num,+ 1) - num;)- ((2·num, + 2) - (num,+ I))

- I

Jeśli i-tą operacją jest TABLE-DELETE, a przy tym a:1_ 1 ~ 1/2, to koszt zamor-
tyzowany jest także ograniczony przez stałą. Szczegółowa analiza została po-
zostawiona jako zad. 18.4-3.
Podsumowując, koszt zamortyzowany każdej operacji jest ograniczony
przez stałą, faktyczny koszt ciągu n operacji na tablicy dynamicznej wynosi
więc O(n).

423
ROZDZIAŁ 18, ANALIZA KOSZTU ZAMORTYZOWANEGO

ZADANIA

18.4-1. Wyjaśnij intuicyjnie, dlaczego jeśli «J-t,::;; 1/2 oraz a:1 ,::;; 1/2, to koszt
zamortyzowany operacji TABLE-INSERT jest równy O.
18.4-2. Mamy zamiar zaimplementować dynamiczną tablicę z haszowaniem
z wykorzystaniem adresowania otwartego. Dlaczego lepiej traktować tab-
licę jak.o wypełnioną już wtedy, gdy jej współczynnik zapełnienia przekra-
cza pewną ustaloną wartość a: mniejszą od 1? Opisz pokrótce, jak zagwa-
rantować, że oczekiwany cz.aszamortyzowany operacji wstawiania do dy-
namicznej tablicy z haszowaniem z wykorzystaniem adresowania otwar-
tego jest 0(1). Dlaczego wartość oczekiwana faktycznego kosztu operacji
wstawiania nie musi być dla wszystkich wstawień równa 0(1)?
18.4-3. Wykaż, że jeśli i-tą operacją na tablicy dynamicznej jest TABLE-DELE-
TE oraz a1_ 1 ~ 1/2, to koszt zamortyzowany tej operacji względem funkcji
potencjału (18.5) jest ograniczony przez stałą.
18.4-4. Przyjmij, że zamiast dwukrotnego zmniejszania rozmiaru tablicy w sy-
tuacji, gdy jej współczynnik zapełnienia maleje poniżej 1/4, zmniejszamy
jej rozmiar, mnożąc go przez 2/3, jeśli jej współczynnik zapełnienia spada
poniżej 1/3. Użyj funkcji potentjalu

<P(T)= 12·num[T]-size[T]I

by wykazać, że przy użyciu tej strategii koszt zamortyzowany operacji


TABLE-DELETE jest ograniczony przez stałą.

Problemy
18-1. Licznik binarny z odwróconymibitami
W rozdziale 32 omówimy ważny algorytm zwany szybkim przekształceniem
Fouriera (FFT, ang. Fast FourierTransform).Pierwszy krok tego algorytmu
stanowi wykonanie permutacji odwracającej bity na tablicy A.[O.. n - 1] o dłu­
gości n= 2!'dla pewnej nieujemnej liczby c.ałkowitej k. Polega to na zamianie
miejscami elementów, których indeksy zapisane binamie mają wzajemnie od-
wrócone bity.
Każdy indeks a można zapisać jako k-bitowy ciąg (a,._ 1 , at-z, ..., a 0 ),

gdzie a=
•L a;J.'.Zdefiniujmy operację rev" następująco:
i"" o

czyli

424
PROBLEMY

•-'
rev (a) = L a 21
1 1 _ 1_ 1
j"' o

Na przykład jeśli n = 16 Qub równoważnie k = 4), to rev1(3) = 12, ponieważ


4-bitową reprezentacją liczby 3 jest 0011, co po odwróceniu daje 1100, czyli
4-bitową reprezentację liczby 12.

(a) Dla danej funkcji rev1 działającej w czasie 0(k) podaj algorytm wykonują­
cy permutację odwracającą bity, działający w czasie O(nk) na tablicy o roz-
miarze n= 21 .

Używając algorytmu opartego na analizie kosztu zamortyzowanego, możemy


poprawić czas wykonywania permutacji odwracającej bity. W tym celu utrzy-
mujemy licznik „na odwróconych bitach" i operację BJT-REVERSED-lNCRE
MENT.Operacja ta zastosowana do licznika zawierającego wartość a wy:macza
liczbę rev1(rev1(a) + I). Jeśli na przykład k = 4, to kolejne wywołania procedu-
ry BIT-REVERSED-INCREMENT na początkowo wyzerowanym liczniku wyzna-
czają następujący ciąg:

0000, 1000, 0100, 1100, 0010, 1010, ... -o, 8, 4, 12, 2, 10, ...
(b) Przyjmij założenie, że słowaw komputerze mają długość k, czyli mogą
reprezentować liczby k-bitowe. Dzięki temu można wykonywać ta.kie ope-
racje na liczbach binarnych, jak przesunięcia bitowe w lewo lub w prawo
o dowolną długość, bitowy AND, bitowy OR itp. Opisz implementację
procedury BIT-REVERSED-INCREMENT, która wykonuje permutację od-
wracającą bity na n-elementowej tablicy w czasie O{n).
(c) Przypuśćmy, że można wykonywać operacje przesunięcia tylko o jeden bit
w lewo lub w prawo. Czy nadal można ograniczyć czas wykonania per-
mutacji odwracającej bity przez O(n)?
18-2. Dyoamiczne wyszukiwanie binarne
Wyszukiwanie binarne uporządkowanej tablicy działa w czasie logarytmicz-
nym, lecz czas wstawienia nowego elementu jest liniowy względem jej rozmia-
ru. Można poprawić czas wstawiania, korzystając w odpowiedni sposób z wie-
lu uporządkowanych tablic.
Załóżmy, że chcemy wykonywać operacje SEARCHoraz INSERTna zbiorze
n-elementowym. Niech k = Llg(n+ l)J i niech (n 1 _ 1 , n1r;-z,... , n0 ) będzie bi-
narną reprezentacją n. Mamy k uporządkowanych tablic A 0 , A 1 , •.• , A 1 _ 1 ,
gdzie dla i= O, 1, ..., k - 1 tablica A 1 ma ro7llliar 21• Każda z tablic jest albo
pusta, albo zapełniona w zależności od tego, czy n1 = O, czy n1 = l. Sumarycz~
na liczba elementów znajdujących się w k tablicach wynosi więc
•-'
L n 2; = n.
1
i=O

425
ROZDZIAŁ 18. ANALIZA KOSZTU ZAMORlYZOWANEGO

Choć każda pojedyncza tablica jest uporządkowana, nie ma żadnych szczegól-


nych zależności między różnymi tablicami.

(a) Opisz sposób wykonywania operacji SEARCH na tej strukturze danych.


Oszacuj pesymistyczny czas działania tej operacji.
(b) Opisz sposób wstawiania nowego elementu do tej struktury. Przeanalizuj
jego pesymistyczny i zamortyzowany czas działania.
(c) Zastanów się, jak zaimplementować operację DELETE.

18-3. Zamortyzowane drzewa zrównoważone


Rozważmy zwykłe drzewa BST, w których każdemu węzłowi x odpowiada
atrybut size{x], oznaczający liczbę kluczy znajdujących się w poddrzewie o ko-
rzeniu w x. Niech o: będzie stałą z przedziału 1/2 ,:s:;;a< 1. Mówimy, że węzeł
x jest Ol'-Zl'Ównoważony, jeśli

size[left[x]] ,:s:;;o:·size[x]

oraz

size [right[x]] ,:s:;;o:· size [x]

Drzewo jako całość jest li-Zrównoważone, jeśli każdy węzeł


w drzewie jest
o:-zrównoważony. Następujące podejście do analizy kosztu zamortyzowanego
operacji na drrewach zrównoważonych zapoczątkował G. Vargbese.

(a) Drzewo 1/2-zrównoważone


jest w powyższym sensie maksymalnie zrów-
noważone. Pokaż, jak dla danego węzła x w dowolnym drrewie BST prze-
budować poddrrewo o korzeniu w x, aby było 1/2-zrównoważone.
Twój algorytm powinien działać w czasie 8(size [x]) oraz wykorzystywać
O(size[x]) pamięci pomocniczej.
(b) Wykaż, że czas wykonania operacji wyszukiwania w drzewie a-zrównowa-
żonym o n węzłach wynosi w najgorszym przypadku O(lgn).

W pozostałej części tego problemu załóżmy, że o:> 1/2. Przyjmijmy, że opera-


cje INSERT oraz DELETE są zaimplementowane tale jale w zwycz.ajnym drzewie
binarnym; tutaj jednale po każdej takiej operacji, jeśli pewien węzeł przestaje
być o:-zrównoważony, to poddrzewo o korreniu będącym najwyżej leżącym
takim węzłem zostaje „przebudowane" tak, że staje się 1/2-zrównoważone.
Dokonajmy analizy takich operacji za pomocą metody potencjału. Dla
węzła x w drzewie binarnym T zdefiniujmy

,i(x)- lsize[left[x]] -size[right[x]]I

426
UWAGI DO ROZDZIAŁU

oraz potencjał drzewa T jako

<P(7)- c L A(s),
;q;T:A(~);;.2

gdzie c jest dostatecznie dużą stalą zależną od "·

(c) Wykaż, że każde


drzewo binarne ma nieujemny potencjał oraz że 1/2-zrów-
noważone drzewo ma potencjał O.
(d) Przyjmijmy, że m jednostek potencjału wystarczy jako zapłata za przebu-
dowanie drzewa o m węzłach. Jak duże musi być c jako funkcja a, aby
koszt zamortyzowany przebudowy poddrzewa do drzewa "-zrównoważo­
nego był równy 0(1).
(e) Wykaż, że koszt zamortyzowany wstawienia lub usunięcia elementu z drze-
wa a-zrównoważonego wynosi O(lg n).

Uwagido rozdziału
Metoda kosztu sumarycznego była używana już przez Aho, Hopcrofta
i Ullmana [4]. W pracy Tarjana [189] można znaleźć liczne zastosowania meto-
dy księgowania i metody potencjału. Do autorów metody księgowania zostali
przez niego zaliczeni między innymi M.R. Brown, R.E. Tarjan, S. Huddleston
i K. Melhorn. Metoda potencjału pochodzi według niego od D.D. Sleatora.
Termin „zamortyzowany" pochodzi od D.D. Sleatora i R.E. Tarjana.
Część V

Złożone strukturydanych
Wprowadzenie
W tej części powracamy do badania struktur danych umożliwiających wykony-
wanie operacji na zbiorach dynamicznych. Poziom złożoności naszych rozwa-
żań będzie jednak dużo wyU.zy od tego z części III. Dla przykładu, w dwóch
rozdziałach zastosujemy szeroko metody analizy kosztu zamortyzowanego,
o których była mowa w ro7.dziale 18.
Rozdział 19 poświęcimy B-drzewom, które są odmianą zrównoważonych
drzew poszukiwań specjalnie zaprojektowanych do organizacji danych na dys-
kach magnetycznych. Ponieważ dostęp do danych na dysku jest dużo wolniej-
szy od dostępu do danych w pamięci wewnętrznej, zachowanie się B-Ofzew
będziemy oceniali nie tylko przez pryzmat czasu potrzebnego na wykonanie
operacji na zbiorach dynamicznych. Będzie nas także interesowała liczba do-
stępów do dysku. Liczba odwołań do dysku w każdej operacji na B-drzewie
wzrasta wraz z jego wysokością. Z drugiej strony operacje te gwarantują utrzy-
mywanie niewielkiej wysokości B-drzewa.
W rozdziałach 20 i 21 podamy implementację kopców złączalnych, które
umożliwiają wykonywanie operacji INSERT, MINIMUM, EXTRACT-MIN
i UNION. Operacja UNIONzłącza Oub inaczej - scala) dwa kopce. Struktury
danych opisane w tych podrozdziałach umożliwiają tak.że wykonywanie opera-
cji DELETEi DECREASE-KEY.
W podrozdziale 21 omówimy kopce dwumianowe, dla których koszt pesy-
mistyczny wykonania każdej z powyższych operacji wynosi O(lgn), gdzie n jest
łączną liczbą elementów w kopcu wejściowym (lub w dwóch kopcach w przy-
padku operacji UNION).Ponieważ kopce złączalne mają umożliwiać wykony-
wanie operacji UNION, kopce dwumianowe mają przewagę nad kopcami bi-
narnymi wprowadzonymi w rozdz. 7, których scalenie zabiera w najgorszym
przypadku czas 0(n).

430
WPROWADZENIE

Kopce Fibonacciego, o których będzie mowa w rozdz. 21, są przynajmniej


w aspekcie teoretycznym lepsze od kopców dwumianowych. Efektywność kop-
ców Fibonacciego zmierzymy, szacując koszty zamortyzowane poszczególnych
operacji. Koszty operacji INSERT, MINIMUM i UNION, rzeczywiste i z.amor-
tyzowane, wynoszą 0(1), a operacje EXTRACT-MINi DELETE są wykonywane
w zamortyzowanym czasie O(lgn). Najistotniejszą zaletą kopców Fibonacciego
jest jednak. to, że operacja DECREASE-KEYjest wykonywana w zamortyzowa-
nym czasie 0(1). Mały koszt zamortyzowany operacji DECREASE-KEYjest
tym, co powoduje, że dla pewnych problemów grafowych kopce Fibonacciego
są sercem algorytmów aktualnie asymptotycznie najszybszych.
Na koniec, w rozdziale 22, przedstawimy struktury danych wspomagające
wykonywanie operacji na zbiorach rozłącznych. W problemie zbiorów rozłącz­
nych dany jest n-elementowy zbiór podzielony na rozłączne, dynamiczne zbio-
ry. Na zbiorach tych wykonuje się operację UNION, która łączy dwa zbiory
w jeden, i operację FIND-SET, zwracająca identyfikator zbioru zawierającego
w danym momencie element, który jest parametrem tej operacji. Reprezentując
każdy zbiór za pomocą prostego drzewa z korzeniem, uzyskuje się zaskakująco
szybkie implementacje powyższych operacji: czas wykonania ciągu m takich
operacji wynosi O(ma.(m,n)), gdzie rx.(m,n) jest nieprawdopodobnie wolno ros-
nąco funkcją - dla n nie większego niż liczba atomów w całym poznanym
wszechświecie rx.(n,m) wynosi co najwyżej 4. Analiza kosztu zamortyzowanego,
w wyniku której dostajemy to ograniczenie, jest bardzo skomplikowana,
w przeciwieństwie do prostoty użytej struktury danych. W rozdziale 22 poka-
żemy interesujące, aczkolwiek trochę prostsze, ograniczenie na czas wykonania
ciągu operacji UNION i FIND-SET.
Struktury danych, o których będzie mowa w tej części, nie są jedynymi
złożonymi strukturami danych. Do takich struktur zalicza się też te, które
wymieniamy poniżej.

• Struktura danych odkryta przez van Emde Boasa (194] umo:iliwia wykony-
wanie operacji MINIMUM, MAXIMUM, INSERT, DELETE, SEARCH, EX-
TRACT-MIN, EXTRACT-MAX, PREDECESSORoraz SUCCESSORw pesymis-
tycznym czasie O(lglgn) pod warunkiem, że przestrzenią kluczy jest zbiór
{!, 2, ... , n).
• Drzewadynamiczne,wprowadzone przez Sleatora i Tarjana [177] i omawia-
ne przez Tarjana w pracy [188], umożliwiają utrzymywanie lasu rozłącznych
drzew z korzeniami. Każda krawędź w drzewie ma koszt o wartości rzeczy-
wistej. Drzewa dynamiczne umo:iliwiają realizację zapytań dotyczących oj.
ców, korzeni, kosztów krawędzi, minimalnego kosztu krawędzi na ścieżce
od danego węzła do korzenia. Drzewami można manipulować, odcinając
krawędzie, zmieniając koszty wszystkich krawędzi na ścieżce od danego wę·
zła do korzenia, przyłącz.ając korzeń jednego drzewa do innego drzewa,

431
WPROWADZENIE

ustanawiając dany węzeł korzeniem drzewa, do którego należy. Jedna z im-


plementacji drzew dynamicmych wnożliwia wykonywanie każdej z tych
operacji w zamortyzowanym czasie O{lgn). Inna, bardziej skomplikowana,
umożliwia wykonywanie tych operacji w pesymistycznym czasie O(lgn).
• Drzewa Sleatora-Tarjanat, opisane przez Sleatora i Tarjana w pracy [178]
i omawiane przez Tarjana w ksiąice [188], są odmianą drzew poszukiwań
binarnych, na których standardowe operacje dla drzew poszukiwań wyko-
nuje się w zamortyzowanym czasie O(lgn). Jednym z zastosowań drzew
Sleatora-Tarjana jest prostsza implementacja drzew dynamicznych.
• Trwale struktury danych umożliwiają odwoływanie się do (a czasami nawet
aktualizację) poprzednich wersji danej struktury danych. Driscoll, Sarnak:,
Sleator i Tarjan [59] zaprezentowali metody przekształcania dowiązanio­
wych struktur danych w struktury trwałe przy małych kosztach, C'La.Sowym
i pamięciowym. W problemie 14-1 jest podany prosty przykład trwałego
zbioru dynamicznego.

1 W literaturze angielskojęzycznej drzewa te występują pod nazwą splay trees (przyp. tłum.).
Rozdział 19

B-drzewa

B-drzewa są zrównoważonymi drzewami poszukiwań, które zostały zaprojek-


towane w taki sposób, żeby dobrze działały na dyskach magnetycznych lub
innych pamięciach zewnętrznych o dostępie bezpośrednim. B-drzewa są po-
dobne do drzew czerwono-cz.arnych (rozdz. 14), lecz mają lepsze własności,
gdy chcemy minimalizować liczbę operacji dysk.owych (odczytów z dysku i za-
pisów na dysk).
Główna różnica między B-drzewami i drzewami czerwono-czarnymi pole-
ga na tym, że liczba synów węzła w B-drzewie może być zarówno mała, jak
i sięgać wielu tysięcy. ,,Współczynnik rozgałęzienia" B-drzewa może być bar-
dzo duży. Wynika on zazwyczaj z charakterystyki używanej jednostki dysko-
wej. B-drzewa są podobne do drzew czerwono-cza.mych tym, że kairle n-węz­
łowe B-drzewo ma wysokość O(lgn). Jednakże współczynnik. rozgałęzienia
B-drzewa może być dużo większy od 2 i dlatego wysokość B-drzewa może być
znacząco mniejsza od wysokości drzewa czerwono-czarnego. Z tego powodu
B-drzewa mogą być też używane do implementacji wielu operacji na zbiorach
dynamicznych w czasie O(lgn).
B-drrewa są naturalnym uogólnieniem drzew poszukiwań binarnych. Na
rysunku 19.1 jest pokazane proste B-drzewo. Jeśli węzeł x w B-drzewie zawiera
n[x] kluczy, to x ma n[x] + 1 synów. Klucze w węźle x są punktami dzielącymi
przedział kluczy odpowiadający węzłowi x na n(x] + 1 podprzedziałów odpowia-
dających synom x. Podczas wyszukiwania klucza w B-drzewie decyzja o kierun-
ku dalsrego wyszukiwania, podejmowana w każdym węźle x, zależy od wyników
porównań wyszukiwanego klucza z n[x] kluczami pamiętanymi w tym węźle.
W podrozdziale 19.1 podajemy precyzyjną defmicję B-drzew i dowodzimy,
i.e wysokość B-drzewa rośnie tylko logarytmicznie wraz z liczbą należących do
niego węzłów. W podrozd.ziale 19.2 dowiemy się, jak wyszukiwać dany klucz
w B-drzewie i jak wstawiać do niego nowy klucz, a w podrozdz. 19.3 omówimy

433
ROZDZIAŁ 19. 8-DRZEWA

root[n

Ry&. 19.1. B-drrewo, którego klucze są spółgłoskami w języku angielskim. Węzeł wewnętrzny x za-
wierający n[x} kluczy ma n{x] + l synów. Wszystkie liście w drzewie znajduj11,&ię na tej samej
głębokości. Jasnoszare wę7.ły są badane podczas wyszukiwania litery R

usuwanie kluczy z B-drzewa. Zanim jednak pnejdziemy do dalszych rozważań,


musimy wyjaśnić, dlaczego efektywność struk:tw danych zaprojektowanych do
pracy na dyskach magnetycznych ocenia się inaczej niż efektywność struktur
danych przechowywanych w całości w pamięci wewnętrznej komputera.

Struktury danych w pamięci zewnętrznej


Pamięci wykorzystywane w systemach komputerowych są wykonane w różno­
rodnych technologiach. Pamięć wewnętrzna (lub pamięć główna) systemu kom-
puterowego jest zazwyczaj pamięcią półprzewodnikową - w jednym układzie
scalonym takiej pamięci można pamiętać kilkanaście milionów bitów danych.
Taka pamięć, w przeliczeniu na I pamiętany bit, jest dużo droższa od pamięci
magnetycznych, takich jak taśmy lub dyski. Typowy system komputerowy jest
wyposażony w p~ zewnętnną opartą na dyskach magnetycznych; pojem-
ność pamięci zewnętrznej jest często większa od pojemności pamięci wewnętrz­
nej o kilka rzędów wielkości.
Na rysunku 19.2 jest pokazany typowy napęd dyskowy. Powierzchnia dys-
ku jest pokryta materiałem magnetycznym. Głowica odczytuje i zapisuje dane
na powierzchni obracającego się dysku. Ramię, na którego końcu znajduje się
głowica, może ją umieszczać w różnych odległościach od środka dysku. Po-
wierzchnię dysku przesuwającą się pod unieruchomioną głowicą nazywamy
ścieżką. Informacja pamiętana na każdej ścieżce jest C7.ęSto podzielona na usta-
loną liczbę st100 o takich samych rozroi8J'ach; dla typowego dysku rozmiar
strony może wynosić 2048 bajtów. Strona jest i.a.zwyczaj podstawową jedno·
stk:ą zapamiętywania informacji na dysku - odczytywanie informacji z dysku
i zapisywanie informacji na dysk odbywa się całymi stronami. Czas dostępu
- czas potrzebny na ustawienie głowicy i odczekanie na pojawienie się żądanej
strony pod głowicą - może być duży (np. 20 ms), natomiast czas odczytu lub
:z.apisu strony już dostępnej jest mały. Tak więc ceną, jaką płacimy za niski
koszt pamięci magnetycznych, jest relatywnie długi czas dostępu do danych.

434
ROZDZIAŁ 19. 8-DRZEWA

Powierzchnia magnetyczna
Dysk dysku
\ Ramię,

i
.···......... ·•·..
- \
• •

Ścieżka dysk.owa
Rys. 19.2. Typowy napęd dyskowy

Ponieważ przemieszczanie elektronów jest znacznie „łatwiejsze" niż przemiesz-


czanie dużych (a również i małych) obiektów, całkowicie elektroniczne urzą­
dzenia pamięciowe, takie jak. pamięci półprzewodnikowe, mają znacznie krót-
szy czas dostępu niż urządzenia pamięciowe z częściami ruchomymi, takie jak
napędy dysków magnetycznych. Kiedy jednak wszystkie ruchome części znaj-
dą się już na właściwych pozycjach, odczyt z dysku lub zapis na dysk jest
calk.owicieelektroniczny (poza obrotem dysku) i duże ilości danych mogą być
szybko odczytywane lub zapisywane.
Często zdarza się, że czas potrzebny na dostęp do strony informacji i od-
czytanie jej z dysku jest dłuższy od czasu potrzebnego na przetworzenie całej
tej informacji przez komputer. Z tego powodu w tym rol.dziale będziemy anali-
zowali oddzielnie dwa zasadnicze elementy wpływające na czas działania al-
gorytmów:
• liczbę dostępów do dysku,
• czas (obliczeń) procesora centralnego ( w skrócie CPU1).
Liczba dostępów do dysku jest mierzona liczbą stron, które muszą być
odczytane z dysk.u lub zapisane na dysk. Zauważmy, że czas dostępu do dysku
nie jest stały - zależy on od odległości między ścieżką, nad którą aktualnie
znajduje się głowica, a ścieżką docelową, a także od stanu, w jakim znajduje się
wirujący dysk w momencie pojawienia się żądania dostępu. My jednak będzie­
my traktować liczbę odczytanych lub zapisanych stron jako zgrubne przybliże­
nie łącznego czasu wykorzystanego na dostępy do dysku.
W typowych zastosowaniach B-drzew ilość pamiętanych danych jest tak
duża, że nie mieszczą się one w całości w pamięci wewnętrznej. W algorytmach
opartych na B-drzewach, w zależności od potrzeb, kopiuje się wybrane strony

f Skrót od ang. Central Processor Unit (przyp. tłum.).

435
ROZDZIAŁ 19. B-DRZEWA

z dysku do pamięci wewnętrznej, a z powrotem na dysk zapisuje się te strony,


w których informacja została zmieniona. Ponieważ w algorytmach opartych na
B-drzewach w pamięci wewnętrznej jest potrzebna tylko stała liczba stron,
rozmiar tej pamięci nie ogranicz.a. rozmiarów przetwarzanych B-drzew.
W zapisie algorytmów (pseudokodach) operacje dyskowe modelujemy
w następujący sposób. Jeźeli obiekt x znajduje się aktualnie w pamięci we-
wnętrznej, to odwołujemy się do pól tego obiektu jak zazwyczaj, pisząc na
przykład key[x]. Jeśli jednak dany obiekt znajduje się na dysku, to zanim od-
wołamy się do jego pól, musimy wcześniej wczytać go z dysku do pamięci
wewnętrznej. Wykonuje się to z.a pomocą operacji DISK-READ(x). (Zakłada­
my, że jeśli x jest już w pamięci wewnętrznej, to DISK-READ(x) nie żąda do-
stępu do dysku - jest wtedy operacją typu „nic nie rób"). Operacja DISK-
-WRITE(x) jest używana do zapamiętywania zmian, które zostały dokonane na
polach obiektu x. Typowy schemat przetwarzania obiektu jest następujący.

1 """
2 żądanie dostępu do obiektu x
3 DISK-READ(x)
4 operacje, które odwołują się i/lub modyfikują pola x
5 DISK.-WRITE(x) I> Ta operacja jest pomijana, jeśli żadne z pól x nie
zostało zmienione.
6 inne operacje, które odwołują się do pól x, ale ich nie modyfikują
7 """

W danej chwili w pamięci wewnętrznej może znajdować się tylko ograniczona


liczba stron. Będziemy 7,akładać, że strony już niepotrzebne są usuwane z pa-
mięci wewnętrznej automatycznie (i zapisywane na dysk, jeśli informacja
w nich zawarta była zmieniana). W omawianych przez nas algorytmach opar-
tych na B-drzewach nie uwzględniamy tej kwestii.

root[11
l wę,ci
1000 kluczy
1001 ~złów
•••
1 001 OOOkluczy

1002001 węzłów
1000 1000 •• • 1002001 OOOkluczy

Rys. 19.3. B-dr:zewo o wysokości 2, zawierające ponad miliard kluczy. Każdy węzeł wewnęlrzny
i każdy liść zawiera 1000 kluczy. Na głębokości I jest 1001 węzłów, a na głębokości 2 jest ponad
jeden milion liści. Wewnątrz każdego węzła x jest za.pisana liczba mwartych w nim kluczy - n[x]

436
19.1. DEFINICJA B-DRZEWA

Ponieważ w większości systemów o czasie działania algorytmów opartych


na B-drzewach decyduje głównie liczba operacji DISK-REA.Oi DISK-WRITE,
należy wykorzystywać te operacje jak najefektywniej, wczytując z dysku lub
zapisując na dysk tak dużo informacji, jak tylko można. Dlatego rozmiar węz­
ła w B-drzewie jest zazwyczaj tak duży, jak rozmiar strony na dysku, a co za
tym idzie, liczba synów, których może mieć jeden węzeł w B-drzewie, jest limi-
towana rozmiarem strony na dysku.
Najczęściej spotykane współczynniki rozgałęzienia w dużych B-drzewach
wahają się między 50 a 1000, zależnie od ronniaru klucza w stosunku do
rozmiaru strony. Duży współczynnik rozgałęzienia znacznie redukuje zarówno
wysokość drzewa, jak i liczbę dostępów do dysku potrzebnych do znalezienia
klucza. Na rysunku 19.3 jest pokazane drzewo o współczynniku rozgałęzienia
1001 i wysokości 2, w którym można pamiętać ponad miliard kluczy. Pomimo
to, ponieważ korzeń drzewa może być na stałe trzymany w pamięci wewnętrz­
nej, do znalezienia dowolnego klucza w tym drzewie wystarczają tylko co naj-
wyżej dwa odwołania do dysku!

19.1. DefinicjaB-drzewa
Dla uproszczenia, podobnie jak to zrobiliśmy dla drzew poszukiwań binarnych
i drzew czerwono..czarnych, zakładamy, że każda dodatkowa informacja zwią­
zana z kluczem jest pamiętana w tym samym węźle co klucz. W praktyce
można by pamiętać z każdym kluczem tylko wskaźnik do innej strony na
dysku, na której są przechowywane informacje związane z tym kluczem.
W tym rozdziale, zapisując algorytmy, niejawnie zakładamy, że informacja
związana z kluczem Oub wskaźnik do niej) wędruje razem z kluczem, kiedykol-
wiek jest on przesuwany z węzła do węzła. W innej, często spotykanej organi-
zacji danych za pomocą B-drzew, dodatkowe informacje gromadzi się w li-
ściach B-drzewa, a w węzłach wewnętrznych znajdują się tylko klucze i wskaź­
niki do synów, przy czym maksymalizuje się wtedy współczynnik rozgałęzienia
węzłów wewnętrznych.
B-drzewo T jest drzewem z korzeniem (o korzeniu root [T]) o poniższych
własnościach.

1. Każdy węzeł x ma następujące pola:

(a) n[x] - liczba kluczy aktualnie pamiętanych w węźle x,


(b) n[x] kluczy pamiętanych w porządku niemalejącym key 1 [x] ~ key 2 [x] ~
~ ... ~ keynrx
1[x],
(c) /eaf[x] - pole logiczne, którego wartością jest TRUE, jeśli x jest liściem,
lub FALSE,jeśli x jest węzłem wewnętrznym.

437
ROZDZIAŁ 19. B·OAZEWA

2. x jest węzłem wewnętrznym, to zawiera także n[x} + 1 wskaźników do


Jeśli
swoich synów c 1 [x],c2 [x], ... , cll[%J+1[x]. Liście nie mają synów, więc ich pola
c1 nie są zdefiniowane.
3. Klucze key 1 [x] rozdzielają przedziały kluczy pamiętanych w poddrzewach:
jeśli k1 jest dowolnym kluczem z poddrzewa o korzeniu c1 [x], to

4. Wszystkie liście leżą na tej samej głębokości równej wysokości drzewa.


5. Istnieją dolne i górne ogranicunia na liczbę kluczy w danym węźle. Ograni-
czenia te zależą od ustalonej liczby całkowitej t ~ 2 nazywanej minimalnym
stopniemB-drzewa:

(a) Każdy węzeł różny od korzenia musi mieć co najmniej t - 1 kluczy.


Każdy węz.el wewnętrmy różny od korzenia ma zatein co najmniej
t synów. Jeśli drzewo jest niepuste, to korzeń musi mieć co najmniej
jeden klucz.
(b) Każdy węzeł może zawierać co najwyżej 2t - 1 kluczy. Dlatego każdy
węzeł wewnętrzny może mieć co najwyżej 2t synów. Powiemy, że węzeł
jest pełny, jeśli zawiera dokładnie 2t - 1 kluczy.

Najprostsze B-drzewo ma minimalny stopień t = 2. Każdy węzeł we-


wnętrzny ma wtedy 2, 3 lub 4 synów. Takie drrewo nazywamy 2-3-4 drzewem.
W praktyce używa się zazwyczaj dużo większych wartości t.

Wysokość B-drzewa
Liczba dostępów do dysku potrzebnych przy realizacji większości operacji na
B--drzewiejest proporcjonalna do jego wysokości. Przeanalizujemy teraz pesy-
mistyczną wysokość B--drzewa.

'fWIERDZENIE 19.1.
Jeślin ~ 1, to dla każdego B--drzewa o n kluczach, wysokości hi minimalnym
stopniu t ~ 2 mamy

DOWÓD
JeśliB--drzewo ma wysokość h, to liczba jego węzłów jest najmniejsza, gdy
korzeń zawiera jeden klucz, a wszystkie pozostałe węzły zawierają t - 1 kluczy.
W takim przypadku mamy 2 węzły na głębokości 1, 2t węzłów na głębokości 2,

438
19.1. DEFINICJA 8-DRZEWA

2t2 węzłów na głębokości 3 itd. aż do głębokości h, na której znajduje się 2r- 1


węzłów. Na rysunku 19.4 jest przedstawione takie drzewo dla h = 3. Stąd wy-
nika, że liczba kluczy n spełnia nierówność

n;,,1+c1-1)L2t-•
I: 1

-1 +2(1-1)(
1
;_ i)
=2t,,-1
co kończy dowód.

Liczba
Głębokość węzłów

O I

I 2

2 2,

,-t ... t-1 1-1 ... I -1 1- l 3 2,'


Rys. 19.4. B-drzewo o wysokości 3 z najmniejszą możliwą liczbą kluczy. Wewnątrz każdego węzła
x jest zapisana liczba n [x]

Widać teraz zalety B-drzew w porównaniu z drzewami czerwono-czarny-


mi. Chociaż wysokość drzewa rośnie w obu przypadkach jak O(lgn) (pamiętaj­
my, że t jest stałą), jednak dla B-drzew podstawa logarytmu może być wiele
razy większa. Tak więc B-drzewa są o czynnik około lg t oszczędniejsze od
drzew czerwono-czarnych w liczbie badanych węzłów w większości operacji na
drzewach. Ponieważ badanie węzła w drzewie wymaga mzwyczaj dostępu do
dysku, liczba dostępów do dysku jest w ten sposób istotnie zredukowana.
ZADANIA
19.1-1. Dlaczego nie dopuszcza się, żeby minimalny stopień t był równy 1?
19.1-2. Dla jakich wartości t drzewo z rys. 19.1jest prawidłowym B-drzewem?
19.1-3. Narysuj wszystkie prawidłowe B-drzewa o minimalnym stopniu 2, któ-
re reprezentują zbiór 1, 2, 3, 4, 5.
19.1-4. Podaj ścisłe górne ograniczenie na liczbę kluczy (jako funkcję minimal-
nego stopnia t), które mogą być przechowywane w B-drzewieo wysokości h.

439
ROZDZIAŁ 19. B-DRZEWA

19.1-5. Opisz strukturę danych, która powstaje z drzewa czerwono-czarnego


w wyniku wchłonięcia przez każdy czarny węzeł jego czerwonych synów
i ustanowienia ich synów synami nowo powstałego węzła.

19.2. Podstawoweoperacjena B-drzewach


W tym podrozdziale zapomamy się szczegółowo z operacjami: wyszukiwania
w B-drzewie (B-TREE-SEARCH),tworzenia nowego B-drzewa (B-TREE-CREA-
TE), wstawiania do B-drzewa (B-TREE-INSERT}).W opisie tych procedur
• • •
przYJDlUJemy,ze:
• Korzeń B-drzewa zawsze majduje się w pamięci wewnętrznej, tak więc ni-
gdy nie jest wczytywany z dysku. Wymaga się jednak, żeby na dysku został
zapisany nowy korzeń, kiedykolwiek llDienia się korzeń drzewa.
• Każdy węzeł przekazywany jako parametr musi być wcześniej wczytany
z dysku.
Wszystkie prezentowane procedury są ,jednoprzebiegowe" i polegają na
przechodzeniu od korzenia w dół drzewa, bez konieczności powracania w górę.

Wyszukiwanie w B-drzewie
Wyszukiwanie w B-drzewie jest bardzo podobne do wyszukiwania w drzewie
poszukiwań binarnych (BST). Różnica polega na tym, że w każdym węźle
B-drzewa dokonuje się wyboru poddrzewa, w którym ma być kontynuowane
wyszukiwanie, spośród poddrzew, których liczba zależy od liczby kluczy w tym
węźle. Dokładniej, takich poddrzew w węźle x jest n[x] + 1. W drzewach bi-
narnych zawsze wybiera się jedno poddrzewo spośród dwóch.
B-TREE-SEARCH jest prostym uogólnieniem procedury TREB-SEARCH dla
drzew BST. Dane wejściowe procedury B-TREE-SEARCHstanowią: wskaźnik
do węzła x i klucz k, który należy znaleźć w poddrzewie o korzeniu w x.
Wywołanie B-TREE-SEARCH(root[7],k) spowoduje rozpoczęcie wyszukiwania
w całym B-drzewie. Jeśli k jest w drzewie, to B-TREE-SEARCH daje w wyniku
uporządkowaną parę (y, z) składającą się z węzła y oraz indeksu i takich, że
key 1 [y] = k. W przeciwnym razie jest zwracana wartość NIL.

B-TREE-SEARCH(x,k)
1 i-1
2 while i~ n[x] i k > keyt[x]
3 doi+-i+l
4 if i .:is;n[x] i k = key 1 [x]
5 then return (x, z)

440
19.2. PODSTAWOWE OPERACJE NA B-DRZEWACH

6 if leaflx]
7 then return NIL
8 else DISK-READ(c,[x])
9 return B-TREE-SEARCH(c,[x],k)

Przeszukując węzeł x liniowo (wiersze 1-3), znajdujemy najmniejsze takie i,


że k ~ keyi [x]. Jeśli wszystkie klucze w x są mniejsze od klucza k, to i przyj-
muje wartość n[x] + 1. W wierszach 4-5 sprawdzamy, czy natrafiliśmy na po-
szukiwany klucz. Jeśli odpowiedź jest pozytywna. to zwracamy (x, r). W wier-
szach 6-9 albo kończymy wyszukiwanie bez sukcesu Geśli x jest liściem), albo
wyszukujemy rekurencyjnie dalej, schodząc do właściwego poddrzewa x.
Wcześniej jednak musimy wczytać z dysku jego odpowiedniego syna.
Rysunek 19.1 ilustruje operację B-TREE-SEARCH; jasnoszare węzły są ba-
dane podczas wyszukiwania klucza R.
Podobnie jak w procedurze TREE-SEARCH dla drzew BST, węzły napoty-
kane podczas rekurencyjnego wyszukiwania tworzą ścieżkę od korzenia w dół
badanego drzewa. Liczba dostępów do stron na dysku w procedurze B-TREE-
=
-SEARCH wynosi zatem E>(h) 0(lgrn), gdzie h jest wysokością wejściowego
B-drzewa, a n liczbą zapisanych w nim kluczy. Ponieważ n [x] < 2t, czas wyko-
nania instrukcji wbile (wiersze 2-3) w każdym węźle wynosi O(t), a łączny czas
obliczeń procesora (CPU) jest O(th) = O(tlgrn).

Tworzenie pustego B-drzewa


Żeby zbudować B-drzewo T, najpierw za pomocą procedury B-TREE-CREATE
tworzymy pusty węzeł-korzeń, a następnie dodajemy nowe klucze za pomocą
B-TREE-INSERT. W obu tych procedurach jest wykorzystywana pomocnicza
procedura ALLOCATE-NODE,która w czasie 0(1) przydziela jedną stronę na
dysku dla nowego węzła. Możemy założyć, że węzeł utworzony przez ALWCA-
TE-NODE nie wymaga czytania z dysku (operacji DISK-READ), ponieważ do-
tychczas jeszcze żadna informacja związana z tym węzłem nie została tam

zapisana.

B-TREE-CREATE(7)
1 X+- ALLOCATE-NODEQ
2 leaflx] +- TRUE
3 n[x]-o
4 DISK-WRITE(x)
5 root [1] +- x

Procedura B-TREE-CREATE wymaga 0(1) operacji dyskowych oraz 0(1) czasu


procesora.

441
ROZDZIAŁ 19. B-DRZEWA

Rozbijaniewęzła w B-drzewie
Wstawianie klucza do B-drzewa jest znacznie bardziej skomplikowane niż
wstawianie klucza do dr rewa BST. Zasadniczą operacją używaną podczas
wstawiania jest rozbijanie pełnego węzła y (mającego 2t - l kluczy) na dwa
węzły o t - 1 kluczach. Rozbicia dokonuje się względem środkowego klucza
key 1[y], który jest przesuwany do ojca y. O ojcu y zakłada się, że w momencie
rozbijania y nie jest pełny. Klucz key 1[y] wyznacza punkt podziału między
nowymi drzewami. Jeśli y nie ma ojca, to wysokość drzewa rośnie o 1. Rozbija-
nie może zatem spowodować zwiększenie wysokości drzewa.
Rozbijanie jest wykonywane za pomocą procedury B-TREE-SPLIT-CHILD,
której dane wejściowe stanowią: niepełny węzeł wewnętrzny x (o którym zakła­
da się, że jest w pamięci wewnętrznej), indeks i oraz węzeł y taki, że y = c1[x]
jest pełnym synem x. Procedura B-TREE-SPLIT-CHILD rozbija y na dwa węzły
i aktualizuje x tak, że zostaje uwzględniony jego nowy dodatkowy syn.
Ten proces został zilustrowany na rys. 19.5. Pełny węzeł y jest rozbijany
względem klucza środkowego S, który zostaje przesunięty w górę do x - ojca
y. Klucze z y, większe od klucza środkowego, są 1nnieS7.Czane w nowym węźle
z, który następnie zostaje synem x.
B-TREE-SPUT-CHILD(x, i, y)
l z+- ALLOCATE-NODEQ
2 leafiz] - leafly]
3 n[z]-1-l
4 forj+-ltot-1
5 dokey 1[z]-key 1+,CYl
6 H not leafly]
7 tb.enfor j +- 1 to t
8 do c 1[z]+-c 1 + 1[y]
9 n[y]-1-l
10 forj+-n[x]+ I downtoi+ I
11 doc J+ 1 [x]+- c1[x]
12 C 1 + 1 [x]+-z
13 for j +- n[x] downto i
14 do key 1 + 1[x)+-key 1[x]
15 key,[x] -key,[y]
16 n[x]- n[x] + l
17 DISK-WRITE(y)
18 DISK-WRITE(z)
19 DISK-WRITE(x)
Procedura B-TREE-SPLIT-CHILD działa na zasadzie „rozetnij i sklej".
W naszym przypadku jest rozbijany węzeł y, który jest i-tym synem x. Począt-

442
19.2. PODSTAWOWE OPERACJE NA B·DRZEWACH

sr" .::, s.::"


.,','-ł.,,
I
..-...,
-..~· '.~
.,.....,"(·•

.,, N N W ...
••.••.•
,•.,•.••.••..
,.•.••
,:111,,, ,/
'
v=r~i]
'
' =(,.' ~t]
~

p ' '
T· tł:1--vtr.
'

''
ł' j ł l' j !T T
T, T, T, T T T, T, T T~ T~
" ' ' ' 6 7

Rys. 19.5. Rozbijanie węzła z t = 4. Węzeł y jest rozbijany na dwa węzły, y oraz z, środkowy klucz
S z y wędruje w górę do ojca y

kowo y ma 2t - 1 kluczy, ale w wyniku rozbicia liczba ta maleje do t - 1.


Węzeł z „adoptuje" t - l skrajnie prawych kluczy węzła y i zostaje nowym
synem x, umieszczanym w tablicy synów węzła x, bezpośrednio po y. Klucz
środkowy z węzła y jest przesuwany w górę do x, gdzie oddziela y od z.
W wierszach 1-8 jest tworzony węzeł z, który z węzła y przejmuje t - 1
największych kluczy i t odpowiednich synów. LiC'ZDiksynów węzła y jest ak-
tualizowany w wierszu 9. Na koniec (wiersze 10-16) węzeł z zostaje synem x,
środkowy klucz z y jest przesuwany w górę do x i jest aktualizowany licznik
kluczy w tym węźle. W wierszach 17-19 wszystkie zmodyfikowane strony są
zapisywane na dysku. Czas obliczeń procesora centralnego w procedurze
B-TREE-SPLIT-CHILD wynosi 0(t) - z powodu pętli w wierszach 4-5 oraz 7-8.
(Liczba iteracji w innych pętlach wynosi co najwyżej t).

Wstawianie klucza do 8-drzewa


Wstawianie klucza k do B-drzewa To wysokości h jest wykonywane w jednym
przejściu w dól drzewa, wymagającym O(h) dostępów do dysku. Wymagany
czas obliczeń procesora wynosi O(th) = O(t log 1 n). Wstawianie jest realizowa-
ne za pomocą procedury B-TREE-lNSERT, w której jest wykorzystywana proce-
dura B-TREE-SPLIT-CHILD. Gwarantuje ona, że w kolejnych zejściach rekuren-
cyjnych nigdy nie schodzimy do pełnego węzła.

B-TREE-INSERT(T, k)
1 r +- root [1]
2 if n [r] - 21 - I
3 tben s +- ALLOCATE-NODE( )
4 root [TJ+- s
5 /eaf1s]+- FALSE
6 n[s]+-0
__________________ ,,,_,,_ ---------
443
ROZDZIAŁ 19. B-DRZEWA

rootln

'

..........................
:w~··

Rys. 19.6. Rozbijanie korzenia z I = 4. Węzeł-korzeń r jest rozbijany na dwa węzły i jest tworzony
nowy węzeł-korzeń 1. Nowy korzeń zawiera środkowy klucz z r, a oba węzły powttałe z rozbicia
zostają. jego synami. Rozbicie korzenia powoduje zwiększenie wysokości drzewa o I

7 c1[s]+-r
8 B-TRBB-SPLIT-CHlw(s, I, r)
9 B-TRBB-INSBRT-NONFULL(s, k)
10 else B-TREE-INSERT-NONFULL(r,
k)

Wiersze 3-9 są wykonywane wtedy, kiedy węzeł-korzeń jest pełny: korzeń


jest rozbijany i nowy węzeł s (z dwoma synami) zostaje korzeniem. Rozbijanie
korzenia jest jedynym sposobem zwiększania wysokości B-drzewa. Ten przy-
padek:został zilustrowany na rysunku 19.6. W przeciwieństwie do drzewa BST
B-drzewo rośnie u góry, a nie na dole. Procedura B-TREE-INSERT kończy się
wywołaniem procedury B-TREE-INSERT-NONFUll, która wstawia klucz k do
drzewa o niepełnym korzeniu. B-TREE-INSERT-NONFULL schodzi rekurencyj-
nie w dół drzewa, dbając o to, żeby węzeł, do którego następuje zejście reku-
rencyjne, nie był pełny. W razie potrzeby jest wywoływana procedura B-TREE-
·SPLIT-CHILD.Procedury B-TREE-INSERTi B-TREE-INSERT-NONFULL są tak
zorganizowane, że powyższy warunek jest zawsze spełniony.

B-TRBB-INSBRT-NONFULL(x, k)
1 i+-n[x]
2 if leafix]
3 tben while i~ 1 i k < key1[x]
4 do key1 + 1 [x]+-key 1[x]
5 i+-i-1
6 keY1+1[X]+-k
7 n[x]~n[x]+I
8 DISK-WRITB(x)
9 else while i~ 1 i k < key1[x]
10 doi+-i-1
11 i+-i+l

444
19.2. PODSTAWOWE OPERACJE NA B-DRZEWACH

12 DISK-READ(c,[x])
13 if n[c,[x]] - 21-1
14 then B-TREE-SPLIT-CHILD(x,
i, c1[x])
15 if k > key,[x]
16 tben i+-i+ I
17 B-TREE-INSERT-NONFULL(c1[x],
k)

Procedura B-TREE-INSERT-NONFULL działa w następujący sposób. Wier-


sze 3-8 są wykonywane wtedy, gdy x jest liściem i klucz k ma się znaleźć w x.
Jeśli x nie jest liściem, tok musi zostać wstawiony do właściwego liścia w pod-
drzewie o korzeniu x. Wówczas w wierszach 9-11 wyznacza się syna x, do
którego następuje zejście rekurencyjne. W wierszu 13 sprawdza się, czy węzeł,
w którym ma być kontynuowane wyszukiwanie, nie jest pełny. Jeśli jest on
pełny, to za pomocą procedury B-TREE-SPLITCmLD zostaje rozbity na dwa
węzły. Powstałe węzły zostają synami x. Następnie -w wierszach 15-16- usta-
la się, do którego z tych dwóch synów nastąpi zejście rekurencyjne. (Zauważ­
my, że nie ma potrzeby wywoływać D1SK-READ(c 1[x]) po tym, jak w wierszu
16 wzrosło i, ponieważ w tym przypadku schodzimy do syna utworzonego
w wyniku wykonania B-TREE-CHILD-SPLIT). Wiersze 13-16są wykonywane,
aby zagwarantować, że wywołanie rekurencyjne nigdy nie nastąpi dla pełnego
węzła. W wierszu 17 klucz kjest wstawiany rekurencyjnie do właściwego pod-
drzewa. Rysunek 19.7 ilustruje różne przypadki występujące podczas wstawia-
nia klucza do B-drzewa.
Liczba dostępów do dysku w procedurze B-TREE-INSERT wykonywanej na
B-drzewie o wysokości h wynosi O(h), ponieważ tylko 0(1) operacji DISK-
-READ i DISK-WRITEjest wykonywanych między kolejnymi wywołaniami
B-TREE-INSERT-NONFULL. Lącmy czas wykorzystania procesora wynosi
O(th) = O(t log 1 n). Ponieważ procedura B-TREE-INSERT-NONFULL jest „ogo-
nowo-rekurencyjna", to można ją zaimplementować alternatywnie za pomocą
instrukcji while, Nietrudno zauważyć, że wówczas w każdej chwili obliczeń jest
potrzebna tylko stała liczba stron w pamięci wewnętrznej.
ZADANIA
19.2-1, Zilustruj wynik.iwstawiania do początkowo pustego B-drzewat kolejno
kluczy

Narysuj tylko te B-drzewa, w których pewne węzły są rozbijane, oraz


ostatnie drzewo.

1
Przyjmij, że stopień B-drzewa t jest równy 3 (przyp. tłum.).

445
FtOLDZIAl 18 l:l DH/I VVA

. M -p,,!:f]
t''lJ-",,_4 ___=:;:_,_,,

AB(:DE
' _..,--*---------.
cJ:~~
i~.tJJu~ •'r:1rw11
------- -
(;AfPT,\'
(cl \\-'s;ta""iono(J ' ../· ; '," -~..~-·

. - -'
{d) \\. ~la\\ l011U /
p


!' (1 ..___,
M ...
•2 • ,-"· .J
[J~Jic-,•.'.ó~&] J
ii!=••. K l. i N a
~-----~·

(<:\ \\.stav..1nrhll
c-·P 1
,_____
... ,.J_
--"


•B D
•E f'
A

Rys. 19.7. Wstawianie kluczy do B-drzewa. Minimalny stopień tego 8-drzewa wynosi 3, lak więc
w każdym wężle można pamiętać co najwyżej 5 kluczy. Węzły modytlk.owane w procesie wstawia-
nia są jasnoszare. (•) Drzewo początkowe. (b) Wynik wstawienia B do drzewa z (a); prollle wsta-
wienie do ~zła-liścia. (c) Wynik wstawienia Q do poprzedniego dnewa. Węzeł RSTUV jest roz-
bijany na dwa ~zły mwierają.ce RS i UV, klucz T jest prze$Uwany do korzenia, Q jest wstawiany
do lewej połowy (węzła RS). (d) Wynik wstawienia L do poprzcdniego drz.ewa. Ponieważ korz.eń
jest pełny, zostaje rozbity. Wysokość B-drzewa rośnie o I. L jest wstawiane do liścia zawierającego
JK. (e) Wynik wstawienia F do poprzcdniego drzewa. Węzeł A.BCDE jest rozbijany, a następnie
F jest wstawiany do prawej połowy (węzła DEJ

19.2-2. Wyjaśnij, w jakich okolicznościach (jeśli takie są w ogóle) podczas


wstawiania nowego klucza do drzewa są wykonywane nadmiarowe opera-
cje odczytywania z dysku (DISK-R.EAD)lub zapisu na dysk (DISK-WRITE).

446
19.3. USUWANIE KLUCZA Z B-DRZEWA

(Operacja DISK-READ jest nadmiarowa, jeśli strona czytana z dysku jest


już w pamięci wewnętrznej. Operacja DISK-WRITEjest nadmiarowa, jeśli
na dysk jest przesyłana strona z identyczną informacją jak ta, która jest
tam już zapisana).
19.2-3. Wyjaśnij, jak w B-dr.zewie znaleźć klucz minimalny i jak wyznaczyć
poprzednik danego klucza.
* 19.2-4. Do początkowo pustego B-drzewa o stopniu t = 2 wstawiamy klucze
1, 2, ... ,n.Ile węzłów ma końcowe B-drzewo?
19.2-5. Ponieważ w węzłach-liściach nie trzeba trzymać wskaźników do sy-
nów, można by :romiast nich pamiętać większą liczbę kluczy, bez zmiany
rozmiaru strony przesyłanej między pamięcią wewnętrzną i dyskiem. Po-
każ, jak zmodyfikować procedury tworzenia nowego B-drzewa i wstawia-
nia do B-drzewa, żeby uwzględnić taką możliwość.
19.2-6. Przypuśćmy, że procedura wyszukiwania B-TREE-SEARCHjest zaim-
plementowana w taki sposób, że w każdym węźle zamiast wyszukiwania
liniowego jest wykonywane wyszukiwanie binarne. Pokaż, że w tej imple-
mentacji czas wykorzystania procesora wynosi 00gn) niezależnie od wy-
boru t jako funkcji n.
19.2-7. Przypuśćmy, że sprzętowa realizacja dostępu do dysku umożliwia wy-
branie dowolnego rozmiaru strony dyskowej, ale czas potrzebny na odczy-
tanie jednej strony wynosi a+ bt, gdzie a i b są pewnymi stałymi zależnymi
od rozwiązań sprzętowych. Opisz, jak dobrać minimalny stopień t, żeby
zminimalizować (w przybliżeniu) czas wyszukiwania w B-drzewie. Podaj
optymalną wartość t dla przypadku, w którym a = 30 ms i b = 40 µs.

19.3, Usuwaniekluczaz B-drzewa


Usuwanie z B-drzewa jest analogiczne do wstawiania, choć jest trochę bardziej
skomplikowane. Zamiast podawać pseudokod dla operacji usuwania, opisze-
my ją słowami.
Usuwanie klucza jest realizowane za pomocą rekurencyjnej procedury
B-TREE-DELETE.Załóżmy, że chcemy usunąć klucz k z poddrzewa o korzeniu
w węźle x. Procedura B-TREE-DELETE jest zaprojektowana w taki sposób,
żeby był spełniony następujący nieimiennik. Kiedykolwiek następuje wywoła­
nie rekurencyjne B-TREE-DELETE dla węzła x różnego od korzenia, w tym
węźle jest co najmniej t kluczy, gdzie t jest minimalnym stopniem węzła w drze-
wie. Zauważmy, iż dzięki temu, że xma o jeden klucz więcej, niż jest to wyma-
gane, istnieje możliwość przesunięcia w razie konieczności jednego klucza do
syna, do którego następuje zejście rekurencyjne. Powyższy niezmiennik umoż­
liwia usunięcie klucza z drzewa w jednym przejściu w dól drzewa, bez koniecz-
ności powracania w kierunku korzenia (z jednym wyjątkiem, który wkrótce

447
ROZDZIAŁ 19. B-DRZEWA

omówimy). W opisie usuwania z B-drzewa zakładamy, że gdy z korzenia x zo·


staną usunięte wszystkie klucze i x jest węzłem wewnętrznym, wtedy jest on
usuwany, a jego jedyny syn c 1 {x] zostaje nowym korzeniem drzewa. W ten
sposób wysokość drzewa jest zmniejszana o jeden, a własność, że korzeń drzewa
z.awiera co najmniej jeden klucz, jest zachowana (chyba że drzewo jest puste).
Rysunek 19.8 ilustruje różne przypadki występujące w procesie usuwania
klucza z B-drzewa.
Usuwanie z B-drzewa wykonujemy następująco.

1. Jeśli klucz k jest w węźle x i x jest liściem, to usuń klucz k z x.


2. Jeśli klucz k jest w węźle x i x jest węzłem wewnętrznym, to wykonaj co
następuje.

(a) Niech y będzie synem x poprzedzającym k. Jeśli y ma co najmniej t ldu·


czy, to w poddrzewie o koI7.eniu wy wyznacz poprzednik k' klucza k.
Rekurencyjnie usuń k 1 i w węźle x zastąp k przez k'. (Wyznaczenie k'
i usunięcie go z poddrzewa może być wykonane w jednym przejściu
w dół drzewa).
(b) Symetrycznie, jeśli syn z, który występuje po k w węźle x, ma co naj·
mniej t kluczy, to wyznacz następnik k' dla kw poddrzewie o korzeniu
w z. Rekurencyjnie usuń k' i zastąp k przez k' w x. (Wyznaczenie k'
i usunięcie go z poddrzewa może być wykonane w jednym przejściu
w dól poddrzewa).
(c) Jeśli obaj synowie y i z mają tylko po t - 1 kluczy, to przenieś
ki wszystko z węzła z do y. W wyniku tej operacji kluczki wskaźnik do
z zostają usunięte z x. Następnie zwolnij pamięć przydzieloną dla
z i usuń rekurencyjnie k z y.
3. Jeśli klucz k nie występuje w wewnętrznym węźle x, to wyznacz korzeń c 1[x]
poddI7.ewa, w którym musi znajdować się k (jeśli tylko jest w drzewie). Jeśli
c 1[x] ma tylko t- 1 kluczy, to wykonaj podkrok 3a lub 3b w celu zagwa·
rantowania, że zejście rekurencyjne następuje do węzła zawierającego co
najmniej t kluczy. Następnie usuń rekurencyjnie k z właściwego poddrzewa.

(a) Jeśli w węźle c 1[x] jest tylko t - 1 kluczy, ale jeden z jego sąsiednich
braci ma t kluczy, to umieść w c 1[x] dodatkowy klucz, przesuwając
odpowiedni klucz z x, a w jego miejsce przenosząc klucz z lewego lub
prawego brata - z tego, który :zawiera t kluczy. Na koniec przesuń
jeszcze z wybranego brata do c 1[x] wskaźnik do odpowiedniego syna.
(b) Jeśli c 1[x] i sąsiedni bracia mają po t - 1 kluczy, to połącz c 1 zjed·
nym z sąsiednich braci, przesuwając odpowiedni klucz z x do nowo
powstałego węzła. Przesunięty klucz jest kluczem środkowym w nowym
węźle.

448
PROBLEMY

Ponieważ większość kluczy w B-drzewie znajduje się w liściach, możemy


oczekiwać, że w praktyce te klucze są najczęściej usuwane. W takim przypadku
usuwanie jest wykonywane w jednym przejściu od korzenia do liścia, bez po-
trzeby powracania w górę drzewa. Jednakie, kiedy jest usuwany klucz z węzła
wewnętrznego, oprócz przejścia w dół drzewa może być też konieczny powrót
do węzła, z którego klucz jest usuwany, w celu zastąpienia go przez poprzednik
lub następnik w drzewie (przypadki 2a i 2b ).
Chociaż opisana procedura wydaje się skomplikowana, wymaga tylko
O(h) operacji dyskowych dla B-drzewa o wysokości h, ponieważ tylko stała
liczba odczytów z dysku i zapisów na dysk jest potrzebna na każdym poziomie
rekursji. Usuwanie wymaga O(th) = O(tlg 1 n) czasu procesora.

ZADANIA

19.3-1. Narysuj B-drzewa powstające w wyniku usuwania z drzewa z rys, 19.Sf


kolejno kluczy C, P i V.
19.3-2. Napisz pseudokod dla procedury B-TREE-DELETE.

Problemy
19-1. Stosy w pamięci zewnętrznej
Rozważmy implementację stosu na komputerze, którego szybka pamięć we-
wnętrzna ma stosunkowo małą pojemność w przeciwieństwie do pamięci dys-
kowej. Operacje na stosie PuSH i Pop są wykonywane dla wartości mieszczą­
cych się w jednym słowie maszynowym. Chcemy wnożliwić wykonywanie ope-
racji na stosie, który może urosnąć tak bardzo, że nie zmieści się w pamięci
wewnętrznej i dlatego musi być pamiętany na dysku.
W prostej, ale nieefektywnej implementacji cały stos jest pamiętany na
dysku. W pamięci wewnętrznej jest trzymany tylko „wskaźnik" do wierzchołka
stosu. Jeśli wartością wskaźnika jest p, to wierzchołek stosu jest zapisany w sło­
wie (pmod m) ze strony l_p/mJna dysku, gdzie m jest liczbą słów na stronie.
Operację PUSH implementujemy w następujący sposób. Wskaźnik do stosu
zwiększamy o jeden, wczytujemy odpowiednią stronę z dysku do pamięci we-
wnętrznej, element wkładany na stos zapisujemy w odpowiednim słowie wczy-
tanej strony, a następnie zapisujemy tę stronę z powrotem na dysk. Operację
POP wykonujemy podobnie. Wskaźnik do stosu zmniejszamy o jeden, wczytu-
jemy odpowiednią stronę z dysku i zwracamy element z wierzchołka stosu. Nie
musimy zapisywać wczytanej strony z powrotem na dysk, ponieważ informacja
w niej zapisana nie została zmieniona.
Ponieważ operacje dyskowe są stosunkowo drogie.jakość każdej implemen-
tacji mierzymy liczbą dostępów do dysku. Liczymy także czas wykorzystania

449
ROZDZIAŁ 19. B-DRZEWA

procesora, ale dostęp do strony na dysku składającej się zm słów obciążamy


kosztem 0(m).

(a) Początkowe drzewo

(b) lJsunięto F: przypadek I

(c) Usunięto M: przypadek 2a ----~---

C GL

(d) Usunięto G: przypad~~:------·

j,c ::i_l
t ..··-
...
D EJKl!ilif3
Rys. 19.8. Usuwanie kluczy z B--<irzewa.Minimalny stopień w tym B--O!zewiewynosi t = 3, tak więc
w żadnym węźle (różnym od korzenia) nie może być mniej niż 2 klucze. Modyfikowane węzły są
jasnoszare. (a) B-drzewo z rysunku l 9.7e. (b) Usuwanie P. Przypadek I: proste usuwanie z liścia.
(c} Usuwanie M. Przypadek 2a: poprzednik L klucza M zostaje przesunięty na pozycję zajmowaną
ptT.el M. (d) Usuwanie G. Przypadek 2c: klucz G zostaje przesunięty w dół i wykorzystany do
utworzenia węzła DEGJK, a następnie jest z niego usuwany. (e) Usuwanie D. Przypadek 3b: nie
można wykonać zejścia rekurencyjnego do węzła CL, ponieważ są. w nim tylko 2 klucze. Dlatego
P jest przesuwane w dól i współtworzy z CL i TX węzeł CLPTX. Następnie D jest usuwane z liścia
{przypadek 1). (e'} Po wykonaniu (e) zostaje usunięty korzeń drzewa i wysokość drzewa maleje o I.
(f) Usuwanie B. Przypadek Ja: C jest przesuwane w dól na miejsce B, a E jest przesuwane w górę
na miejsce C

4~50~-----------------------~
PROBLEMY

Usunięto D:
{e) przypadek 3b

L P T

Rys. 19.8. cd.

(a) Jaka jest (asymptotycznie) największa liczba dostępów do dysku wykony-


wanych w tej prostej implementacji dla n operacji na stosie? Jaki jest czas
wykorzystania procesora dla n operacji na stosie? (Zarówno w tym pod-
punkcie, jak i następnych podawaj swoją odpowiedź jako funkcję m i n).

Rozważmy teraz implementację


stosu, w której w pamięci wewnętrznej
trzymamy jedną stronę stosu. (Potrzebujemy także niewielkiej ilości pamięci na
zapamiętanie, która strona jest aktualnie w pamięci). Możemy wykonać opera-
cję na stosie tylko wtedy, kiedy właściwa strona znajduje się w pamięci. Jeśli
jest to konieczne, należy bieżącą stronę z pamięci zapisać na dysk, a w jej
miejsce wczytać potrzebną stronę. Jeśli właściwa strona z dysku jest już w pa-
mięci, to dostęp do dysku nie jest wymagany.

(b) Ile wynosi liczba dostępów do dysku dla n operacji PUSH w najgorszym
przypadku? Jaki jest czas wykorzystania procesora?
(c) Ile wynosi liczba dostępów do dysku dla n operacji na stosie w najgorszym
przypadku? Jaki jest czas wykorzystania procesora?
Przypuśćmy teraz, że implementujemy stos, przechowując w pamięci dwie
strony (plus dodatkowo kilka słów na pamiętanie pomocniczych informacji).
(d) Opisz, jak należy zarządzać stronami stosu, żeby zamortyzowana liczba
dostępów do dysku dla każdej operacji na stosie wynosiła 0(1/m), a za-

-------·-··---·"------------------~~
451
ROZDZIAŁ 19, 8-DRZEWA

mortyzowany czas wykorzystania procesora dla każdej operacji stosowej


był stały.

19-2. Sklejanie i rozbijanie 2-~ drzew


Operacja sklejania (ang. join) polega na połączeniu dwóch dynamicznych zbio-
rów S' i S" oraz elementu x takich, że key [x1 < key[x] < key[x1 dla każdych
x' ES' i x" ES", w jeden zbiór S = S' u {x} u S". Operacja rozbijania jest ope-
racją „odwrotną" do sklejania: dla danego dynamicznego zbioru Si elementu
x w wyniku rozbicia otrzymujemy zbiór S' złożony ze wszystkich elementów
zbioru S, których klucze są mniejsze od key[x] i zbiór S" zawierający wszystkie
elementy z S, których klucze są większe od key[x]. Naszym celem jest zbadanie
możliwości implementacji tych operacji na 2-3-4 drzewach. Dla wygody przyj-
miemy, że każdy element składa się tylko z klucza i wszystkie klucze są różne.

(a) Z każdym węzłem x 2-3-4 drzewa wiążemy atrybut h [x], którego wartością
jest wysokość poddrzewa o korzeniu w x. Pokaż, jak wykonywać na 2-3-4
drzewie operacje wyszukiwania, wstawiania i usuwania, żeby wartości
height [x] dla wszystkich węzłów x w drzewie były zawsze poprawne. Pa-
miętaj, żeby utrzymywanie poprawności atrybutu height nie wpływało na
asymptotyczny czas działania poszczególnych operacji.
(b) Pokaż, jak zaimplementować operację sklejania. Dla danych 2-3-4 drzew
T' i T" i klucza k algorytm powinien działać w czasie O(lh' - h"\), gdzie h'
i h" są wysokościami, odpowiednio, T' i T".
(c) Rozważmy ścieżkę p w 2-3-4 drzewie T prowadzącą od korzenia do węzła
zawierającego klucz k, zbiór S' zawierający klucze z Tmniejsze od ki zbiór
S" zawierający klucze większe od k. Pokaż, że p rozbija S' na zbiór drzew
(a dokładniej na zbiory kluczy z ich węzłów) {TO,TJ,,..., T:.,}i zbiór kluczy
{kl, k',,, ..., k;,,}takie, że y < kl < z dla i = 1, 2, ..., m i każdej pary kluczy
YE Tj_ 1 i ZE Tj. Jaki jest związek między wysokościami drzew Tf_ 1 i Tj?
Opisz, w jaki sposób p rozbija S" na zbiory drzew i kluczy.
(d) Pokaż, jak zaimplementować operację rozbijania drzewa T. Wykorzystaj
operację sklejania do połączenia wszystkich kluczy z S' w jedno 2~3-4 drze~
wo T' i wszystkich kluczy z S" w jedno 2-3-4 drzewo T". Czas działania
operacji rozbijania powinien wynosić O(lgn), gdzie n jest liczbą kluczy
w T. (Wskazówka: Koszty scalania powinny sumować się teleskopowo).

Uwagido rozdziału
Więcejo różnych rodzajach drzew zrównoważonych i B-drzewach można prze-
czytać w książkach Knutha [123], Aha, Hopcrofta, Ullmana [4] i Sedgewicka
[175]. Wyczerpujący przegląd tematyki dotyczącej B-drzew można znaleźć

452
UWAGI 00 ROZDZIAŁU

w pracy Camera [48]. Guibas i Sedgewick [93] omówili związki między róż­
nymi rodzajami drzew zrównoważonych, włącznie z drzewami czerwono-czar-
nymi i 2-3-4 drzewami.
W 1970 r. J.E. Hopcroft odkrył 2-3 drzewa, które były zwiastunami
B-drzew i 2-3-4 drzew. W 2-3 drzewach każdy węzeł wewnętrzny ma albo
dwóch, albo trzech synów. B-drzewa zostały wprowadzone przez Bayera
i McCreighta w 1972 r. [18]; autorzy nie uzasadnili wyboru przyjętej nazwy.
Rozdział 20

Kopcedwumianowe

---------

W tym rozdziale i w rozdziale 21 przedstawiamy struktury danych znane jako


kopce złączalne (ang. mergeab/e heaps), które umożliwiają wykonywanie na-
stępujących operacji.

MAKE-HEAP() tworzy i zwraca nowy, pusty kopiec.


INSERT(H, x) wstawia do kopca H węzeł x o danym kluczu key[x].
MINIMUM(H} zwraca wskaźnik do węzła w kopcu H, który zawiera minimalny
klucz.
ExrRACT-MIN(H) usuwa z kopca H węzeł o minimalnym kluczu, zwracając
jednocześnie wskaźnik do tego węzła.
UN10N(H 1 , H 2 } tworzy i zwraca nowy kopiec, który zawiera wszystkie węzły
z kopców H 1 i H 2 . Kopce H 1 i H 2 są w tej operacji „niszczone".
Na strukturach danych omawianych w tych rozdziałach można wykonywać
dwie dodatkowe operacje.
DECREASE-KEY(H, x, k) nadaje kluczowi w węźle x z kopca H nową wartość
k, o której zakłada się, że jest nie większa od bieżącej wartości klucza.
DELETE(H, x) usuwa węzeł x z kopca H.
Jak wynika z tabeli na rys, 20.1, jeżeli nie potrzebujemy operacji UNION,
to zwykły kopiec binarny, jak ten używany w algorytmie heapsort (rozdział 7),
zachowuje się bardzo dobrze. Operacje inne niż UNION działają na kopcu
binarnym w czasie pesymistycznym O(lgn) (lub lepszym). Jeżeli jednak opera-
cja UNION ma być wykonywana, to kopce binarne zachowują się nie najlepiej.
Wykonanie operacji UNION polegającej na scaleniu tablic, w których są prze-
chowywane łączone kopce, a następnie zbudowaniu nowego kopca za pomocą
procedury HEAPIFY, zabiera w najgorszym przypadku czas 8(n).
W tym rozdziale omawiamy „kopce dwumianowe". Pesymistyczne koszty
poszczególnych operacji na kopcach dwumianowych są również zamieszczone
20.1. DRZEWA t KOPCE DWUMIANOWE

Kopiec binarny Kopiec dwumianowy Kopice Fibonacciego


Procedura (koszt pesymistyczny) (koszt pesymistyczny) (koszt zamortyzowany)
MAKE-HEAP 0(1) 0(1) 0(1)
INSERT 0(lgn) O(lgn) 0(1)
MINIMUM 0(1) O(lgn) 0(1)
E:XTRACT-MIN 0(lgn) 0(1gn) O(lg n)
UNION S(n) O(lgn) 0(1)
DECREASE-KEY 0(lgn) S(lgn) 0(1)
DELETE 0(lgn) 0(1gn) O(lgn)

Rys. 20.1. Czasy wykonania poszczególnych operacji w trzech implementacjach kopców złączalnych;
n jest liczbą elementów w kopcu(ach) w chwili wykonywania operacji

w tabeli na rys. 20.1. Wynika z niej w szczególności, że operacja scalania


dwóch kopców dwumianowych zabiera tylko czas O(lgn), gdzie n jest łączną
liczbą elementów w obu kopcach.
Rozdział 21 jest poświęcony kopcom Fibonacciego, dla których koszty
wykonania pewnych operacji są jeszcze lepsze. Zauważmy jednak, że koszty
tych operacji dla kopców Fibonacciego są kosztami zamortyzowanymi, a nie
pesymistycznymi.
W tym rozdziale pomijamy kwestie przydziału pamięci dla nowo tworzo-
nych węzłów oraz zwalniania pamięci po usunięciu węzła. Przyjmujemy, że
w programach wywołujących procedury realizujące operacje na kopcach jest
zagwarantowane rozwiązanie tych problemów.
Wszystkie trzy rodzaje kopców - binarne, dwumianowe i Fibonacciego
·· są nieefektywne, jeżeli chodzi o wykonywanie operacji SEARCH. Ta operacja
jest zdecydowanie kosztowniejsza czasowo od pozostałych. Z tego powodu
takie operacje, jak DECREASE-KEYi DELETE, które odnoszą się do konkret-
nego węzła, wymagają wskaźnika do tego węzła jako składnik.a danych wejś­
ciowych. W wielu zastosowaniach nie powoduje to żadnych problemów.
W podrozdziale 20.l definiujemy najpierw drzewa dwumianowe, a następ­
nie kopce dwumianowe. Drzewa dwumianowe są składową kopców dwumia-
nowych. Przedstawiamy także pewną szczególną reprezentację kopców dwu-
mianowych. W podrozdziale 20.2 pokażemy, w jaki sposób zaimplementować
na kopcu dwumianowym poszczególne operacje, żeby działały w czasach poda-
nych na rys. 20.1.

20.1. Drzewai kopcedwumianowe


Kopiec dwumianowy jest kolekcją drzew dwumianowych, dlatego ten rozdział
rozpoczynamy od zdefiniowania drzew dwumianowych i pokazania kilku ich
najistotniejszych własności.
_,,,,,.,_.,.,, ..._____________ _
455
ROZDZIAŁ 20. KOPCE DWUMIANOWE

20.1.1 . Drzewa dwumianowe


Drzewem dwumianowymBk (ang. binomial tree) nazywamy drzewo uporządko~
wane (patrz podrozdz. 5.5.2) zdefiniowane rekurencyjnie w następujący sposób.
Jak pokazano na rys. 20.2a, drzewo dwwnianowe B0 składa się z pojedynczego
węzła. Drzewo dwumianowe B1:. składa się z dwóch drzew dwumianowych Bk- 1 ,
które są razem powiązane: korzeń jednego drzewa jest skrajnie lewym synem
drugiego. Na rysunku 20.2b widać drzewa dwumianowe od B0 do B4 .

(o)

8 1-1
B1-1

•• •• G~bokość

o
I
(b) 2

:
••• .,
3
4

B, B, ••

(c) •••

B •,
Bł-l '
••
Rys. 20.2, (•) Rekurenc)'ina definicja drzewa dwumianowego Bk. Trójkąty przedstawiają ukorzenio-
ne poddrzewa. (b) Drzewa dwumianowe od B0 do B4 • W B4 zamaczono głębokości węzłów. (c)
Inne ą,ojrzenie na drzewo dwumianowe Bk

Następujący lemat podaje kilka własności drzew dwumianowych.

LEMAT20.1. (Własności drzew dwumianowych}


W drzewie dwumianowym Bk:

(I) jest 2k węzłów;

456
20.1. DRZEWA I KOPCE DWUMIANOWE

(2) wysokość drzewa wynosi k;

(3) dokładnie(~) węzłów i.najduje się na głębokości i, dla i= O, 1, ... , k;


(4) stopień korzenia wynosi ki jest większy od stopnia każdego innego węzła;
ponadto, jeżeli synów korzenia ponumerujemy kolejno, od lewego do pra-
wego k - l, k - 2, ... , O, to syn o numerze i jest korzeniem poddrzewa B;.

DOWÓD
Dowód przeprowadzamy przez indukcję względem k. Łatwo sprawdza się, że
B 0 ma każdą z powyższych własności.
W celu przeprowadzenia kroku indukcyjnego załóżmy, że lemat zachodzi
dla drzewa Bk-1·

I. Drzewo dwumianowe Bk składa się z dwóch kopii drzewa Bk-l• tak więc Bk
ma 2k- I + 2A- l = 2k węzłów.
2. Sposób, w jaki dwie kopie drzewa B 1 _ 1 są łączone w celu utworzenia drze-
wa B1 , implikuje, że maksymalna głębokość węzła w B1 jest o jeden większa
od maksymalnej głębokości w B 1 _ 1. Z założenia indukcyjnego głębokość ta
wynosi (k-1)+ 1-k.
3. Niech D(k, 1) będzie liczbą węzłów na głębokości i w drzewie dwumiano-
wym Bk. Ponieważ Bk jest zbudowane z dwóch, połączonych ze sobą kopii
drzewa Bk- l• więc węzeł o głębokości i w Bk- 1 występuje w Bk raz na
głębokości i i raz na głębokości i+ I. Innymi słowy, liczba węzłów na
głębokości i w Bk jest liczbą węzłów na głębokości i w Bk- i powiększoną
o liczbę węzłów na głębokości i - 1 w Bk- t · A zatem
D(k, 1) - D(k - 1, 1) + D(k - 1, i - 1)

-(k~l)+(~~
:)
-(~)
Druga z równości wynika z założenia indukcyjnego, trzecia zaś z zadania
6.1-7.
4. Jedynym węzłem o większym stopniu w Bk niż w B1:-i jest korzeń, który ma
jednego syna więcej niż w Bk- l · Ponieważ korzeń drzewa B1 _ 1 ma stopień
k - 1, więc stopień korzenia drzewa B1:wynosi k. Z założenia indukcyjnego
synowie korzenia drzewa B 1 _ 1 są korzeniami drzew, od lewego do prawego,
B 1 _ 2 , Bk- 3, ... , B 0 • Po połączeniu dwóch drzew Bk-I synowie korzenia
wynikowego drzewa są korzeniami drzew, od lewej do prawej, Bk- t• Bk- 2 ,
... , B 0 (zob. rys. 20.2c).

457
ROZDZIAŁ 20. KOPCE DWUMIANOWE

WNIOSEK 20.2.
Maksymalny stopień węzła w n-węzłowym drzewie dwumianowym wynosi lgn.

DOWÓD
Natychmiastowy wniosek z własności (1) i (4) z lematu 20.1.

Określenie „drzewo dwumianowe" pochodzi z własności (3) z lematu 20.1,

ponieważ symbole (~) są nazywane współczynnikami dwumianowymi. Z za-


dania 20.1-3 wynika dalsze uzasadnienie tego określenia.

(a)
head[H] @--
:,, .,(i)

(b)
head[H]-

Rys. 20.3. Kopiec dwumianowy Ho n= 13 węzłach. (a) Kopiec składa się z drzew dwumianowych
B0 , B 2 oraz B 3 , które mają, odpowiednio, I, 4 i 8 węzłów, co daje w sumie n= 13 węzłów.
Ponieważ na drzewach dwumianowych jest zachowany porządek kopcowy, klucz w każdym węźle
jest nie mniejszy od klucza w jego ojcu. Korzenie drzew znajdują s.ię na liście uporządkowanej
rosnąco względem ich stopni. (b) Bardziej szczegółowa reprezentacja kopca dwumianowego H.
Każde drzewo dwumianowe jest pamiętane w reprezentacji „na lewo syn, na prawo brat". Z każ­
dym węzłem jest pamiętany jego stopień

458
20.1. DRZEWA ł KOPCE DWUMIANOWE

20.1.2. Kopce dwumianowe

Kopiec dwumianowy H jest zbiorem drzew dwumianowych, które mają nastę­


pujące własności kopca dwumianowego.

(1) Każdedrzewo dwumianowe w kopcu H jest uporządkowane kopcowo:


klucz w węźle jest nie mniejszy niż klucz ojca.
(2) Dla każdego d ~ O istnieje w H co najwyżej jedno drzewo dwumianowe,
którego korzeń ma stopień równy d.

Własność (1) mówi, że klucz w korzeniu drzewa z porządkiem kopcowym


jest najmniejszym kluczem w drzewie.
Z własności (2) wynika, że n-węzłowy kopiec dwumianowy H składa się
z co najwyżej LlgnJ + 1 drzew dwumianowych. Żeby się o tym przekonać,
zauwaimy, że w binarnej reprezentacji n jest Llgnj + I bitów, powiedzmy
L!911J
(blls•J• bLignJ-t• ... , b 0), takich że n= L b;21• Z własności (1) z lematu 20.1
/ac O
wynika zatem, że drzewo dwumianowe B 1 występuje w Hwtedy i tylko wtedy,
gdy bit b1 = 1. Tak więc kopiec dwumianowy H zawiera co najwyżej llg nJ + I
drzew dwumianowych.
Na rysunku 20.3a widać kopiec dwumianowy Ho 13 węzłach. Binarną
reprezentacją liczby 13 jest (1101), wobec tego Jl składa się z uporządkowa­
nych kopcowo drzew dwumianowych B 3 , B2 i B 0 , mających, odpowiednio, 8,
4 i 1 węzłów, co daje w sumie 13 węzłów.

Reprezentowanie kopców dwumianowych


Jak widać na rys. 20.3b, każde drzewo dwumianowe należące do kopca dwumia-
nowego jest pamiętane w reprezentacji „na lewo syn, na prawo brat" opisanej
w rozdziale 11.4. Z każdym węzłem jest związane pole klucz, a także, zależnie
od zastosowań, inne dodatkowe infonnacje. Poza tym każdy węzeł x ma wskaź­
niki: p[x] do ojca, child[x] do swojego skrajnie lewego syna oraz sibling[x] do
brata x występującego bezpośrednio z prawej strony. Jeżeli węzeł x jest korze-
niem, to p [x] = NIL. Jeśli węzeł x nie ma synów, to child[x] = NIL, a jeżeli x
jest skrajnie prawym synem swojego ojca, to sibling[x] =NIL.Każdy węzeł xma
także pole degree[x], o wartości równej liczbie synów x.
Jak widać na rys. 20.3, korzenie drzew dwumianowych w kopcu dwumia-
nowym są połączone w listę, nazywaną dalej listą korzeni. Porządek stopni
korzeni na liście jest ściśle rosnący. Z drugiej własności kopców dwumiano-
wych wynika, że stopnie korzeni w n-węzłowym kopcu dwumianowym tworzą
podzbiór zbioru {O, 1, ... , llgnJ }. Znaczenie pola sibling jest różne dla korzeni
i niekorzeni. Je7..elix jest korzeniem, to sibling [x] wskazuje na następny korzeń

459
ROZDZIAŁ 20. KOPCE DWUMIANOWE

na liście korzeni. (Jak zwykle sibling[x] = NIL, jeśli x jest ostatnim korzeniem
na liście korzeni).
Dany kopiec dwumianowy H jest dostępny przez pole head[H}, któ~
re jest po prostu wskaźnikiem do pierwszego korzenia na liście korzeni H.
Jeżeli kopiec dwumianowy H nie zawiera żadnych elementów, to
head[H] - NIL.
ZADANIA

20.1-1. Załóżmy, że x jest węzłem w drzewie dwumianowym z pewnego kopca


dwumianowego oraz że sib/ing[x] :;f NIL. Jeżeli x nie jest korzeniem, to
jaka jest zależność między stopniami degree[sib/ing[x]] oraz degree[x]?Ja-
ka jest odpowiedź, gdy x jest korzeniem?
20.1-2. Jeżeli x jest węzłem różnym od korzenia w drzewie dwumianowym
w pewnym kopcu dwumianowym, to jaka jest zależność między stopniami
degree[p[x]] oraz degree[x]?

1110

Rys. 20.4. Drzewo dwumianowe B„ z węzłami ponumerowanymi binamie w porządku postorder

20.1-3. Załóżmy, że węzły drzewa dwumianowego B1 są ponumerowane binar-


nie w porządku postorder, jak na rys. 20.4. Rozważmy węzeł x o numerze
/ na głębokości i i niech j = k - i. Wykaż, że w binarnej reprezentacji / jest
dokładniej jedynek. Ile jest k-elementowych słów binarnych zawierających
dokładnie k jedynek? Wykaż, że stopień x jest równy liczbie jedynek na
prawo od skrajnie prawego zera w rozwinięciu binarnym /.

20.2. Operacjena kopcachdwumianowych


W tym rozdziale pokażemy, jak wykonywać poszczególne operacje na kop-
cach dwumianowych w czasach z rys. 20.1. Zanalizujemy tylko górne ogra~
niczenia na czasy działania; analizę dolnych ograniczeń pozostawiamy jako
zad. 20.2-10.

460
20.2. OPERACJE NA KOPCACH DWUMIANOWYCH

Tworzenie nowego kopca dwumianowego

W celu zbudowania pustego kopca dwumianowego wywołujemy procedurę


MAKE-BINOMIAL-HEAP,która przydziela pamięć zwracanemu następnie obie-
ktowi H, dla którego head[H] =NIL.Czas działania tej operacji wynosi E>(l).

Znajdowanie minimalnego klucza


Procedura BINOMIAL-HEAP-MINIMUM zwraca wskaźnik do węzła z minimal-
nym kluczem w n-węzłowym kopcu dwumianowym H. W tej realizacji zakłada
się, że w kopcu nie ma kluczy o wartości oo (patrz zad. 20.2-5).

BINOMIAL-HEAP-MINIMUM(Jl)
1 y+- NlL
2 x +- head[ll]
3 min+- oo
4 while x -:ft NIL
5 do if key [x} < min
6 then min +-key [x]
7 y+-x
8 X+- sib/ing[x]
9 returny

Ponieważ klucze w drzewach kopca dwumianowego są uporządkowane kop-


cowo, minimalny klucz musi być w korzeniu któregoś drzewa. Procedura BI-
NOMIAL-HEAP-MINIMUM sprawdza kolejno wszystkie korzenie, których jest
co najwyżej LignJ + I, pamiętając bieżące minimum w zmiennej min, a wskaź­
nik do węzła z tym minimum w zmiennej y. Procedura BINOMIAL-HEAP-MINI-
MUM wywołana dla kopca dwumianowego z rys. 20.3 zwróci wskaźnik do
węzła z kluczem l. Ponieważ jest sprawdzanych co najwyżej llgnJ + 1 korzeni,
czas działania BINOMIAL-łlEAP-MINJMUM wynosi O(lgn).

Łączenie dwóch kopców dwumianowych

Operacja łączenia dwóch kopców dwumianowych jest używana jako podpro-


gram w większości pozostałych operacji. Działanie procedury BINOMIAL-
-HEAP-UNION polega na łączeniu drzew dwumianowych, których korzenie
mają te same stopnie. Następująca procedura dowiązuje drzewo B1:- 1 o korze-
niu w węźle y do drzewa B1 _ 1 o korzeniu w węźle z; z staje się ojcem y. Węzeł
z zostaje w ten sposób korzeniem drzewa BA.

BINOMIAL-LINK(y, z)
I p[yJ-z
_______________ ___________
____
,, ,,, _
461
ROZDZIAŁ 20. KOPCE DWUMIANOWE

2 sib/;ng[y] ~ ,h;/d[z]
3 child[z]...._
y
4 degree[z]...._degree[z] + 1

Procedura BINOMIAL-LlNK działa w czasie stałym. W wyniku jej wykonania


węzeł y zostaje nową głową listy synów węzła z. Jest to możliwe, ponieważ
reprezentacja ,,na lewo syn, na prawo brat" każdego drzewa dwumianowego
zachowuje następującą własność uporządkowania drzewa: w drzewie Bk skraj-
nie lewy syn korzenia jest korzeniem drzewa B1;_1.
Procedura BINOMIAL-HEAP-UNION łączy kopce dwumianowe H 1 i H 2
w jeden kopiec. W procesie łączenia reprezentacje H 1 i H 2 są niszczone.
Oprócz BINOMIAL-LINK procedura łączenia używa pomocniczej procedury BI-
NOMIAL-llEAP-MERGE, która scala listy korzeni kopców H1 i H2 W pojedyn-
czą listę uporządkowaną. niemalejąco według stopni. Procedura BINOMIAL-
-HEAP-MERGE, której zapisanie pozostawiamy jako zad. 20.2-2, jest podobna
do procedury MERGE z pod.rozdz. 1.3.l.

BINOMIAL-llEAP-UNION(H 1, H 2 )
1 H ...._
MAKE-BINOMIAL-HEAPQ
2 head[H]- BINOMIAL-łlEAP-MERGE(H1, H2)
3 zwolnij obiekty H 1 i H 2 , ale nie listy na które wskazują
4 if head[H] - NIL
5 then return Il
6 prev-x ...._
NIL
1 x-head[H]
8 next-x- sibling[x]
9 while next-x of.NIL
10 do if (degree[x] of.degree[next-x]) lub
(sibling[next-x] 'F NIL
i degree[sibling[next-x]J= degree[x])
Il then prev-x ...._ x I> Przypadki I i 2
12 x ...._next-x t> Przypadki 1 i 2
13 else if key [x] .:::;key [next-x]
14 then sibling [x] ...._siblin.g[next-x] t> Przypadek 3
15 BINOMIAL-LINK.(next-x, x) t> Przypadek 3
16 else if prev-x = NIL I> Przypadek 4
17 then head[H] ...._next-x I> Przypadek 4
18 else sibling[prev-x]- next-x I> Przypadek 4
19 BINOMIAL-LlNK(x, next-x) I> Przypadek 4
20 x- next-x I> Przypadek 4
21 next-x ...._ siblin.g[x]
22 return H

462
20.2. OPERACJE NA KOPCACH DWUMIANOWYCH

Na rysunku 20.5 widać przykład działania procedury BINOMIAL-HEAP-


-UNION, w którym zademonstrowano wszystkie cztery przypadki rozpatrywa-
ne w tej procedurze.
Procedura BINOMIAL-HEAP-UNION pracuje w dwóch fazach. w fazie
pierwszej, wykonywanej w wyniku wywołania BINOMIAL-HEAP-MERGE, są
scalane listy korzeni kopców dwumianowych H 1 i H 2 w pojedynczą listę H,
uporządkowaną niemalejąco według stopni. Na liście wynikowej mogą się zna-
leźć co najwyżej dwa korzenie o tym samym stopniu. W fazie drugiej są łączo­
ne korzenie o tym samym stopniu, aż pozostanie co najwyżej jeden korzeń dla
każdego stopnia. Ponieważ lista H jest uporządkowana według stopni, wszyst-
kie operacje łączenia korzeni mogą być wykonywane szybko.
Dokładniej, procedura łączenia kopców działa następująco. W wierszach
1-3 listy korzeni kopców dwumianowych H 1 i H 2 są scalane w pojedynczą listę
korzeni Il. Listy korzeni kopców 111 i H 2 są uporządkowane rosnąco według
stopni, a BINOMIAL-lłEAP-MERGE zwraca listę korzeni H, która jest uporząd­
kowana niemalejąco. Jeśli listy H 1 i H 2 zawierają w sumie m korzeni, to BJNO-
MIAL-HEAP-MERGE działa w czasie O(m), porównując korzenie znajdujące się
w głowach scalanych list i dodając korzeń o mniejszym stopniu do listy wyni-
kowej, usuwając go jednocześnie z listy wejściowej.
Jeśli oba łączone kopce są puste, to procedura BINOMIAL-HEAP-UNION
kończy swoje działanie (wiersze 4-5). W przeciwnym razie na liście korzeni
kopca H znajduje się co najmniej jeden korzeń. Do przechodzenia po liście
używamy trzech wskaźników:

• x wskazuje na aktualnie badany korzeń,


• prev-x wskazuje na korzeń poprzedzający x na liście korzeni:
sib/ing[prev-x]= x,
• next-x wskazuje na korzeń występujący po x na liście korzeni:
sib/ing[xJ = next-x.
Początkowo lista H zawiera co najwyżej dwa korzenie o tym samym stop-
niu d: 111 i H 2 są kopcami dwumianowymi i każdy z nich ma co najwyżej jeden
korzeń o stopniu d. Ponadto procedura BINOMIAL-HEAP-MERGE gwarantuje,
że dwa korzenie na liście Ho tych samych stopniach są sąsiadami.
w trakcie wykonywania procedury BINOMIAL-HEAP-UNION na liście ko-
rzeni H mogą w pewnej chwili pojawić się trzy korzenie o tym samym stopniu.
Dalej pokażemy, w jakiej sytuacji może się to zdarzyć. W każdej iteracji pętli
wbile, w wierszach 9-21, jest podejmowana decyzja, czy łączyć x i next-x.
W tym celu są badane stopnie tych węzłów i być może stopień sibling[next-x].
Niezmiennikiem pętli jest, że ilekroć rozpoczyna się wykonywanie kolejnej ite-
racji, zarówno x, jak i next-x są różne od NIL.
Przypadek 1, przedstawiony na rys. 20.6a, występuje, kiedy degree [x] =f'-
=f'-degree[next-x], tj. gdy x jest korzeniem Bk-drzewa, a next-x jest korzeniem

463
ROZDZIAŁ 20, KOPCE DWUMIANOWE

30 23 =y® 17
BINOM!AL-HEAP-MERGE •• 32@)

(b)
'
head[H]

Przypadek. 3

(c)
X ne.xt-.x
head[HJ
'._3}-- --,."""------;;;~~
2a"33 29
41 48
Przypadek 2 SO
i
Rys. 20.5. lluslracja działania procedury BtNOMIAL-HEAP-UNtON. (a) Kopce dwumianowe H 1
i H 1 . (b) Kopiec dwumianowy H powstały w wyniku wywołania procedury B1NOM1AL-HJW
-MERGE(H1,H 2). Początkowo x jest pierwszym korzeniem na liście H. Ponieważ oba węzły,
x i next-x, mają stopień Oi key[x] < key [11ext-xJ,
ma u.stosowanie przypadek 3. (c) Po dowiązaniu
next-x do x, korzeń x jest pierwszym z trzech korzeni o tym samym stopniu, tak więc ma za-
stosowanie przypadek 2. (d) Po przesunięciu wszystkich trzech wskażnik.ów o jedną pozycję w pra-
wo na liście ma Zlllitosowanie przypadek 4 (x jest pierwszym z dwóch korzeni o takim samym
stopniu). (e) Po dowiązaniu next-x ma u.stosowanie przypadek 3. (f) Po połączeniu dwóch kolej-
nych drzew ma zastosowanie przypadek 1 (x ma stopień 3, a 11ext-xma stopień 4). Ta iteracja pętli
wbile jest ostatnia, ponieważ po przesunięciu wskaźników o jedną pozycję na liście, 11ext-x= NIL

B1-drzewa, dla pewnego / > k. Przypadek 1 jest obsługiwany w wierszach 11


i 12. Węzły x i next-x nie są łączone, wobec tego wskaźniki przemieszczają się
po prostu o jedną pozycję na liście. Aktualizacja wskaźnika next-x w tak.i
sposób, 7.eby wskazywał węzeł występujący po nowym węźle x, odbywa się
w wierszu 21 i jest taka sama dla wszystkich przypadków.
Przypadek 2, przedstawiony na rys. 20.6b, występuje, kiedy x jest pierw~
szym z trzech korzeni o takich samych stopniach, tj. gdy

464
20.2. OPERACJE NA KOPCACH DWUMIANOWYCH

(d)
prel'-t
head[Hl >@
@ 8 -

41
IPrzypadek 4

®
(cl
pre1•-.t nexl-.t
12 3' . ~ 1
head[ln -


--
® ~
/42><, 29 10 44
ć

25 41 30\ 23 22 ~®@
i Przypadek 3 '4 " 32 ® ®
55
(0
prn·-x ne.tl-x
heud[IIJ ----@--
@ /2_8", ------·i9 '
10 @

28 ®"'' 22 48 ®@
Przypadek 1 @ @®® ®
®
Rys. 20,5, cd.

degree[x] = degree[next-x] = degree[sibling{next-x]]

W tym przypadku postępujemy tak samo jak w przypadku 1: wskaźniki prze-


suwają się tylko o jedną pozycję na liście. W wierszu 10 sprawdza się, czy
zachodzi przypadek 1 lub przypadek 2, a w wierszach 11-12 przypadki te są
obsługiwane.
Przypadki 3 i 4 zachodzą, gdy x jest pierwszym z dwóch korzeni o rów-
nych stopniach, tj. gdy

degree[x] = degree[next-x] =I=degree[sibling[next-x]]

Te przypadki mogą pojawić się w następnej iteracji pętli po każdym innym


przypadku, ale jeden z nich pojawia się zawsze bezpośrednio po przypadku 2.
W przypadkach 3 i 4 są łączone x i next-x. To, który przypadek zachodzi,
zależy od tego, który z korzeni x oraz next-x zawiera mniejszy klucz. Węzeł
z mniejszym kluczem zostaje korzeniem połączonych drzew.

465
ROZDZIAŁ 20. KOPCE DWUMIANOWE

(•)
sihling[ next- xJ
prev-x
~
next-.l
...
Przypadek 1
.....
..................11<,

B, B, B, B,

(b)
next-x sihling[next-x]
~ >-----<
Przypadek 2
........ ·~··
.,.......

B, B, B, B, B,

(c)
prev-x
1'?- ~
nexl-x
~- sibling[next-x]
... pr1!11-x
... --1'( nexr-x
.....
LJ '..~
B, B, 81
Pr~.~~.~._3 /_\
B,
iB,
~
key[xl key[next-x]
-~--
B,
B 1+1
(d)
prev-x
L...'.~-
x
>--><
next-x
·i ..
sibling[next-x]
·>p~~~ •.4
> ...

B, B1. B1 B,
key[x] > key[next-xj
B ,,,
Rys. 20.6. Cztery przypadki występujące w BINOMIAL-HEAP-UNION. Etykiety a, b, c oraz d służą
tylko do identyfikacji rozważanych korzeni; etykiety te nie oznaczają ani ich stopni, ani ich kluczy.
W każdym przypadku x jest korzeniem pewnego Bk-drzewa i I> k. (a) Przypadek I:
degree(x] 'F degree[next-x]. Wskażniki przesuwają się o jedną pozycję na liście. (b) Przypadek 2:
degree[x] = degree[next-x]= degree[sibling[next-x]]. Ponownie wskaźniki przesuwają się na liście
i w następnej iteracji zachodzi albo przypadek 3, albo przypadek 4. (c) Przypadek 3:
degree[x]""degree[next-x] 'F degree(sibling(next-x)] i key[x) ~ key[next-x); next-x jest usuwany
z listy i dowiązywany do x, tworząc B1 + 1-drzewo. (d) Przypadek 4: degree[x] = degree[next-xJ'F
'F degree(.l"ibling[next-x]}
i key [next-x] < key [x]; x jest usuwany z listy i dowiązywany do next-x,
tworząc ponownie B1 + 1-drzewo

W przypadku 3, przedstawionym na rys. 20.6c, key[x] ,s;;key[next-x], więc


next-x jest przyłączany do x. W wierszu 14 next-x jest usuwany z listy korzeni,
a w wierszu 15 next-x zostaje skrajnie lewym synem x.
W przypadku 4, zaprezentowanym na rys. 20.6d, next-x zawiera mniejszy
klucz, x jest więc dołączany do next-x. W wierszach 16-18 węzeł x jest usuwany
z listy korzeni. Mamy dwa przypadki, zależnie od tego czy x jest pierwszym

466
20.2. OPERACJE NA KOPCACH DWUMIANOWYCH

korzeniem na liście (wiersz 17) czy nie (wiersz 18). W wierszu 19 x zostaje
skrajnie lewym synem next-x, a w wierszu 20 następuje aktualizacja x przed
następną iteracją.
Zarówno w przypadku 3, jak i w przypadku 4 ustawianie zawartości
zmiennych przed następną iteracją pętli while jest takie samo. Połączone właś­
nie dwa Bk-drzewa tworzą Bk+ 1 -d.rzewo, na które wskazuje x. Na liście po-
wstałej w wyniku wywołania procedury BINOMIAL-HEAP-MERGEmieliśmy ze-
ro, jedno lub dwa inne Bt+ 1 -d.rzewa, wobec tego x jest teraz pierwszym zjed-
nego, dwóch lub trzech Bk+ 1 -drzew na liście korzeni. Jeśli x jest tylko jednym
takim drzewem, to w następnej iteracji mamy do czynienia z przypadkiem 1:
degree[x] =Fdegree[next-x]. Jeśli x jest pierwszym z dwóch drzew, to w następ­
nej iteracji zachodzi albo przypadek 3, albo przypadek 4. Gdy x jest pierwszym
z trzech drzew, w następnej iteracji zachodzi przypadek 2.
Czas działania procedury BINOMIAL-HEAP-UNION wynosi O(lgn), gdzie
n jest łączną liczbą węzłów w kopcach dwumianowych H 1 i H 2 • Możemy to
uzasadnić następująco. Niech n 1 będzie liczbą węzłów w H 1, a n2 liczbą węzłów
w H 2 • Wtedy H 1 zawiera co najwyżej LlgnJ + I korzeni, a H 2 zawiera co
najwyżej LlgnJ + 1 korzeni i dlatego bezpośrednio po wywołaniu proce-
dury BINOMIAL-HEAP-MERGE kopiec H zawiera co najwyżej llgnJ +
+ llgn,J + 2.; 2 LlgnJ + 2 - OQgn) korzeni. Czas wykonania BINDMIAL-
-HEAP-MERGE wynosi zatem O(lgn). Każda iteracja pętli while zabiera czas
0(1), a liczba iteracji wynosi co najwyżej LlgnJ + llgni.J + 2 -w każdej ite-
racji albo wskaźniki przesuwają się o jedną pozycję na liście korzeni H, albo
jeden korzeń jest usuwany z listy. Łączny czas działania wynosi zatem O{lg n).

Wstawianie węzła

Następująca procedura wstawia węzeł x do kopca dwumianowego H, oczy-


wiście przy założeniu, że pamięć dla węzła x została już przydzielona i key [x]
ma już nadaną wartość.

BINOMIAL-HEAP-INSERT(H, x)
1 H' +- MAKE-BINOMIAL-HEAP( )
2 p[x) ~ NIL
3 chi/d[x] +- NIL
4 .vibling[xJ+-- NIL
5 degree[x] +- O
6 head[H1 +-- x
1 H +- BINOMIAL-HEAP-UNION(H, HJ

Powyższa po prostu tworzy w czasie 0(1) I-węzłowy kopiec dwu-


procedura
mianowy H' i łączy go w czasie O{lgn) z n-węzłowym kopcem dwumianowym

467
ROZDZIAŁ 20. KOPCE DWUMIANOWE

H. Zakładamy, że po wykonaniu BINOMIAL-HEAP-UNION pamięć przeznaczo-


na na tymczasowy kopiec dwumianowy H' jest zwalniana. (Bezpośrednią im-
plementację wstawiania, w której nie wywołuje się BINOMIAL-HEAP-UNION,
pozostawiamy jako zad. 20.2-8).

Znajdowanie i usuwanie węzła z minimalnym kluczem


Następująca procedura znajduje, a następnie usuwa węzeł z minimalnym klu-
czem z kopca dwumianowego H, zwracając jednocześnie wskaźOik do usunię­
tego węzła.

BINOMIAL-HEAP-EXTRACT-MIN(H)
I znajdź korzeń x z minimalnym kluczem na liście korzeni H
i usuń x z listy korzeni H
2 H' +- MAKE-BINOMIAL-HEAP( }
3 odwróć kolejność elementów na liście synów węzła x
i zapamiętaj wskaźnik do głowy wynikowej
listy w zmiennej head[H1
4 H +- BINOMIAL-HEAP-UNION(H, H')
5 return X

Zasada działania powyższej procedury jest zilustrowana na rys. 20. 7. Wej-


ściowy kopiec dwumianowy H jest pokazany na rys. 20.7a. Na rysunku 20.7b
widać sytuację po wykonaniu wiersza 1: korzeń x z minimalnym kluczem zo-
stał usunięty z listy korzeni kopca H. Jeśli x jest korzeniem B,:·drzewa, to
z własności (4) z lematu 20.1 wynika, że synami węzła x, od lewego do prawe-
go, są korzenie drzew Bi-i, Bi_ 2 , ••• , B 0 • Na rysunku 20.7c widać, że po
odwróceniu listy synów węzła x w wierszu 3 otrzymujemy kopiec dwumianowy
H', który zawiera każdy węzeł z drzewa o korzeniu x z wyjątkiem jego samego.
Ponieważ drzewo o korzeniu x jest usuwane z H w wierszu I, kopiec dwu-
mianowy powstający w wyniku połączenia Hi H' w wierszu 4, pokazany na
rys. 20.7d, zawiera wszystkie węzły z wejściowego kopca Hz wyjątkiem x. Na
koniec węzeł x jest zwracany w wierszu 5.
Ponieważ wykonanie każdego z wierszy 1-4 zabiera czas O(lgn), gdzie
n jest liczbą węzłów w H, czas działania procedury BINOMIAL-HEAP-
-EXTRACT-MIN wynosi O(lgn).

Zmniejszanie wartości klucza


Następująca procedura nadaje kluczowi w węźle x w kopcu dwumianowym
H nową wartość k. Gdy k jest większe od bieżącego klucza w x, sygnalizowany
jest błąd.

468
20.2. OPERACJE NA KOPCACH DWUMIANOWYCH

(a)
head[H] -~

(b)
headflfl -~ 10
13

li

27
(c)

head[Hl -~ 37 10 head[H'J-~ 12
41 13 18

(d)

head[ HJ ~ IZ

41

42

Rys. 20.7. Działanie procedury BINOMIAL·HEAP-ExTRACT-MlN. (•) Kopiec dwumianowy H. (b) Ko-
rzeń x z Illlnimalnym kluczem został usunięty z listy korzeni H. (c) Odwrócona lista synów węzła
x tworzy kopiec dwumianowy H'. (d) Wynik połączenia kopców Hi H'

BINOMIAL-HEAP-DECREASE-KEY(H, x, k)
1 if k > key[x]
2 tben error „nowy klucz jest większy od bieżącego klucza"
3 key[x] ~ k
4 y+- X
5 z~p[y]
6 while z 'F NIL i key [y] < key [z]

469
ROZDZIAŁ 20. KOPCE DWUMIANOWE

7 do zamiana key[y]+-+key[z]
8 [> Jeśli y i z zawierają pola z dodatkowymi
informacjami, to zamień wartości tych pól
9 y+-z
10 z-p[y]

Jak pokazano na rys. 20.8, nnniejszanie wartości klucza odbywa się tak
samo jak w kopcu binarnym: przez „wypychanie klucza do góry". Po upew-
nieniu się, że nowy klucz jest rzeczywiście nie większy od bieżącego klucza, i po
przypisaniu go do węzła x, posuwamy się w górę drzewa re wskaźnikiem y po-
czątkowo wskazującym na x. W każdej iteracji pętli while (wiersze 6-10) key [y]
jest porównywany z kluczem z węzła z - ojca węzła y. Jeśli y jest korzeniem lub
key[y] ~ key [z], to porządek kluczy w drzewie dwumianowym jest porządkiem

' • f ' • •fi '


>·J.Z_

' ' i i
".' ' "
'
'.
'Jl;
'
Ją; i (J (ijJ(j (j)
4i; @ ((~)1!~(ił (8
\li

"'·..6

'.}J; .)-4)
:.4t,
·--
/

Rys. 20.8. Działanie procedury BINOMIAL·HEAP-DECREASE·KEY. (•) Sytuacja tuż po wykonaniu


wiersza 5, a przed pierwszą. iteracją pętli wbite. Klucz w węźle y został m,niejszony do 7 i jest
mniejszy 00 klucza jego ojca z. (b) Klucze w węzłach y i z są rnmieniane. Sytuacja tuż przed drugą
iteracją pęUi. Wskaźniki y i z przesunęły się o jeden poziom w górę, ale porządek kopcowy jest
nadal naruszony. (c) Po ponownej zamianie i przesunięciu wskaźników o jeszcze jeden poziom
w górę porządek kopcowy jest zachowany i wykonywanie instrukcji wbile kończy się

470
20.2. OPERACJE NA KOPCACH DWUMIANOWYCH

kopcowym. W przeciwnym razie węzeł y narusza porządek kopcowy i wtedy


jego klucz jest zamieniany z kluczem jego ojca z, razem ze wszystkimi związa­
nymi z nim informacjami. Następnie wskaźnik y zostaje przesunięty o jeden
poziom w górę drzewa do z i rozpoczyna się następna iteracja.
Procedura BINOMIAL-HEAP-DECREASE-KEYdziała w czasie O(lgn).
Z własności (2) z lematu 20.1 wynika, że maksymalna głębokość węzła x wy-
nosi LlgnJ. Dlatego liczba iteracji pętli while (wiersze 6-10) wynosi co naj-
wyżej LignJ .

Usuwaniewęzła
Usuwanie klucza (i związanej z nim informacji) z danego węzła x w kopcu
dwumianowym Hwykonuje się łatwo w czasie O(lgn). Do tego celu stosujemy
procedurę BJNOMIAL-łłEAP-DELETE. W implementacji tej procedury zakłada­
my, że żaden węzeł w drzewie nie ma klucza - oo.

BINOMIAL-HEAP-DELETE(H,x)
1 BINOMIAL-HEAP-DECREASE-KEY(H,x, - oo)
2 BINOMIAL-HEAP-EXfRACT-MIN(Jl)

Procedura BINOMIAL-HEAP-DELETEprzypisuje węzłowi X unikatowy


w całym kopcu minimalny klucz - oo. (Zadanie 20.2-6 dotyczy sytuacji, w któ-
rej -oo nie może pojawiać się jako klucz, nawet tymczasowo). Następnie ten
klucz i związaną z nim informację wypycha się w górę do korzenia drzewa
przez wywołanie BINOMIAL-HEAP-DECREASE-KEY. Na koniec korzeń drzewa
jest usuwany przez wywołanie BINOMIAL-lłEAP-EXTRACT-MlN.
Procedura BINOMIAL-HEAP-DELETEdziała w czasie O(lgn).

ZADANIA
20.2-1. Podaj przykład dwóch n-elementowych kopców binarnych, których
scalenie za pomocą procedury BUILD-HEAP wymaga czasu 0(n).
20.2-2. Napisz pseudokod dla procedury BINOMIAL-HEAP-MERGE.
20.2-3. Narysuj kopiec dwumianowy powstały w wyniku wstawienia węzła
z kluczem 24 do kopca dwumianowego z rys. 20.7d.
20.2-4. Narysuj kopiec dwumianowy powstały w wyniku usunięcia klucza 28
z kopca dwumianowego z rys. 20.7c.
20.2-5. Wyjaśnij, dlaczego procedura BINOMIAL-HEAP-MINIMUMmogłaby
nie zadziałać poprawnie, gdyby klucze mogły przyjmować wartość oo. Na-
pisz od nowa pseudokod dla tej procedury w taki sposób, żeby działała
poprawnie i w takim przypadku.
20.2-6. Przypuśćmy, że nie mamy możliwości reprezentacji klucza - oo. Na-
pisz od nowa pseudokod dla procedury BINOMIAL-HEAP-DELETEtak,
--- '"" -··- - '" ' -- """"""""""""-"'_, ____
,,,_, ,,,,.,._.,,,~

471
ROZDZIAŁ 20. KOPCE DWUMIANOWE

żeby działała poprawnie w takiej sytuacji. Czas działania powinien nadal


wynosić O(lgn).
20.2-7. Zbadaj związek między wstawianiem do kopca dwumianowego a zwię­
kszaniem o jeden liczby binarnej oraz związek między łączeniem dwóch
kopców dwumianowych a dodawaniem dwóch liczb binarnych.
20.2-8. Biorąc pod uwagę zadanie 20.2-7, napisz od nowa pseudokod dla pro-
cedury BlNOMIAL-HEAP-lNSERT tak, żeby wstawianie węzła do kopca
dwumianowego odbywało się bezpośrednio, bez konieczności użycia pro-
cedury BINOMIAL-HEAP-UNION.
20.2-9. Wykaż, że jeżeli listy korzeni są uporządkowane malejąco według stop-
ni (zamiast rosnąco), to każdą z operacji dla kopca dwumianowego można
zaimplementować bez 2JJ1ianyjej asymptotycznego czasu działania.
20.2-10. Podaj dane wejściowe, dla których procedury BINOMIAL-HEAP-EX-
TRACT-MIN, BINOMIAL-HEAP-DECREASE-KEYi BINOMIAL-HEAP-DELE-
TE działają w czasie O:(lgn). Wyjaśnij dlaczego pesymistyczne czasy działa-

nia tych procedur



są OOgn), ale nie !l(lgn) (zob. problem 2-5).

Problemy
20-1. :Z.-3-4kopce
W rozdziale 19 zostały przedstawione 2-3-4 drzewa, w których każdy węzeł
wewnętrzny ma dwóch, trzech lub czterech synów i wszystkie liście znajdują się
na tej samej głębokości. Zajmiemy się teraz implementacją 2-3-4 kopców, które
umożliwiają wykonywanie operacji na kopcach złączalnych.
2-3-4 kopce różnią się od 2-3-4 drzew następująco. W 2-3-4 kopcach klu-
cze są przechowywane tylko w liściach i w każdym liściu x jest zapisany do-
kładnie jeden klucz w polu key [x]. Nie istnieje żaden szczególny porządek
kluczy w liściach ~ patrząc od strony lewej do prawej, klucze mogą wystę­
pować w dowolnym porządku. W każdym węźle wewnętrznym x jest prze-
chowywana wartość sma/l[x], która jest równa najmniejszemu kluczowi z liści
w poddrzewie o korzeniu w x. Korzeń drzewa r zawiera pole height [r], którego
wartością jest wysokość drzewa. Zakładamy, że 2-34 kopce są pamiętane
w pamięci wewnętrznej (żadne operacje dyskowe (odczyt i zapis) nie są wy-
konywane).
Podaj implementacje następujących operacji na 2-3-4 kopcach. Każda
z operacji z punktów (a)-(e) powinna być wykonywana w czasie O(lgn) na
n-węzłowym 2-3-4 kopcu. Operacja UNION z punktu (f) powinna być wykony-
wana w czasie O(lgn), gdzie n jest liczbą węzłów w obu wejściowych kopcach.

(a) MINIMUM, która zwraca wskaźnik do liścia z najmniejszym kluczem.

472
PROBLEMY

(b) DECREASE-KEY,która zmniejsza klucz w danym liściu x do podanej war-


tościk.:::;; key[x].
(c) INSERT, która wstawia liść x z kluczem k.
(d) DELETE, która usuwa dany liść x.
(e) EXfRACT-MIN, która znajduje i usuwa liść z najmniejszym kluczem.
(f) UNION, która łączy dwa 2-3-4 kopce, zwracając pojedynczy 2-3-4 kopiec
i niszcząc kopce wejściowe.

20-2. Algorytm obliczania minimalnego drzewa rozpinającego z użyciem kopców


zlączalnych
W rozdziale 24 omówimy dwa algorytmy rozwiązywania problemu znajdowa-
nia minimalnego drzewa rozpinającego w grafie nieskierowanym. Tutaj zoba-
czymy, w jaki sposób można zastosować kopce zlączalne do otrzymania jesz-
cze innego algorytmu oblic:zania minimalnego drzewa rozpinającego.
Dany jest spójny graf nieskierowany G = (V, E) oraz funkcja w:E-> R.
Wielkość w(u, v) nazywamy wagą krawędzi (u, v). Należy znaleźć minimalne
drzewo rozpinające w grafie G, tzn. acykliczny podzbiór Tc E, który łączy
wszystkie wierzchołki z V i którego całkowita waga

w(1) - L w(u, v)
(u, u)eT

jest najmniejsza.
Algorytm MST-MERGE-HEAP opisany poniżej, którego poprawność moż­
na udowodnić z pomocą metod z podrozdz. 24.1, znajduje minimalne drzewo
rozpinające T. W algorytmie jest utrzymywany podział { V1} zbioru wierzchoł­
ków V, a z każdym zbiorem V1 zbiór

krawędzi incydentnych z wierzchołkami z V;,

MST-MERGEABLE-HEAP(G}
1 r-0
2 for każdy wierzchołek V;E V[G]
3 do V1 +--{v1}
4 E,-{(v,, v)eE[G])
5 whilejest więcej niż jeden zbiór V1
6 do wybierz dowolny zbiór V1
7 znajdź i usuń krawędź (u, v) w E 1 o minimalnej wadze
8 załóż bez straty ogólności, że u E V 1, a vE Vi
9 ilia'j
IO then T- Tu {(u, v))

473
ROZDZIAŁ 20. KOPCE DWUMIANOWE

Il V1 +- V1 u V1, niszcząc Vi
12 E;+-E;uE 1

Opisz implementację powyższego algorytmu z wykorzystaniem operacji na


kopcu zlączalnym podanych w tabeli na rys, 20,1. Przeanalizuj czas działania
zaimplementowanego algorytmu przy założeniu, że kopce zlączalne zostały za-
implementowane za pomocą kopców dwumianowych.

Uwagido rozdziału
Kopce dwumianowane zostały wprowadzone w 1978 r. przez Vuillemina [I 96].
Brown [36, 37] zbadał szczegółowo ich własności.
Rozdział 21 ---------------"""""'-~------

KopceFibonacciego

W rozdziale 20 wyjaśniliśmy, w jaki sposób kopce dwumianowe umożliwiają


realizowanie w pesymistycznym czasie O(lg n) operacji kopca złączalnego,
a więc operacji INSERT, MINIMUM, EXTRACT-MIN i UNION oraz operacji
DECREASE-KEYi DELETE. w tym rozdziale omówimy kopce Fibonacciego,
umożliwiające wykonywanie tych samych operacji, ale mające tę zaletę,
że operacje nie związane z usuwaniem elementu działają w czasie zamortyzo-
wanym 0(1).
Z teoretycznego punktu widzenia kopce Fibonacciego są szczególnie przy-
datne, jeśli liczba operacji EXTRACT-MINi DELETE jest niewielka w stosunku do
liczby pozostałych operacji. W wielu zastosowaniach występuje taka właśnie
sytuacja. Niektóre algorytmy grafowe na przykład mogą wykonywać operację
DECREASE-KEYraz dla każdej krawędzi. Dla grafów gęstych, o wielu krawę­
dziach, stały zamortyzowany czas wykonania DECREASE-KEYbędzie po zsumo-
waniu znacznie lepszy niż pesymistyczny czas 0(lgn) wykonania tej operacji na
kopcach binarnych lub dwumianowych. Asymptotycznie najszybsze znane algo-
rytmy służące do rozwiązywania takich problemów, jak obliczanie minimalnego
drzewa rozpinającego (rozdz. 24) lub znajdowanie najkrótszych ścieżek z ustalo-
nego węzła (rozdz. 25), w istotny sposób wykorzystują kopce Fibonacciego.
Aspekty praktyczne, tak.ie jak wielkość stałych współczynników w funkcji
kosztu i skomplikowana implementacja kopców f'ibonacciego, powodują jed-
nak, że w większości zastosowań lepiej jest używać zwykłych kopców binar-
nych (lub wyższych rzędów). Kopce Fibonacciego są zatem interesujące głów­
nie z teoretycznego punk.tu widzenia. Gdyby udało się zaprojektować znacznie
prostszą strukturę danych o takich samych ograniczeniach kosztu zamortyzo-
wanego, miałaby ona tak.że duże znaczenie praktyczne.
Podobnie jak kopiec dwumianowy, kopiec Fibonacciego stanowi zbiór
drzew. W istocie rzeczy idea kopców Fibonacciego opiera się lu7..nona strukturze

475
ROZDZIAŁ 21. KOPCE FIBONACCIEGO

kopców dwumianowych. Jeśli w kopcu Fibonacciego ani razu nie zostanie


wywołana procedura DECREASE-KEYani DELETE, to każde drzewo w tym
kopcu wygląda jak drzewo dwumianowe. Kopce Fibonacciego różnią się jednak.
od dwumianowych nieco swobodniejszą strukturą, której zawdzięczają lepsze
asymptotyczne oszacowania czasu wykonywania operacji. Pracę związaną z za-
rządzaniem strukturą danych można tu odkładać na później -do chwili, kiedy
jej wykonanie będzie dogodne.
Tak jak tablice dynamiczne z podrozdz. 18.4, kopce Fibonacciego stano-
wią dobry przykład struktury danych zaprojektowanej z myślą o analizie kosz-
tu zamortyzowanego. Intuicja i analiza operacji na kopcu Fibonacciego przed-
stawione w tym rozdziale opierają się na metodzie potencjału z pod.rozdz. 18.3.
W tym rozdziale zakładamy, że czytelnik zapoznał się z treścią rozdz. 20
traktującego o kopcach dwumianowych. Znajdują się w nim specyfikacje ope-
racji wykonywanych na kopcu, jak. również zestawienie (rys. 20.1) oszacowania
czasów wykonywania poszczególnych operacji na kopcach binarnych, dwu-
mianowych i Fibonacciego. Strukturę kopców Fibonacciego przedstawimy za
pomocą struktury kopca dwumianowego. Zwrócimy również uwagę na podo-
bieństwo niektórych operacji na kopcach Fibonacciego i ich odpowiednik.ów
dla kopców dwumianowych.
Podobnie jak w przypadku kopców dwumianowych, konstrukcja kopców
Fibonacciego nie umożliwia efektywnej realizacji operacji wyszukiwania
SEARCH;operacje, które dotyczą konkretnego węzła, wymagają zatem dostar-
czenia wskaźnika do tego węzła jako części danych wejściowych.
W podrozdziale 21.1 zdefiniujemy kopce Fibonacciego, omówimy ich re-
prezentację i wprowadzimy funkcję potencjału, wykorzystywaną w analizie ich
kosztu zamortyzowanego. W podrozdziale 21.2 pokażemy, jak zaimplemen-
tować operacje kopca zlączalnego, żeby dostać oszacowania kosztu zamorty-
zowanego podane w tabeli na rys. 20.1. Dwie pozostałe operacje, DECREASE-
-KEY i DELETE, przedstawimy w podrozdz. 21.3. Wres:zci.e,w podrozdziale
21.4, zamieścimy kończący analizę jej kluczowy fragment.

21.1. Strukturakopców Fibonacciego


Podobnie jak kopiec dwumianowy, kopiec Fibonacciego jest zbiorem drzew,
z których każde ma własność kopca. Drzewa w kopcu Fibonacciego nie muszą
jednak. być drzewami dwumianowymi. Na rysunku 21.la widać przykład kop-
ca Fibonacciego.
W odróżnieniu od uporządkowanych drzew w kopcach dwumianowych,
drzewa w kopcach Fibonacciego są ukorzenione, ale nie uporządkowane. Jak
widać na rysunku 21.1 b, każdy węzeł x zawiera wskaźnik p[x] do swojego
ojca oraz wskaźnik child[x] do któregokolwiek. ze swoich synów. Synowie wę-
--------------------------------
476
21.1. STRUKTURAKOPCÓWFIBONACCIEGO

min [H]
.j,
' 'I > (73) ('i) ,G)
··--·

• (f:i)(_'iii)
~y
6ó)
,,
.,

/)I/!/ I/fi

d» ·.'(i~). \V.
'
'
,c-.
~t46l
,_,,

.'@ .•
Rys. 21.1. (a) Kopiec Fibonacciego złożony z 5 drzev. z własnością kopca i 14 węzłów. Linia przery-
wana oznacza listę korzeni. Węzeł minimalny w tym kopcu to ten zawierający klucz 3. Trzy węzły
zaznaczone zostały zamalowane na czarno. Potencjał tego kopca Fibonacciego wynosi
5 + 2 · 3 = 11. (b) Pełniejsze przedstawienie, uwidaczniajfł,Ce wskaźniki p (strzałki do góry), child
(strzałki do dołu) oraz le/t i right (strza.łk.i na bok.i). Szczegóły te będziemy pomijać na wszystkich
pozostałych rysunkach w tym rozdziale, ponieważ całą zawartą tu informację można odczytać
i z tego, co przedstawia część (a)

zła x są powiązani w cykliczną listę dwukierunkową, którą nazywamy listą


synów x. Każdy węzeł y na liście synów zawiera wskaźniki left[y] i right[v],
wskazujące, odpowiednio, na lewego i prawego brata y. Jeśli węzeł y jest jedy-
nym synem na liście, to left[v] = right [v] = y. Kolejność węzłów na liście sy-
nów jest dowolna.
Zastosowanie w kopcach Fibonacciego cyk.licznych list dwukierunkowych
(patrz pod.rozdz. 11.2) ma dwie zalety. Po pierwsze, usunięcie węzła z cyklicz-
nej listy dwukierunkowej można zrealizować w czasie 0(1). Po drugie, mając
dwie takie listy, możemy je skonkatenować (czyli „skleić") w jedną cykliczną
listę dwukierunkową w czasie 0(1). W opisie operacji na kopcach Fibonac-
ciego będziemy się odwoływać do tych operacji na listach nieformalnie, pozo-
stawiając czytelnikowi uzupełnienie szczegółów ich implementacji.
W każdym węźle znajdują się jeszcze dwa inne pola. Liczba węzłów na
liście synów węzła x jest przechowywana w polu degree[x]. Natomiast za-
wierające wartość logiczną pole mark [x] określa, czy węzeł x stracił syna
od ostatniej chwili, kiedy sam został synem innego węzła (węzeł taki będziemy
nazywali zaznaczonym). Szczegółami zaznaczania węzłów zajmiemy się dopiero
-----------------------4=77
ROZDZIAŁ 21. KOPCE FIBONACCIEGO

w podrozdz. 21.3. Nowo utworzone węzły są nie zaznaczone, a węzeł x staje się
nie zaznaczony za każdym razem, kiedy zostaje synem innego węzła.
Dostęp do kopca F'ibonacciego Hzapewnia wskaźnik min[H} do korzenia
drzewa zawierającego najmniejszy klucz; węzeł ten nazywamy węzłem minimal-
nym kopca Fibonacciego. Jeśli kopiec Fibonacciego H jest pusty, to
min[H] = NIL.
Korzenie wszystkich drzew w kopcu Fibonacciego są połączone za pomo-
cą wskaźników left i right w cykliczną listę dwukierunkową, zwaną listą ko-
rzeni kopca Fibonacciego. Wskaźnik min [H] wskazuje zatem na ten węzeł na
liście korzeni, którego klucz jest najmniejszy. Kolejność drzew na liście korzeni
jest dowolna.
Będziemy korzystać z jeszcze jednego atrybutu kopca Fibonacciego H:
liczba węzłów należących aktualnie do H jest przechowywana w polu n [H].

Funkcja potencjału
Jak.już wspomnieliśmy, do analizy efektywności
operacji na kopcach Fibonac-
ciego zastosujemy metodę potencjału z podrozdz. 18.3. Dla danego kopca Fi-
bonacciego H przez t(H) oznaczamy liczbę drzew na liście korzeni H, a przez
m(H) liczbę zaznaczonych węzłów w H. Potencjał kopca Fibonacciego H jest
wówczas zdefiniowany wzorem

(l>(H) - t(H) + 2m(H) (21.1)

Na przykład potencjał kopca Fibonacciego przedstawionego na rys. 21.1 wy-


nosi 5 + 2 · 3 = 11. Potencjał zbioru kopców Fibonacciego jest sumą potencja-
łów składających się nań kopców. Będziemy zakładać, że jednostka potencjału
może opłacić wykonanie pewnej stałej pracy, przy czym wielkość tej stałej jest
na tyle duża, żeby pokryć koszt dowolnej spośród występujących w algoryt-
mach operacji wykonywalnych w czasie stałym.
Zakładamy, że w algorytmie wykorzystującym kopce Fibonacciego zaczy-
namy od pustego kopca. Początkowy potencjał jest zatem równy O i na mocy
równania (21.1) pozostaje już stale nieujemny. Zgodnie z równaniem (18.2)
górne ograniczenie całkowitego kosztu zamortyzowanego jest więc zarazem
górnym ograniczeniem całkowitego faktycmego kosztu ciągu operacji.

Ograniczenie stopnia
Przeprowadzając analizę kosztu zamortyzowanego, którą przedstawiamy
w dalszej części tego rozdziału, zakładamy, że znane jest górne ograniczenie
D(n) maksymalnego stopnia dowolnego węzła w n-węzłowym kopcu Fibonac-
ciego. Celem zadania 21.2-3 jest wykazanie, że jeśli wykonywane są wyłącznie

478
21.2. OPERACJE KOPCA ZŁĄCZALNEGO

operacje kopca zlączalnego, to D(n) = LlgnJ.W podrozdziale 21.3 wykażemy,


że również przy uwzględnieniu operacji DECREASE-KEY i DELETE mamy
D(n) - O(lgn).

21.2. Operacjekopcaz/ączalnego
W niniejszym podrozdziale zajmiemy się opisem i analizą operacji kopca złą­
czalnego zaimplementowanych dla kopca Fibonacciego. Jeśli ograniczymy się
tylko do tych operacji - MAKE-HEAP, INSERT, MINIMUM, ExrRACT-MIN
i UNION - to zauważymy, że każdy kopiec Fibonacciego stanowi po prostu
zbiór „nieuporządkowanych'' drzew dwumianowych. Nieuporządkowane drze-
wo dwwnianowejest podobne do zwykłego drzewa dwumianowego i, podobnie
jak tamto, definiuje się je rekurencyjnie. Nieuporządkowane drzewo dwumia-
nowe U0 składa się z pojedynczego węzła, a nieuporządkowane drzewo dwu-
mianowe Ukjest zbudowane z dwóch nieuporządkowanych drzew dwumiano-
wych Ut- t w ten sposób, że korzeń jednego z nich zostaje dowolnym synem
korzenia drugiego drzewa. Lemat 20.1, dotyczący własności drzew dwumiano-
wych, pozostaje w mocy także dla drzew nieuporządkowanych, tyle że ze zmo-
dyfikowaną jak niżej wersją własności (4) (patrz zad. 21.2-2):

(4') W nieuporządkowanym drzewie dwumianowym U1 stopień korzenia wy-


nosi k i jest większy niż stopień każdego innego węzła. Synowie korzenia
są korzeniami poddrzew U0 , U 1 , ... , U1 _ 1 , pamiętanymi w dowolnej ko-
lejności.

Jeślizatem n-węzłowy kopiec Fibonacciego jest zbiorem nieuporządkowanych


drzew dwumianowych, to D(n) = lgn.
Podstawowa idea realizacji operacji kopca zlączalnego na kopcach Fibo-
nacciego polega na opóźnianiu wykonywania pracy tak długo, jak to tylko
możliwe. Istnieje współzależność między efektywnością realizacji poszczegól-
nych operacji. Jeśli liczba drzew w kopcu Fibonacciego jest mała, to potrafnny
szybko wyznaczyć nowy węzeł minimalny w trakcie wykonywania operacji
EXTRACT-MIN. Jak jednak przekonaliśmy się w przypadku kopców dwumia-
nowych w zad. 20.2-1 O, zagwarantowanie tego, że liczba drzew będzie mała,
ma swoją cenę: wstawienie węzła do kopca dwumianowego lub połączenie
dwóch kopców dwumianowych może kosztować O(lgn). Jak wkrótce zobaczy-
my, wstawiając nowy węzeł lub łącząc dwa kopce, nie próbujemy sklejać drzew
w kopcu Fibonacciego. Odkładamy to do operacji EXTRACT-MIN, kiedy na-
prawdę musimy znaleźć nowy węzeł minimalny.

479
ROZDZIAŁ 21. KOPCE FIBONACCIEGO

Tworzenie nowego kopca Fibonacciego

W celu utworzenia pustego kopca Fibonacciego procedura MAKE-FIB-HEAP


rezerwuje pamięć i zwraca reprezentujący kopiec Fibonacciego obiekt H, gdzie
n[.H] = O, a min[H] = NIL; H nie zawiera żadnych drzew. Ponieważ t(H) = O
oraz m(H) = O, potencjał pustego kopca Fibonacciego <IJ(H)= O. Koszt
zamortyzowany procedury MAKE-FIB-HEAPjest zatem równy jej kosztowi
faktycznemu 0(1).

Wstawianie węzła
Następująca procedura wstawia węzeł x do kopca Fibonacciego H, zakJadając
oczywiście, że sam węzeł został utworzony i że pole key [x] jest już wypełnione.

FJB-HEAP-lNSERT(H,x)
1 degree[x]- O
2 p[x] +- NIL
3 child[xJ +- NIL
4 /eft(x] - x
5 right[x]+-x
6 mark[x] +-FALSE
7 połącz Gednoelementową) listę korzeni zawierającą x z listą korzeni H
8 if min(H] - NJL lub key[x] < key[min[H]
9 then min[H] +-x
10 n[H]-n[H]+l

Po wypełnieniu w wierszach 1-6 pól węzła


x, czyniącym z niego Gednoelemen-
tową) cykliczną listę dwukierunkową, w wierszu 7 dodajemy x do listy korzeni
H w czasie faktycznym 0(1 ), Węzeł x staje się zatem jedno węzłowym drzewem
z własnością kopca, a więc nieuporządkowanym drzewem dwumianowym
w kopcu Fibonacciego. Węzeł ten nie ma synów i jest nie zaznaczony. W wier-

(a) (b)

Rys. 21.2. Wstawienie węzła do kopca Fibonacciego. (1.}Kopiec Fibonacciego H. (b) Kopiec Fibo-
nacciego H po wstawieniu węzła o kluczu 21. Węzeł staje się osobnym drzewem z własnością
kopca, a następnie, dodany do listy korzeni, zostaje lewym bratem korzenia

480
21.2. OPERACJE KOPCA ZtĄCZALNEGO

szach 8-9 uaktualniamy następnie, jeśli trzeba, wskaźnik do minimalnego węz­


ła w kopcu Fibonacciego H. Na koniec, w wierszu 10, zwiększamy n [H], od-
notowując dodanie nowego węzła. Rysunek 21.2 ilustruje operację wstawienia
węzła o kluczu 21 do kopca Fibonacciego z rys, 21.1.
W odróżnieniu od procedury BINOMIAL-HEAP-INSERT,wykonując FIB-
-HEAP-INSERT, nie próbujemy wcale sklejać drzew w kopcu Fibonacciego. Je-
śli następuje k kolejnych operacji FIB-HEAP-INSERT,to do listy korzeni zostaje
dodanych k drzew jednowęzłowych.
W celu wyznaczenia zamortyzowanego kosztu operacji FIB-HEAP-INSERT
oznaczmy przez Hwejściowy kopiec Fibonacciego, a przez H' kopiec po wyko-
naniu operacji. Wówczas t(H') = t(H) + 1 i m(H') = m(_H), zatem przyrost
potencjału wynosi

((t(H) + I)+ 2m(H)) - (t(H) + 2m(H)) - I

PonieważfaktycznykoszttoO(l),kosztzamortyzowanywynosiO(l) + 1 = 0(1).

Znajdowanie węz/a minimalnego


Węzeł minimalny w kopcu Fibonacciego H jest wskazywany przez wskaźnik
min[H], możemy więc go znaleźć w faktycznym czasie 0(1). Ponieważ poten-
cjał kopca H przy tym się nie zmienia, koszt zamortyzowany tej operacji jest
równy kosztowi faktycznemu 0(1).

Łączenie dwóch kopców Fibonacciego


Następująca procedura służy do łączenia kopców Fibonacciego H 1 i H 2 w no-
wy kopiec, niszcząc przy tym H 1 i H 2 .

FIB-HEAP-UNION(H1, H 2 )
1 H - MAKE-FIB-HEAPO
2 min[H]+-min[H 1]
3 sklej listę korzeni H 2 z listą korzeni H
4 il (min[H,]- NIL) lub (min[H 2] # NIL i min[H,] < min[H,J)
5 then min[H]-min[H 2]
6 n[H]-n[H,] + n[H,]
7 zwolnij pamięć przydzieloną obiektom H 1 i H 2
8 return H

W wierszach 1-3 sklejamy listy korzeni H 1 i H 2 w nową listę korzeni H,


W wierszach 2, 4 i 5 jest ustalany węzeł minimalny H, a w wierszu 6 w polu
n [H] jest zapisywana łączna liczba węzłów. W wierszu 7 jest zwalniana pamięć

481
ROZDZIAŁ 21. KOPCE FIBONACCIEGO

przydzielona reprezentującym kopce Fibonacciego obiektom H 1 i H 2 ,


a w wierszu 8 zostaje zwrócony nowo otrzymany kopiec Fibonacciego H. Tak
jak w procedurze FIB-HEAP-INSERT,nie próbujemy sklejać drzew wchodzą­
cych w skład kopca.
Zmiana potencjału wynosi

(f)(H) - ((f)(H,) + (f)(H,))


= (t(H) + 2 m(H)) - ((t(H,) + 2 m(H,)) + (t(H,) + 2m(H,)))
=0

ponieważ t(H) = t(H,) + t(H,)


i m(H) = mi,H,) + m(H,). Koszt zamortyzo-
wany operacji FIB-lłEAP-UNION jest zatem równy kosztowi faktycznemu,
czyli 0(1).

Usuwaniewęzła minimalnego
Proces usuwania węzła minimalnego jest najbardziej skomplikowaną operacją
przedstawioną w tym podrozdziale. To właśnie tu jest wykonywana odkładana
wcześniej praca polegająca na sklejaniu drzew z listy korzeni. Przedstawiona
poniżej procedura realizuje usuwanie węzła minimalnego. Dla wygody zakłada­
my, że przy usuwaniu węzła z listy wskaźniki zawarte w elementach listy zostają
uaktualnione, ale wskaźniki w usuwanym węźle pozostają bez zmian. Korzys-
tamy także z pomocniczej procedury CONSOLIDATE, przedstawionej dalej.

FIB-HF.AP-EXTRACT-MIN(H)
1 z+-min[H]
2 ifz#-NIL
3 then for każdy syn x węzła z
4 do dodaj x do listy korzeni H
5 p[x]+-NIL
6 usuń z z listy korzeni H
7 if z= right [z]
8 then min [H] +- NIL
9 elsemin[H]+-right[z]
10 CONSOLIDATE(H)
Il n[H]-n[H]-1
12 return z

Jak widać
na rysunku 21.3, procedura FIB-HEAP-ExTRACT-MIN zaczyna
działanie od uczynienia korzeniem każdego z synów węzła minimalnego i usu-
nięcia węzła minimalnego z listy korzeni. Następnie skraca listę korzeni, łącząc

482
21.2. OPERACJE KOPCA ZŁĄCZALNEGO

węzły jednak.owego stopnia, dopóki nie pozostanie co najwyżej po jednym


korzeniu każdego stopnia.
Zaczynamy w wierszu 1, zapamiętując wskaźnik z do węzła minimalnego;
on właśnie będzie zwróconą na końcu wartością. Jeśli z= NIL, to kopiec Fibo-
nacciego H jest już pusty i nasze zadanie jest zakońC'lone. W przeciwnym razie,
tak jak w procedurze BINOMIAL-HEAP-EXTRACT-MIN, usuwamy węzeł
z z kopca H w wierszach 3-5, C'lyniąc wszystkich jego synów korzeniami (wsta-
wiając ich na listę korzeni), a w wierszu 6 - usuwając z z listy korzeni. Jeśli po
wykonaniu operacji w wierszu 6 zachodzi z= right[z], to z był jedynym węz­
łem na liście korzeni i nie miał synów, więc przed zwróceniem. z należy jedynie
instrukcją w wierszu 8 odnotować, że kopiec Fibonacciego jest pusty. W prze-
ciwnym razie do wskaźnika min [H] do listy korzeni przypisujemy węzeł różny
od z (tutaj right [z]).Na rysunku 21 .3b widać kopiec Fibonacciego z rys. 21.3a
po wykonaniu instrukcji w wierszu 9.
Kolejny krok, w którym redukujemy liczbę drzew w kopcu Fibonacciego,
to skracanie listy korzeni H. Wykonuje się je, wywołując procedurę CoNSOLI-
DATE(H). Skracanie listy korzeni polega na wielokrotnym powtarzaniu poniż­
szych operacji, dopóki każdy korzeń na liście nie będzie miał innej wartości
pola degree.

1. Znajdź na liście korzeni dwa węzły x i y tego samego stopnia, przy czym
key[x].; keyfy].
2. Dołącz y do x: usuń y z listy korzeni i uczyń go synem x. Operację tę
realizuje procedura FIB-HEAP-LINK. Wartość w polu degree[x] jest zwięk­
szana o 1, a y przestaje być zaznaczony fjeśli był).

Procedura CoNSOLIDATEwykorzystuje pomocniczą tablicę A [O.. D (n [H])];


jeśli A[1]= y, to y jest aktualnie korzeniem takim, że degree[y]= i.

CoNSOLIDATE(R)
1 for i-O to D(n[H])
2 do A [1]+- NlL
3 for każdy węzeł w na liście korzeni H
4 dox+-w
5 d +- degree[xJ
6 wbile A [dj ,' NIL
7 doy-A[dj
8 if key [x] > key [y]
9 thenzamień x +-+y
10 FIB-HEAP-LINK(H, y, x)
11 A[d]-NJL
12 d+-d+ l

483
H(llDZIAl 11 KOf'Cf I IBUNACClf CiO

(aJ !li!/! [/li ( b) !/)/fi 1111


'
•••
il I / 1 4

A ~>F·MTJm~•
(C) (d)

Ołfa9(E)8.@' li
• if)~ $ I!)

( l')
lli.'1-1 • ,n

l)i:1.1

"c:11,1=i,, (h)

Rys. 21.3. Działanie procedury FIB·lłEAP-EXTRACT-MIN. (•) Kopiec Fibonacciego H. (b) Sytuacja po
usunięciu węzła minimalnego z i dodaniu jego synów do listy korzeni. (c)-.{e)Tablica A i wchodzą­
ce w skład kopca drzewa po kazdym z pierwszych trzech prmbiegów pętli for w wierszach 3-13
procedury CoNSOUPATE. Lista korzeni jest prmtwarzana, poczynając od węzła minimalnego
i przechodząc po wskaźnikach right. Na każdej części rysunku widać wartości mriennych w i x pod
koniec przebiegu. (f)-(h) Kolejny prz.ebieg pętli lor z pokazanymi wartościami w i x pod koniec
każdego przebiegu pętli wbite w wiersiach 6-12. Częśc (I) dotyczy sytuacji po pierwszym przejściu
pętli wbile. Węzeł o kluczu 23 został dołączony do węzła o kluczu 7, wskazywanego obecnie przez
x. W części (g) węzeł o kluczu 17 zostaje dołączony do węzła o kluczu 7, nadal wskazywanego
przez x. W części (h) do tego samego węzła zostaje dołączony kolejny, o kluczu 24. Ponieważ do tej
pory wskaźnik w komórce A (3] nie wskazywał na żaden węzeł, pod koniec tego przebiegu pętli for
w A [3] zostaje iapisany wskai:nik do korzenia otrzymanego drzewa. (i)-0) Sytuacja po każdym
z kolejnych czterech przebiegów pętli ror. (m) Kopiec Fibonacciego H po odtwoneniu listy korzeni
z tablicy A i malezieniu nowej wartości wskaźnika min[H]

484
21.2. OPERACJE KOPCA ZŁĄCZALNEGO

012.14 O I 2 3 4
__ •I 11I 11I I Af!III 111I
(i) 1w~·@38 u) <ti)
7 __________ 38
41 23 41

(k) 7 -------·· 38 (JI ---:k'


------~"

24 \!~ 21 ~ 41 21 @)
52 52

1nin[H]

(m)
'
7 ---------·-· 38
24 @ 23 21 41
46@) 52

Rys. 21.3. cd.

13 A[dJ-x
14 min [H] +- NIL
15 for i-O to D(n[H])
16 doif A[1] #NlL
17 then dodaj A [l] do listy korzeni H
18 =
if min [H] NIL lub key [A [1] < key[min [H]]
19 thenmin[H]-A[1]

FlB-HEAP-L!NK(H, y, x)
1 usuń y z listy korzeni H
2 uczyń y synem x i zwiększ degree[x] o 1
3 mark[y]+-FALSE

Szczegóły działania procedury CONSOLIDATE przedstawiają się następują­


co. W wierszach 1-2 nadajemy początkową wartość NIL wszystkim elementom

485
ROZDZIAŁ 21. KOPCE FIBONACCIEGO

tablicy A. Kiedy kończymy przetwarzanie każdego korzenia w, znajduje się on


w drzewie o korzeniu w pewnym węźle x, który może, ale nie musi, być równy
w. W komórce tablicy A [degree[x]] zostaje wówczas zapisany wskaźnik do x.
W pętli for w wierszach 3-13 zajmujemy się po kolei każdym węzłem w na liście
korzeni. Niezmiennikiem zachowywanym w każdym przebiegu pętli for jest to,
że węzeł x jest korzeniem drzewa zawierającego węzeł w. Pętla wbile w wier-
szach 6-12 zachowuje niezmiennik, że d = degree[x] (z wyjątkiem wiersza 11,
co zobaczymy za chwilę). W każdym przebiegu pętli while A [dj wskazuje na
pewien korzeń y. Ponieważ d = degree[x] = degree[y], chcemy połączyć drze-
wa o kor7.Clliach x i y w jedno. Ten z węzłów x i y, który zawiera mniejszy
klucz, w wyniku operacji połączenia stanie się ojeem drugiego, zatem w wier-
szach 8-9 dokonujemy, jeśli trzeba, zamiany wskaźników do x i do y. Następ­
nie dołączamy y do x, wywołując w wierszu 10 procedurę Fm-HEAP-LINK
(H, y, x). Wywołanie to zwiększa degree[x], ale pozostawia w polu degree[y]
wartość d. Ponieważ węzeł y nie jest już korzeniem, w wierszu 11 z tablicy
A zostaje usunięty wskaźnik do niego. Ponieważ w wywołaniu FIB-HEAP-LINK
wartość degree[x] została zwiększona o 1, instrukcja w wierszu 12 przywraca
niezmiennik, że d = degree[x]. Pętlę while wykonujemy dopóty, dopóki nie
będzie A [dj = NIL, co oznacza, że nie ma innego korzenia tego samego stopnia
co x. W wierszu 13 w komórce A [dj umieszczamy wskaźnik do x i wykonujemy
następny przebieg pętli for. Na rysunkach 21.3c-e jest przedstawiona tablica
A i drzewa otrzymywane w pierwszych trzech przebiegach pętli for w wierszach
3-13. W następnym przebiegu pętli for trzykrotnie dochodzi do połączenia
drzew; jest to zilustrowane na rys. 21.3f-h. Na rysunkach 21.3i-l widać sytuację
po kolejnych czterech przebiegach pętli for.
Pozostaje jedynie zrobić porządek. Po zakończeniu pętli for w wierszach
3-13 instrukcją w wierszu 14 opróżniamy listę korzeni, a w wierszach 15-19
dokonujemy jej rekonstrukcji. Tak otrzymany kopiec Fibonacciego jest przed-
stawiony na rys. 21.3m. Po skróceniu listy kor7.Clli procedura FIB-HEAP-
-EXTRACT-MIN kończy działanie, zmniejszając wartość n[H] w wierszu 11
i zwracając wskaźnik do usuniętego węzła z w wierszu 12.
Zwróćmy uwagę, że jeśli wszystkie drzewa w kopcu Fibonacciego są nie~
uporządkowanymi drzewami dwumianowymi przed wykonaniem procedury
FIB-HEAP-EXTRACT-MIN, to pozostają nimi i później. Drzewa zm.ieniają się
na dwa sposoby. Po pierwsze, w wierszach 3-5 procedury FIB-HEAP-
-EXTRACT-MIN każdy syn x korzenia z staje się korzeniem. W myśl zadania
21.2-2 każde takie nowe drzewo jest nieuporządkowanym drzewem dwumiano-
wym. Po drugie, drzewa są łączone za pomocą procedury Fm-HEAP-LINK, jeśli
są tego samego stopnia. Ponieważ przed operacją połączenia wszystkie drzewa
są nieuporządkowanymi drzewami dwumianowymi, dwa drzewa, których ko-
rzenie mają pok synów, muszą mieć strukturę drzewa u,..Otrzymane drzewo
ma zatem strukturę drzewa U,.+1 .

486
21.2. OPERACJEKOPCAZŁĄCZALNEGO

Możemy już teraz wykazać, że zamortyzowany koszt usunięcia węzła mini-


malnego z n-węzłowego kopca Fibonacciego wynosi O(D(n)). Oznaczmy przez
H kopiec Fibonacciego tuż przed operacją FIB-HEAP-EXfRACT-MIN. Faktycz-
ny koszt usunięcia węzła minimalnego można oszacować następująco. Wkład
w wysokości O(D(n)) jest związany z tym, że w procedurze FIB-HEAP-
-EXTRACT-MINjest przetwarzanych co najwyżej D(n) synów węzła minimal-
nego, oraz z pracą wykonywaną w wierszach 1-2 i 14-19 procedury CONSOLI-
DATE. Pozostaje przeanalizować wkład wniesiony przez pętlę for w wierszach
3-13. Rozmiar listy korzeni w chwili wywołania procedury CONSOLIDATE nie
przekracza D(n) + t(H) - 1, ponieważ składa się ona z t(H) pierwotnie znaj-
dujących się na niej węzłów minus usunięty korzeń plus synowie usuniętego
korzenia, których liczba wynosi co najwyżej D(n). W każdym przebiegu pętli
wbile w wierszach 6-12 jeden z korzeni zostaje dołączony do innego, więc
łączna praca wykonywana w pętli for jest co najwyżej proporcjonalna do
D(n) + «Il). Reasumując, łączny koszt faktyczny to O(D(n) + «Il)).
Wartość potencjału przed usunięciem węzła minimalnego wynosi
t(H) + 2m(H), a po usunięciu węzła- co najwyuj (D(n) +I)+ 2m(H), ponie-
waż na liście pozostaje co najwyżej D(n) + 1 korzeni, a podczas operacji nie
zaznaczamy żadnego węzła. Koszt zamortyzowany wynosi zatem co najwyżej

O(D(n) + t(H)) + ((D(n) + I) + 2m(H)) - (t(H) + 2m(H))


~ O(D(n)) + O(t(H)) - t(H)
~ O(D(n))

ponieważ możemy przeskalować jednostkę potencjału tak, by zdominowała


stałą ukrytą w wyrażeniu O(t(H)). Intuicyjnie rzecz ujmując, koszt wykonania
każdej operacji dołączenia jednego korzenia do drugiego jest opłacony przez
spadek potencjału spowodowany zmniejszeniem o jeden liczby korzeni.

ZADANIA
21.2-1. Narysuj kopiec Fibonacciego otrzymany w wyniku wywołania proce-
dury FIB-HEAP-EXTRACT-MIN dla kopca Fibonacciego z rys. 21.3m.
21.2-2. Udowodnij, że lemat 20.1 zachodzi również dla nieuporządkowanych
drzew dwumianowych, jeśli własność (4) zastąpimy przez (4').
21.2-3. Wykaż, że jeśli wykonujemy tylko operacje kopca zlączalnego, to ma-
ksymalny stopień węzła D(n) w n-węzłowym kopcu Fibonacciego nie prze-
kracza llgnJ.
21.24. Profesor McGee obmyślił nową strukturę danych opartą na kopcach
Fibonacciego. Kopiec profesora ma taką samą strukturę jak kopiec Fibo~
nacciego i umożliwia wykonywanie wszystkich operacji kopca złączalnego.
Implementacja tych operacji jest taka sama jak dla kopców Fibonacciego

487
ROZDZIAŁ 21. KOPCE FIBONACCIEGO

z tą różnicą, że przy wstawianiu elementu i łącreniu dwóch kopców


w ostatnim kroku skracamy listę korzeni, wywołując procedurę CoNSOLI-
DATE.Jakie są czasy wykonywania poszczególnych operacji w najgorszym
przypadku w takiej strukturze? Na ile nowatorski jest pomysł profesora?
21.2-5. Uzasadnij, że jeśli jedynymi operacjami na kluczach są porównania
dwóch kluczy Gakma to miejsce we wszystkich przedstawionych w tym
rozdziale implementacjach), to nie wszystkie operacje kopca złączalnego
mogą działać w czasie zamortyzowanym 0(1).

21.3. Zmniejszaniewartości kluczai usuwaniewęzła


W tym podrozdziale pokazujemy, jak 7111Diejszać wartość klucza w węźle kop-
ca Fibonacciego w czasie zamortyzowanym 0(1) oraz jak usuwać dowolny
węzeł z n-węzłowego kopca Fibonacciego w czasie zamortyzowanym O(D(n)),
Jeśli stosujemy te operacje, to nie mamy gwarancji, że wszystkie drzewa w kop-
cu Fibonacciego będą nieuporządkowanymi drzewami dwumianowymi. Będą
jednak na tyle do nich zbliżone, że maksymalny stopień węzła D(n) da się
oszacować jak.o O(lgn). Z oszacowania tego będzie wynikać to, że procedury
FIB-HEAP-EXTRACT-MIN i FIB-HEAP-DELETEdziałają w zamortyzowanym
czasie O(lgn).

Zmniejszaniewartości klucza
w przedstawionym poniżejpseudokodzie operacji FIB-HEAP-DECREASE-KE
zakładamy jak poprzednio, że usunięcie węzła z listy nie zmienia zawartości
żadnych pól w strukturze reprezentującej usuwany węzeł.

FIB-HEAP-DECREASE-K.EY{H, x, k)
1 if k > key[x]
2 then ermr „nowa wartość klucza jest większa niż bieżąca"
3 key[x] -k
4 y-p[x]
5 if y ,' NIL i key[x] < key[y]
6 then Cur(H, x, y)
7 CASCADING-Cur(H, y)
8 if key[x] < key[min[H]]
9 then min [HJ- x

CUT(H, X, y)
1 usuń x z listy synów y i zmniejsz degree[y] o I
2 dodaj x do listy korzeni H

488
21.3. ZMNIEJSZANIE WARTOSCI KLUCZA I USUWANIE WĘZŁA

3 p[x] ~ NIL
4 mark[x]- FALSE

CASCADING-CUT(H,y)
I z~p[yJ
2 if z -;i, NIL
3 then if mark[y] = FALSE
4 tb.enmark[y]+-TRUE
5 else Cur(H, y, z)
6 CASCADING-Cur(H, z)

Procedura FIB-HEAP-DECREASE-KEY działa następująco. W wierszach


1-3 upewniamy się, że nowa wartość klucza nie jest większa niż bieżący klucz
w węźle x, a następnie zapisujemy w x nowy klucz. Jeśli x jest korzeniem lub
key[x];;::: key[y], gdzie y jest ojcem x, to nie ma potneby zmian w strukturze
kopca, ponieważ porządek kopcowy nie został naruszony. Warunek ten spraw-
dzamy w wierszach 4-5.
Jeśli porządek kopcowy został naruszony, to w kopcu może zajść wiele
zmian. Zaczynamy od odcięcia węzła x w wierszu 6. Procedura CUT „odcina"
połączenie między x a jego ojcem y, czyniąc x korzeniem.
W celu otrzymania zapowiadanego oszacowania czasu wykonywania ope-
racji wykorzystujemy pola mark. Pomagają one w uzyskaniu następującego
efektu. Przypuśćmy, że x jest węzłem o następującej historii:

I. W pewnej chwili x był korzeniem.


2. Następnie x został dołączony do innego węzła.
3. Potem od x zostało odciętych dwóch jego synów.

Zaraz po utracie drugiego syna węzeł x zostaje odcięty od swojego ojca i zo-
staje nowym korzeniem. Pole mark[x] ma wartość TRUE,jeśli zaszły zdarzenia
1 i 2 oraz został odcięty jeden z synów x. W wierszu 4 procedury CUT pole
mark[x] przyjmuje zatem wartość FALSE, ponieważ następuje właśnie zdarze-
nie 1. (Widzimy teraz, dlaczego w wierszu 3 procedury FIB-HEAP-LINK pole
mark[y] przyjmuje wartość FALSE:węzeł y zostaje dołączony do innego węzła,
zachodzi więc zdarzenie 2. Następnym razem, kiedy zostanie odcięty syn y,
pole mark[y] przyjmie wartość TRUE).
To jeszcze nie koniec, ponieważ x mógł być drugim synem odciętym od
swojego ojca y, licząc od chwili, kiedy y został dołączony do innego węzła.
W wierszu 7 procedury FIB-HEAP-DECREASE-KEY wykonujemy zatem na wę­
źle y operację odcięcia kaskadowego. Jeśli y jest korzeniem, to sprawdzenie
warunku w wierszu 2 procedury CASCADING-CUT powoduje jedynie powrót
z wywołania. Jeśli y nie jest zaznaczony, to w wierszu 4 zostaje zaznaczony,

489
ROZDZIAŁ 21. KOPCE FIBONACCIEGO

ponieważ jego pierwszy syn został właśnie odcięty, po czym następuje powrót
z wywołania. Jeśli natomiast y jest zaznaczony, to oznacza, że utracił on właś­
nie drugiego syna; w wierszu 5 y zostaje odcięty, a w wierszu 6 następuje
rekurencyjne wywołanie procedury CASCADINO-CUT dla węzła z będącego oj-
cem y. Rekurencyjne wywołania procedury CASCADINO-Cur „wędrują" w ten
sposób w górę drzewa, aż do napotkania korzenia lub nie zaznaczonego węzła.
Po wykonaniu wszystkich kaskadowych odcięć procedura FIB-HEAP-DEC
REASE-KEY kończy działanie, uaktualniając (jeśli trzeba) wartość min [Il]
w wierszach 8-9.
Na rysunku 21.4 widać przebieg dwóch wywołań procedury FIB-HEAP-
-DECREASE-KEY, zaczynając od kopca Fibonacciego z rys. 21.4a. W pierw-

mu, i/fi min ff{]


'
al'I • c1n9 $' ~ 9
,w"••••
"417..• @e
$
fllee •
••
G>•
• nun IIIJ
• rmn I/fi
'
••

min Ili!

,,,eeee '
§i ~ e
• -• @e
• u
Ry&.llA. Dwa wywołania procedury FIB-HEAP-DECREASE-KEY. (a) Początkowy kopiec FibonaOO.e-
go. (b) Klucz 46 zostaje zmniejszony do wartości 15. 2.awierają.cy go węzeł staje się korT.CDiem,
a jego ojciec (z kluczem 24), który poprzednio nie był zaznaczony, zostaje zaznaczony. (c)-(e)
Klucz 35 zostaje zmniejszony do wartości 5. W części (c) ~zeł zawierający teraz klucz 5 staje się
korzeniem. Jego ojciec, z kluczem 26, zostaje zaznaczony i następuje kaskadowe odcięcie. Węzeł
z k1uczem 26 zostaje odcięty od swojego ojca i staje się n.ie zaznaczonym korzeniem w części (d).
Ponieważ ~zeł z k1uczem 24 jest również zaznaczony, następuje kolejne kaskadowe odcięcie.
W części (e) rysunku węzeł ten zostaje odcięty od swojego ojca i staje się nie mznaczonym korze-
niem. Kaskadowe odcinanie zatrzymuje się w tym punkcie, ponieważ węzeł z k1uczem.7 jest korze-
niem. (Nawet gdyby nie był, seria odcięć skol\czylaby się, ponieważ ~zeł ten nie jest zaznaczony).
Część (e) przedstawia otrzymany w wyniku operacji Fm-HEAP-DECR.EASE-KEY kopiec Fibonac-
ciego, w którym wskaźnik min [/l] wskazuje na nowy węzeł minima.lny

490
21.3. ZMNIEJSZANIE WARTO$CJ KLUCZA I USUWANIE WĘZŁA

szym wywołaniu, przedstawionym na rys. 21.4b, nie ma kaskadowych odcięć.


W drugim, widocznym na rys. 21.4c-e, występują dwa kaskadowe odcięcia.
Wykażem.y teraz, że zamortyzowany koszt operacji FIB-HEAP-
-DECREASE-KEYwynosi tylko 0(1). Zaczniemy od wyznaczenia kosztu fak-
tycznego. Czas działania procedury FIB-HEAP-DECREASE-KEY jest stały, jeśli
nie liczyć czasu spędzonego na wykonywaniu kaskadowych odcięć. Przypuść­
my, że w trakcie wykonywania procedury FIB-HEAP-DECREASE-KEY nastąpi­
ło c rekurencyjnych wywołań procedury CASCADING-Cur. Każde wywołanie
procedury CASCADING-CUTzajmuje czas stały, jeśli pominąć wywołania reku-
rencyjne. Zatem faktyczny koszt procedury FIB-HEAP-DECREASE-KEY
z uwzględnieniem. wszystkich wywołań rekurencyjnych, wynosi O(c).
Obliczymy teraz zmianę potencjału. Oznacz111yprzez H kopiec Fibonac-
ciego tuż przed operacją FIB-HEAP-DECREASE-KEY.Każde rekurencyjne wy-
wołanie procedury CASCADING-CUT,z wyjątkiem ostatniego, odcina zazna-
czony węzeł i polu mark nadaje wartość FALSE. Na końcu mamy t(H) + c
drzew (początkowych t(H) drzew, c - 1 drzew utworzonych przez kaskadowe
odcięcia oraz drzewo o korzeniu x) i co najwyżej m(ll) - c + 2 zaznaczonych
węzłów (c - 1 węzłów przestało być węzłami zaznaczonymi podczas kaskado-
wych odcięć, a ostatnie wywołanie procedury CASCADING-CUTmogło spowo-
dować zaznaczenie węzła). Zmiana potencjału nie przekracza zatem

((t(H) + c) + 2(m(H) - c + 2)) - (t(H) + 2m(H)) - 4- c

Z.amortyzowany koszt operacji FIB-HEAP-DECREASE-KEYwynosi więc co naj-


. .
wyzeJ

O(c) + 4 - c - 0(1)

ponieważ możem.y tak: przeskalować jednostki potencjału, by ;,,dominowały


stałą ukrytą w wyrażeniu O(c).
Widać teraz, dlaczego w definicji funkcji potencjału wystąpił składnik rów-
ny podwojonej liczbie zaznaczonych węzłów. Kiedy zaznaczony węzeł y zostaje
odcięty w trakcie kaskadowego odcinania, jego polu mark zostaje nadana war-
tość FALSE, potencjał zmniejsza się więc o 2. Jedna jednostka potencjału po-
krywa koszt odcięcia i wyzerowania bitu zaznaczenia, a druga równoważy
jednostkowy wzrost potencjału związany z tym, że węzeł y zostaje korzeniem.

Usuwanie węzła
Nietrudno usunąć dowolny węzeł z n-węzłowego kopca Fibonacciego w za-
mortyzowanym czasie O(D(n)), co realizuje poniższa procedura. Zakładamy,
że w kopcu Fibonacciego nie ma aktualnie klucza o wartości - oo.

491
ROZDZIAŁ 21. KOPCEFIBONACCIEGO

FIB-HEAP-DELETE(H, x)
1 x, -co)
FIB-HEAP-DECREASE-KEY(H,
2 FIB-HEAP-EXTRACT-MIN(H)

Procedura Fm-HEAP-DELETEjest podobna do BINOMIAL-HEAP-DELET


Robi ona z x węzeł minimalny, nadając mu mniejszą niż wszystkie pozostałe
wartość klucz.a - co. Węzeł x zostaje następnie usunięty z kopca Fibonacciego
za pomocą procedury FIB-HEAP-EXTRACT-MIN. Zamortyzowany koszt opera-
cji FIB-HEAP-DELETE jest sumą wynoszącego 0(1) zamortyzowanego kosztu
FIB-HEAP-DECREASE-KEY i wynoszącego O(D(n)) zamortyzowanego kosztu
Fm-HEAP-EXTRACT-MIN,
ZADANIA
21.3-1, Przypuśćmy, że korzeń x w kopcu Fibonacciego jest zaznaczony. Wy-
jaśnij, jak mogło do tego dojść. Uzasadnij, że z punktu widzenia analizy
fakt, iż x jest zawaC'lOny, nie ma znaczenia, chociaż nie jest on węzłem,
który był wcześniej dołączony do innego, a później stracił jednego syna.
21.3-2. Uzasadnij oszacowanie 0(1) zamortyzowanego kosztu operacji FIB-
-HEAP-DECREASE-KEY metodą kosztu sumarycznego z podrozdz. 18.1.

21.4. Oszacowaniemaksymalnego
stopnia
Aby udowodnić, że :zamortyzowany koszt operacji FIB-HEAP-EXTRACT-MIN
i Fm-HEAP-DELETEwynosi O(lgn), musimy wykazać, że górne ograniczenie
D(n) na stopień dowolnego węzła w n-węzłowym kopcu Fibonacciego jest rów-
ne O(lgn). W myśl zadania 21.2-3, jeśli wszystkie drzewa w kopcu Fibonac-
ciego są nieuporządkowanymi drzewami dwumianowymi, to D(n) = llgnJ.
Odcięcia wykonywane w trakcie operacji FIB-HEAP-DECREASE-KEY mogą je-
dnak spowodować naruszenie przez drzewa w kopcu Fibonacciego własności
nieuporządkowanych drzew dwumianowych. W niniejszym podrozdziale wy-
każemy, że dzięki temu, iż odcinamy węzeł od jego ojca, kiedy tylko traci on
drugiego syna, dalej zachodzi oszacowanie D(n) = O(lgn). Dokładniej, poka-
żemy, że D(n) <; Liog, nJ,gdzie</>= (I + ,,/5)/2.
Dla każdego węzła x w kopcu Fibonacciego definiujemy size(x) jako liczbę
węzłów (z x włącznie) w poddrzewie o korzeniu x. (Nadmieńmy. że x nie musi
znajdować się na liście korzeni - może być zupełnie dowolnym węzłem). Najis-
totniejszy w naszej analizie okaże się fakt, że wartość size(x) jest wykładnicza
ze względu na degree[x].Pamiętajmy, że w polu degree[x]jest stale przechowy-
wana dokładna wartość stopnia węzła x.

492
21.4. OSZACOWANIE MAKSYMALNEGO STOPNIA

LEMAT 21.1.
Niech x będzie dowolnym węzłem w kopcu Fibonacciego. Załóżmy, że de-
gree[x] = k. Oznaczmy przez y 1 , y 2 , ••• , Yt synów węzła x w kolejności przyłą­
czania ich do x, od najwcześniej do najpóźniej przyłączonego. Wówczas de-
gree [y1] ~ O oraz degree[y,] ~ i- 2 dla i= 2, 3, ..., k.

DOWÓD
Oczywiście degree[y1] ~O.Dla i~ 2 zauważmy, że kiedy węzeł y 1 byl przy-
łączany do x, węzły y 1 , y 2 , ••• , y 1_ 1 były już synami x, musiało zatem być
degree[x] ~i-I. Węzeł y 1 zostaje przyłączony do x tylko wtedy, kiedy
degree[x] = degree[y1], musiało więc także zachodzić wówczas
degree[y1] ~ i - 1. Od tamtej pory węzeł y 1 stracił co najwyżej jednego syna,
bo gdyby stracił dwóch, to zostałby odcięty od x. Stąd wniosek, że de-
gree[y1]~ i - 2.


Doszliśmy wreszcie do tej części analizy, która wyjaśnia nazwę „kopce
Fibonacciego". Przypomnijmy z podrozdz. 2.2, że dla k = O, 1, 2, ... k-ta liczba
Fibonacciego jest zdefiniowana wzorem rekurencyjnym

o, jeśli k=O
F" = 1, jeśli k =I
Ft-1 + Ft-2 jeśli k ~ 2

Oto inny sposób przedstawienia Ft.

LEMAT 21.2.
Dla wszystkich liczb całkowitych k ;,i:.O

Ft+2=

1 + I F1
J"' o

DOWÓD
Dowód przeprowadza się przez indukcję względem k. Dla k =O

i"' o
=1+0
=1

493
ROZDZIAŁ 21. KOPCE FIBONACCIEGO

Przyjmując teraz założenie indukcyjne. że Ft+


•-'
=I+ LF mamy
1 1,
I"' O


Następujący lemat i wynikający z niego wniosek kończą analizę. Będziemy
korzystać z nierówności (której udowodnienie jest celem zad. 2.2-8)

gdzie t/Jjest współczynnikiem złotego podziału, :zdefmiowanym w równaniu


(2.14)jako </>=(I +../-5)/2= 1,61803....

LEMAT 21.3.
Niech x będzie dowolnym węzłem w kopcu Fibonacciego i niech k = de-
gree [x]. Wówczas size(x) > Ft+ 2 > cpt, gdzie cf,= (I+ /5)/2.

DOWÓD
Oznaczmy przez St najmniejszą możliwą wartość size(z) dla wszystkich węzłów
z takich, że degree[zJ= k. Widać, że s0 = 1, s 1 = 2, a s 2 = 3. Liczba St jest
mniejsza bądź równa size(x). Tak jak w lemacie 21.1 oznaczmy przez y 1 , y 2 ,
..., Yt synów x w kolejności ich przyłączania do x. Aby wyznaczyć dolne ogra-
niczenie na wartość size(x), liczymy jednostkowe wkłady do sumy samego węz­
ła x i jego pierwszego syna y 1 (dla którego size(y 1) ~ 1), a następnie stosujemy
lemat 21.l do pozostałych synów. Mamy zatem

size(x) > st

Wykażemy teraz przez indukcję względem k, że st> F1 + 2 dla dowolnych


nieujemnych liczb całkowitych k. Warunek początkowy indukcji, przypadki
k = Oi k = 1 są oczywiste. W celu wykonania kroku indukcyjnego załóżmy, że
k> 2 i żes; ~F 1+ 2 dla i= O, l, ... , k-1. Zachodzi

St~2+

L S1-2
I= 2

494
PROBLEMY

Ostatnia równość wynika z lematu 21.2.


Wykazaliśmy zatem, że size(x) ~ s1 ~ Fł+z ~ </>
1.


WNIOSEK 21.4.
Maksymalny stopień D(n) dowolnego węzła w n-węzłowym kopcu Fibonac-
ciego wynosi 00gn).

DOWÓD
Niech x będzie dowolnym węzłem w n-węzłowym kopcu Fibonacciego i niech
k = degree[x]. Na mocy lematu 21.3 mamy n~ size(x) ~ rj,1. Biorąc logarytm
przy podstawie <p,otrzymujemy nierówność k ~ log.;n. (W rzeczywistości, po-
nieważ k jest liczbą całkowitą, zachodzi k ~ llog,;nJ). Maksymalny stopień
D(n) dowolnego węzła jest zatem równy O(Jgn).

ZADANIA

21.4-1. Profesor Pinoccbio twierdzi, że wysokość n-węzłowego kopca Fibonac-
ciego wynosi O(lgn). Wykaż, że profesor jest w błędzie, podając dla do-
wolnej dodatniej liczby całkowitej n przykład ciągu operacji na kopcu Fi-
bonacciego, tworzącego kopiec złożony tylko z jednego drzewa stanowią­
cego liniowy łańcuch n węzłów.
21.4-2. Przypuśćmy, że uogólnilibyśmy zasadę kaskadowego odcinania w ten
sposób, że węzeł x byłby odcinany od swojego ojca zaraz po utracie swoje-
go k-tego syna dla pewnej ustalonej liczby całkowitej k. (W regule z pod-
rozdz. 21.3 jest k = 2). Dla jakich wartości k zachodzi D(_n)= O(lgn)?

Problemy
21-1. Alternatywnaimplementacjaoperacjiusuwaniawęzła
Profesor Pisano zaproponował następujący wariant procedury FIB-HEAP-DE-
LETE,twierdząc, że działa on szybciej, kiedy usuwany węzeł nie jest wskazywa-
ny przez wskaźnik min [H].

495
ROZDZIAŁ 21. KOPCEFIBONACCIEGO

PISANO-DELETE(H,x)
I ifx-min[H]
2 lhen FIB-HEAP-EXTRACT-MIN(H)
3 elsey~p[x]
4 ify;<NJL
5 lheo CUT(H, x, y)
6 CASCADING-CUT(H,y)
7 dodaj synów węzła x do listy korzeni H
8 usuń x z listy korzeni H

(a) Teza profesora, że powyższa procedura jest szybsza, opiera się w części na
założeniu, iż operację w wierszu 7 można wykonać z faktycznym kosztem
0(1 ). Gdzie tkwi błąd w tym założeniu?
(b) Podaj dobre górne oszacowanie faktycznego kosztu wykonania procedury
PISANO-DELETE,kiedy x =J:. min [H]. W Twoim oszacowaniu powinna wy-
stępować wartość degree[x] oraz c, czyli liczba wywołań procedury CAs-
CADING-Cur.
(c) Niech H' będzie kopcem Fibonacciego otrzymanym w wyniku wykonania
procedury PISANO-DELETE(H, x). Zakładając, że węzeł x nie jest korze-
niem, osza<Uj potencjał H' ze względu na degree [x], c, t(H) i m(H).
(d) Wyprowadź stąd wniosek, że zamortyzowany koszt operacji PISANO-DE-
LETE asymptotycznie nie jest lepszy niż koszt FIB-HEAP-DELETE, nawet
jeśli x 'F min [H].

21-2. hne operacjena kopcachFibonacciego


Chcemy wzbogacić strukturę kopca Fibonacciego H możliwością wykonywa-
nia dwóch nowych operacji, nie zmieniając przy tym zamortyzowanego kosztu
żadnej z pozostałych operacji.

(a) Podaj efektywną implementacjęoperacji FIB-HEAP-CHANGE-KEY(H,x, k),


która zmienia wartość klucza w węźle x na k. Dokonaj analizy z,amortyzo-
wanego kosztu swojej implementacji w przypadkach, kiedy k jest większe,
mniejsze lub równe key[x].
(b) Podaj efektywną implementację operacji FIB-HEAP-PRUNE(H, r), która
usuwa min(r, nf.H]) węzłów z H. Węzły do usunięcia można wybrać dowol-
nie. Dokonaj analizy zamortyzowanego czasu działania swojej implemen-
tacji. (Wskazówka: Być może trzeba będzie zmodyfikować strukturę da-
nych i funkcję potencjału).

496
UWAGI DO ROZDZIAŁU

Uwagi do rozdziału

Kopce Fibonacciego wprowadzili Fred.man i Tarjan [75]. Ich praca zawiera


także opis zastosowania kopców Fibonacciego do problemu najkrótszych
ścieżek z jednego węzła, najkrótszych ścieżek między wszystkimi parami węz­
łów, ważonych skojarzeń w grafach dwudzielnych i minimalnego drzewa raz-
• •
ptnaJącego.

Nieco później Driscoll, Sarnak, Sleator i Tarjan [58] przedstawili konstru-


kcję „kopców swobodnych" jako alternatywę kopców Fibonacciego. Istnieją
dwa warianty tej konstrukcji. W pierwszym oszacowania zamortyzowanego
kosztu poszczególnych operacji są takie same jak w przypadku kopców Fibo-
nacciego. Drugi umożliwia wykonanie operacji DECREASE-KEYw czasie 0(1}
w najgorszym przypadku (a nie w stałym koszcie zamortyzowanym}, a operacji
EXTRACT-MIN i DELETE w czasie O(lgn) w najgorszym przypadku. Kopce
swobodne mają także pewne zalety w porównaniu z kopcami Fibonacciego
przy zastosowaniach do algorytmów równoległych.
Rozdział 22

Strukturydanych
dla zbiorów rozłącznych

W niektórych zastosowaniach grupuje się n różnych elementów w pewną liczbę


zbiorów rozłącznych. Dwiema podstawowymi operacjami są wówczas: znaj-
dowanie zbioru, do którego należy dany element, oraz łączenie dwóch zbio-
rów. W rozdziale tym omówimy metody zarządzania strukturami danych
umożliwiającymi takie operacje.
W podrozdziale 22.1 opiszemy operacje na strukturach danych dla zbio-
rów rozłącznych i przedstawimy ich proste zastosowanie. W podrozdziale 22.2
rozpatrzymy prostą implementację zbiorów rozłącznych
na listach. Bardziej
efektywną reprezentacją z uZyciem drzew ukorzenionych zajmiemy się w pod-
rozdz. 22.3. Czas wykonywania ciągu operacji w reprezentacji drzewiastej jest
z praktycznego punktu widzenia liniowy, chociaż teoretycznie opisuje go funk-
cja rosnąca szybciej niż liniowo. W podrozdziale 22.4 zdefiniujemy i omówimy
funkcję Ackermanna i jej niesłychanie wolno rosnącą funkcję odwrotną, wy-
stępującą we wzorze na czas wykonywania ciągu operacji w implementacji
drzewiastej. Udowodnimy też nieco słabsze górne ograniczenie na czas wyko-
nywania ciągu operacji, stosując analizę kosztu zamortyzowanego.

22.1. Operacjena zbiorachrozłącznych


Struktura danych dla zbiorów rozłącznych umożliwia zarządzanie rodziną
[I'= {S 1 , S2 , .•• , S1;} rozłącznych zbiorów dynamicznych. Każdy zbiór jest
identyfikowany przez swojego repreuntanta, będącego pewnym elementem te-
go zbioru. W niektórych zastosowaniach nie ma znaczenia, którego elementu
użyjemy jako reprezentanta. Ważne jest tylko, żeby zadając dwukrotnie pyta-
nie o reprezentanta zbioru dynamicznego, otrzymywać za każdym razem taką
samą odpowiedź, jeśli zbiór w tym czasie się nie zmieniał. W innych zastosowa-

498
22.1. OPERACJE NA ZBIORACH ROZŁĄCZNYCH

niach może istnieć pewna ustalona na początku zasada wyboru reprezentanta,


na przykład najmniejszego elementu w zbiorze (zakładając oczywiście, że ele-
menty można uporządkować).
Tak jak w innych omawianych przez nas implementacjach zbiorów dyna-
micznych, każdy element zbioru jest reprezentowany przez pewien obiekt.
O:maczając taki obiekt przez x, chcemy, żeby struktura umożliwiała wykony-
wanie następujących operacji.

MAKE-SET(x) tworzy nowy zbiór, którego jedyny element (a więc i reprezen-


tant) jest wskazywany przez x. Ponieważ zbiory mają być rozłączne, x nie
może być elementem innego zbioru.

UNION(x, y) łączy dwa zbiory dynamiczne zawierające odpowiednio x i y,


powiedzmy S„ i S 1 , w nowy zbiór będący ich sumą. Zakładamy, że te dwa
zbiory przed wykonaniem operacji były rozłączne. Reprezentantem otrzy-
manego zbioru może być dowolny element S„ u S 1 , chociaż w wielu im-
plementacjach operacji UNION nowym reprezentantem jest albo reprezen-
tant S,,, albo S 1 . Ponieważ zbiory w rodzinie mają być rozłączne, ,,nisz-
czymy" zbiory S„ i S 1 , usuwając je z rodziny $/'.

FIND-SET(x) zwraca wskaźnik do reprezentanta (jedynego) zbioru zawierają­


cego x.

W dalszej części tego rozdziału będziemy analizować czas wykonywania


operacji na strukturach danych dla zbiorów rozłącznych z uwagi na dwa para-
metry: n, czyli liczbę operacji MAKE-SET, oraz m, czyli łączną liczbę operacji
MAKE-SET, UNION i FI ND-SET, Ponieważ zbiory są rozłączne, każda operacja
UNION zmniejsza liczbę zbiorów o jeden. Po wykonaniu n - l operacji UNION
pozostaje więc tylko jeden zbiór. Liczba operacji UNION wynosi zatem co
najwyżej n - 1. Zauważmy tak.że, że ponieważ w łączną liczbę operacji m wli-
czamy także operacje MAKE-SET, zachodzi zależność m ~ n.

Zastosowanie struktur danych dla zbiorów rozłącznych


Jednym z wielu zastosowań struktur danych dla zbiorów rozłącznych jest roz-
poznawanie spójnych składowych w grafie nieskierowanym (patrz pod-
rozdz. 5.4). Na rysunku 22.la widać przykład grafu o czterech spójnych skła­
dowych.
Zamieszczona poniżej procedura CONNECTED-COMPONENTS, służąca do
obliczania spójnych składowych grafu, używa operacji na zbiorach rozłącz­
nych. Po jednorazowym wykonaniu procedury CoNNECTED~COMPONENTS na
wstępie, procedura SAME-COMPONENT udziela odpowiedzi na pytania, czy da-

499
ROZDZIAŁ 22. STRUKTURY DANYCH DLA ZBIORÓW ROZŁĄCZNYCH

ne dwa wierzchołki nale-lą do tej samej spójnej skladowejJJ. (Zbiór wierzchoł­


ków grafu G jest oznaczony przez V[G], a zbiór krawędzi przez E[G]).

CONNECTED-COMPONENTS( G}
1 for każdy wierzchołek ve V[G]
2 do MAKE-SET(v)
3 for każda krawędź (u, v)eE[G]
4 do if FIND-SET(u) 'F FIND-SET(v)
5 then UNION(u, v)

SAME-COMPONENT(u, v)
I if FIND-SET(u) - FIND-SET(v)
2 then return TR UE
3 else return F ALSE

I
(,)

Przetworzone krawędzie Rodzina zbiorów rozłącznych


- ' ,., ..,_ ...., .., ,- .., """""""- - ---
Zbiory początkowe {a) {,) {d} {•l
{b} {/) {gl {hl Ul {il
(b, d) {al {h,d) {cl {•l {Il {,l {hl {;l {j)
(e, g) •
{a) {b, d) {,) {,, g) {!) {hl {;) {il
(a, c) 1
{a, c} {b, dl {,, g) {!) {hl Ul {il
(h, i) !{a. c} {h, d) {e,g} {!) {b, ;l {il
(a, b) {a. b, c, d} {•, g) {!} {h,;l {jl
(e,f) {a. b, c, d} {,,f, ,l {h, ;l {il
(b, c) {a, h, c, d} {,,J. ,l {h, ;l {il
(b)

Rys. 22.1. (a) Graf o czterech spójnych składowych: {a, h, c, d}, {e,f, g}, {h, i} oraz {i}. (b) Rodzina
zbiorów rozłącznych po przetworzeniu kaidej krawędzi

Jesli krawędzie grafu są „statyczne" - nie zmieniają się w czasie - to spójne składowe
!)

można obliczyć szybciej za pomocą algorytmu przeszukiwania w głąb (zad. 23.3-9). Czasem jednak
krawędzie są dodawane „dynamicznie" i musimy w miarę ich przybywania uaktualniać spójne
składowe. W takim przypadku przedstawiona tu implementacja może być bardziej efektywna niż
wykonywanie algorytmu przeszukiwania w głąb dla każdej nowej krawędzi.

500
22.2. LISTOWA REPREZENTACJA ZBIORÓW ROZŁĄCZNYCH

Procedura CONNECTED-COMPONENTS umieszcza początkowo każdy


wierzchołek v w osobnym zbiorze. Następnie dla każdej krawędzi (u, v) łączy
zbiory zawierające u i v. W myśl zadania 22.1-2, po przetworzeniu wszystkich
krawędzi dwa wierzchołki znajdują się w tej samej wspólnej składowej wtedy
i tylko wtedy, gdy odpowiadające im obiekty należą do tego samego zbioru.
Zatem po obliczeniu zbiorów przez procedurę CONNECTED-COMPONENTS
procedura SAME-COMPONENT może sprawdzić, czy dwa wierzchołki należą do
tej samej spójnej składowej. Proces obliczania zbiorów rozłącznych przez pro-
cedurę CONNECTED-COMPONENTS ilustruje rys. 22.lb.

ZADANIA

22.1-1. Przypuśćmy, że uruchamiamy procedurę CONNECTEO-COMPONENTS


dla grafu nieskierowanego G = (V, E), gdzie V= {a, b, c, d, e, f, g, h, i,
j, k}, a krawędzie ze zbioru E są przetwarzane w następującej kolejności:
~O.~~.~~~~~.h~~D.~~.0.D.~ft~~~~(~~.
Wypisz wierzchołki każdej spójnej składowej po każdym przebiegu pętli
w wierszach 3-5.
22.1-2. Wykaż, że po przetworzeniu wszystkich krawędzi za pomocą procedu-
ry CONNECTED-COMPONENTS dwa wierzchołki należą do tej samej spójnej
składowej wtedy i tylko wtedy, gdy należą do tego samego zbioru.
22.1-3. Ile razy w czasie wykonywania procedury CONNECTED-COMPONENTS
dla grafu nieskierowanego G = (V, E) ok spójnych składowych następuje
wywołanie FIND-SET? Ile razy wywoływane jest UNION? Podaj odpowiedź
w zależności od IVI,IEIoraz k.

zbiorówrozłącznych
22.2. Listowareprezentacja
Prostym sposobem implementacji struktury danych dla zbiorów rozłącznych
jest reprezentowanie każdego zbioru za pomocą listy. Pierwszy element na
każdej liście służy jako reprezentant swojego zbioru. Każdy obiekt na liście
składa się z elementu zbioru, wskaźnika do obiektu zawierającego następny
element zbioru oraz prowadzącego wstecz wskaźnika do reprezentanta.
Na rysunku 22.2a widać dwa zbiory. Na każdej liście obiekty mogą występo­
wać w dowolnej kolejności (przy uwzględnieniu naszego założenia, że pierwszy
obiekt na każdej liście jest reprezentantem odpowiadającego jej zbioru).
W reprezentacji listowej wykonanie zarówno MAKE-SET, jak i FIND-SET
jest proste i wymaga czasu 0(1). Żeby wykonać MAKE-SET{x), tworzymy no-
wą listę, której jedynym elementem jest x. FIND-SET{x) wykonujemy, zwraca-
jąc po prostu wskaźnik od x do reprezentanta jego zbioru.

501
ROZDZIAŁ 22. STRUKTURY DANYCH DLA ZBIORÓW ROZŁĄCZNYCH

Ee C· h
•/
I 3-
d
/
(a)

d.

(b)

Rys. 22.2. (a) Listowe reprezentacje dwóch zbiorów. Jeden :zawiera obiekty b, c, e, h, oraz c jako
reprezentanta, a w skład drugiego wchodzą d, fi g, zaś jego reprezentantem jest/ Każdy obiekt
na liście :zawiera element zbioru, wskaźnik. do następnego elementu na liście oraz wskainik. prowa-
dzący do pierwszego obiektu na liście, będącego jej reprezentantem. (b) Wynik. wykonania
UNloN(e, g). Reprezentantem otrzymanego zbioru jest/

Prosta implementacja operacji łączenia zbiorów


Wykonywanie operacji UNJON w najprostszej implementacji przy użyciu lis-
towej reprezentacji zbiorów zajmuje znacznie więcej czasu niż wykonanie ope-
racji MAKE-SETlub FIND-SET.Jak widać na rys. 22.2b, operację UNION(x, y)
wykonujemy, dołączając listę z elementem x na koniec listy z elementem y.
Reprezentantem nowego zbioru jest element będący pierwotnie reprezentan-
tem zbioru zawierającego y. Musimy jeszcze niestety uaktualnić wskaźnik do
reprezentanta we wszystkich obiektach znajdujących się pierwotnie na liście
z elementem x, co zajmuje czas liniowy względem długości tej listy.
Nietrudno podać przykład ciągu m operacji, wymagającego czasu 0(m 2).
Przyjmijmy n= fm/21 + I oraz q = m- n= Lm/2J- 1 i załóżmy, Ze naszymi
obiektami są x 1 , x 2 , ••• , xn. Będziemy wykonywać ciąg operacji przedstawiony
na rys. 22.3. Wykonanie n operacji MAKE-SETzajmuje czas 0(n). Ponieważ

502
22.2. LISTOWA REPREZENTACJA ZB10R0W ROZŁĄCZNYCH

Operacja Liczba uaktualnianych


obiektów

MAKE-SET(x 1) I
MAKE-Strr(x2) I
• •
• •
MAKE-SET(x.) I
1, x2)
UNION(X I
UNION{X2,X3) 2
UNION(X3,X4) 3
• .
• •

q-1

Rys. 22.3. Ciąg m operacji, który zajmuje łącznie cz.as O(m 2) przy prostej implementacji operacji
UNIONw listowej reprezentacji zbioru. W przykładzie tym n= rm/11 + l, a q = m - n

i-ta operacja UNION wymaga uaktualnienia i obiektów, łączna liczba obiektów


uaktualnianych we wszystkich operacjach UNION wynosi

,- '
L ;- ®(ą'l
i"" 1

Całkowity czas wykonania ciągu operacji wynosi zatem 0(n czyli + q 2),
0(m 2 ), ponieważ n= E>(m), a q = 0(m). Średnio na każdą operację przypada
więc czas E>(m). Oznacza to, że zamortyzowany czas operacji wynosi 0(m).

Heurystyka łączenia z wyważaniem


Opisana powyżej implementacja operacji UNION wymaga średnio czasu 0(m)
na każde wywołanie, ponieważ zdarza się, że dołączamy listę dłuższą do krót-
szej; musimy uaktualniać wskażnik do reprezentanta dla każdego elementu
dłuższej listy. Załóżmy więc, że każdy reprezentant zawiera dodatkowo infor-
mację o długości listy (którą łatwo uaktualniać) i że zawsze dołączamy krótszą
listę do dłuższej, rozstrzygając remisy w dowolny sposób. Czas wykonania
pojedynczej operacji UNION przy użyciu tej prostej heurystyki łączenia z wywa-
żaniem nadal może wynosić O(m), jeśli obydwa zbiory mają po O(m) elemen-
tów. Jak jednak wynika z następującego twierdzenia, ciąg m operacji MAKE-
-SET, UNION i FINO-SET, spośród których n to operacje MAKE-SET, zajmuje
czas O(m + nlgn).

TwIERDZENIE 22.1.
W listowej reprezentacji zbiorów rozłącznych przy zastosowaniu heurystyki
łączenia z wyważaniem wykonanie ciągu m operacji MAKE-SET, UNION i FIND-
-SET, spośród których n to operacje MAKE-SET, zajmuje czas O(m + nlgn).

503
ROZDZIAŁ 22. STRUKTURY DANYCH DLA ZBIORÓW ROZŁĄCZNYCH

DOWÓD
Zaczniemy od obliczenia dla każdego obiektu w zbiorze rozmiaru n górnego
ograniczenia na liczbę uaktualnień wskaźnika od tego obiektu do reprezentan-
ta. Ustalmy obiekt x. Wiemy, że za każdym razem, kiedy był uaktualniany
wskaźnik od x do reprezentanta, x musiał znajdować się w mniejszym zbiorze.
Zatem po pierwszym uaktualnieniu tego wskaźnika otrzymany zbiór musiał
zawierać przynajmniej 2 elementy. Podobnie po kolejnym uaktualnieniu
wskaźnika powstały zbiór musiał być przynajmniej 4-elementowy. Kontynu-
ując to rozumowanie, widzimy, że dla dowolnego k ~ n po uaktualnieniu
wskaźnika od x do reprezentanta fig kl razy otrzymany zbiór liczy przynaj-
mniej k elementów. Ponieważ największy zbiór zawiera co najwyżej n elemen-
tów, wskaźnik do reprezentanta każdego obiektu był uaktualniany co najwy-
żej flgnl razy we wszystkich operacjach UNION. Łączny czas uaktualniania
n obiektów wynosi zatem O(nlgn).
Stąd łatwo już oszacować czas wykonywania całego ciągu m operacji. Każ­
da operacja MAKE-SET i FIND-SET zajmuje czas 0(1), co w sumie daje O(m).
Łączny czas wykonania całego ciągu operacji wynosi zatem O(m + nlgn) .

ZADANIA

22.2-1. Napisz pseudokod operacji MAKE-SET, FINO-SET i UNION z wykorzy-
staniem reprezentacji listowej i heurystyki łączenia z wyważaniem. Przyj-
mij, że każdy obiekt x ma atrybuty: rep[x] wskazujący na reprezentanta
zbioru zawierającego x, last [x] wskazujący na ostatni obiekt na liście za-
wierającej x oraz size [x] podający rozmiar zbioru zawierającego x. Załóż,
że sięgnięcie do last [x] i size [x] jest dozwolone tylko wtedy, kiedy x jest
reprezentantem.
22.2-2. Przedstaw otrzymaną strukturę danych i odpowiedzi udzielone przez
operacje FINO-SET w poniższym programie. Użyj repre;rentacji listowej
z heurystyką łączenia z wyważaniem.

1 fori+-ltol6
2 do MAKE-SET(x1)
3 fori+-1 to 15by2
4 do UNION(x,, X;+1)
5 for i+- 1 to 13 by 4
6 do UNION(x,, X1+2)
7 UNJON(x1 , x 5 )
8 UNION(x11 , X13)
9 UNION(X1, X10)
10 FIND-SET(x2)
11 FIND-SET(x9)

504
22.3. LASY ZBIORÓW ROZŁĄCZNYCH

22.2-3. Opierając się na twierdzeniu 22.1, uzasadnij, że w reprezentacji listowej


z heurystyką łączenia z wyważaniem zamortyzowany czas wykonywania
operacji MAKE-SET i FINO-SET można oszacować przez 0(1), a zamor-
tyzowany czas UNION przez O(lgn).
22.2-4. Podaj dokładne asymptotyczne oszacowanie czasu wykonywania ciągu
operacji na rys. 22.3 w reprezentacji listowej z heurystyką łączenia z wy-
ważaniem.

22.3. Lasyzbiorówrozłącznych
W efektywniejszej niż poprzednia implementacji zbiorów rozłącznych repre-
zentujemy zbiory za pomocą drzew ukorzenionych, przy czym każdy węzeł
odpowiada jednemu elementowi zbioru, a każde drzewo reprezentuje jeden
zbiór. W lesie zbiorów rozłącznych, zilustrowanym na rys. 22.4a, każdy element
zawiera jedynie wskaźnik do swojego ojca w drzewie. Korzeń każdego drzewa
zawiera reprezentanta, a jego wskaźnik do ojca wskazuje na niego samego. Jak
się przekonamy, chociaż najprostsze algorytmy korzystające z tej reprezentacji
nie są szybsze niż używające reprezentacji listowej, dzięki zastosowaniu dwóch
heurystyk - ,,łączenia według rangi" i „kompresji ścieżki" - możemy osiągnąć
asymptotycznie najefektywniejszą ze znanych strukturę danych dla zbiorów
rozłącznych.
Trzy operacje na zbiorach rozłącznych wykonujemy w sposób następują­
cy. Operacja MAKE-SET polega na utworzeniu drzewa składającego się zjed-
nego węzła. Operację FIND-SET wykonujemy, przechodząc po wskaźnikach do
ojca, dopóki nie dotrzemy do korzenia drzewa. Węzły odwiedzone na tej dro-
dze do korzenia tworzą ścieżkę do reprezentanta. Operacja UNION, przedsta-
wiona na rys. 22.4b, polega na zmianie wskaźnika w korzeniu jednego z drzew,
tak aby wskazywał na korzeń drugiego drzewa.

' 'j'
' ,,
' '
h j'
., ,,
' '
h /i
'' '

Rys. 22.4. Las rozłącznych drzew. (1) Dwa drzewa reprezentujące dwa zbiory z rys. 22.2. Drzewo po
lewej stronie odpowiada zbiorowi {b, c, e, h}, którego reprezentantem jest c; drzewo po prawej
odpol'riada zbiorowi {d,f, g}, którego reprezentantem jest[ (b) Rezultat wykonania UNION(e,g)

505
ROZDZIAŁ 22. STRUKTURY DANYCH DLA ZBIORÓW ROZŁĄCZNYCH

Heurystyki poprawiające efektywność


Jak dotądnie widać przewagi implementacji drzewiastej nad listową. Za pomo-
cą ciągu n - l operacji UNJON możemy utworzyć drzewo stanowiące liniowy
łańcuch n węzłów. Stosując jednak dwie opisane poniżej heurystyki, możemy
osiągnąć czas działania niemal liniowy ze względu na łączną liczbę operacji m.
Pierwsza heurystyka, łączenie według nngi, przypomina heurystykę łącze­
nia z wyważaniem, której używaliśmy w reprezentacji listowej. Pomysł polega
na tym, żeby wskaźnik w korzeniu drzewa o mniejszej liczbie węzłów tak zmie-
nić, by wskazywał na korzeń większego drzewa. Zamiast w sposób jawny prze-
chowywać w każdym węźle rozmiar poddrzewa, którego jest korzeniem, za-
stosujemy podejście, które uprości późniejszą analizę. Dla każdego węzła prze-
chowujemy jego rangę stanowiącą przybliżenie logarytmu z rozmiaru poddrze-
wa, a zarazem górne ograniczenie na wysokość węzła. W metodzie łączenia
według rangi przy wykonywaniu operacji UNION wskaźnik w korzeniu
o mniejszej randze zmienia się tak, by wskazywał korzeń o większej randze.
Druga heurystyka, kompresja ścieżki, jest również dosyć prosta i bardzo
efektywna. Jak widać na rys. 22.5, stosujemy ją podczas operacji FIND-SET,
zmieniając tak wskaźnik w każdym węźle na ścieżce do reprezentanta, by

(•l (b)

Rys. 22.5. Kompresja ścieżki podcrn operacji FlND-SET.Na rysunku nie zaznaczono strzałek ani
pętli w korz.eni.ach. (a) Drzewo reprezentują.ce zbiór przed wykonaniem FlND-SET(a). Trójkąty
symbolizują poddrzewa, których korzeniami są narysowane węzły. Każdy węzeł zawiera wskaźnik
do swojego ojca. (b) Ten sam zbiór po wykonaniu FIND-SET(a).Wskaźnik w każdym wężle na
ścieżce do reprezentanta wskazuje teraz bezpośrednio na korzeń

506
22.3. LASY ZBIORÓW ROZŁĄCZNYCH

wskazywał bezpośrednio na korzeń. Kompresja ścieżki nie zmienia rangi żad­


nego węzła.

Pseudokod operacji na lesie zbiorów rozłącznych


Aby zaimplementować las zbiorów rozłącznych z heurystyką łączenia według
rangi, musimy przechowywać rangi węzłów. W każdym węźle x przechowuje-
my całkowitoliczbową wartość rank[x], stanowiącą górne ograniczenie na wy-
sokość x (liczbę krawędzi na najdłuższej ścieżce od x do liścia będącego jego
potomkiem w drzewie). Kiedy podczas operacji MAKE-SET jest tworzony zbiór
jednoelementowy, początkową rangą jedynego węzła w odpowiadającym mu
drzewie jest O. Operacje PIND-SET nie zmieniają żadnych rang. Kiedy stosuje-
my operację UNION do dwóch drzew, korzeń o większej randze czynimy ojcem
korzenia o mniejszej randze. W przypadku remisu na ojca wybieramy który-
kolwiek z korzeni i zwiększamy jego rangę.
Zapiszmy powyższe operacje w formie pseudokodu. Ojca węzła x będzie­
my oznaczać przez p[x]. Dane wejściowe pomocniczej procedury LINK, wywo-
ływanej przez UNION, to wskaźniki do dwóch korzeni.

MAKE-SET(x)
1 p[x]-x
2 rank[x] ._..O

UNION(x, y)
I LINK(F!ND-SET(x),FIND-SET(y))

LINK(x,y)
1 if rank [xJ > rank[y]
2 thenp[y] - x
3 else p[x] ._..y
4 if rank[x] - rank[y]
5 tben rank[y] ._.,rank[y] +1
Procedura PIND-SET z kompresją ścieżki jest całkiem prosta.

FIND-SET(x)
I if x ,' p[x]
2 thenp[x] - FIND-SET(p[x])
3 returnp[x]

Procedura PIND-SET jest dwuprzebiegowa:wykonuje pierwszy przebieg w górę


ścieżki do reprezentanta w poszukiwaniu korzenia, a drugi w dół tej ścieżki,
uaktualniając wskaźnik w każdym węźle, aby wskazywał bezpośrednio na

----------------"""""' __________ _
,,

507
ROZDZIAŁ 22. STRUKTURY DANYCH DLA ZBIORÓW ROZŁĄCZNYCH

korzeń. Kai.de wywołanie procedury FINO-SET(x) zwraca wartość p[x] w wier-


szu 3. Jeśli x jest korzeniem, to instrukcja w wierszu 2 nie jest wykonywana
i zwrócona zostaje wartość p[x] = x. Jest to przypadek, w którym kończy się
łańcuch wywołań rekurencyjnych. W przeciwnym razie w wierszu 2 następuje
wywołanie rekurencyjne z parametrem p[x], które zwraca wskaźnik do korze-
nia. W tym samym wierszu zostaje uaktualniony wskaźnik w węźle x tak, by
wskazywał bezpośrednio na korzeń, a wierszu 3 zostaje zwrócona wartość tego
wskaźnika.

Wpływ heurystykna czas wykonywania operacji


na zbiorach rozłącznych
Zarówno metoda łączenia według rangi, jak i metoda kompresji ścieżki za-
stosowane osobno powodują polepszenie czasu wykonywania operacji na lesie
zbiorów rozłącznych, a poprawa ta jest jeszcze większa, jeśli obie te heurystyki
zastosujemy razem. Samo łączenie według rangi daje taki sam czas działania,
jak heurystyka łączenia z wyważaniem w reprezentacji listowej: czas wykona-
nia ciągu operacji w takiej implementacji wynosi O(mlgn) (patrz zad. 22.4-3).
Oszacowanie to jest dokładne (patrz zad. 22.3-3). Chociaż nie będziemy tutaj
tego dowodzić, jeśli jest wykonywanych n operacji MAKE-SET (a zatem co
najwyżej n - 1 operacji UNION) oraz f operacji FINO-SET, sama heurystyka
kompresji ścieżki daje w najgorszym przypadku czas działania 0(/lo8( 1 +fln)n),
jeśli f ~ n, zaś E>(n+ /lg n), jeśli/ < n.
Jeśli zastosujemy zarówno łączenie według rangi, jak i kompresję ścieżki,
to czas działania w najgorszym przypadku wynosi O(m rx(m,n)), gdzie rx(m,n)
jest bardzo wolno rosnącą odwrotnością funkcji Ackermanna, którą definiuje-
my w podrozdz. 22.4. W każ.dym wyobrażalnym zastosowaniu struktury da-
nych dla zbiorów rozłącznych a(m, n)~ 4; możemy zatem traktować czas wy-
konywania ciągu m operacji jako liniowy względem m we wszystkich praktycz-
nych sytuacjach. W podrozdziale 22.4 przedstawimy dowód nieco słabszego
oszacowania O(mlg" n).

ZADANIA
22.3-1. Wykonaj zadanie 22.2-2 z użyciem reprezentacji drzewiastej z łącze­
niem według rangi i kompresją ścieżki.
22.3-2. Napisz nierekurencyjną wersję procedury FINO-SET z kompresją ścieżki.
22.3-3. Podaj ciąg m operacji MAKE-SET, UNION i FINO-SET, spośród których
n to operacje MAKE-SET, wykonujący się w czasie O(mlgn), pod warun-
kiem zastosowania tylko samej heurystyki łączenia według rangi.
* 22.3-4. Wykaż, że dowolny ciąg m operacji MAKE-SET, FINO-SET i UNION,
w którym wszystkie operacje UNION poprzedzają każdą operację PIND-
-SET, wykonuje się w czasie O(m), jeśli zastosujemy kompresję ścieżki i łą-

508
* 22.4. ANALIZA METODY ŁĄCZENIA WEDŁUG RANGI Z KOMPRESJĄ $CIEżKI

czenie według
rangi. Co by się działo w takiej samej sytuacji, jeśli zastoso-
walibyśmy jedynie kompresję ścieżki?

*22.4. Analizametodyłączenia według rangi


z kompresją ścieżki
Jak nadmieniliśmy w podrozdz. 22.3, czas wykonywania ciągu m operacji na
n elementach w implementacji drzewiastej z zastosowaniem łączenia według
rangi i kompresji ścieżek wynosi O(mr:1.(m,n)). W tym podrozdziale zbadamy
funkcję a. i przekonamy się, jak niesłychanie wolno rośnie. Następnie zamiast
bardzo skomplikowanego dowodu oszacowania O(mr:1.(m,n)) przedstawimy
prostszy dowód nieco słabszego górnego ograniczenia na czas wykonywania
ciągu operacji: O(mlg • n).

Funkcja Ackermanna i jej odwrotność


Aby zrozumieć definicję funkcji Ackermanna i jej odwrotności a., pomocne
będzie specjalne oznaczenie operacji iterowanego potęgowania. Dla liczby cał­
kowitej i ~ O wyrażenie

22···2}1

oznacza funkcję g(i) zdefiniowaną rekurencyjnie wzorem


21, jeśli i= o
g(1)- 2' , jeśli i= 1
2,0- 1) , jeśli i> I
Intuicyjnie rzecz biorąc, parametr i oznacza „wysokość stosu dwójek" stano-
wiącego wykładnik. Na przykład

'. ') 4 22
22· = 22 2 = 265536

Przypomnijmy definicję funkcji lg• (str. 58) z wykorzystaniem funkcji lg(Jl,


określonej dla liczb całkowitych i ~ O:

n, jeśli i= o
lg(lg(i- 11n, jeśli i> O oraz lgU- 1 >n> O
lg(l>n=
nieokreślone, jeśli i> O oraz Igli- 1ln ~ O lub wartość
Jg<i-lJn jest nieokreślona

lg• n= min{i ~ O:Igli>n~ 1}


ROZDZIAŁ 22. STRUKTURY DANYCH DLA ZBIORÓW ROZŁĄCZNYCH

Można powiedzieć, że funkcja lg" jest odwrotnością operacji iterowanego


potęgowania:

lg•2 2 ·· ·'}n=n+l

Możemy już zdefiniować funkcję Ackermanna, określoną dla liczb całko­


witych i, j ~ 1 wzorem

A(l,1) -2' dlaj~l


A(i, 1) - A(i - I, 2) dlai~2
A(i, J) - A(i - I, A(i,j - 1)) dlai,j~2

Rysunek 22.6 zawiera wartości tej funkcji dla małych i orazj.

j=l j=2 j=3 j=4


--l------- ---------- -- --------------
i= I 2' 2' 2' 2•

,, ,,
i= 2 2' 2•' 2' 2•'

22··-2}16 22·
_.2} .•
l
"')16 l
2·.. }2·
•• 2)2···2)16
j =3 2'' 2

Rys. 22.6. Wartości A(i, J) dla małych i orazj

Kolumna

~;
1
~

2 •
'
I, '
;; ~

4 '

•.

'
Rys. 22.7. Gwałtowny wzrost funktji Ackermanna. Linie między wierszem i - 1 a i oznaczają warto-
ści z wiersza i - I występują.ce w wierszu i. Ze względu na szybkoSCwzrostu skala w poziomie nie
jest za.chowana. Odstępy między wartościami z wiersza i - 1 pojawiają.cym.i się w wierszu i rosną
błyskawic.mie wraz ze wzrostem numeru kolumny i wiersza. Jeśli prześledzimy drogę elementów
w wierszu i do ich pierwotnej pozycji w wierszu l, to szybkość wzrostu staje się jeszcze lepiej
widoczna

510
* 22.4. ANALIZA METODY ŁĄCZENIA WEDŁUG RANGI Z KOMPRESJĄ SCIEŻKI

Rysunek 22. 7 ilustruje schematycznie przyczynę tak gwałtownego wzrostu


funkcji Ackermanna. Wartości w pierwszym wierszu, wykładnicze ze względu
na numer kolumny j, rosną już bardzo szybko. Drugi wiersz zawiera rzadki
2
podciąg wartości z pierwszego wiersza w kolumnach 2, 2 ,2 2 22
Linie , 2
22
, ....
między sąsiednimi wierszami wskazują kolumny w wierszu o niższym nwnerze,
z których wartości należą do podciągu tworzącego wiersz o wyższym numerze.
Trzeci wiersz stanowi :macznie rzadszy podciąg elementów drugiego wiersza
2 2···2}16 2···2}2·"
·2) 16
w kolumnach 2, 2 , 2 ,2 , ... , będący jeszcze rzadszym pod-
ciągiem elementów wiersza pierwszego. W ogólnym przypadku odstępy między
kolumnami w wierszu i - 1 zawierającymi sąsiednie elementy podciągu w wier-
szu i rosną błyskawicznie zarówno ze względu na numer kolumny, jak i na
numer wiersza. Zauważmy, że A(2,J) = 2 ••• } dla wszystkich całkowitych
2
2 1

~ 1. Zatem dla i > 2 funkcja A(i, ;) rośnie jeszcze szybciej niż 2 2 • · • } i.


2
j
Odwrotność funkcji Ackermanna definiujemy wzorem 1l

•(m, n) - min{i;, I: A(i, Lm/nj) > lgn}


Jeśli ustalimy wartość n, to wraz ze wzrostem m funkcja a(m, n) monotonicznie
maleje. Żeby się o tym przekonać zauważmy, że wartość Lm/nJmonotonicznie
rośnie wraz ze wzrostem m; zatem ponieważ n jest ustalone, najmniejsza war-
tość i, dla której A(i, Lm/nj)przekracza lgn, monotonicznie maleje. Własność
ta jest zgodna z naszą intuicją dotyczącą drzewiastej reprezentacji zbiorów
rozłącznych z kompresją ścieżki: dla ustalonej liczby różnych elementów n mo-
żemy się spodziewać, że wraz ze wzrostem liczby operacji m średnia długość
ścieżki do reprezentanta będzie maleć, ze względu na kompresję ścieżek. Jeśli
wykonujemy m operacji w czasie O(m a(m, n)), to średni czas przypadający na
jedną operację wynosi O(a.(m, n)), a wielkość ta monotonicznie maleje wraz ze
wzrostem m.
W celu uzasadnienia naszego wcześniejszego stwierdzenia, iż a(m, n) ~ 4
we wszystkich praktycznych zastosowaniach, zauważmy najpierw, że war-
tość Lm/njwynosi przynajmniej 1, bom~ n. Ponieważ funkcja Ackermanna
jest ściśle rosnąca ze względu na każdy ze swoich argumentów, więc z tego,
że Lm/nj~ 1, wynika, że A(i, Lm/nj)~ A(i, 1) dla każdego i~ 1. W szczegól-
ności A(4, Lm/nj)~ A(4, 1). Zachodzi jednak równość

ll Chociaż
funkcja ta nie jest odwrotnością funkcji Ackermanna w ścisłym matematycznym
sensie, zachowuje się jak odwrotność w tym znaczeniu, że rośnie tak. wolno, jak szybko rośnie
funkcja Ackermanna. Pojawienie się w definicji tajemniczej granicznej wartości lgn wynika z do-
wodu (który wykracza poza zakres tej książki), że c,..a.swykonywania ciągu operacji wynosi
O(m~(m, n)).

511
ROZDZIAŁ 22. STRUKTURY DANYCH DLA ZBIORÓW ROZŁĄCZNYCH

A(4, 1) = A(3, 2)

a liczba ta znacznie przekracza oszacowanie liczby atomów w obserwowa-


nej części wszechświata (około 1080 ). Nierówność A(4, 1) ~ lgn zachodzi je-
dynie dla nie spotykanych w praktyce ogromnych wartości n, a zatem we
wszystkich praktycznych zastosowaniach cx(m,n) ~ 4. Zauważmy, że oszaco-
wanie O(m lg• n) jest tylko trochę słabsze nii O(m cx(m,n)); lg.65 536 = 4,
a lg ·2 65 536 = 5, więc dla wszystkich praktycznych wartości n mamy lg •n :::,;
5.

Własności rang
W końcowej części tego podrozdziału udowodnimy górne ograniczenie
O(m lg• n) na czas wykonywania ciągu operacji na zbiorach rozłącznych z łą­
czeniem według rangi i kompresją ścieżki. W tym celu wykażemy najpierw
kilka własności rang.

LEMAT 22.2.
Dla każdego węzła x zachodzi rank[x] .::;;;
rank[p[x] ], przy czym nierówność jest
ostra, jeśli x #:-p[x]. Wartość rank[x] jest początkowo równa O i rośnie do
chwili, kiedy x "Fp[x]; od tego momentu rank[x] się już nie zmienia. Wartość
rank[p[x]] jest monotonicznie rosnącą funkcją czasu.

DOWÓD
Dowód przebiega przez prostą indukcję względem. liczby operacji z wykorzys-
taniem implementacji MAKE-SET, UNION i FINO-SET przedstawionej w pod-
rozdz. 22.3. Pozostawiamy go jako zad. 22.4-1.

Definiujemy size(x) jako liczbę węzłów w drzewie o korzeniu x, włącznie
z samym węzłem x.

LEMAT 22.3.
Dla dowolnego korzenia x zachodzi zależność size(x) ~ 2nnk1:cJ.

DOWÓD
Dowód przebiega przez indukcję względem liczby operacji LINK.. Zauważmy,
że operacje FIND-SET nie zmieniają ani rangi korzenia drzewa, ani rozmiaru
jego poddrzewa.

512
* 22.4. ANALIZA METODY ŁĄCZENIA WEDŁUG RANGI Z KOMPRESJĄ $CIEżKI

Warunek początkowy: Lemat jest prawdziwy przed pierwszym wywołaniem


LINK, ponieważ wszystkie rangi są początkowo równe O, a każde drzewo
zawiera przynajmniej jeden węzeł.
Krok indukcyjny: Załóżmy, że lemat jest spełniony przed wykonaniem operacji
LINK(x, y). Niech ranieoznacza rangę węzła tuż przed wykonaniem LINK,
a rank' zaraz potem. Podobnie definiujemy size i size'.

Jeśli
rank[x] i:- rank[y], to bez straty ogólności możemy założyć, że
rank[x] < rankfy]. Węzeł y zostaje korzeniem drzewa utworzonego przez ope-
rację LINK i mamy

size'(y) - size(x) + size(y)


+
~ 2ran1<[x] 2'""'*1Yl

= 2nmk'IYJ

Nie zmieniają się przy tym rangi ani rozmiary poddrzew żadnych innych węz­
łów oprócz y.
Jeśli rank[x] = rank[y), to węzeł y znowu jest korzeniem nowego drzewa

imamy

size'(y) - size(x) + size(y)


~ 2r,mk[x] + 21'<111klYl
= 21'IPlklYJ+ I
= 2'ank'[y]

LEMAT 22.4.
Dla dowolnej liczby całkowitej r ~ O istnieje co najwyżej n/2' węzłów rangi r.

DOWÓD
Ustalmy konkretną wartość r. Wyobraźmy sobie, że przypisując węzłowi x
rangę r (w wierszu 2 procedury MAKE-SET lub w wierszu 5 procedury LINK),
dołączamy etykietę x do każdego węzła w drzewie o korzeniu x. Na mocy
lematu 22.3 za każdym razem etykietę otrzymuje co najmniej 2' węzłów. Przy-
puśćmy, że zmienia się korzeń drzewa zawierającego węzeł x. Z lematu 22.2
wynika, ze
ranga nowego korzenia (a tak naprawdę to dowolnego przodka x

513
ROZDZIAŁ 22. STRUKTURY DANYCH DLA ZBIORÓW ROZŁĄCZNYCH

w drzewie) wynosi przynajmniej r + 1. Poniewa.z etykiety dołączamy tylko


wtedy, kiedy korzeń uzyskuje rangę r, żaden węzeł w tym nowym drzewie
już nigdy etykiety nie otrzyma. Zatem każdy węzeł otrzymuje etykietę co naj-
wyżej raz, kiedy jego korzeń uzyskuje rangę r. Paniewa.i w sum.ie jest n węzłów,
co najwyżej n węzłów może mieć etykiety, przy czym kaidy węzeł rangi r po-
woduje nadanie przynajmniej 2r etykiet. Gdyby istniało więcej niż n/2r węzłów
rangi r, to etykiety od węzła rangi r otrzymałoby więcej niż 2r · (n/2F) = n
węzłów, co stanowi sprzecmość. Zatem rangę r może uzyskać w sumie co
najwyżej n/2' węzłów.

WNIOSEK 22.5.

Ranga żadnego węzła nie przekracza llg nJ .

DOWÓD
Jeśli weźmiemy r > lg n, to istnieje co najwyżej n/2' < 1 węzłów rangi r, a rangi
muszą być liczbami naturalnymi.

Dowód górnego oszacowania
Do wykazania górnego ograniczenia czasu wykonywania ciągu operacji
O(mtg·n) użyjemy metody kosztu sumaryC"ZDegow analizie zamortyzowanej
(patrz pod.rozdz. 18.1). W analizie kosztu zamortyzowanego wygodnie jest za-
kładać, że wykonujemy bezpośrednio operacje LINK, a nie UNION. A więc
ponieważ parametry procedury LINK muszą być wskaźnikami do dwóch ko-
rzeni, zakładamy, że Geśli trzeba) są wykonywane odpowiednie operacje
FINO-SET. Z następującego lematu wynika, że nawet jeśli policzymy osobno
dodatkowe operacje FI ND-SET, asymptotyczny czas wykonywania ciągu ope-
racji się nie zmieni.

LEMAT 22.6.
Dany ciąg S' złożony z m' operacji MAKE-SET, UNION i FIND-SET przekształ­
camy na ciąg S złożony z m operacji MAKE-SET, LINK i FIND-SET, zamienia-
jąc każdą operację UNION na dwie operacje FIND-SET i jedną operację LINK.
Wówczas jeśli ciąg S wykonywał się w czasie O(m lg• n), to ciąg S' wykonuje się
w czasie O(m'lg·n).

DOWÓD
Ponieważ każda operacja UNION w ciągu S' zostaje zastąpiona przez trzy
operacje w S, mamy m' ~ m ~ 3m'. Ponieważ m = O(m'), z górnego ograni-
czenia O(m lg• n) na czas wykonywania ciągu po zamianie S wynika ogranicze..
nie O(m'tg·n) na czas wykonywania ciągu operacji w pierwotnej wersji S' .

514
* 22.4. ANALIZA METODY ŁĄCZENIA WEDŁUG RANGI Z KOMPRESJĄ $CIEŻKI

W pozostałej części
tego podrozdziału będziemy zakładać, że początkowy
ciąg m' operacji MAKE-SET,UNION i PIND-SETzostał przekształcony w ciąg
m operacji MAKE-SET,LINK i PIND-SET. Udowodnimy górne ograniczenie
O(mlg•n) dla ciągu po przekształceniu, a z niego po odwołaniu się do lema-
tu 22.6 wywnioskujemy, że czas wykonywania oryginalnego ciągu m' operacji
wynosi O(m'lg.n).

TwlEIIDZENIE22.7.
Ciąg m operacji MAKE-SET,LINK i PIND-SET,spośród których n to operacje
MAKE-SET,w reprezentacji drzewiastej zbiorów rozłącznych z łączeniem we-
dług rangi i kompresją ścieżki w najgorszym przypadku można wykonać
0
w czasie O(mlg n).

Dowón
PosłuZymy się pojęciem opiaty odpowiadającej faktycznemu kosztowi kazdej
operacji na zbiorach i obliczymy sumę wszystkich opłat po wykonaniu całego
ciągu operacji. Suma ta da nam łączny koszt wszystkich operacji.
Kwestia opłaty związanej z operacjami MAKE-SETi LINKjest prosta: na
każdą operację przypada jednostkowa opłata. Ponieważ faktyczny czas wyko-
nywania tych operacji jest równy 0(1), wniesione opłaty są równe faktycznym
kosztom operacji.
Zanim poruszymy sprawę opłat odpowiadających operacjom FIND-SET,
podzielimy zbiór rang węzłów na bloki, umieszczając rangę r w bloku lg ·r dla
r - O,I, ..., LignJ.(Przypomnijmy, ż, LlgnJ jest maksymalną wartością rangi).
Najwy:iszym numerem bloku jest zatem lg•Ogn) = lg•n-1. Dla wygody ozna-
czeń zdefmiujmy dla liczb całkowitych j ;a: - 1 zależność

-1 , jeślij=-1

jeśli j - O
jeśli j =1

jeśli j ;a:2

Wówczas dlaj = O, 1, ..., tg·n - 1 blokj-ty to zbiór rang

{B(i - I)+ I, B(i - I)+ 2, ..., Bij))

W operacji FIND-SETbędą występować dwa rodzaje opłat: opiaty za bloki


i opiaty za ścieżki. Przypuśćmy, że operacja FIND-SETrozpoczyna się w węźle
x 0 i Ze ścieżka do reprezentanta składa się z węzłów x 0 , x 1 , ... , x„ gdzie dla
i= l, 2, ... I węzeł. x 1 to p [x1_ 1], a x 1 (korzeń) jest równy p [x,]. Dla j = O,

515
ROZDZIAŁ 22. STRUKTURY DANYCH DLA ZBIORÓW ROZŁĄCZNYCH

1, ... , lg"n - 1 przypisujemy jednostkową opłatę za blok ostatniemu węzłowi


o randze należącej do bloku j na tej ścieżce. (Zauważmy, iż z lematu 22.2
wynika, że na dowolnej ścieżce do reprezentanta węzły o rangach należących
do jednego bloku występują kolejno koło siebie). Przypisujemy także jedno-
stkową opłatę za blok synowi korzenia, to znaczy węzłowi x 1_ 1 • Ponieważ
wartości rang ściśle rosną wzdłuż dowolnej ścieżki do reprezentanta, równo-
ważne powyższemu jest przypisanie pojedyncz.ej opłaty za blok każdemu węz­
łowi x 1 takiemu, że p[xJ = x 1 (x; jest kor:r.eniem albo synem korzenia) lub
lg"rank[x1] < lg"rank[x;+ 1J (ranga X; należy do innego bloku niż ranga jego
ojca). Każdemu węzłowi na ścieżce do repre;rentanta, któremu nie przypisali-
śmy opłaty za blok, przypisujemy jednostkową opłatę za ścieżkę.
Jeśli węzłowi nie będącemu korzeniem ani jego synem została raz przypisa-
na opłata za blok, nigdy już nie przypiszemy mu opłaty za ścieżkę. Żeby się
o tym przekonać, zauważmy, że przy każdej kompresji ścieżki ranga węzła x 1,
dla którego p [x1] -=I-x 1, pozostaje bez zmian, ale nowy ojciec x 1 ma rangę więk­
szą niż poprzedni. Różnica rangi x 1 i jego ojca jest monotonicznie rosnącą
funkcją czasu. Zatem różnica między lg•rank [p [x1]] a lg "rank[x1] także mono-
tonicznie rośnie wraz z czasem. Jeśli w pewnej chwili rangi x 1 i jego ojca należą
do różnych bloków, to będą one już zaws;rew różnych blokach, a więc węzłowi
x 1 nigdy nie przypiszemy opiaty za ścieżkę.
Ponieważ każdemu z węzłów odwiedzonych w trakcie wykonywania każ­
dej operacji FIND-SBT przypisaliśmy jednostkową opłatę, suma wszystkich
opłat jest równa łącznej liczbie węzłów odwiedzonych we wszystkich opera-
cjach FIND-SBT.Chcemy wykazać, że suma ta wynosi O(mlg"n).
Łączna suma opłat za bloki jest łatwa do oszacowania. Na ustalonej ścież­
ce do reprezentanta mamy jednostkową opłatę za blok przypisany synowi
korzenia, a poza tym na każdy numer bloku przypada co najwyżej jedna opla-
ta za blok. Ponieważ bloki są numerowane od Odo lg n - 1, w każdej operacji
0

FIND-SBT przypisujemy co najwyżej lg"n + 1 opłat za bloki. We wszystkich


operacjach FINO-SET przypisujemy zatem w sumie co najwyżej m(lg"n + 1)
opłat za bloki.
Oszacowanie opłat za ścieżki jest nieco subtelniejsze. Zaczniemy od spo-
strzeżenia, że jeśli węzłowi x 1 przypisujemy opłatę za ścieżkę, to przed kompre-
sją ścieżki musiało zachodzić p [xi] -=I-x 1, żeby podc2.aSkompresji mógł się :zmie-
nić ojciec X;. Co więcej, jak już zauważyliśmy, nowy ojciec x 1 ma wyższą rangę
niż popr:r.edni. Załóżmy, że ranga węzła X; należy do blokuj. Ile razy może
nastąpić zmiana ojca x 1, a więc i przypisanie mu opłaty za ścieżkę, zanim ojcem
x 1 nie stanie się węzeł, którego ranga należy do innego bloku (po czym węzłowi
x 1 już nigdy więcej nie przypiszemy opłaty za ścieżkę)? Liczba wystąpień takiej
sytuacji jest największa, jeśli ranga x 1 jest najniższa w swoim bloku, a rangi
zro.ieniających się ojców x 1 przybierają kolejno wartości B(j - 1) + 2,
B(j-1) + 3, ... , BIJ).Ponieważ takich rang jest w sumie B(J)-B(j-1)-1,
516
* 22.4. ANALIZA METODY ŁĄCZENIA WEDŁUG RANGI Z KOMPRESJĄ $CIEŻKI

wnioskujemy, że węzłowi,
którego ranga należy do blokuj opłatę za ścieżkę
możemy przypisać co najwyżej B(J) - BU- I) - 1 razy.
Naszym następnym krokiem w oszacowaniu sumy opłat za ścieżki będzie
wyznaczenie ograniczenia na liczbę węzłów o rangach należących do bloku
j dla liczb całkowitych j ~ O. (Przypomnijmy, że na mocy lematu 22.2 ranga
węzła przestaje się zmieniać z chwilą, gdy staje się on synem innego węzła).
Liczbę węzłów o rangach należących do blokuj oznaczmy przez N(j). Na
mocy lematu 22.4 mamy

BU) n
NU).; L ·;
r=BU-1)+1 2
Dla j = O wartością tej sumy jest
N(O) - n/2° + n/2'
- 3n/2
- 3n/2B(O)

Dlaj~ 1 mamy
n BU)-<BU-1)+1) 1
N(j) :::;_;
2BU-l)+l ,LO 2'
n w I
< 2 su-1)+1,L 2 ,
0

n
2BU-1)

n
B(J)

3n/2B(j) dla wszystkich liczb c.ałkowitych j ~ O.


Zatem N(j) :::;;:
Oszacowanie liczby opłat za ścieżki zakończymy, sumując po wszystkich
blokach iloczyn maksymalnej liczby węzłów o randze należącej do danego
bloku i maksymalnej liczby opiat za ścieżkę przypadających na jeden węzeł
o randze z tego bloku. Oznaczając przez P(n) całkowitą opłatę za ścieżki, mamy
Js•n-1 3n
P(n).; ,I, ZB(j) (BU) - B(j - I) - I)

Jg•n-1 3n
,;; ,I, 2B(j) . B(j)

517
ROZDZIAŁ 22. STRUKTURY DANYCH DLA ZBIORÓW ROZŁĄCZNYCH

= .~..nlg 0
n
2

Zatem łączna opłata przypisywana węzłom podczas operacji FINO-SET


n), czyli O(mlg n), gdyż m~n. Ponieważ jest
0 0 0
wynosi O(m(lg n+ l)+nlg
jeszcze O(n) operacji MAKE-SBT i LINK, z których każda wnosi jednostkową
opłatę, całkowity czas wykonywania ciągu operacji wynosi O(mlg n).
0


WNIOSEK22,8,
Ciąg m operacji MAKE-SET, UNION i FINO-SET, spośród których n to operacje
MAKE-SET, w implementacji drzewiastej z łączeniem według rangi i kompresją
ścieżki można wykonać w najgorszym przypadku w czasie O(mlg"n).

DOWÓD
Natychmiastowy na mocy twierdzenia 22.7 i lematu 22.6.

ZADANIA

22.4-1. Udowodnij lemat 22.2.
22.4-2. Ile bitów potrzeba do zapamiętania wartości size(x) dla dowolnego
węzła rl Ile do zapamiętania rank[x]?
22.4-3. Wykorzystując lemat 22.2 i wniosek 22.5, przedstaw prosty dowód, że
ciąg operacji w implementacji drzewiastej z łączeniem. według rangi, ale bez
kompresji ścieżki wykonuje się w czasie O(mlgn).
* 22.4-4. Przypuśćmy, że zmienimy zasadę przypisywania opłat, przypisując jed-
nostkową opłatę za blok ostatniemu węzłowi na ścieź.ce do reprezentanta,
którego ranga należy do bloku j dla j = O, 1, ... , lg• n - 1. Pozostałym
węzłom przypisujemy po jednej opłacie za ścieżkę. Jeśli zatem węzeł jest
synem korzenia i nie jest ostatnim węzłem o randze z danego bloku, to
przypisujemy mu opłatę za ścieżkę, a nie za blok. Wykaż, że węzłowi,
którego ranga pozostaje w danym blokuj, możemy przypisać Cl(m) opłat
za ścieżki.

Problemy
22-1. Minim1DD„off-line"
„off-line" dotyczy zarządzania dynamicznym zbiorem T ele-
Problem mi11inu1D1
mentów z dziedziny {1, 2, ... , n}, na którym są wykonywane operacje INSERT
i EXTRACT-MIN. Mamy dany ciąg S składający się z n operacji INSERT oraz
m operacji EXTRACT~MIN,przy czym każdy element zbioru {l, 2, ... , n} jest

518
PROBLEMY

wstawiany dokładnie raz. Chcemy obliczyć, które elementy zostaną zwrócone


przez poszczególne wywołania procedury EXTRACT-MIN.Ściślej mówiąc, na-
szym celem jest wypełnienie tablicy extracted[l .. m], gdzie dla i = 1, 2, ..., m,
extracted[z1to element zwracany przez i-te wywołanie EXTRACT-MIN.Problem
jest „off-line" w tym sensie, że możemy przetwarzać cały ciąg S przed wy-
znaczeniem wartości któregokolwiek. ze zwracanych elementów.

(a) W następującym przykładzie problemu minimum „off-line" każda opera-


cja INSERT jest reprezentowana przez liczbę, a każda operacja EXTRACT-
·MIN jest reprezentowana przez literę E:

4, 8, E, 3, E, 9, 2, 6, E, E, E, 1, 7, E, 5

Wypełnij tablicę extracted odpowiednimi wartościami.

W celu skonstruowania algorytmu dla tego problemu rozbijemy ciąg S na


podciągi jednorodne, to znaczy przedstawimy S jako

gdzie każdy symbol E reprezentuje pojedyncze wywołanie EXTRACT-MIN,


a każde li oznacza (być może pusty) ciąg wywołań INSERT.Dla każdego pod-
ciągu 1 na początku umieszczamy wstawiane przez te operacje elementy do
1
zbioru K1 (który pozostaje pusty, jeśli ciąg 11jest pusty), a potem wykonujemy
co następuje.

0FF-LINE-MINIMUM(m, n)
I fori+-1 ton
2 do wyznacz j takie, że i E K1
3 ifj=l=m+l
4 then extracted[j] +- i
5 niech / będzie najmniejszą wartością większ.ą niż j,
dla której zbiór K, istnieje
6 Ki +- K1u Ki, przy czym K1 zostaje zniszczone
7 return extracted

(b) Uzasadnij, że wartości w tablicy extracted zwracanej przez procedurę


OFF-LINE-MINIMUM są poprawne.
(c) Opisz, jak wykorzystać strukturę danych dla zbiorów rozłącznych do
efektywnej implementacji procedury OFF-LINE-MINIMUM. Podaj do-
kładne oszacowanie czasu działania Twojej implementacji w najgorszym
przypadku.

519
ROZDZIAŁ 22. STRUKTURY DANYCH DLA ZBIORÓW ROZŁĄCZNYCH

22.2. Wyznaczaniegłębokości
Problemwyznaczaniagłębokości dotyczy lasu § = {T1} ukorzenionych drzew
z trzema operacjami:
MAKE-TREE(v}tworzy drzewo, którego jedynym węzłem jest v.
FIND-DEPTH(v}zwraca głębokość węzła v w jego drzewie.
GRAFI'(r, v) czyni węzeł r, o którym zakładamy, że jest korzeniem drzewa,
synem węzła v, o którym zakładamy, że jest w innym drzewie niż r, ale nie musi
być jego korzeniem.

(a} Przypuśćmy, że użyjemy reprezentacji drzewiastej, podobnej do lasu zbio-


rów rozłącznych: p[v] jest ojcem węzła v, chyba że p[v] = v, czyli v jest
korzeniem. Wykaż, że jeśli zaimplementujemy operację GRAFT(r, v}jako
przypisanie p [r] +- v, a FIND-DEPTH(v}jako przejście w górę ścieżką do
korzenia i zwrócenie liczby napotkanych węzłów różnych od v, to w naj-
gorszym przypadku czas wykonywania ciągu m operacji MAKB-TREE
FIND-DEPTHi GRAFT wynosi 0(m 2 ).

Stosując heurystyki łączenia według rangi i kompresji ścieżki, możemy


zmniejszyć czas działania w najgorszym przypadku. Użyjemy lasu zbiorów
rozłącznych f/' = {S1}, gdzie każdy zbiór S; (sam będący drzewem} odpowiada
drzewu T 1w lesie §. Struktura drzewa w zbiorze S 1nie musi jednak koniecznie
odpowiadać strukturze T 1• W rzeczywistości, implementacja S1 nie odzwiercie-
dla dokładnie relacji ojciec-syn, mimo to umożliwia nam wyznaczenie głęboko­
ści dowolnego węzła w T1•
Podstawowy pomysł polega na przechowywaniu w każdym węźle v „pseu-
doodległości" d[v], zdefiniowanej tak, żeby suma pseudoodległości wzdłuż
ścieżki od v do korzenia jego zbioru S 1 była równa głębokości v w T1• To
oznacza, że jeśli ścieżką od v do korzenia jego drzewa S1jest v0 , v1 , .•. , v1, gdzie
v0 = v, a v1 jest korzeniem S 1, to głębokość węzła v w drzewie T1 jest równa
•L d[v;l-
1=0

(b} Podaj implementację operacji MAKB-TREE.


(c} Opisz, jak zmodyfikować procedurę FIND-SET, żeby zaimplementować
operację FIND-DEPTH.Twoja implementacja powinna wykonywać kom-
presję ścieżki, a czas jej działania powinien być liniowy ze względu na
długość ścieżki do reprezentanta. Musi też oczywiście _poprawnieuaktual-
niać pseudoodległości.
(d} Opisz, jak 11Dodyfikować procedury UNJONi LINK, żeby uimplemento-
wać operację GRAFT(r, v}, która łączy zbiory zawierające r i v. Twoja

520
PROBLEMY

implementacja musi poprawnie uaktualniać pseudoodległości. Zwróć uwa-


gę, że korzeń w zbiorze S; nie musi być korzeniem w odpowiadającym mu
drzewie T1•
(e) Podaj dokładne oszacowanie czasu wykonywania ciągu m operacji MAKE-
·TREE, FIND-DEPTH i GRAFT, spośród których n to operacje MAKE-TREE,
w najgorszym przypadku.

22-3. Algorytm Tarjana znajdowania najnitszycb wspólnych przodków „off-


-line"
Najnii:szy wspólny przodek dwóch węzłów u i v w drzewie ukorzenionym T to
węzeł w będący przodkiem zarówno u, jak i v o największej głębokości w T.
W problemie znajdowania najniż'Szycb wspólnych pnodków „off-line" mamy da-
ne drzewo ukorzenione T oraz dowolny zbiór P = {{u, v}}nieuporządkowa­
nych par węzłów z Ti chcemy wyznaczyć najniższego wspólnego przodka dla
każdej pary z P.
W celu rozwiązania problemu najniższych wspólnych przodków „off-line"
poniższa procedura obchodzi drzewo T, zaczynając obchód od wywołania
LCA(root [71). Zakładamy, że kolorem każdego węzła przed obchodem jest
BIAŁY.

LCA(u)
I MAKE·SET(u)
2 ancestor[FIND-SET(u)]._ u
3 for każdy syn v węzła u w T
4 do LCA(v)
5 UN!ON(u, v)
6 ancestor[FIND-SET(u)]- u
1 color[u]._ CZARNY
8 for każdy węzeł v taki, że {u, v}eP
9 do if co/or{v] = CZARNY
10 tb.en wypisz „Najniższym wspólnym przodkiem"
u „i" v ,Jest" ancestor[FIND-SET(v)]

(a) Uzasadnij, że instrukcja w wierszu 10 wykona się dokładnie jeden raz dla
każdej pary {u, v) eP.
(b) Uzasadnij, że w chwili wywołania LCA(u) liczba zbiorów w strukturze
danych dla zbiorów rozłącznych jest równa głębokości u w drzewie T.
(c) Udowodnij, że procedura LCA poprawnie wypisuje najniższego wspólnego
przodka węzłów u i v dla każdej pary {u, v} e P.
(d) Dokonaj analizy czasu działania procedury LCA, zakładając użycie im-
plementacji struktury danych dla zbiorów rozłącznych z pod.rozdz. 22.3.

521
ROZDZIAŁ 22. STRUKTURY DANYCH DLA ZBIORÓW ROZŁĄCZNYCH

Uwagido rozdziału

Wiele spośród najważniejszych wyników dotyczących struktur danych dla


zbiorów rozłącznych pochodzi przynajmniej częściowo od R.E. Tarjana. Gór-
ne ograniczenie O(ma(m, n)) jak.o pierwszy podał Tarjan [186, 188]. Dowód
oszacowania O(mtg·n) podali wcześniej Hopcroft i Ullman [4, 103]. Tarjan
i van Leeuwen [190] przedstawili warianty heurystyki kompresji ścieżki, w tym
„metody jednoprzebiegowe", charakteryzujące się niekiedy lepszym stałym
współczynnikiem w oszacowaniu kosztu niż metody „dwuprzebiegowe". Ga-
how i Tarjan [76] wykazali, że w niektórych zastosowaniach operacje na zbio-
rach rozłącznych można wykonywać w czasie O(m).
Tarjan w [187] wykazał dolne ograniczenie O:(mlX(m,n)) na czas wyko-
nywania ciągu operacji w dowolnej strukturze danych dla zbiorów rozłącznych
spełniającej pewne techniczne założenia. To dolne ograniczenie zostało później
uogólnione przez Fredmana i Saksa [74], którzy udowodnili, że w najgorszym
przypadku musi zachodzić O(mlX(m, n)) odwołań do (lgn)-bitowych słów
• •
w pamięci.
Część VI

Algorytmygrafowe
Wprowadzenie
Grafy są powszechniestosowane w informatyce, a algorytmy grafowe zaliczają
się do podstawowych w tej dziedzinie. Istnieją setki interesujących problemów
obliczeniowych, które wyraża się w ,języku" grafów. W tej części przedstawi-
my kilka najważniejszych z tych problemów.
W rozdziale 23 pokażemy, jak można reprezentować graf w komputerze
i omówimy dwie metody przeszukiwania grafów: w głąb i wszerz. Następnie
podamy dwa zastosowania przeszukiwania w głąb: do sortowania topologicznego
acyklicznego grafu skierowanego i do podziału grafu na silnie spójne składowe.
W rozdziale 24 opiszemy, jak obliC'lać minimalne drzewo rozpinające da-
nego grafu. Takie drzewo określa najmniejszy wagowo sposób połączenia
wszystkich wierzchołków grafu, w którym z każdą krawędzią jest związana
pewna waga. Algorytmy obliczania minimalnych drzew rozpinających są dob-
rymi przykładami algorytmów zachłannych.
Rozdziały 25 i 26 poświęcimy problemowi obliczania najkrótszych ścieżek
między wierzchołkami, gdy każda krawędź ma określoną długość lub wagę.
W rozdziale 25 zajmiemy się obliczaniem najkrótszych ścieżek z danego wierz-
chołka (źródła) do wszystkich pozostałych wierzchołków w grafie, a w roz-
dziale 26 pokażemy, jak obliczać najkrótsze ścieżki między wszystkimi parami
wierzchołków.
Na koniec, w rozdziale 27, opiszemy, jak obliczyć maksymalny przepływ
w sieci (grafie skierowanym) z ustalonego źródła do ustalonego ujścia, przy
ustalonej przepustowości ograniczającej przepływ przez każdą krawędź. Ogól-
ny problem maksymalnego przepływu pojawia się w wielu zagadnieniach i do-
bre algorytmy służące do rozwiązywania tego problemu mogą być użyte do
efektywnego rozwiązania wielu problemów pokrewnych.
Czas działania algorytmów grafowych dla danego grafu G= (V, E) będzie­
my mierzyli w zależności od liczby wierzchołków ]VI i liczby krawędzi IE!. Tak

524
WPROWADZENIE

więc rozmiar danych wejściowych podaje się za pomocą dwóch parametrów,


a nie jak dotychczas tylko jednego. Przyjmiemy następującą konwencję ozna-
c-zeń. Wewnątrz wyrażeń asymptotycznych (takich jak wyrażenia z O i 0),
i tylko w nich, symbol V oznacza IVJ, a symbol E oznacza !El.Piszemy na
przykład „algorytm działa w c:rasie O( VE)", co omacza, że algorytm działa
w c-zasie O(]V] · IEI). Przyjęta konwencja umożliwia zapisywanie formuł opisu-
jących czasy działania w postaci, która jest łatwiejsza do odczytania i nie po-
woduje niejednoznaczności.
Przyjmiemy także, że w zapisach algorytmów (pseudokodach) V[G] oma-
cza zbiór wierzchołków grafu G, a E[G] oznacza zbiór jego krawędzi. Tak
więc w pseudokodach zbiory wierzchołków i krawędzi są traktowane jako
atrybuty grafu.
Rozdział 23

Podstawowealgorytmygrafowe

W tym rozdziale przedstawimy metody reprezentowania i przeszukiwania gra-


fów. Przez przeszukiwanie grafu rozumie się systematyczne pr:zechodzenie
wzdłuż jego krawędzi w celu odwiedzenia wszystkich wierzchołków. Algorytm
przeszukiwania grafu może służyć do zbierania informacji o strukturze grafu.
Wiele algorytmów grafowych rozpoczyna się od przeszukania wejściowego
grafu w celu zdobycia takiej strukturalnej informacji. Inne algorytmy grafowe
są modyfikacjami podstawowych algorytmów przeszukiwania. Metody prze-
szukiwania grafu są sercem dziedziny algorytmów grafowych.
W podrozdziale 23.1 omówimy dwie najpowszechniej wykorzystywane
w obliczeniach reprezentacje grafów: listy i macierze sąsiedztwa. W podroz-
dziale 23.2 zaprezentujemy algorytm przeszukiwania grafów nazywany prze-
szukiwaniem wszerz (ang. breadth-first search) i pokażemy, w jaki sposób bu-
dować drzewo przeszukiwania wszerz. W podrozdziale 23.3 przedstawimy
przeszukiwanie w głąb (ang. depth-first search) i udowodnimy pewne podsta-
wowe fakty o porządku, w którym są odwiedzane wierzchołki w przeszukiwa-
niu w głąb. W podrozdziale 23.4 pokażemy nasze pierwsze, rzeczywiste za-
stosowanie przeszukiwania w głąb: sortowanie topologiczne grafu skierowa-
nego bez cykli. Kolejne zastosowanie przeszukiwania w głąb, znajdowanie sil-
nie spójnych składowych grafu skierowanego, omówimy w podrozdz. 23.5,

23.1. Reprezentacje grafów


Istniejądwa standardowe sposoby reprezentowania grafu G = (V, E): za po-
mocą list sąsiedztwa lub macierzy sąsiedztwa. Zazwyczaj preferuje się repre-
zentację listową, ponieważ umożliwia ona przedstawienie w zwarty sposób gra-
fów rzadkich - to jest takich, dla których IEIjest dużo mniejsze od JVl2 • Dla
większości algorytmów grafowych omawianych w tej książce zakłada się, że

526
23.1. REPREZENTACJE GRAFÓW

wejściowy graf jest reprezentowany przez listy sąsiedztwa. Kiedy graf jest gęsty
- IE! jest bliskie IVl2 - lub gdy istnieje potrzeba szybkiego stwierdzania, czy
istnieje krawędź łącząca dwa dane wierzchołki, wtedy może być korzystniejsza
reprezentacja macierzowa. Dla przykładu, w dwóch algorytmach znajdowania
najkrótszych ścieżek, opisanych w ro7.dz. 26, zakłada się, że grafy wejściowe są
reprezentowane przez macierze sąsiedztwa.

I 2 3 4 5
I I o I o o I
2 2 I o I I I
3 3 o I o I o
4 4 o I I o I
5 5 I I o I o
(,) (b) (c)

Rys. lll. Dwie reprezentacje grafu nieskierowanego. (a) Graf nieskierowany G z pięcioma wierz-
chołkami i siedmioma krawędziami (b) Listy sąsiedztwa grafu G. (c) Macierz sąsiedztwa grafu G

W reprezentacji grafu G = (V, E) za pomocą list sąsiedztwa dana jest


tablica Adj zawierająca IVI list, po jednej dla każdego wierzchołka z V. Dla
każdego u E V elementami listy sąsiedztwa Adj [u] są wszystkie wierzchołki v ta-
kie, że krawędź (u, v)EE; tm. Adj[u] składa się ze wszystkich wierzchołków
sąsiadujących z u w G. Zazwyczaj porządek wierzchołków na każdej liście
sąsiedztwa jest dowolny. Na rysunku 23.lb widać listy sąsiedztwa grafu nie-
skierowanego z rys. 23.la. Podobnie, na rys. 23.2b są przedstawione listy
sąsiedztwa grafu skierowanego z rys. 23.2a.

123456
4 1010100
2000010

' ' 3000011


4010000
5000100
6 6 0 O O O O I
,,, (b) (,)

Rys. 23.2. Dwie reprezentacje grafu skierowanego. (a) Graf skierowany G z sześcioma wierzchołkami
i ośmioma krawędziami. (b) Listy sąsiedztwa grafu G. (c) Macierz sąsiedztwa grafu G

Jeśli G jest
grafem skierowanym, to suma długości wszystkich list sąsiedz­
twa wynosi !El, ponieważ krawędź postaci (u, v) jest reprezentowana przez
wystąpienie v na liście Aąj[u]. Jeśli G jest grafem nieskierowanym, to suma

527
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

długości wszystkich list sąsiedztwa wynosi 21EI, ponieważ dla nieskierowanej


krawędzi (u, v) wierzchołek u występuje na liście sąsiedztwa v i odwrotnie,
v występuje na liście u. Niezależnie od tego, czy graf jest skierowany czy nie,
reprezentacja listowa ma pożądaną własność - rozmiar wymaganej przez nią
pamięci wynosi O(max(V, E)) = O(V + E).
Listy sąsiedztwa mogą być w oczywisty sposób dostosowane do reprezen-
towania grafów z wagami, tzn. takich grafów, w których z każdą krawędzią jest
związana jej waga. Wagi krawędzi są zazwyczaj dane przez funkcję wagową w:
E-+ R. Na przykład, niech G = (V, E) będzie grafem z wagami o funkcji wa-
gowej w. Waga w(u, v) krawędzi (u, v) e E jest pamiętana po prostu z wierzchoł­
kiem v na liście sąsiedztwa u. Reprezentacja listowa jest bardzo elastyczna
i umożliwia przedstawianie wielu wariantów grafów.
Pewną wadą list sąsiedztwa jest to, że w celu stwierdzenia, czy dana kra-
wędź (u, v) występuje w grafie, nie ma szybszego sposobu niż przejrzenie listy
sąsiedztwa Adj[u] w poszukiwaniu v. Wady tej nie mają macierze sąsiedztwa,
ale rozmiar użytej pamięci w tym przypadku jest asymptotycznie większy.
W reprezentacji grafu G = (V, E) za pomocą macierzy sąsiedztwa zakłada­
my, że wierzchołki są ponumerowane 1, 2, ... , IVI w pewien dowolny sposób.
Reprezentacja macierzowa grafu G składa się wtedy z macierzy A= (ar) wy-
miaru IVI x IVl takiej, że

jeśli (i, j)eE


a,= { I,
o, •
w przeciwnym razie

Na rysunkach 23.lc i 23.2c widać macierze sąsiedztwa grafów (nieskie-


rowanego i skierowanego) z rysunków, odpowiednio, 23.la i 23.2a. Macierz
sąsiedztwa grafu wymaga 0( V2 ) pamięci, niezależnie od liczby krawędzi
w tym grafie.
Zauważmy symetrię względem głównej przekątnej macierzy sąsiedztwa
z rys. 23.lc. Zdefmiujmy transpozycję macierzy A= (ay) jak.o macierz
AT= (ai), w której ai = ai1• Ponieważ w grafie nieskierowanym (u, v) i (v, u)
oznaczają tę samą krawędź, macierz sąsiedztwa A grafu nieskierowanego i jej
transpozycja AT są takie same: A = AT. W pewnych zastosowaniach opłaca się
pamiętać tylko elementy na i powyżej głównej przekątnej macierzy sąsiedztwa,
redukując w ten sposób ilość potrzebnej pamięci prawie o połowę.
Podobnie jak. reprezentacja listowa, reprezentacja macierzowa może być
używana dla grafów z wagami. Na przykład, jeśli G = (V, E} jest grafem z wa-
gami z funkcją wagową w, waga w(u, v) krawędzi (u, v)eE jest po prostu
pamiętana w wierszu u i kolumnie v macierzy sąsiedztwa. Jeśli jakaś krawędź
nie istnieje, to w odpowiednim miejscu macierzy może być zapisana wartość
NIL, chociaż w wielu problemach jest wygodnie zapisać O albo oo.

528
23.1. REPREZENTACJEGRAFOW

Mimo że repreuntatja listowa jest asymptotycznie co najmniej tak efek-


tywna jak reprezentacja macierzowa, prostota macierzy sąsiedztwa może uczy-
nić tę drugą korzystniejszą dla grafów o małych rozmiarach. Ponadto dla grafu
bez wag istnieje jeszcze pewna dodatkowa korzyść w wykorzystaniu pamięci
w reprezentacji macierzowej. Do pamiętania jednego elementu macierzy moż­
na użyć tylko jednego bitu zamiast jednego słowa maszynowego.
ZADANIA
23,1-1. Dana jest reprezentacja listowa pewnego grafu skierowanego. Ile czasu
potrzeba na obliczenie stopnia wyjściowego każdego wier7.Cholka?Ile cza-
su potrzeba na obliczenie stopni wejściowych?
23.1-2. Dana jest reprezentacja listowa pełnego drzewa binarnego o 7 wierz-
chołkach. Podaj równoważną reprezentację macierzową. Przyjmij, że
wierzchołki są ponumerowane od 1 do 7, tak. jak w kopcu binarnym.
23.1-3. Transpozycją grafu skierowanego G = (V. E) jest graf <P= (V, ET),
w którym E' = {(v, u)E V x V: (u, v)e E}. Tak więc <Pjest grafem G z od-
wróconymi wszystkimi krawędziami. Opisz efektywne algorytmy oblicza-
nia grafu GT z G dla obu jego reprezentacji -listowej i macierzowej. Doko-
naj analizy czasów działania swoich algorytmów.
23.1-4, Dana jest reprezentacja listowa multigrafu G = (V, E). Opisz algorytm
działający w czasie O( V+ E), który obliczy listy sąsiedztwa „równoważ­
nego" grafu G' = (V, E') takiego, że E' powstaje z E przez zamianę wszys-
tkich wielokrotnych krawędzi między dwoma wierzchołkami przez poje-
dynczą krawędź oraz usunięcie wszystkich krawędzi-pętli.
23.1-5. Kwadratem grafu skierowanego G = (V, E) nazywamy graf G2 =
= (V, E 2) taki, że (u, w)eE 2 wtedy i tylko wtedy, gdy dla pewnego ve V,
obie krawędzie (u, v) oraz (v, w) należą do E. To znaczy, graf G2 ma
krawędź między wierzchołkami u i w, jeżeli graf G zawiera ścieżkę między
u i w złożoną z dokładnie dwóch krawędzi. Opisz efektywne algorytmy
obliczania grafu G2 z G dla obu jego reprezentacji - listowej i macierzowej.
Dokonaj analizy czasów działania swoich algorytmów.
23.1-6. Dla reprezentacji macierzowej większość algorytmów grafowych wy-
maga czasu 0(V 2 ). Są jednak pewne wyjątki. Pokaż, że w czasie O(V)
można sprawdzić, czy graf skierowany ma ujście - wierzchołek o stopniu
wejściowym IV!- 1 i stopniu wyjściowym O-nawet jeśli do reprezentowa-
nia grafu jest używana macierz sąsiedztwa.
23.1-7. Macierzą incydencji grafu skierowanego G = (V, E) nazywamy macierz
B = (b,J) wymiaru IVIx IEltaką, że

-1, jeśli krawędź j wychodzi z wier7.Chołka i


bii = 1, jeśli krawędź j wchodzi do wierzchołka i
O, w pozostałych przypadkach

529
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

Opisz, co przedstawiają elementy macierzy BBT, gdzie BT jest transpozycją


macierzy B.

23.2. Przeszukiwanie
wszerz
Przeszukiwanie wszerz jest jednym z najprostszych algorytmów przeszukiwania
grafu i pierwowzorem wielu innych algorytmów grafowych. Algorytm Dijkstry
dla problemu najkrótszych ścieżek z jednym źródłem (rozdz. 25) oraz algorytm
Prima dla problemu minimalnego drzewa rozpinającego (podrozdz. 24.2) dzia-
łają z wykorzystaniem idei podobnych do tych z przeszukiwania wszerz.
Dane są graf G = (V, E) i wyróżniony wierzchołek początkowy s (nazywa-
ny dalej źródłem). W przeszukiwaniu grafu wszerz są systematycznie badane
krawędzie G w celu odwiedzenia każdego wierzchołka, który jest osiągalny z s.
Jednocześnie są obliczane odległości (najmniejsza liczba krawędzi) od źródła
s do wszystkich osiągalnych wierzchołków. Wynikiem działania algorytmu jest
też drzewo przeszukiwania wszerz o korzeniu w s, które zawiera wszystkie
osiągalne wierzchołki. Dla każdego wierzchołka v osiągalnego z s ścieżka
w drzewie przeszukiwania wszerz od s do v odpowiada najkrótszej ścieżce od
s do v w G, tzn. ścieżce zawierającej najmniejszą możliwą liczbę krawędzi.
Algorytm przeszukiwania wszerz działa zarówno dla grafów skierowanych, jak
i nieskierowanych.
Nazwa przeszukiwanie wszerz bierze się stąd, że w tym algorytmie granica
między wierzchołkami odwiedzonymi i nie odwiedzonymi jest przekraczana
jednocześnie na całej jej szerokości. To znaczy, wierzchołki w odległości k od
źródła są odwiedzane przed wierzchołkami w odległości k + 1.
Podczas przeszukiwania wszerz każdy wierzchołek jest kolorowany na bia-
ło, szaro lub czarno. Początkowo wszystkie wierzchołki są białe i mogą potem
zmienić kolor na szary lub czarny. Podczas przeszukiwania każdy nowo napot-
kany wierzchołek staje się odwiedzony, a jego kolor zmienia się na inny niż
biały. Zatem wierzchołki szare i czarne są już odwiedzone, ale rozróżnia się je
w celu zapewnienia poprawności wykonywania przeszukiwania. Jeśli (u, v)e E
i wierzch olek u jest czarny, to wierzchołek v jest albo s2ary albo czarny; tzn.
wszystkie wierzchołki sąsiadujące z v są już odwiedzone. Wierzchołki szare
mogą mieć białych sąsiadów; tworzą one granicę między odwiedzonymi i nie
odwiedzonymi wierzchołkami.
Algorytm przeszukiwania wszerz buduje drzewo przeszukiwania wszerz,
początkowo zawierające tylko korzeń, który jest wierzchołkiem źródłowym s.
Gdy podczas przeglądania listy sąsiedztwa odwiedzonego wierzchołka u napo-
tykany jest nie odwiedzony wierzchołek v, krawędź (u, v) i wierzchołek v są
dodawane do drzewa. Mówimy, że u jest popnednikiem lub ojcem v w drzewie
przeszukiwania wszerz. Ponieważ wierzchołek jest odwiedzany co najwyżej raz,

530
23.2. PRZESZUKIWANIE WSZERZ

ma zatem co najwyżej jednego ojca. Relacje przodek-potomek w drzewie prze-


szukiwania wszerz są definiowane względem korzenia s jak. zazwyczaj: jeśli
u znajduje się na ścież.ce prowadzącej od s do wierzchołka v, to u jest przod-
kiem v i v jest potomkiem u.
W algorytmie przeszukiwania wszerz BFS zakłada się, że wejściowy graf
G = (V, E) jest reprezentowany przez listy sąsiedztwa. Z każdym wierzchoł­
kiem w grafie wiążemy kilka dodatkowych zmiennych. Kolor każdego wierz-
chołka uE V jest pamiętany w zmiennej color[u],a poprzednik u jest pamiętany
w zmiennej n[u]. Jeśli u nie ma poprzednika (np. jeśli u= s lub u nie został
odwiedzony), to n[u] = NIL. Odległość od źródła s do wierzchołka u jest ob-
liczana w zmiennej d[u]. W algorytmie jest używana też kolejka Q typu FIFO
(patrz pod.rozdz. 11.1), w której pamięta się szare wierzchołki.

BFS(G, s)
1 for każdy wierzchołek ue V[GJ- {s}
2 do color[u]+- BIAŁY
3 d[u]- oo
4 n:[u]- NIL
5 color[s]+- SZARY
6 d[s]-0
7 n(s]- NIL
8 Q- {s)
9 whileQ,'0
10 do u - head[Q]
11 for każdy veAdj(u]
12 do if color[v]= BIAŁY
13 then color[v]+- SZARY
14 d[v] - d[u] + 1
15 n[v]-u
16 ENQUEUE(Q, v)
17 DEQUEUE(Q)
18 color[u]+- CZARNY

Rysunek 23.3 ilustruje działanie procedury BFS na przykładowym grafie.


Procedura BFS działa w następujący sposób. W wierszach 1-4 każdy
wierzchołek u różny od korzenia jest kolorowany na biało, zmienna d[u] jest
inicjowana na nieskończoność, a wskaźnik n[u] do ojca u przyjmuje wartość
NIL. W wierszu 5 źródło sjest kolorowane na szaro, poniewaz przyjmuje się, że
s zostaje odwiedzony na początku działania procedury. W wierszu 6 odległość
d[s] jest inicjowana na O, a w wierszu 7 wskaźnik do ojca s przyjmuje wartość
NIL. W wierszu 8 jest inicjowana kolejka Q. Początkowo Q zawiera tylko
wierzchołek s; później Q zawiera zawsze szare wierzchołki.

531
ROZDZIAŁ 23. PODSTAWOWEALGORYTMY GRAFOWE

--
' o' '- '- "
- "
Q ~ (b)
-
Q GEJ
-' - - -
w X y
o
' w
- -
X y
I I

" ' ' ' "


-
- Q 1,1,1,1 (d) Q 1,1,1,1
-
w y
I 2 2
w X
-
y
2 2 2

' X
'
.,
' ' ' " ' ' "
Q 1,1,1,1 (0 Q l•l•ltl
2 2 3 2 3 3
w y w X y
' X
'
' ' "
(g) Q [iliJ (h)
3 3

(i) Q 0

Rys, 23.3. Działanie procedury BFS na grafie nieskierowanym. Krawędzie drzewowe tworzone przez
BFS są :zacieniowane. W kafflym wierzchołku u jest podana wartość d[u]. Stan kolejki Q jest
przedstawiony na początku każdej iteracji instrukcji fflllle (wiersze 9-18). Poniiej wierzchołków
w kolejce :znajdują się ich odległości od źródła

Główna pętla programu jest zapisana w wierszach 9-18. Pętla jest wykony-
wana tak długo, jak długo istnieją szare wierzchołki. Szare wierzchołki są wie-
rzchołkami odwiedzonymi, których listy sąsiedztwa nie zostały jeszcze w całości
przejrzane. W wierszu 1Ojest pobierany szary wierzchołek u z poc7.ątku kolejki
Q. Każdy wierzchołek v na liście sąsiedztwa u jest rozważany w pętli for w wier-
szach 11-16. Jeśli v jest biały, to nie był dotychcms odwiedzony. Wierzchołek
v jest odwiedzany w wierszach 13-16. Najpierw v jest kolorowany na sza.ro,
a d[v] przyjmuje wartość d[u] + 1. Następnie wierzchołek u jest zapamiętywany
jako ojciec wierzchołka v. Na koniec v jest umiesz.czanyjako ostatni element
w kolejce Q. Kiedy wszystkie wierzchołki z listy sąsiedztwa wierz.cbolkau są już
zbadane, u jest usuwany z Q i kolorowany na czarno (wiersze 17-18).

532
23.2. PRZESZUKIWANIE WSZERZ

Analiza
Zanim udowodnimy własności przeszukiwania wszerz, podejmiemy się trochę
prostszego zadania - analizy czasu działania przeszukiwania wszerz dla danego
grafu G = (V, E). Po zainicjowaniu żaden wierzchołek nie jest nigdy kolorowa-
ny na biało. Dlatego test z wiersza 12 gwarantuje, że każdy wierzchołek jest
wstawiany do kolejki co najwyżej raz i co najwyżej raz jest z niej usuwany.
Operacje wstawiania do kolejki i usuwania z kolejki mjmują czas 0(1). Stąd
łączny czas wykonywania operacji na kolejce wynosi O(V). Ponieważ lista są­
siedztwa każdego wierzchołka jest przeglądana tylko wtedy, gdy wierzchołek
zostanie usunięty z kolejki, lista sąsiedztwa każdego wierzchołka jest przeglą­
dana co najwyżej raz. Ponieważ suma długości wszystkich list sąsiedztwa wy-
nosi @(E), łączny czas spędzany na przeglądaniu list sąsiedztwa wynosi O(E).
Inicjowanie zabiera czas O(V) i dlatego łączny czas działania procedury BFS
wynosi O(V + E). Tak więc przeszukiwanie wszerz jest wykonywane w czasie
liniowo zależnym od rozmiaru reprezentacji listowej grafu G.

Najkrótsześcieżki
Na początku tego rozdziału stwierdziliśmy, że przy przeszukiwaniu wszerz są
obliczane odległości od danego źródła s E V do każdego osiągalnego z s wierz-
chołka w grafie G = (V, E). Zdefiniujmy odległość t:5(s,v) od źródła s do wierz-
chołka v jak.o minimalną liczbę krawędzi na ścieżce od wierzchołka s do v lub
oo, gdy takiej ścieżki nie ma. O każdej ścieżce między wierzchołkami si v o dłu­
gości ó(s, v) powiemy, że jest najkrótszą ścleżk.ą 1 l łączącą s z v. Zanim pokaże­
my, że w przeszukiwaniu wszerz rzeczywiście są obliczane najkrótsze odległo­
ści, omówimy ich pewną ważną własność.

LEMAT23.1.
Niech G = (V, E) będzie grafem skierowanym lub nieskierowanym i niech se V
będzie dowolnym wierzchołkiem. Dla każdej krawędzi (u, v)E E zachodzi wów-
czas zależność

ó(s, v) <; ó(.v,u)+ I

Dowoo
Jeśli wierzchołek
u jest osiągalny z s, to także wierzchołek v jest osiągalny z s.
W tym przypadku najkrótsza ścieżka z s do v nie może być dłuższa od najkrót-

1
> W rozdziałach 25 i 26 uogólnimy nas1.e rozważania dotyczące najkrótszych ścieżek na grafy
z wagami, w których każda krawędź ma wagę o wartości rzeczywistej, a wagą. ścieżki jest !inma wag
jej krawędzi składowych. Krawędzie w grafach rozważanych w tym rozdziale nie mają. wag.

533
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

szej ścieżki z s do u rozszerzonej o krawędź (u, v), co dowodzi prawdziwości


powyższej nierówności. Jeśli wierzchołek u nie jest osiągalny z s, to ó(s, u) = oo
i nierówność także jest prawdziwa.

Naszym celem jest pokazanie, że procedura BFS poprawnie oblicza
d[v] = ó(s, v) dla każdego wierzchołka ve V. Najpierw pokażemy, że d[v] ogra-
nicza z góry ó(s, v).

LEMAT 23.2.
Niech G = (V, E) będzie grafem skierowanym lub nieskierowanym. Załóżmy,
że procedura BFS zostaje wywołana dla G i danego wierzchołka źródłowego
se V. Wtedy, po zakończeniu działania BFS, d[v] ~ ó(s, v) dla każdego wierz-
chołka v e V.

DOWÓD
Wykażemy przez indukcję, że po każdym wstawieniu wierzchołka do kolejki
zachodzi d[v] ~ ó(s, v) dla każdego ve V.
Warunkiem początkowym indukcji jest sytuacja bezpośrednio po umiesz-
czeniu s w kolejce Q w wierszu 8 procedury BFS. Teza indukcyjna jest w tym
miejscu prawdziwa, ponieważ d[s] = O = ó(s, s) i d[v] = oo ~ ó(s, v) dla wszyst-
kich ve V - {s).
W celu przeprowadzenia kroku indukcyjnego rozważmy biały wierzchołek
v, który jest odwiedzany w cmsie przeglądania listy sąsiedztwa u. Z założenia
indukcyjnego wynika, że d[u] ;;i, ó(s, u). Z przypisania wykonywanego w wier-
szu 14 oraz z lematu 23.1 otrzymujemy

d[v] = d[u] + I
~ ó(s, u) +I
~ ó(s, v)

Następnie wierzchołek v jest wstawiany do kolejki Qi nigdy nie będzie do niej


wstawiany ponownie (ponieważ jednocześnie jest kolorowany na szaro, a in-
strukcja po tben w wierszach 13-16 jest wykonywana tylko dla białych wierz-
chołków). A zatem wartość zmiennej d[v] nigdy nie zmienia się ponownie i nie-
równość d[v] ~ ó(s, v) zostaje zachowana.

Żeby udowodnić, że d[v] = c5(s,v), musimy dokładniej prześledzić



zacho-
wanie się kolejki Q w cz.asie działania procedury BFS. Z następnego lematu
wynika, że w każdej chwili obliczeń odległości d wierzchołków w kolejce mają
co najwyżej dwie różne wartości.

534
23.2. PRZESZUKIWANIE WSZERZ

LEMAT23.3.
Załóżmy, że podczas wykonywania procedury BFS dla grafu G = (V, E) kolej-
ka Q zawiera wierzchołki (v 1, v2, ••• , v,), gdzie v1 znajduje się na pocz.ątku Q,
a v, znajduje się na jej końcu. Wtedy d[v,] ~ d[v 1] + 1 oraz d[v;] ~ d[v 1+ 1 ] dla
i=l,2, ...,r-1.

DOWÓD
Dowód przeprowadzamy przez indukcję względem liczby operacji na kolejce.
Początkowo, gdy kolejka zawiera tylko s, lemat jest oczywiście prawdziwy.
Żeby przeprowadzić krok indukcyjny, musimy udowodnić, że lemat pozo-
staje prawdziwy zarówno po wstawieniu do kolejki nowego wierzchołka, jak
i po usunięciu z niej wierzchołka. Jeśli z początku kolejki jest usuwany wierz-
chołek v1, nowym początkiem kolejki zostaje v2 • (Jeśli kolejka staje się pusta, to
lemat jest oczywiście prawdziwy). Ale wtedy mamy d[v.] is;;d[v 1] + 1 ~
~ d[v:J + I, a pozostałe nierówności nie ulegają zmianie. Stąd wynika, że le-
mat zachodzi dla kolejki z wierzchołkiem v2 na początku. Wstawianie wierz-
chołka do kolejki wymaga bliższego przyjrzenia się procedurze BFS. Kiedy
wierzchołek v jest wstawiany do kolejki (wiersz 16), stając się w ten sposób
wierzchołkiem v,+i• wierzchołek v1 z początku kolejki Q jest w rzeczywistości
wierzchołkiem u, którego lista sąsiedztwa jest właśnie przeglądana. Stąd
d[v,+,l - d[v] - d[u] + I - d[v,] + I. Mamy także d[v,] <; d[v,] + I - d[u] +
+ 1 = d[v] = d[v,+ 1], a pozostałe nierówności nie ulegają zmianie. A zatem
lemat pozostaje prawdziwy po wstawieniu v do kolejki.

Możemy teraz udowodnić, że w przeszukiwaniu wszerz najkrótsze odległości
są obliczane poprawnie.

TwIERDZENIE 23.4. (Poprawność przeszukiwania wszen)


Niech G = (V, E) będzie grafem skierowanym lub nieskierowanym. Załóżmy,
że procedura BFS zostaje wywołana dla grafu G i danego wierzchołka źródło­
wego SE V. Wtedy, podczas wykonywania BFS, zostaje odwiedzony każdy
wierzchołek v E V, który jest osiągalny ze źródła s, a po jej wykonaniu
d[v] = ó(s, v) dla wszystkich wierzchołków ve V. Co więcej, dla każdego wierz-
chołka v 'F s osiągalnego ze źródła s, jedną z najkrótszych ścieżek z s do v jest
najkrótsza ścieżka z s do n{v] przedłużona o krawędź (n[v], v).

DOWÓD
Rozpoczniemy od przypadku, w którym wierzchołek v nie jest osiągalny re
źródła s. Z lematu 23.2 mamy: d[v] ~ ó(s, v) = co, a zatem zmienna d[v] nie
może w wierszu 14 przyjąć skończonej wartości. Można udowodnić przez in-
dukcję, że dla każdego wierzchołka w Q wartość d jest skończona. Dlatego

535
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

wiersz 14jest wykonywany tylko dla wierzchołków o skończonych wartościach


d. Stąd wynika, że jeśli wierzchołek v nie jest osiągalny z s, to nigdy nie zosta-
nie odwiedzony.
Główna część dowodu dotyczy wierzchołków osiągalnych ze źródła s.
Niech V.t będzie zbiorem wierzchołków odległych od źródła s o k; tzn.
V,~ {ve V: ~(s, v) ~ k}. Dowód przebiega przez indukcję względem k. Za tezę
indukcyjną przyjmujemy, że podczas wykonywania procedury BFS, dla każ­
dego wierzchołka v e V.t tylko raz
• v jest kolorowany na szaro,
• d[v] przyjmuje wartość k,
• jeśli v =I-s, to wartością n[v] zostaje u dla pewnego ue Vk_,,
• v jest wstawiany do kolejki Q.
Warunek początkowy indukcji jest dla k =O.Ponieważ jedynym wierzchoł­
kiem w odległości Ood źródła sjest sam wierzchołek s, mamy V0 = {s}.Podczas
inicjowania wierzchołek sjest kolorowany na szaro, d[s] przyjmuje wartość O,
a s jest umieszczany w kolejce, tak więc teza indukcyjna jest spełniona.
W celu wykonania kroku indukcyjnego zauważmy, że kolejka Q nigdy nie
jest pusta przed zakończeniem wykonywania procedury oraz że po wstawieniu
wierzchołka u do kolejki ani d[u], ani 1t[u]nie ulegają już zmianie. Z lematu
23.3 wynika, że jeśli w trak.cie wykonywania algorytmu wierzchołki są wsta-
wiane do kolejki w porządku v 1, v2, ... , v„ to ciąg odległości jest niemalejący;
d[vJ :E:;d(v;+i1 dla i= 1, 2, ..., r-1.
Rozważmy teraz dowolny wierzchołek ve V.t, gdzie k ~ 1. Z własności
monotoniczności, z nierówności d[v] ~ k (z lematu 23.2) oraz założenia induk-
cyjnego wynika, że jeśli v jest w ogóle odwiedzany, to musi zostać odwiedzony
po wstawieniu wszystkich wierzchołków z Vk-i do kolejki.
Ponieważ ó(s, v) = k, istnieje więc ścieżka od s do v złożona z k krawędzi
i istnieje wierzchołek uEV.t-i taki, że (u, v)EE. Bez straty ogólności możemy
założyć, że u będzie tak.im wierzchołkiem, który jako pierwszy został pokoloro-
wany na szaro. Taki wierzchołek istnieje, ponieważ z założenia indukcyjnego
wszystkie wierzchołki w V.t-i są kolorowane na szaro. Z opisu procedury BFS
wynika, że każdy szary wierzchołek. jest wstawiany do kolejki. Dlatego wierzcho-
łek u ostatecznie znajdzie się na początku kolejki (wiersz 10). Gdy u znajduje się
na początku kolejki, jego lista sąsiedztwa jest przeglądana i wierzchołek v zostaje
odwiedzony, (Wierzchołek v nie mógł być odwiedzony wcześniej, ponieważ nie
sąsiaduje z żadnym z wierzchołków u zbiorów V1dlaj < k - 1-w przeciwnym
razie v nie może należeć do V*- oraz u jest pierwszym odwiedzanym wierzchoł­
kiem z Vk-i• z którym sąsiaduje v). W wierszu 10 wierzchołek v jest kolorowany
na szaro, w wierszu 14jest obliczane d[v] = d[u] + 1 = k, w wierszu 15 wartością
1t[v]zostaje u, a w wierszu 16 wierzchołek v jest wstawiany do kolejki. Ponieważ
v jest dowolnym wierzchołkiem z V.t, teza indukcyjna została udowodniona.

536
23.2. PRZESZUKIWANIEWSZERZ

Żeby zakończyć dowód lematu, zauważmy, i.e jeśli vE Vk, to z tego, co


dotychczas powiedzieliśmy, mamy n[v]E Vk-i· Dlatego najkrótszą ścieżkę
z s do v możemy otrzymać, biorąc najkrótszą ścieżkę z s do 1t[v]i przedłużając
ją o krawędź (n[v], v).


Drzewo przeszukiwaniawszerz
Jak widać na rys. 23.3, podczas przeszukiwania grafu za pomocą procedury
BFS jest budowane drzewo przeszukiwania wszerz. Drzewo to jest reprezen-
towane przez pola n: związane z wierzchołkami grafu, Bardziej formalnie, dla
każdego grafu G = (V, E) z wyróżnionym źródłem s defm.iujemypodgraf po-
przednikówgrafu G jako graf G. = (V., EJ, gdzie

V.= {vE V: n[v],;, NJL}u {s)

oraz

E. = {(nfv], v)EE: VEv. - {s))

Podgraf poprzedników G'ltjest drzewem pn;eszukiwania wszerz, jeśli V„


składa się ze wszystkich wierzchołków osiągalnych z s oraz jeśli dla każdego
VE V„ istnieje w G" dokładnie jedna ścieżka z s do v, która jest jednocześnie
najkrótszą ścieżką z s do v w G. Drzewo przeszukiwania wszerz jest rzeczywi-
ście drzewem, ponieważ jest spójne i !E„1= IV„1- I (patrz tw. 5.2). Krawędzie
ze zbioru E" są nazywane krawędziami drzewowymi.
Z następującego lematu wynika, że po wykonaniu procedury BFS dla gra-
fu G i źródła s graf poprzedników jest drzewem przeszukiwania wszerz.

LEMAT23.5.
Procedura BFS wykonywana dla skierowanego lub nieskierowanego grafu
G = (V, E) oblicza 1t w taki sposób, i.e graf poprzedników G,.= (G,., E,.) jest
drzewem przeszukiwania wszerz.

DOWÓD
W wierszu 15 procedury BFS m1iennej 1t[v]zostaje nadana wartość u tylko
wtedy, gdy (u, v) EE i i5(s, v) < oo (tzn. gdy v jest osiągalne z s). Dlatego V"
składa się z tych wierzchołków ze zbioru V, które są osiągalne z s. Ponieważ G"
jest drzewem, zawiera dokładnie jedną ścieżkę z s do każdego wierzchołka z V,...
Stosując indukcyjnie twierdzenie 23.4, otrzymujemy, że każda taka ścieżka jest
najkrótszą ścieżką.


537
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

Następująca procedura wypisuje wierzchołki najkrótszej ścieżki z s do v przy


założeniu, że drzewo najkrótszych ścieżek zostało wcześniej zbudowane za po-
mocą procedury BFS.

PRINT-PATH(G,s, v)
I ifv=s
2 then wypisz s
3 else if 1t[v]~ NIL
4 tb.enwypisz „nie ma ścieżki z" s „do" v
5 else PRINT-PATH(G,s, x[v])
6 wypisz v

Procedura PRINT-PATHdziała w czasie liniowo zależnym od liczby wypisanych


wierzchołków na ścieżce, ponieważ każde kolejne wywołanie rekurencyjne na-
stępuje dla ścieżki o jeden wierzchołek krótszej.

ZADANIA
23.2-1. Podaj wynik działania przeszukiwania wszerz dla grafu skierowanego
z rys. 23.2a, przyjmując za źródło wierzchołek 3.
23,2-2. Podaj wynik działania przeszukiwania wszerz dla grafu nieskierowa-
nego z rys. 23.2, przyjmując za źródło wierzchołek u.
23.2-3. Jaki będzie czas dzlałania procedury BFS, jeśli graf wejściowy jest re-
prezentowany przez macierz sąsiedztwa, a algorytm jest zmodyftlcowany
w taki sposób, żeby działał poprawnie dla tej reprezentacji?
23,2-4. Uzasadnij, że w przeszukiwaniu wszerz wartość d[u] związana z wierz-
chołkiem u jest niezależna od porządku, w którym wierzchołki występują
na listach sąsiedztwa.
23.2-S. Podaj przykład grafu skierowanego G = ( V, E), wierzchołka źródło­
wego SE V i zbioru krawędzi drzewowych E„ c E takich, że dla każdego
v e V jedyna ścieżka w E„ z s do v jest naJ'krótszą ścieżką z s do v w grafie
G, ale zbiór krawędzi E„ nie może zostać utworzony w wyniku wykonania
procedury BFS dla G, bez względu na to,jak wierzchołki są uporządkowa­
ne na każdej liście sąsiedztwa.
23.2-6. Podaj efektywny algorytm sprawdzający, czy dany graf jest dwudzielny.
* 23.2-7. Swlnicę drzewa T= (V, E) definiujemy jako

max ó (u, v)
u,1:tEY

średnicą jest więc największa z odległości w drzewie. Podaj efektywny


algorytm obliczania średnicy drzewa i przeanalizuj czas działania swojego
algorytmu.

538
23,3. PRZESZUKIWANIE W GŁĄB

23.2--8. Niech G = (V, E) będzie grafem nieskierowanym. Podaj działający


w czasie O(V + E) algorytm obliczania ścieżki w G, która przechodzi przez
każdą krawędź dokładnie raz w każdym z dwóch kien1nków. Opisz, w jaki
sposób można znaleźć wyjście z labiryntu, jeśli mamy do dyspozycji wy-
starczająco wiele kamyków.

w głąb
23.3. Przeszukiwanie
Jak sama nazwa wskazuje, przeszukiwanie w głąb polega na sięganiu „głębiej"
w graf, jeżeli jest to tylko możliwe. Przy przeszukiwaniu w głąb są badane
krawędzie ostatnio odwiedzonego wierzchołka v, z którego jeszcze wychodzą
nie zbadane krawędzie. Gdy wszystkie krawędzie opuszczające wierzchołek
v są zbadane, przeszukiwanie „wraca" do wierzchołka, z którego v został od-
wiedzony. Proces ten jest kontynuowany dopóty, dopóki wszystkie wierzchołki
osiągalne z początkowego wierzchołka źródłowego nie zostaną odwiedzone.
Jeśli pozostanie jakikolwiek nie odwiedzony wierzchołek, to jeden z takich
wierzchołków wybiera się jako nowe źródło i przeszukiwanie jest powtarzane
z tego źródła. Cały proces powtarza się, a.zwszystkie wierzchołki w grafie
zostaną odwiedzone.
Jeżeli przy przeszukiwaniu w głąb, podobnie jak przy przeszukiwaniu
wszerz, w trakcie przeglądania listy sąsiedztwa już odwiedzonego wierzchołka
u jest wykrywany nie odwiedzony wierzchołek v, to zdarzenie takie jest rejest-
rowane przez zapamiętanie w zmiennej n[v] wierzchołka u - poprzednik.a v.
W przeciwieństwie do przeszukiwania wszerz, gdzie podgraf poprzedników
jest drzewem, podgraf poprzedników tworzony w przeszukiwaniu w głąb
może składać się z kilku drzew, ponieważ przeszukiwanie może być wykony-
wane z wielu źródeł. Dlatego właśnie podgraf poprzedników w przeszukiwaniu
w głąb definiujemy trochę inaczej niż drzewo przeszukiwania wszerz: teraz
G, - (V, E,), gdzie

E, - {(n[u], u): UC V i •[u]" NIL}

Podgraf poprzednik.ów w przeszukiwaniu w głąb jest lasem przeszukiwania


w głąb złożonym z jednego lub więcej drzew przeszukiwania w głąb. Krawędzie
ze zbioru E„ nazywamy krawędziami drzewowymi.
Podczas przeszukiwania w głąb, podobnie jak przy przeszukiwaniu wszerz,
wierzchołki są kolorowane w celu określenia ich stanów. Początkowo każdy
wierzchołek jest kolorowany na biało. Kolor wierzchołka zmienia się na szary
gdy jest odwiedzany po raz pierwszy podczas przeszukiwania. Wierzchołek jest
kolorowany na czarno, gdy zostaje pn:etworzony, tzn. gdy jego lista sąsiedztwa
zostaje całkowicie zbadana. Ta metoda gwarantuje, że każdy wierzchołek będzie

539
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

należał do dokładnie jednego drzewa przeszukiwania w głąb; drzewa te są więc


rozłączne.
Przy przeszukiwaniu w głąb, oprócz tworzenia lasu przeszukiwania, wierz-
chołkom przypisuje się etykiety czasowe. Każdemu wierz.chołkowi v są przypi-
sywane dwie etykiety: pierwsza etykieta, d[v], jest numerem kroku obliczeń,
w którym v jest odwiedzany po raz pierwszy (i kolorowany na szaro), a druga
etykieta, J1v], jest numerem kroku w przeszukiwaniu, w którym kończy się
badanie listy sąsiedztwa wierzchołka v (i v jest kolorowany na czarno). Te
etykiety są wykorzystywane w wielu algorytmach grafowych i są zazwyczaj
pomocne w badaniu przeszukiwania w głąb. Etykiety czasowe są liczbami cał­
va.
kowitymi z przedziału [l, 21 ponieważ każdy wierzchołek jest odwiedzany
po raz pierwszy tylko raz i tylko raz jest przetworzony. Dla każdego wierzchoł­
ka u zachodzi zależność

d[u] <Jiu] (23.1)

Wierzchołek u jest BIALYdo kroku d[u], SZARY w krokach od d[u] do fiu],


a potem już CZARNY.
Procedura DFS jest podstawowym algorytmem przeszukiwania w głąb.
Graf wejściowy może być nieskierowany lub skierowany. Zmienna time jest
7lTlienną globalną używaną do etykietowania wierzchołków.

DFS(G)
1 for każdy wierzchołek uE V[G]
2 do color[u]+- BIAŁY
3 n[u] +- NIL
4 time+-0
5 for każdy wierzchołek uE V{G]
6 do if color[u]= BIAŁY
7 thenDFS-VISIT(u)

DFS-VISIT(u)
1 color[u]+- SZARY [> Biały wierzchołek. u właśnie został odwiedzony.
2 d[u] +- time+- time + 1
3 for każdy veAdj[u] I> Zbadaj krawędź (u, v)
4 do if color[v]= BIALY
5 !ben it[v]- u
6 DFS-VISIT(v)
1 co/or[u]+- CZARNY [> Pokoloruj u na czarno - został przetworzony
8 f(uJ+-time+- time+ l
Rysunek 23.4 ilustruje działanie procedury DFS dla grafu z rys. 23.2.

540
23.3. PRZESZUKIWANIE W GŁĄB

,,
" " )
"
,,,---,
_)
"
I/ I/"
" "
-

"
- ''
)
,
;:,
" '
- ,/ '
"
(
.J-.....
, ,,

'"'
{a,
' ' '
(,I I

" ' " ' r, w


- " " "
--

" /
""
_.1. . ..,..
C_~) (
·--
'
.J__./
·-'

(,)
' ' ' '
10
'" '"'
"
I/
w

'
,," ®
w

(...I.~")
' ·--~' -
,ID
-- ,-
'' --
- ,,
.--"--·'
, (-1~~-
- ~

' ' ' '


u, ' '" ' ' ' '
I' >
w
'" (I)

" " '

" " "


(m)
' ' '
(n)
' '
Io)
' ' ' '

Rys. 23.4. Działanie algorytmu przeszukiwania w głąb


"'
Krawędzie
DFS dla grafu skierowanego.
zbadane w wyniku działania algorytmu są albo zacieniowane (jeśli ą krawędziami drzewowymi),
albo zaznaczone linią. przerywaną. (w przeciwnym razie). Krawędzie niedrzewowe są poetykietowa-
ne literami B, C lub F w zależności od tego, czy są. one powrotne (ang. back), poprzeczne (ang.
cross) lub w przód (ang. forward). Etykiety wierz.chołków są. postaci czas-odwiedzenia/czas.prze-
tworzenia

Procedura DFS działa następująco. W wierszach 1-3 wszystkie wierzchołki


są kolorowane na biało, a ich pola n: są inicjowane na NIL. W wierszu 4 jest
zerowany licznik C"ZaSU. W wierszach 5-7 jest badany każdy wierzchołek z V.
Kiedy zostaje wykryty biały wierzchołek, jest on odwiedzany przy użyciu pro-
cedury DFS-VISIT. Za każdym razem, gdy procedura DFS-VISIT(u}jest wywo-
ływana w wierszu 7, wierzchołek u staje się korzeniem nowego drzewa w lesie
przeszukiwania w głąb. Po zakończeniu działania procedury DFS każdy wierz-
chołek u ma przypisany czas odwiedzenia d[u] i czas przetworzenia/[u].
W każdym wywołaniu DFS-VISIT(u} wierzchołek u jest na początku biały.
W wierszu 1 wierzchołek u jest kolorowany na szaro, a w wierszu 2 jest zwięk­
szana o 1 wartość 71D.iennejglobalnej time i jest zapisywany czas odwiedzenia
d[u]. W wierszach 3-6 jest badany każdy wierzchołek v sąsiadujący z u. Jeśli v
jest biały to jest odwiedzany rekurencyjnie. Dla każdego wierzchołka v e Adj[u]

541
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

rozważanego w wierszu 3 mówimy, że krawędź (u, v) jest badana w przeszuki-


waniu w głąb. Na koniec, po zbadaniu każdej krawędzi opuszczającej u, wierz-
chołek u jest kolorowany na czarno (wiersze 7-8) i w zmiennej /[u] jest zapa-
miętywany czas przetworzenia wierzchołka u.
Jaki jest czas działania procedury DFS? Pętle w wierszach 1-2 i w wier-
szach 5-7 w procedurze DFS ubierają czas 0( V), wyłączywszy czas wykonania
wywołań procedury DFS-VISIT. Procedura DFS-VISITjest wywoływana do-
kładnie raz dla każdego wierzchołka ve V. Jest tak, ponieważ DFS-VISITjest
wywoływana tylko dla białych wierzchołków, a pierwszą czynnością wykony-
waną w tej procedurze jest pokolorowanie wierzchołka na szaro. Po wywoła­
niu DFS-VISIT(v)pętla w wierszach 3-6 wykonuje się JA4i[v]lrazy. Ponieważ

L JAdj[v]I - 0(E)
•• v

łączny koszt wykonania wierszy 5-6 w procedurze DFS-VISIT wynosi 0(E).


Czas działania procedury DFS wynosi zatem 0(V + E).

Własności przeszukiwania w głąb

Wykonując przeszukiwanie w głąb, możemy zebrać dużo


informacji o struk-
turze grafu. Być może najistotniejszą własnością przeszukiwania w głąb jest to,
że graf poprzedników G"'jest faktycznie lasem drzew, ponieważ struktura prze-
szukiwania w głąb dokładnie odzwierciedla strukturę wywołań rekurencyjnych
procedury DFS-VISIT.Oznacza to, że u= n{v]wtedy i tylko wtedy, gdy proce-
dura DFS-VISIT{v)została wywołana podczas przeszukiwania listy sąsiedztwa
wierzchołka u.
Inną ważną własnością przeszukiwania w głąb jest to, że
czasy odwiedzania
i przetworzenia mają strukturę nawiasową. Jeśli będziemy oznaczać chwilę od-
wiedzenia wierzchołka u za pomocą nawiasu otwierającego ,.(u", a chwilę prze-
tworzenia u za pomocą nawiasu zamykającego „u)", to historia odwiedzania
i przetwarzania wierzchołków jest poprawnie zbudowanym wyrażeniem nawia~
sowym - nawiasy są właściwie zagnieżdżone. Na przykład przeszukiwaniu
w głąb z rys. 23.5a odpowiada wyrażenie nawiasowe z rys. 23.5b. Następujące
twierdzenie opisuje w inny sposób strukturę nawiasową przeszukiwania w głąb.

TwIERDZENIE 23.6. (Twien:benie o nawiasach)


W każdym przeszukiwaniu w głąb dla grafu (skierowanego lub nieskierowa-
=
nego) G (V, E), dla każdej pary wierzchołków u i v zachodzi dokładnie jeden
z trzech następujących warunków:

• przedziały [d[u],/[u]] i [d[v],f[v]] są całkowicie rozłączne;

542
23.3. PRZESZUKIWANIEW Gł.ĄB

(,)

...

(b)

'
''
' '
'' ''
' '
' ' '' ' ''
' '
2 3 4 5 6 7 8 9 IO 11 12 13 14 IS 16
(, (, (y (x x) y) (w w) ,) .,) (I (v v) (u u) ,)

(,)
'

Rys. 23.S. Włamości przeszukiwania w głąb. (a) Wynik przeszukiwania w głąb dla grafu skierowa-
nego. Wierzchołki są poctykietowane w ten sam spos6b, jak na rys. 23.4. Podobnie są zamaczone
typy krawędzi (b) Przedziały wyznaczone przez cmsy odwiedzania i czasy przetworzenia wicrz-
chołk6w odpowiadają wyrażeniu nawiasowemu poniżej. Kaidy prostokąt rozpina przedział wy.
znaczony przez czas odwiedzenia i czas przetworzenia odpowiadającego mu wierzchołka. Zostały
zamaczone krawędzie drzewowe. Jeśli dwa przedziały zachodzą na siebie, to jeden z nich jest
zawarty wewnątrz drugiego, a wierzchołek odpowiadający mniejszemu przedziałowi jest potom-
k:icm wierzchołka odpowiadającego przedziałowi większemu. (c) Graf z części (a) narysowany
w ta.kispos6b, że wszystkie krawędzie drzcwowe i w przód prowadzą w dół drzewa przeszukiwania
w głąb, a wszystkie krawędzie powrotne prowadzą od potomka do przodka

543
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

• przedział [d[u],/(ull jest całkowicie zawarty w przedziale [d[v],/[vTI, a wierz-


chołek. u jest potomkiem v w drzewie przeszukiwania w głąb;
• przedzjał [d[v],/(vil jest całkowicie zawarty w pnedziale [d[u],/[ull, a wierz-
chołek v jest potomkiem u w drzewie przeszukiwania w głąb.

DOWÓD
Rozpacz.niemy od przypadku, w którym d[u] < d[v]. Do rozpatrzenia są dwa
podprzypadki w zależności od tego, czy d[v] <J[u], czy nie. W pierwszym
podprzypadku d[v] </[u], wierzeholek v został więc odwiedzony wtedy, kiedy
wierzchołek u byłjeszc:ze szary. Stąd wynika, że v jest potomkiem u. Co więcej,
ponieważ wierzchołek v jest odwiedzany później niż wierzchołek u, wszystkie
krawędzie wychodzące z v zostaną zbadane i v zostanie przetworzony, zanim
przeszukiwanie powróci do u i wierzchołek u zostanie przetworzony. Dlatego
w tym przypadku przedział [d[v], /[v]] jest całkowicie zawarty w przedziale
[d[u], /[ull, W drugim podprzypadku /[u] < d[v]; z nierówności 23.1 wynika
więc, że przedziały [d[u], /[uil i [d[v], /[•Il są rozłączne.

Przypadek, w którym d[v] < d{u], jest podobny. W powyższej argumen-


tacji u oraz v zamieniają się rolami.

WNIOSEK 23.7. (0 zagnieMw,iu pnedzialów)
Wierzchołek. v jest właściwym potomkiem wierzchołka u w lesie przeszukiwa-
nia w głąb grafu (skierowanego lub nieskierowanego) G wtedy i tylko wtedy,
gdy d[u] < d[v] </[v] </[u].

DowOD
Natychmiastowy wniosek z twierdzenia o nawiasach.

W-następnym twierdzeniu jest podana inna ważna cecha wierzchołk.a-po­
tomka w lesie przeszukiwania w głąb.

TwlERDZENIE 23.8. (fwierdzenie o białej ścieżce)


Wierzchołek v jest potomkiem wierzchołka u w lesieprzeszukiwania w głąb grafu
(skierowanego lub nieskierowanego) G = (V, E) wtedy i tylko wtedy, gdy w kro-
ku d[u], w którym zostaje odwiedzony wierzchołek. u, można dotr:zeć z wierzchoł­
ka u do wierzchołka v ścieżką złożoną całkowicie z białych wierzchołków.

DOWÓD
=> Załóżmy, że wierzchołek v jest potomkiem wierzchołka u. Niech w będzie
dowolnym wierzchołkiem na ścieżce w drzewie przeszukiwania w głąb leżącym

544
23.3. PRZESZUKIWANIE W GŁĄB

między u i v. Z wniosku 23.7 wynika, że d[u] < d[w] i stąd w jest biały
w kroku d[u].
..;;:,Przypuśćmy, że wierzchołek v w kroku d{u] jest osiągalny z wierzchołka
u ścieżką złożoną z białych wierzchołków, ale v nie zostaje potomkiem
u w drzewie przeszukiwania w głąb. Bez straty ogólności załóżmy, że każdy
inny wierzchołek z tej ścieżki zostaje potomkiem u. (W przeciwnym rarie niech
v będzie najbliżej położonym od u wierzchołkiem na ścieżce, który nie zostaje
potomkiem u). Niech w będzie poprzednikiem v na tej ścieżce. Zatem w jest
potomkiem u (faktycznie w i u mogą być tym samym wierzchołkiem), a z wnio-
sku 23.7 wynika, 7.e/[w] ~f[u]. Zauważmy, że wierzchołek v musi zostać od-
wiedzony po odwiedzeniu u, ale zanim wierzchołek w wstanie przetworzony.
Dlatego d[u] < d[v] <f[w] .:;;;/[u). Z twierdzenia 23.6 wynika wtedy, że prze-
dział [d[v],f[vTI jest całkowicie zawarty w przedziale [d[uJ, f[uTI. Z wnios-
ku 23.7 dostajemy, że wierzchołek v musi ostatecznie zostać potomkiem u .

Klasyfikacjakrawędzi
Inną interesującą własnością przeszukiwania w głąb
jest to, że można je za-
stosować do sklasyfikowania krawędzi wejściowego grafu G = (V, E). Taka
klasyfikacja może być używana do zbierania ważnych informacji o grafie. Dla
przykładu, w następnym podrozdziale zobaczymy, że graf skierowany jest acy-
kliczny wtedy i tylko wtedy, gdy przy przeszukiwaniu w głąb nie pojawiają się
krawędzie powrotne (lemat 23.10).
Możemy zdefiniować cztery typy krawędzi w odniesieniu do lasu przeszu-
kiwania w głąb G„ otrzymywanego w wyniku przeszukiwania w głąb grafu G.
1. Krawędziami drzcwowymi są krawędzie w lesie przeszukiwania w głąb G,,.
Krawędź (u, v) jest krawędzią drzewową, jeśli wierzchołek v został odwie-
dzony w wyniku zbadania krawędzi (u, v).
2. Krawędziami powrotnymi są krawędzie (u, v) łączące wierzchołek u z jego
przodkiem v w drzewie przeszukiwania w głąb. Pętle są traktowane jako
krawędzie powrotne.
3. Krawędziami w przód są te krawędzie niedrzewowe (u, v), które łączą wierz-
chołek u z jego potomkiem v w drzewie przeszukiwania w głąb.
4. Krawędziami poprzecznymi są wszystkie inne krawędzie. Krawędzie poprze-
czne łączą wierzchołki z tego samego drzewa przeszukiwania w głąb, jeżeli
tylko jeden z wierzchołków nie jest przodkiem drugiego, lub łączą wierz-
chołki z różnych drzew przeszukiwania w głąb.

Krawędzie na rys. 23.4 i 23.5 mają etykiety określające ich typy (F - kra-
wędź w przód (ang.forward), B -krawędź powrotna (ang. back), C - krawędź
poprzeczna (ang. cross)). Na rysunku 23.5c jest pokazane, w jaki sposób nary-

545
ROZDZIAŁ 23. PODSTAWOWEALGORYTMYGRAFOWE

sować graf z rys. 23.5a, żeby wszystkie krawędzie drzewowe i w przód były
skierowane w dól drzewa, a wszystkie krawędzie powrotne były skierowane
w górę drzewa. Każdy graf można rysować w ten sposób.
Algorytm DFS moi..na zmodyfikować w taki sposób, żeby napotykane
krawędzie były odpowiednio klasyfikowane. Zasadnicza obserwacja polega na
tym, że każda krawędź (u, v), gdy jest badana po raz pierwszy, może zostać
sklasyfikowana za pomocą koloru wierzchołka v, do którego prowadzi (w ten
sposób nie można rozróżnić krawędzi w przód od poprzecznych):

(1) BIAŁY wskazuje na krawędź drzewową,


(2) SZARY wskazuje na krawędź powrotną,
(3) CZARNY wskazuje na krawędź w przód lub poprzeczną.

Przypadek pierwszy wynika bezpośrednio z opisu algorytmu. Żeby uzasadnić


przypadek drugi, zauważmy, że szare wierzchołki tworzą zawsze liniowy łań­
cuch potomków odpowiadający stosowi aktywnych wywołań procedury DFS-
-VISIT. Liczba szarych wierzchołków jest o 1 większa od głębokości ostatnio
odwiedzonego wierzchołka w lesie przeszukiwania w głąb. Badanie grafu jest
zawsze kontynuowane z najgłębszego szarego wierzchołka, a więc krawędź,
która prowadzi do innego szarego wierzchołka, prowadzi do pewnego przod-
ka. Przypadek trzeci dotyczy pozostałych możliwości. Można pokazać, że kra-
wędź (u, v) jest krawędzią w przód, jeśli d[u] < d[v], lub jest krawędzią poprze-
czną, gdy d[u] > d[v] (patrz zad. 23.3-4).
W grafach nieskierowanych może zaistnieć pewna niejednoznaczność
w klasyfikowaniu krawędzi, ponieważ (u, v) i (v, u) są tak. naprawdę tą samą
krawędzią. W takim przypadku krawędź jest pierwszego z typów, który się do
niej stosuje. Równoważnie (patrz zad. 23.3-5), taka krawędź jest klasyfikowa-
na w zależności od tego, która z krawędzi (u, v) lub (v, u) jest napotykana jak.o
pierwsza podczas wykonywania algorytmu.
Pokażemy teraz, że krawędzie w przód i poprzeczne nigdy nie pojawiają
się w przeszukiwaniu w głąb grafu nieskierowanego.

TwIERDZENIE 23.9.
W przeszukiwaniu w głąb grafu nieskierowanego G każda krawędź jest albo
krawędzią drzewową, albo krawędzią powrotną.

DOWÓD
Niech (u, v) będzie dowolną krawędzią z G. Załóżmy bez straty ogólności, że
d[u] < d[v]. Ponieważ wierzchołek v znajduje się na liście sąsiedztwa wierzchoł­
ka u, to musi on zostać odwiedzony i przetworzony, zanim zostanie przetwo~
rzony wierzchołek u. Jeśli krawędź (u, v) jest badana po raz pierwszy w kierun-
ku od u do v, to (u, v) zostaje krawędzią drzewową. Jeśli (u, v) jest badana po

546
23.3. PRZESZUKIWANIE W GŁĄB

raz pierwszy w kierunku od v do u, to (u, v) jest krawędzią powrotną, ponieważ


podczas badania krawędzi na liście v wierzchołek u jest jeszcze szary.


W następnych podrozdziałach pokażemy wiele zastosowań udowodnio-
nych tu twierdzeń.
ZADANIA

23.3-1. Narysuj tabelę o 3 wierszach i 3 kolumnach poetykietowanych kolo-


rami BIAŁYM, SZARYM i CZARNYM. w każdym polu (i, j) tej tabeli za-
znacz, czy w przeszukiwaniu w głąb grafu skierowanego może pojawić
się krawędź prowadząca od wierzchołka o kolorze i do wierzchołka o ko-
lorze j. Dla każdej możliwej krawędzi określ, jakiego typu może być ta
krawędź. Wykonaj podobną tabelę dla przeszukiwania w głąb w grafie
nieskierowanym.
23.3-2. Zilustruj działanie przeszukiwania w głąb dla grafu z rys. 23.6. Załóż,
że w pętli for w wierszach 5-7 procedury Df'S wierzchołki są przeglądane
w porządku alfabetycznym i każda lista sąsiedztwa jest uporządkowana
alfabetycznie. Podaj dla każdego wierzchołka czas jego odwiedzenia i prze-
tworzenia oraz sklasyfikuj każdą krawędź.

Rys. 23.6. Graf skierowany z zad. 23.3,2 i 23.5-2

23.3-3. Podaj strukturę nawiasów przeszukiwania w głąb pokazanego na


rys. 23.4.
23.3-4. Pokaż, że krawędź (u, v) jest

(a) krawędzią drzewową lub krawędzią w przód wtedy i tylko wtedy, gdy
d[u] < d[v] <f[v] <f[u];
(b) krawędzią powrotną wtedy i tylko wtedy, gdy d[v] < d[u] <f[u] <
<f[v];
(c) krawędzią poprzeczną wtedy i tylko wtedy, gdy d[v] <f[v] < d[u] <
<f[u].

547
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

23.3-5. Pokaż, że w grafie nieskierowanym sklasyfikowanie krawędzi (u, v)


jako krawędzi drzewowej lub krawędzi powrotnej zależnie od tego, która
z krawędzi (u, v) lub (v, u) jest napotykana jako pierwsza podczas prze.
szukiwania w głąb, jest równoważne sklasyfikowaniu krawędzi (u, v) zależ.
nie od kolejności typów na liście typów w schemacie klasyfikacji.
23.3-6. Podaj kontrprzykład do hipotezy mówiącej, że jeśli istnieje ścieżka od
wierzchołka u do v w grafie skierowanym G i jeśli d[u] < d[v] w prze.
szukiwaniu w głąb grafu G, to wierzchołek v jest potomkiem wierz.cholka
u w zbudowanym lesie przeszukiwania w głąb.
23.5-7. Zmodyfikuj kod procedury przeszukiwania w głąb w taki sposób, żeby
została wypisana każda krawędź grafu skierowanego G wraz z jej typem.
Pokaż, jakie zmiany są potrzebne (gdyby cokolwiek musiało zostać zmie·
nione), jeżeli G jest nieskierowany.
23.3-8. Wyjaśnij, w jaki sposób wierzchołek u w grafie skierowanym może
zostać jedynym wier2.ehołkiem w drzewie przeszukiwania w głąb nawet
wtedy, gdy wierz.chałek u ma w G zarówno krawędzie wychodzące, jak
i wchodzące.
23.3-9. Pokaż, że przeszukiwanie w głąb może być użyte do znajdowania
spójnych składowych w grafie nieskierowanym G oraz że las przeszu.
kiwania w głąb składa się z tylu drzew, ile spójnych składowych ma
G. Dokładniej, pokaż, w jaki sposób 7Jllodyfikować przeszukiwanie
w głąb, żeby każdemu wierzchołkowi v przypisać całkowitoliczbową ety~
kietę cc[v] z przedziału [1, k] taką, że cc[u] = cc[v] wtedy i tylko wtedy,
gdy wierzchołki u oraz v są w tej samej spójnej składowej, a k jest liczbą
spójnych składowych grafu G.
* 23.3-10. Powiemy, że graf skierowany G = (V, E) jest pojedynczo spójny, jeśli
dla wszystkich wier2.eholków u, v E V z faktu u "'l> v wynika, że istnieje co
najwyżej jedna prosta ścieżka z u do v w G. Podaj efektywny algorytm
sprawdzania, czy dany graf skierowany jest pojedynczo spójny.

----------
23.4. Sortowanietopologiczne
W tym podrozdziale pokażemy, w jaki sposób przeszukiwanie w głąb moźe być
użyte do wykonania sortowania topologicznego acyklicznych grafów skiero~
wanych, zwanych z angielskiego dagamit. Sortowanie topologiczne dagu
G = (V, E) polega na uporządkowaniu wszystkich jego wierzchołków w taki
sposób, że jeśli graf G zawiera krawędź (u, v), to w tym porządku wierz.eholek u

-~~-~·
1 Dag jest słowem powstałym z pierwszych liter słów directed acyclic graph; tym zwięzłym
określeniem będziemy się odtąd często posługiwać (przyp. tłum.).

548
23.4. SORTOWANIETOPOLOGICZNE

występuje przed wierzchołkiem v. (Jeśli graf nie jest acykliczny, to takie uporząd­
kowanie nie jest możliwe). Na sortowanie topologiczne grafu można spojrzeć jak
na umieszczanie jego wierzchołków na linii poziomej w taki sposób, żeby wszyst-
kie krawędzie były skierowane od strony lewej do prawej. Sortowanie topolo-
giczne różni się zatem od zwyczajnego sortowania omawianego w części II.
Skierowane grafy acykliczne stosuje się często do określania kolejności
wykonywania czynności. Na rysunku 23. 7 widać przykładowy graf kolejności
wykonywania czynności związanych z porannym ubieraniem się profesora Bu-
msteada. Profesor musi zakładać pewne części garderoby przed innymi (np.
skarpetki przed butami). Inne części garderoby mogą być zakładane w dowol-
nej kolejności (np. skarpetki i spodnie). W dagu z rys. 23.7a krawędź skierowa-
na (u, v) oznacza, że część garderoby u musi zostać założona przed częścią v.
Dowolne uporządkowanie topologiczne tego grafu podaje zatem kolejność za-
kładania składowych ubioru. Na rysunku 23.7b widać posortowany topolo-
gicznie dag z wierzchołkami uporządkowanymi na linii poziomej w taki spo-
sób, że wszystkie krawędzie są skierowane od strony lewej do prawej.
Następujący prosty algorytm służy do sortowania topologicznego danego
dagu G.

TOPOLOGICAL-SORT(G)
I wykonaj DFS(G) w celu obliczenia czasów przetworzenia/[v] dla wszystkich
wierzchołków v
2 wstaw każdy wierzchołek v na początek listy, kiedy tylko zostanie przetwo-
rzony
3 return lista wierzchołków

Na rysunku 23.7b wierzchołki posortowane topologicznie występują w od-


wrotnym porządku względem ich czasów przetworzenia.
Sortowanie topologiczne można wykonać w czasie 0(V + E), ponieważ
przeszukiwanie w głąb zabiera czas 9( V + E), a czas wstawienia każdego z IV]
wierzchołków na początek listy wynosi 0(1).
W celu udowodnienia poprawności powyżsi.ego algorytmu, użyjemy na-
stępującego lematu charakteryzującego acykliczne grafy skierowane.

LEMAT 23.10.
Graf skierowany G jest grafem acyklicznym wtedy i tylko wtedy, gdy przy
przeszukiwaniu w głąb grafu G nie pojawiają się krawędzie powrotne.

DOWÓD
=> Załóżmy, że istnieje krawędź powrotna (u, v). Wtedy wierzchołek v jest
przodkiem wierzchołka u w lesie przeszukiwania w głąb. Zatem w grafie G ist~
nieje ścieżka od v do u, która uzupełniona krawędzią (u, v) daje cykl.

549
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

,)
9/JO

b)
·----

11/1b ,n 3/4

Rys. 23.7. (a) Kiedy profesor Bumstead ma zamiar się ubrać, sortuje topologicznie części swojej
garderoby. Ka7da skierowana krawędź (u, v) oznacza część garderoby u, która musi zostać zało.żo~
na przed częścią 11.Obok każdego wierzchołka są pokazane czasy jego odwiedzenia i przetworzenia
w przeszukiwaniu w głąb. (b) Ten sam graf posortowany topologicznie. Jego wierzchołki są upo-
rządkowane malejąco względem czasów przetworzenia. 2.auważmy, że wszystkie krawędzie skiero-
wane prowadzą od strony lewej do prawej

-= Załóżmy, że graf G zawiera pewien cykl c. Pokażemy, że


w przeszukiwaniu
w głąb grafu G pojawia się krawędź powrotna. Niech v będzie pierwszym
odwiedzanym wierzchołkiem z cyklu ci niech (u, v) będzie krawędzią poprze.
dzającą wierzchołek v w cyk.lu c. W kroku d[v] istnieje ścieżka z v do u zawiera·
jąca tylko białe wierzchołki. Z twierdzenia o białej ścieżce wynika, że wierz·
chołek u staje się potomkiem v w lesie przeszukiwania w głąb. Dlatego (u, v)
jest krawędzią powrotną.

TwlERDZENIE 23.11.
Algorytm TOPOLOGICAL·SORT(G)sortuje topologicznie acykliczny graf skie·
rowany G.

DOWÓD
Załóżmy, że algorytm DFS jest wykonywany dla danego dagu G = (V, E)
w celu policzenia czasów przetworzenia jego wierzchołków. Wystarczy poka·
zać, że dla każdej pary różnych wierzchołków u, v E V, jeśli w grafie G istnieje
krawędź (u, v), to/[v] <f[u]. Rozważmy krawędź (u, v) badaną w procedurze
DFS(G). Kiedy ta krawędź jest badana, wierzchołek v nie może być szary
ponieważ wtedy v byłby przodkiem u i krawędź (u, v) byłaby krawędzią poM

550
23.4. SORTOWANIE TOPOLOGICZNE

wrotną, wbrew lematowi 23.10. Dlatego wierzchołek v musi być albo biały,
albo czarny. Jeśli wierzchołek v jest biały, to zostaje potomkiem wierzchołka u
if[v] <f[u]. Jeśli wierzchołek v jest czarny, to również/(v] </[u]. Stąd dla
każdej krawędzi (u, v) w dagu mamy /[v] <f[u], co kończy dowód twierdzenia .


ZADANIA

23.4-1. Podaj uporządkowanie wierzchołków obliczane w algorytmie TOPOLO-


GICAL-SORTwykonywanym dla dagu z rys. 23.8.

X
'
Rys. 23.8. Dag do ilustracji sortowania topologici:nego

23.4-2. Może istnieć wiele różnych uporządkowań topologicznych danego da-


gu G. w wyniku działania procedury TOPOLOOICAL-SORTotrzymujemy
uporządkowanie wierzchołków w porządku przeciwnym do ich czasów
przetworzenia. Pokaż, że nie wszystkie uporządkowania topologiczne mo-
gą być otrzymane w ten sposób: istnieje graf G taki, że jedno z topologicz-
nych uporządkowań nie może być obliczone przez procedurę TOPOLOGI-
CAL-SORT, niezależnie od tego jaka jest struktura list sąsiedztwa grafu G.
Pokaż także, że istnieje graf, dla którego dwie różne reprezentacje listowe
dają ten sam porządek topologiczny.
23.4-3. Podaj algorytm sprawdzania, czy dany graf nieskierowany G = (V, E)
ma cykl. Twój algorytm powinien działać w czasie O(V) niezależnym
od \El,
23.4-4. Udowodnij następujące twierdzenie lub pokaż, że jest ono niepraw-
dziwe: Jeśli graf skierowany G zawiera cykle, to procedura TOPOLOGI-
CAL-SORT(G)znajduje uporządkowanie wierzchołków minimalizujące licz-
bę „złych" krawędzi, tzn. takich, które są niezgodne ze znalezionym po-
rządkiem.
23.4-5. Inny sposób sortowania topologicznego dagu G polega na znajdowa-
niu wierzcholk.a o stopniu wejściowym O, wypisaniu i usunięciu go z grafu
wraz ze wszystkimi opuszczającymi go krawędziami i powtarzaniu powyż­
szych operacji dopóty, dopóki wszystkie wierzchołki nie zostaną usunięte
---------------------~5=5;
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

z grafu. Wyjaśnij, w jaki sposób moZna :z.aimplementować ten algorytm,


ż.eby otrzymać algorytm sortowania topologicznego działający w czasie
+
O(V E). Co staniesię w tym algorytmie,gdygraf G ma cykl1

23.5. Silniespójneskładowe
Rozważymy teraz klasyczne zastosowanie przeszukiwania w głąb: podział gra-
fu skierowanego na silnie spójne składowe. W tym podrozdziale pokażemy,jak
dokonać takiego podziału za pomocą dwóch przeszukań w głąb. Wiele algoryt-
mów dla grafów skierowanych rozpoczyna się od takiego podziału; przy takim
podejściu istnieje często możliwość podzielenia wyjściowego problemu na pod-
problemy, po jednym dla każdej składowej. Łączenie rozwiązań dla tych pod-
problemów jest wykonywane zazwyczaj zgodnie ze strukturą połączeń między
silnie spójnymi składowymi. Taka struktura może być reprezentowana przez
graf znany jako graf „składowych", który definiujemy w zad. 23.54.
Przypomnijmy (patrz rozdz. 5), ze silnie spójną składową skierowanego
grafu G = (V, EJjest maksymalny zbiór wierzchołków Uf; V taki, że dla każ­
dej pary wierzchołków u i v z U istnieją ścieżki u..-. v oraz v,....u; tzn. wierz-
chołki u i v są osiągalne jeden z drugiego. Na rysunku 23.9 jest poka:rany
stosowny przykład.
W naszym algorytmie znajdowania silnie spójnych składowych grafu
G = (V, EJużywamy transpozycji grafu G, która została zdefiniowana w zad.
23.1-3 jako graf(,~ -(V, I!!), gdzie I!!- {(u, v):(v, u)eE}. To znaczy, J!!
składa się z krawędzi grafu G ze zwrotami zamienionymi na przeciwne. Dla
danej reprezentacji listowej grafu G czas potrzeby na skonstruowanie (ff wy-
nosi O(V +EJ.Warto zauważyć, że grafy G i armają dokładnie te same silnie
spójne składowe: wierzchołki u i v są osiągalne jeden z drugiego w grafie G wte-
dy i tylko wtedy, gdy są osiągalne jeden z drugiego w grafie (ff. Na rysun-
ku 23.9b jest pokazana transpozycja grafu z rys. 23.9a z zacieniowanymi silnie
spójnymi składowymi.
W algorytmie STRONGLY-CONNECTED-COMPONENTS, działającym w cza-
sie liniowym (tzn. w czasie @(V+ E)), obliczamy silnie spójne składowe grafu
skierowanego G = (V, E), stosując dwa razy przeszukiwanie w głąb - raz dla
grafu G i raz dla grafu (ff.

STRONGLY-CONNECTED-COMPONENTS(G)
I wykonaj DFS(G) w celu obliczenia czasu przetworzenia f[u] dla każdego
wierzchołka u
2 oblicz G'
3 wykonaj DFS(cP), ale w głównej pętli procedury DFS rozwaZaj wierzchołki
w kolejności malejących wartości/[uJ (obliczonych w wierszu I)
--------·-·-------------------
552
23.5. SILNIE SPÓJNE SKŁADOWE

(,)

• '
(b)

• g h

(c)

h
Rys. 23.9. (a) Graf skierowany G. Silnie spójne składowe grafu G znajdują się w zacieniowanych
obszarach. Każdy wierzchołek ma przypisane c-zasy odwiedzenia i przetworzenia. Krawędzie drze-
wowe są zaznac-zone ciemnoszarym kolorem. (b) Graf <.P,transpozytja grafu G. Pokazano drzewo
przeszukiwania w głąb obliczane w wierszu 3 algorytmu STRONGLY"CONNECTED-COMPONllNTS.
Krawędzie drzewa są zaznaczone ciemnoszarym kolorem. Każda silnie spójna składowa odpowia-
da jednemu drzewu przeszukiwania w głąb. Wierzchołki b, c, g oraz h, które są zaznaczone naj-
ciemniejszym kolorem, są praprzodkami każdego wierz.chołka w ich silnie spójnych składowych; te
wierzchołki są takie korzeniami drzew przeszukiwania w głąb obliczanymi w przeszukiwaniu
w głąb dla grafu GT. (c) Acykliczny graf składowych G!ICC
otrzymany przez ściągnięcie każdej silnie
spójnej składowej grafu G do pojedynczego wierzchołka.

4 wypisz wierzchołki z każdego drzewa w lesie przeszukiwania w głąb z kroku


3 jako oddzielną silnie spójną składową

Ten prosto wyglądający algorytm wydaje się nie mieć nic wspólnego z sil-
nie spójnymi składowymi. Resztę tego podrozdziału poświęcimy wyjaśnieniu
tajemnic algorytmu STRONGLY-CONNECTED-COMPONENTS i udowodnieniu
jego poprawności. Rozpoczniemy od dwóch pożytecznych obserwacji.

LEMAT 23.12.
Jeśli dwa wierzchołki należą do tej samej silnie spójnej składowej, to żadna
ścieżka między nimi nie zawiera wierzchołków spoza tej silnie spójnej skła­
dowej.
________ ________________________ _
,,, "

553
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

DOWÓD
Niech u i v będą wierzchołkami z tej samej silnie spójnej składowej, Z definicji
silnie spójnej składowej wynika, że istnieją ścieżki z u do v oraz z v do u. Niech
w będzie wierzchołkiem na pewnej ścieżce u.,...w.,...v. Tak więc wierzchołek
w jest osiągalny z wierzchołka u. Ponadto, ponieważ istnieje ścieżka v--+ u,
wiemy, że wierzchołek u jest osiągalny z wierzchołka w ścieżką w .,...v --+ u.
Dlatego u i w znajdują się w tej samej silnie spójnej składowej. Ponieważ wierz-
chołek w został wybrany dowolnie, twierdzenie jest dowiedzione.


TWIERDZENIE23.13.
W dowolnym przeszukiwaniu w głąb wszystkie wierzchołki z tej samej silnie
spójnej składowej są umieszczane w tym samym drzewie przeszukiwania
w głąb.

DOWÓD
Niech r będzie
pierwszym odwiedzanym wierzchołkiem spośród wszystkich
wierzchołków z ustalonej silnie spójnej składowej. Ponieważ r jest pierwszym
odwiedzanym wierzchołkiem, pozostałe wierzchołki w tej silnie spójnej składo­
wej są białe w chwili odwiedzania r. Do każdego wierzchotka z rozważanej
silnie spójnej składowej prowadzi ścieżka o początku w r. Ponieważ takie ścież­
ki zawierają tylko wierzchołki z tej składowej (lemat 23.12), wszystkie wierz-
chotki na tych ścieżkach są białe. Stąd i z twierdzenia o białej ścieżce wynika,
że każdy wierzchołek rozważanej silnie spójnej składowej staje się potomkiem
wierzchotka r w drzewie przeszukiwania w głąb.

W pozostałej części
tego podrozdziału oznaczenia d[u] i f[u] odnoszą się
do czasów odwiedzenia i przetworzenia, obliczanych w pierwszym przeszuki-
waniu w głąb (wiersz 1 procedury STRONGLY-CONNECTED-CoMPONEN
Podobnie oznaczenie u.,...v odnosi się do ścieżki w grafie G, a nie w if.
Żeby udowodnić, że algorytm STRONGLY-CONNECTED-COMPONENT
poprawny, wprowadzimy pojęcie praprzodka. Praprzodkiem tj,(u) wierzchołka
u nazywamy wierzchołek w osiągalny z u o największym czasie przetworzenia
w przeszukiwaniu w głąb z wiersza I. Innymi słowy

tj,(u) to taki wierzchołek w, że u.,...w i wartość /[w] jest największa

Zauważmy, że możliwe jest tj,(u) = u, ponieważ u jest osiągalny sam z siebie


i stąd

f[u] <s/[Ql(u)] (23.2)

554
23.5. SILNIE SPÓJNE SKŁADOWE

Z następującego rozumowania wynika, że = cj,(u).Dla dowolnych wie-


tp(cJ,(u))
rzchołków u, v E V

z u~ v wynika/[,p(v)] .;/[</>(u)] (23.3)

ponieważ {w: v ,.,..w} s { w: u ---i, w} i praprzodek u ma największy czas przetwo-


rzenia ze wszystkich wierzchołków osiągalnych z u. Ponieważ tp(u)jest osiągal­
ny z wierzchołka u, ze wzoru (23.3) wynika, że/[tp(cj,(u))] ~f[tp(u)]. Z nierów-
ności (23.2) mamy także f[,p(u)] .;f[<J,(<J,(u))]. -f[<J,(u)].
A zatem /[</>(</>(u))]
Ponieważ dwa różne wierzchołki mają różne czasy przetworzenia, otrzymuje-
- <J,(u).
my </>(</>(u))
Jak wkrótce zobaczymy, każda silnie spójna składowa ma jeden wierz-
chołek, który jest praprzodkiem każdego wierzchołka z tej składowej. Ten
praprzodek jest wierzchołkiem „reprezentującym" silnie spójną składową.
W przeszukiwaniu w głąb jest on pierwszym odwiedzanym i ostatnim prze-
tworzonym wierzchołkiem z tej składowej. W przeszukiwaniu w głąb grafu GT
reprezentant silnie spójnej składowej jest korzeniem drzewa przeszukiwania
w głąb. Teraz udowodnimy te własności.
Pierwsze twierdzenie tłumaczy nazywanie tp(u)praprzodkiem wierzchołka u.

TwIERDZENIE 23.14.
Niech G = (V, E) będzie grafem skierowanym. Wówczas w każdym przeszuki-
waniu w głąb grafu G praprzodek tp(u) dowolnego wierzchołka ue V jest przo-
dkiem wierzchołka u.

DOWÓD
Jeśli tp(u) = u, to twierdzenie jest oczywiście prawdziwe. Dla tp(u) ~ u rozważ­
my kolory wierzchołków w kroku d[u]. Jeśli <J,(u)jest czarny, to /[<J,(u)]<f[u]
- otrzymujemy sprzeczność z nierównością (23.2). Jeśli cJ,(u)jest szary, to jest
on przodkiem wierzchołka u i twierdzenie jest udowodnione.
Pozostaje więc udowodnić, że tp(u) nie jest biały. W zależności od kolorów
pośrednich wierzchołków na ścieżce z u do cj,(u) (jeśli takie są) zachodzą dwa
przypadki.

1. Jeśli każdy pośredni wierzchołekjest biały, to z twierdzenia o białej ścieżce


wynika, że tp(u) zostaje potomkiem wierzchołka u. Ale wtedy /[tp(u)] </[u],
co przeczy nierówności (23.2).
2. Jeśli pewien pośredni wierzchołek nie jest biały, to niech t będzie ostatnim
niebiałym wierzchołkiem na ścieżce z u do cJ,(u).Wtedy wierzchołek t musi
być szary, ponieważ nigdy nie istnieje krawędź od wierzchołka czarnego do
wierzchołka białego, a następnik t jest biały. Ale wtedy istnieje ścieżka od
t do tp(u) złożona z białych wierzchołków. Z twierdzenia o białej ścieżce

555
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

wynika, że i:j,(u) jest potomkiem wierzchołka t. Stąd otrzymujemy, że


f[t] > f[tp(u)]. Przeczy to naszemu wyborowi rj,(u), ponieważ istnieje ścieżka
z wierzchołka u do t.

WNIOSEK23.15.

W każ.dym przeszukiwaniu w głąb grafu skierowanego G = (V, E) wierzchołki
u i tp(u) leżą w tej samej silnie spójnej składowej dla każdego uE V.

DOWÓD
Z definicji praprzodka mamy u,... c/>(u),a ponieważ c/>(u)
jest przodkiem u,
więc i:j,(u),...u.

Następujące twierdzenie określa silniejsze związki między praprzodkami



a silnie spójnymi składowymi.

TWIERDZENIE 23.16.
W grafie skierowanym G = (V, E) dwa wierzchołki leżą w tej samej silnie
spójnej składowej wtedy i tylko wtedy, gdy mają tego samego praprzodka
w przeszukiwaniu w głąb grafu G.

DOWÓD
-=> Załóżmy, że wierzchołki u i v są w tej samej silnie spójnej składowej. Ponie-
waż istnieją ścieżki między wierzchołkami u i v w obu kierunkach, więc każdy
wierzchołek osiągalny z v jest osiągalny z u i odwrotnie. Zatem z defrnicji
praprzodka wnioskujemy, że c/>(u) = rj,(v).
= Załóżmy, że cJ>(u)= tp(v). Z wniosku 23.15 mamy, że wierzchołek u jest
w tej samej silnie spójnej składowej co cJ>(u),a wierzchołek v jest w tej samej
silnie spójnej składowej co cJ>(v).
Dlatego wierzchołki u i v są w tej samej silnie
spójnej składowej.

Twierdzenie 23.16, pozwala lepiej zrozumieć algorytm STRONGLY-CONNE-
CTED-COMPONENTS.Silnie spójne składowe są zbiorami wierzchołków o tym
samym praprzodku. Ponadto z twierdzenia 23.14 i twierdzenia o nawiasach
(tw. 23.6) wynika, że podczas przeszukiwania w głąb, w wierszu 1 procedury
STRONGLY-CONNECTEO-COMPONENTS, praprzodek jest zarówno pierwszym
odwiedzonym, jak i ostatnim przetworzonym w silnie spójnej składowej, do
której należy.
Żeby zrozumieć, dlaczego w wierszu 3 procedury STRONGLY-CONNECT-
ED-COMPONENTSjest wykonywane przeszukiwanie w głąb dla grafu <P,roz-
ważmy wierzchołek r z największym czasem przetworzenia obliczonym w prze-
szukiwaniu w głąb w wierszu 1. Z definicji praprzodka wynika, że wierzcho-

556
23.5. SILNIE SPÓJNE SKŁADOWE

łek r musi byćpraprzodkiem. Jest tak dlatego, gdyż r jest sam swoim pra-
przodkiem (jest sam z siebie osiągalny) i żaden inny wierzchołek w grafie nie
ma większego czasu przetworLenia. Jakie są inne wierzchołki w silnie spójnej
składowej zawierającej wierzchołek r? Są nimi wierzchołki, dla których r jest
praprzodkiem. - tzn. takie, dla których r jest osiągalny, ale nie jest osiągalny
żaden inny wierzchołek z czasem przetworzenia większym od f[r]. Ale ponie-
waż wierzchołek r ma największy czas przetworzenia ze wszystkich wierzchoł­
ków w grafie G, silnie spójna składowa zawierająca r składa się po prostu
z tych wierzchołków, z których można osiągnąć r. Równoważnie, silnie spójna
składowa zawierająca wierzchołek r składa się z tych wierzchołków, które są
osiągalne z r w grafie (łf. Wobec tego podczas przeszukiwania w głąb w wier-
szu 3 są znajdowane wszystkie wierzchołki w silnie spójnej składowej zawiera-
jącej r i są kolorowane na czarno. (Zbiór ten można by znaleźć równie łatwo
za pomocą pr7A!Szukiwaniawszerz lub jakiegokolwiek przeszukiwania zastoso-
wanego do znajdowania osiągalnych wierzchołków).
Po zakończeniu przeszukiwania w głąb w wierszu 3, identyfikującego silnie
spójną składową zawierającą wierzchołek r, przeszukiwanie w głąb jest kon-
tynuowane z wierzchołka r' z największym c:zasem przetworzenia spośród
wszystkich wierzchołków spoza silnie spójnej składowej, do której należy r.
Wierzchołek r' musi być swoim praprzodkiem, ponieważ żadnego wierzchołka
z większym czasem przetworzenia nie można z niego osiągnąć (w przeciwnym
razie r' zostałby włączony do silnie spójnej składowej wierzchołka r). Rozumu-
jąc podobnie, każdy wierzchołek, z którego jest osiągalny r', który nie jest już
czarny, musi należeć do tej samej silnie spójnej składowej co r'. Zatem, jeśli
przeszukiwanie w głąb w wierszu 3 jest kontynuowane, to każdy wierzchołek
z silnie spójnej składowej zawierającej r' zostaje zidentyfikowany i pokoloro-
wany na czarno w wyniku przeszukania z wierzchołka r' w grafie (łf.
W ten sposób przy przeszukiwaniu w głąb w wierszu 3 silnie spójne skła­
dowe są „wyłuskiwane" jedna po drugiej. Każda składowa jest identyfikowana
w wlierszu 7 procedury DFS, w wyniku wywołania DFS-VISIT, z praprzod-
kiem tej składowej jako argumentem. W wyniku wywołań rekurencyjnych we-
wnątrz DFS-VISIT każdy wierzchołek składowej jest na koniec kolorowany na
c:zarno. Gdy DFS-V1SIT powraca do DFS, cała składowa jest pokolorowana
na czarno i w ten sposób „wyłuskana". Następnie DFS znajduje wierzchołek
o największym czasie przetworzenia spośród wszystkich wierzchołków, które
nie są pokolorowane na czarno. Ten wierzchołek jest praprzodkiem innej skła­
dowej i proces jest kontynuowany.
Następujące twierdzenie formalizuje powyższe rozważania.

TwlERDZENIE 23.17.
Algorytm STRONGLY-CONNECTED-COMPONENTS(G)
poprawnie oblicza silnie
spójne składowe grafu skierowanego G.

557
ROZDZIAŁ 23, PODSTAWOWE ALGORYTMY GRAFOWE

DOWÓD
Udowodnimy przez indukcję względem liczby drzew przeszukiwania w głąb
znajdowanych w przeszukiwaniu grafu cP, że wierzchołki każdego drzewa
tworzą silnie spójną składową. W kroku indukcyjnym wykażemy, że drzewo
formowane w przeszukiwaniu w głąb grafu (1f wyznacza silnie spójną składo­
wą przy założeniu, że wszystkie poprzednie uformowane drzewa wyznaczały
silnie spójne składowe. Krok podstawowy indukcji jest oczywisty, ponieważ
pierwsze formowane drzewo nie ma poprzedników i jego wierzchołki tworzą
silnie spójną składową.
Rozważmy drzewo przeszukiwania w głąb To korzeniu w r obliczane przy
przeszukiwaniu grafu cP.Niech C(r) oznacza zbiór wierzchołków, dla których
praprzodkiem jest wierzchołek r:

C(r) ={,eV: ,p(,) = r)


Udowodnimy, że wierzchołek u jest umieszczany w drzewie T wtedy i tylko
wtedy, gdy ue C(r).
= Z twierdzenia 23.13 wynika, że każdy wierzchołek z C(r) jest umieszczany
w tym samym drzewie przeszukiwania w głąb. Ponieważ reC(r) i r jest korze-
niem drzewa T, każdy element z C(r) jest umieszczany w drzewie T.
=> Pokażemy, że żaden wierzchołek w, dla którego /[q',(w)] > f[r] lub
f[ tJ,(w)] </[r], nie jest umieszczany w drzewie T. Rozważmy te dwa przypadki
oddzielnie. Z założenia indukcyjnego żaden wierzchołek w, taki że
f[ q',(w)] > f[r], nie jest umieszczany w drzewie T. Jest tak dlatego, bo w chwili,
w której r jest wybierany, w znajduje się już w drzewie o korzeniu (j, (w). Żaden
wierzchołek w, taki że/[ (j, (w)] <f[r], nie może być 1unieszczony w drzewie T,
ponieważ to implikowałoby w.....,. r. W ten sposób ze wzoru (23.3) i z własności,
że r = ,f,(r), otrzymujemy/[ ,f,(w)] ;, /[ ,f,(r)] = /[r], co przeczy nierówności
/[,f,(w)] </[r].
Dlatego drzewo T zawiera tylko te wierzchołki u, dla których q,(u) = r.
Stąd wynika, że zbiór wierzchołków drzewa T jest równy silnie spójnej składo­
wej C(r), co kończy dowód indukcyjny.

ZADANIA

23.S-1. O ile może zmienić się liczba silnie spójnych składowych w grafie w wy-
niku dodania nowej krawędzi?
23.S-2. Przedstaw działanie procedury STRONGLY-CONNECTED-COMPO-
NENTS dla grafu z rys. 23 .6. W szczególności pokaż czasy przetworzenia
obliczane w wierszu 1 oraz las formowany w wierszu 3. Załóż, że w pętli
z wierszach 5-7 procedury DFS wierzchołki są rozważane w porządku
alfabetycznym i że listy sąsiedztwa są uporządkowane alfabetycznie,

558
PROBLEMY

23.5-3. Profesor Deaver twierdzi, że


algorytm dla silnie spójnych składowych
można uprościć, wykonując drugie przeszukiwanie w głąb w grafie wyj-
ściowym (zamiast w jego transpozycji) i przeglądając wier:zcholki w po-
rządku rosnącym względem czasów prretworzenia. Czy profesor ma rację?
23.5-4. Oznaczmy przez Gscc = (Vscc, Esc.') graf składowych grafu G =
= ( V, E), gdzie vscczawiera jeden wierzchołek dla każdej silnie spójnej
składowej grafu G, a Esce zawiera krawędź (u, v), jeśli istnieje krawędź
skierowana z pewnego wier:zchołk.a z silnie spójnej składowej grafu G od-
powiadającej u do wierzchołka w silnie spójnej składowej G odpowiada-
jącej v. Na rysunku 23.9c widać przykład takiego grafu. Udowodnij, 7,e
G 5cc jest dagiem.
23.5-5. Podaj algorytm obliczania grafu składowych dla danego grafu sk:iero~
wanego G = (V, E), działający w czasie O(V + E). Zapewnij, żeby Twój
algorytm tworzył co najwyżej jedną krawędź między dwoma wierzchoł­
kami grafu składowych.
23.S-6. Wyjaśnij, w jaki sposób dla danego grafu skierowanego G = (V, E)
zbudować graf G' = (V, E) taki, że (a) G' ma te same silnie spójne składo­
we co G, (b) G' ma ten sam graf składowych co G oraz (c) E jest tak mały,
jak tylko jest to możliwe. Opisz szybki algorytm obliczania grafu G'.
23.5-7. O grafie skierowanym G = (V, E) mówi się, że jest częściowo spójny,
jeśli dla każdych dwóch wier:zchołków u, v E V mamy u ,....v lub v ,....u. Po-
daj efektywny algorytm sprawdzania, czy graf G jest częściowo spójny.
Udowodnij, że Twój algorytm działa poprawnie i przeanalizuj czas jego
działania.

Problemy
~1. Klasyfikowanie krawędzi za pomocą przeszukiwania wszerz
Przy przeszukiwaniu w głąb krawędzie grafu są dzielone na drzewowe, powrot-
ne, w przód i poprzeczne. Przeszukiwanie wszerz może też zostać użyte do
podziału krawędzi osiągalnych ze źródła przeszukiwania na te cztery kategorie.

(a) Udowodnij, że przeszukiwanie wszerz w grafie nieskierowanym ma nastę-


pujące własności:

(1) nie istnieją krawędzie powrotne i w przód;


(2) dla każdej krawędzi drzewowej (u, v) zachodzi d[v] - d[u] + I;
(3) dla każdej krawędzi poprzecznej (u, v) zachodzi d[v] = d[u] lub
d[v] - d[u] + I.

(b) Udowodnij, że przeszukiwanie wszerz w grafie skierowanym ma następują­


ce własności:

559
ROZDZIAŁ 23. PODSTAWOWE ALGORYTMY GRAFOWE

(I) nie istnieją krawędzie w przód;


(2) dla każdej krawędzi drzewowej (u, v) zachodzi d[v] - d[u] + I;
(3) dla każdej krawędzi poprzecznej (u, v) zachodzi d[v] ,,; d[u] + I
(4) dla każdej krawędzi powrotnej (u, v) zachodzi O ,,; d[v] < d[u].

23,.2. Punkty artykulacji,mosty i dwuspójneskładowe


Niech G = (V, E) będzie spójnym grafem nieskierowanym. Punktemartykula-
cji grafu G jest każdy wierzchołek, którego usunięcie „rozspójnia" G. Mostem
w grafie G jest każda krawędź, której usunięcie „rozspójnia" G. Dwuspójną
składową grafu G nazywamy maksymalny zbiór krawędzi, taki że każ.de dwie
krawędzie z tego zbioru leżą na wspólnym cyklu prostym. Rysunek 23.10
ilustruje te definicje. Punk.ty artykulacji, mosty i dwuspójne składowe można
wyznaczyć, stosując przeszukiwanie w głąb. Niech G,.= (V, EJ będzie drze-
wem przeszukiwania w głąb w grafie G.

Rys. 23.10. Punkly artykulacji, mosly i dwuspójne &k.lerlowew spójnym grafie nieskierowanym uży·
wanym do ilustracji problemu 23-2. Punkly artykulacji i mosty są ciemnoszare. Dwu&pójnymi
&kład owymi są zbiory krawędzi w jasnoszarych obszarach. Wewnątrz jasnoszarych obszarów znaj-
dują się numery bee

(a) Udowodnij, że korzeń drzewa G„ jest punktem artykulacji w grafie G wte-


dy i tylko wtedy, gdy ma on co najmniej dwóch synów w drzewie G,,..
(b) Niech v będzie wierzchołkiem, który nie jest korzeniem w drzewie G,..Udo-
wodnij, że wierzchołek v jest punktem artykulacji w grafie G wtedy i tylko
wtedy, gdy nie istnieje krawędź powrotna (u, w), taka że wierzchołek u jest
potomkiem v i w jest właściwym przodkiem v w drzewie G,..
(c) Niech

d[v],
low[v] = min {
{d[w]: (u, w) jest krawędzią powrotną dla pewnego
potomka u wierzchołka v}

Pokaż,jak w czasie O(E) obliczyć /ow[v]dla wszystkich wierzchołków vE V.


(d) Pokaż, jak w czasie O(E) obliczyć punkty artykulacji,

560
UWAGI DO ROZDZIAŁU

(e) Udowodnij, że krawędź z grafu G jest mostem wtedy i tylko wtedy, gdy nie
leży na żadnym cyklu prostym w grafie G.
(f) Pokaż, jak obliczyć wszystkie mosty w grafie G w czasie O(E).
(g) Udowodnij, że dwuspójne składowe grafu G tworzą podział zbioru tych
krawędzi, które nie są mostami w grafie G.
(h) Podaj algorytm działający w _czasie O(E), który służy do etykietowania
każdej krawędzi e grafu G dodatnią liczbą całkowitą bcc[e] tak, że
bcc[e]= bcc[e1 wtedy i tylko wtedy, gdy e i e' są w tej samej dwuspójnej
składowej.

23-3. Cykl Eulera


Cyklem Eulera w spójnym grafie skierowanym G = (V, E) nazywamy każdy
cykl, który przechodzi przez każdą krawędź z grafu G dokładnie raz, chociaż
ten sam wierzchołek może być odwiedzany więcej niż raz.

(a) Pokaź, że graf G ma cykl Eulera wtedy i tylko wtedy, gdy

in-degree(v) = out-degree(v)
dla każdego wierzchołka v E V.
(b) Opisz algorytm, który w czasie O(E} znajduje w grafie G cykl Eulera, o ile
taki cykl istnieje. (Wskazówka: Łącz cykle rozłączne krawędziowa).

Uwagido rozdziału

Książki Evena [65] i Tarjana [188] są znakomitym źródłem infonnacji o al-


gorytmach grafowych.
Przeszukiwanie wszerz zostało odkryte przez Moore'a [150] w kontekście
znajdowania ścieżek w labiryntach. Lee [134] od.kryl niezależnie ten sam al-
gorytm, badając zagadnienie łączenia elementów w układzie scalonym.
Hopcroft i Tarjan [102] byli zwolennik.ami użycia list sąsiedztwa (zamiast
macierzy sąsiedztwa) do reprezentowania grafów rzadkich. Byli też pierwszy-
mi, którzy dostrzegli algorytmiczne znaczenie przeszukiwania w głąb. Przeszu-
kiwanie w głąb było powszechnie używane od późnych lat pięćdziesiątych,
szczególnie w sztucznej inteligencji.
Tarjan [185] podał pierwszy liniowy algorytm znajdowania silnie spójnych
składowych. Algorytm obliczania silnie spójnych składowych z podro7.dz. 23.5
został zaadaptowany z książki Abo, Hopcrofta, Ullmana [5], którzy przypisują
ten algorytm S.R. Kosaraju i M. Sharirowi. Knuth [121] był pierwszym, który
podał liniowy algorytm sortowania topologicznego.
Rozdział 24

Minimalnedrzewarozpinające

Przy projektowaniu układów elektronicznych często końcówki wielu elemen-


tów składowych należy uczynić elektrycznie równoważnymi, łącząc je przewo-
dami. Do połączenia zbioru n końcówek możemy użyć n - I przewodów,
z których każdy łączy dwie końcówki. Ze wszystkich możliwych sposobów
połączeń najbardziej pożądany jest zazwyczaj ten, który minimalizuje łączną
długość użytych przewodów.
Problem łąC'lenia końcówek można modelować za pomocą spójnego grafu
nieskierowanego G = (V, E), w którym V jest zbiorem końcówek, a E jest
zbiorem możliwych połączeń między parami końcówek. Z każdą krawędzią
(u, v)eE jest związana waga w(u, v) określająca koszt (długość potrzebnego
przewodu) połączenia wierzchołków u i v. Wówczas naszym celem jest znale-
zienie acyklicznego podzbioru Tc E, który łączy wszystkie wierzchołki i któ-
rego łączna waga

w(T) - L w(u, v)
(11,v)eT

jest najmniejsza.
Ponieważ T jest acykliczny i łączy wszystkie wierzchołki, więc jest drze~
wem. Drzewo T „rozpina" graf G, dlatego jest nazywane dnewem. rozpinają­
cym. Problem wyznaczania drzewa T nazywamy problemem minimalnego drze-
wa rozpinającego 11, Na rysunku 24.1 widać przykładowy graf spójny i jego
minimalne drzewo rozpinające.

11 Zwrot „minimalne drzewo rozpinające" jest skróconą wersją zwrotu „drzewo rozpinające
o minimalnej wadze". Naszym celem nie jest minimalizacja liczby krawędzi w T, ponieważ na
podstawie tw. 5.2, każde drzewo rozpinające ma dokładnie !VI- I krawędzi.

562
24.1. ROZRASTANIE SIĘ MINIMALNEGO DRZEWA ROZPINAJĄCEGO

Rys. 24.1. Minimalne drzewo rozpinające w grafie spójnym. Obok krawędzi znajdują się ich wagi.
Krawędzie minimalnego drzewa rozpinającego są zacieniowane. Lą.cma waga przedstawionego
drzewa wynosi 37. To drzewo nie jest jedynym minimalnym drzewem rozpinającym: w wyniku
zastąpienia krawędzi (b, c) przez krawędź (a, h) otrzymujemy inne drzewo o wadze 37

W tym rozdziale zbadamy dwa algorytmy służące do rozwiązywania prob-


lemu minimalnego drzewa rozpinającego: algorytm K.ruskala i algorytm Pri-
ma. Stosując zwykłe kopce binarne, każdy z tych algorytmów można zaimple-
mentować w taki sposób, żeby działał w czasie O(Elg V). Wykorzystując kop-
ce Fibonacciego, można usprawnić algorytm Prima tak, żeby działał w czasie
O(E + Vlg V). Jest to pewne ulepszenie, jeżeli IVIjest dużo mniejsze od IEI·
Oba wspomniane algorytmy są przykładami zachłannych algorytmów op-
tymalizacyjnych. W każdym kroku takiego algorytmu musimy dokonać jed-
nego z kilku możliwych wyborów. Stosując strategię zachłanną, dokonujemy
wyboru, który jest w danej chwili najlepszy. Taka strategia ogólnie nie gwaran-
tuje znalezienia rozwiązania optymalnego. Dla problemu minimalnego drzewa
rozpinającego możemy jednak udowodnić, że stosując pewne strategie zachłan­
ne, otrzymamy drzewo rozpinające o minimalnej wadze. Strategie zachłanne
omawialiśmy dokładnie w rozdz. 17. Chociaż niniejszy ro7.d.ział można czytać
niezależnie od rozdz. 17, metody zachłanne omawiane tutaj są klasycznym
zastosowaniem wprowadzonej tam teorii.
W podrozdziale 24.1 przedstawimy pewien schemat obliczania minimal-
nego drzewa rozpinającego, w którym drzewo rozrasta się przez dodawanie
pojedynczych krawędzi. W podrozdziale 24.2 podamy dwa sposoby implemen-
tacji tego schematu. Pierwszy algorytm, pochodzący od Kruskala, jest podob-
ny do algorytmu dla spójnych składowych z podrozdz. 22.1, Drugi algorytm,
pochodzący od Prima, jest podobny do algorytmu Dijkstry dla problemu naj-
krótszych ścieżek (patrz podrozdz. 25.2).

24.1. Rozrastaniesię minimalnegodrzewarozpinającego


Załóżmy, że dany jest spójny graf nieskierowany G = (V, E) z f11nkcją wagową
w: E-+ R i chcemy znaleźć w G minimalne drzewo rozpinające. W obu algoryt-
mach rozważanych w tym rozdziale jest stosowana strategia zachłanna, cho-
ciaż sposoby jej użycia są różne.

563

ROZDZIAŁ 24. MINIMALNE DRZEWA ROZPINAJĄCE

Strategia zachłanna jest zawarta w algorytmie GENERIC-MST, w którym


minimalne drzewo rozpinające rozrasta się w wyniku dodawania pojedynczych
krawędzi. Podczas wykonywania algorytmu jest utrzymywany zbiór A, który
zawsze jest podzbiorem pewnego minimalnego drzewa rozpinającego. W każ­
dym kroku algorytmu jest wyznaczana krawędź (u, v), którą można dodać do
A bez naruszenia tego niezmiennika, tzn. A u {(u, v)} jest także podzbiorem
minimalnego drzewa rozpinającego. Taką krawędź nazywamy krawędzią bez-
pieczną dla A, ponieważ można dodać ją bezpiecznie do A bez naruszenia
niezmiennika.

GENERIC-M!IT(G, w)
1 A+--0
2 wbile A nie tworzy drzewa rozpinającego
3 do znajdź krawędź (u, v), która jest bezpieczna dla A
4 A-Au{(u,v))
5 return A

Zauważmy, że po wykonaniu wiersza 1 nieztoieonik, że A jest podzbiorem


minimalnego drzewa rozpinającego, jest w oczywisty sposób spełniony. Pętla
w wierszach 24 :zachowuje ten niezmiennik. Dlatego zbiór A, zwracany w wier-
szu 5, musi być minimalnym drzewem rozpinającym. Trudnym do wykonania
fragmentem schematu jest oczywiście znajdowanie krawędzi bezpiecznej w wier-
szu 3. Tak.a krawędź musi istnieć, ponieważ niez1uiennik gwarantuje, że w chwili
wykonywania wiersza 3 istnieje drzewo rozpinające T, którego A jest podzbio-
rem (A c T). Każda krawędź (u, v)e Ttaka, że (u, v)f A jest bezpiem.na dla A.
W dalszej części tego podrozdziału podamy pewną regułę (tw. 24.1) na
rozpoznawanie krawędzi bezpiecznych. W następnym podrozdziale opiszemy
dwa algorytmy, które wykorzystują tę regułę do efektywnego znajdowania kra-
wędzi bezpiecznych.
Na początek podamy kilka defmitji. Przekrojem (S, V - S) grafu nieskie-
rowanego G = (V, E) nazywamy podział V na zbiory Si V - S. Rysunek 24.2
ilustruje to pojęcie. Mówimy, że krawędź (u, v)eE knyżuje się z przekrojem
(S, V - S), jeśli jeden z jej końców należy do S, a drugi do V - S. Powiemy, że
przekrój uwzględnia zbiór krawędzi A, jeśli żadna z krawędzi z A nie krzyżuje
się z tym przekrojem. Krawędź krzyżująca się z przekrojem jest krawędzią
lekką, jeśli jej waga jest najmniejsza spośród wszytkich wag krawędzi krzyżują­
cych się z tym przekrojem. Zauważmy, że w przypadku równych wag może być
więcej niż jedna krawędź lekka krzyżująca się z przekrojem. Uogólniając, kra-
wędź jest krawędzią lekką o danej własności, jeśli jej waga jest najmniejsza.
spośród wag wszystkich krawędzi o tej własności.
Następujące twierdzenie stanowi regułę na rozpoznawanie krawędzi bez-
piecznych.

564
24.1. ROZRASTANIE SIĘ MINIMALNEGO DRZEWA ROZPINAJĄCEGO

2
st Is
V-Sj jV-S

(•)
--
S V-S
(b)

Rys. 24.2. Dwa sposoby spojrzenia na przekrój (S, Jl - S) grafu z rys. 24.1. (a) Wierzchołki ze zbioru
Ssą cza.me, a te ze zbioru Jl - Sbiałe. Krawędziami krzyżującymi się z przekrojem są te, które łączą
wierzchołki białe z wierzchołkami czarnymi. Krawędź (d, c) jest jedyną krawędzią lekką krzyżującą
się z przekrojem. Podzbiór krawędzi A jest zacieniowany; zauważmy, że przekrój (S, Y - S)
uwzględnia A, ponieważ żadna krawędź z A. nie krzyżuje się z tym przekrojem. (b) Ten sam graf
z wierzchołkami ze zbioru S na lewo, a z wierzchołkami ze zbioru Jl - S na prawo. Krawędź
krzyżuje się z przekrojem, jeśli łączy wierzchołek z lewej strony z wierzchołkiem z prawej strony

TwIERDZENIE 24.1.
Niech G = (V, E) będzie spójnym grafem nieskierowanym z funkcją wagową
w o wartościach rzeczywistych określoną na E. Niech A będzie podzbiorem
E zawartym w pewnym minimalnym drzewie rozpinającym grafu G, niech
(S, V - S) będzie dowolnym przekrojem G uwzględniającym A i niech (u, v)
będzie krawędzią lekką krzyżującą się z (S, V - S). Wtedy krawędź (u, v) jest
bezpieczna dla A.

Dowon
Niech T będzie dowolnym minimalnym drzewem rozpinającym zawierającym
A i załóżmy, że Tnie zawiera krawędzi lekkiej (u, v). (Jeśli T zawiera (u, v), to
dowód jest zakończony). Stosując metodę „wycinania i wklejania", zbudujemy
inne minimalne drzewo rozpinające T' zawierające zbiór A u {(u, v)}. Tym
samym pokażemy, że (u, v) jest krawędzią bezpieczną dla A.
Jak widać na rys. 24.3, krawędź (u, v) oraz krawędzie ze ścieżki p z u do
v w drzewie T tworzą cykl. Ponieważ u i v znajdują się po przeciwnych stro-
nach przekroju (S, V - S), istnieje co najmniej jedna krawędź w T ze ścieżki p
krzyżująca się z tym przekrojem. Niech (x, y) będzie dowolną z tak.ich kra-

565
ROZDZIAŁ 24. MINIMALNE DRZEWA ROZPINAJĄCE

wędzi. Ponieważ rozważany przekrój uwzględnia A, krawędź (x, y) nie należy


do A. Krawędź (x, y) leży na jedynej ścieżce w T z u do v. Usuwając krawędź
(x, y), rozbija się drzewo T na dwie składowe. Dodając krawędź (u, v), ponow-
nie się je łączy i tworzy nowe drzewo rozpinające T' = T- {(x, y)} u {(u,v)}.

''
'
'
'
'

Rys. 24.3. Dowód twierdzenia 24.L Wierzchołki w zbiorze Ssą czarne, a wierwholki w V-Ssą
białe. Pokazane są krawędzie minimalnego drzewa rozpinającego T, ale nie ma pozostałych krawę­
dzi z grafu G. Kra.wędzie z.e zbioru A są zacieniowane. Krawędź (u, v) jest krawędzią lekką
krzyżującą się z pnekrojem (S, V- S). Krawędź (x, y) jest krawędzią na jedynej ścieżcep z u do
v w drzewie T. Minimalne drz.ewo rozpinają.ce T' zawierające (u, v) powstaje z T w wyniku
usunięcia krawędzi (x, y) i dodania krawędzi (u, v)

Teraz pokażemy, że T' jest minimalnym drzewem rozpinającym. Ponieważ


(u, v) jest krawędzią lekką krzyżującą się z (S, V - S), a krawędź (x, y) także
krzyżuje się z tym przekrojem, w(u, v) ~ w(x, y). Dlatego

w(T') - w(T) - w(x, y) + w(u, v)


.; w(T)
Ale T jest minimalnym drzewem rozpinającym, tak więc w(T) ~ w(T'); a za-
tem T' musi być tak.że minimalnym drzewem rozpinającym.
Pozostaje pokazać, że (u, v) jest rzeczywiście krawędzią bezpieczną dla
A. Mamy Ac T', ponieważ Ac Ti (x, y),f;A; zatem A u {(u, v)} c T'. Tak
więc, ponieważ T' jest minimalnym drzewem rozpinającym, (u, v) jest bez-
pieczna dla A.

Twierdzenie 24.l ułatwia zrozwnienie zachowania się algorytmu GENERIC-
-MST na spójnym grafie G = (V, E). W trakcie wykonywania algorytmu
zbiór A jest zawsze acykliczny; w przeciwnym razie minimalne drzewo roz-

566
24.1. ROZRASTANIE SIĘ MINIMALNEGO DRZEWA ROZPINAJĄCEGO

pinające zawierające A miałoby


cykl - sprzeczność. W każdej chwili działania
algorytmu graf GA = ( V, A) jest lasem, a każda spójna składowa GA jest drze~
wem. (Pewne drzewa mogą składać się tylko z jednego wierzchołka np. na
początku działania algorytmu: A jest pusty, a las zawiera IVIjednowierzchoł­
kowych drzew). Ponadto, ponieważ A u {(u, v)} musi być acykliczny, każda
bezpieczna krawędź (u, v) dla A łączy różne składowe z G.t·
Pętla w wierszach 2-4 procedury GENERIC-MST jest wykonywana IVI-1
razy. W każdej iteracji jest znajdowana kolejna krawędź z IV I - 1 krawędzi
minimalnego drzewa rozpinającego. Początkowo, gdy A= 0, graf GA składa
się z IVI drzew. W każdej iteracji liczba drzew maleje o I. Kiedy las zawiera
tylko jedno drzewo, algorytm kończy działanie.
W obu algorytmach z podrozdz. 24.2 ma zastosowanie następujący wnio-
sek z twierdzenia 24.1.

WNIOSEK 24.2.
Niech G = (V, E) będzie spójnym grafem nieskierowanym z funkcją wagową w
o wartościach rzeczywistych określoną na E. Niech A będzie podzbiorem E
zawartym w pewnym minimalnym drzewie rozpinającym grafu G i niech C
będzie spójną składową (drzewem) w lesie GA = (V, A). Jeśli (u, v) jest krawę­
dzią lekką łączącą C z pewną inną składową w GA• to krawędź (u, v) jest
bezpieczna dla A.

DOWÓD
Przekrój (C, V - C) uwzględnia A i dlatego (u, v) jest krawędzią lekką dla tego
przekroju. +
ZADANIA
24.1-1. Niech (u, v) będzie krawędzią o najmniejszej wadze w grafie G. Pokaż,
że krawędź (u, v) należy do pewnego minimalnego drzewa rozpinającego
grafu G.
24.1-2. Profesor Sabatier przypuszcza, że następujące twierdzenie - odwrotne
do twierdzenia 24.1 -jest prawdziwe. Niech G = (V, E) będzie spójnym
grafem nieskierowanym z funkcją wagową w o wartościach rzeczywistych
określoną na E. Niech A będzie podzbiorem E zawartym. w pewnym mini-
malnym drzewie rozpinającym grafu G, niech (S, V - S) będzie dowolnym
przekrojem. G uwzględniającym A i niech (u, v) będzie krawędzią bezpiecz-
ną dla A, krzyżującą się z (S, V - S). Wtedy krawędź (u, v) jest krawędzią
lekką dla przekroju (S, V - S). Podaj kontrprzykład świadczący o tym, że
profesor Sabatier się myli.
24.1-3. Pokaż, że jeżeli krawędź (u, v) należy do pewnego minimalnego drzewa
rozpinającego, to jest ona krawędzią lekką krzyżującą się z pewnym prze-
krojem grafu.

567
ROZDZIAŁ 24. MINIMALNE DRZEWA ROZPINAJĄCE

24.1-4. Podaj prosty przykład takiego grafu, że zbiór wszystkich krawędzi,


które są krawędziami lekkimi krzyżującymi się z pewnym przekrojem tego
grafu, nie tworzy minimalnego drzewa rozpinającego.
24.1-5. Niech e będzie krawędzią o największej wadze spośród wag krawędzi
z pewnego cyklu w grafie G = (V, E). Udowodnij, że istnieje minimalne
drzewo rozpinające w grafie G' = (V, E - {e}), które jest także minimal-
nym drzewem rozpinającym w G.
24.1-6. Pokaż, że graf ma dokładnie jedno minimalne drzewo rozpinające, jeśli
dla każdego przekroju w tym grafie istnieje dokładnie jedna krawędż lek-
ka, która się z nim krzyżuje. Pokaż, że twierdz.enieodwrotne nie jest praw-
dziwe, podając stosowny kontrprzykład.
24.1~7. Uzasadnij, że jeśli wszystkie wagi krawędzi są dodatnie, to każdy pod-
zbiór krawędzi rozpinający wszystkie wierzchołki, którego łączna waga
jest minimalna, musi być drzewem. Podaj przykład świadczący o tym, że
powyższa teza nie jest prawdziwa, gdy dopuszczamy wagi niedodatnie.
24.1-8. Niech T będzie minimalnym drzewem rozpinającym grafu G i niech
L będzie uporządkowaną listą wag krawędzi z drzewa T. Pokaż, że dla
każdego innego minimalnego drzewa rozpinającego T' grafu G lista L jest
także uporządkowaną listą wag krawędzi drzewa T'.
24.1-9. Niech T będzie minimalnym drzewem rozpinającym grafu G = (V, E)
i niech V' będzie podzbiorem V. Niech T' będzie pod.grafem T indukowa-
nym przez V' i niech G' będzie pod.grafem G indukowanym przez V'.
Pokaż, że jeśli T' jest spójny, to T' jest minimalnym drzewem rozpinają­
cym grafu G'.

24.2. AlgorytmyKruskalai Prima


Dwa algorytmy służące do obliczania minimalnego drzewa rozpinającego, które
opiszemy w tym podroz.dziale,są szczegółowymi wersjami procedury GENERIC-
-MSI. W każdym z nich została zastosowana ściśle określona reguła wyznacza-
nia bezpiecznej krawędzi w wierszu 3 procedury GENERIC-MST. W algorytmie
Kruskala zbiór A jest lasem. Krawędź bezpieczna dodawana do A jest zawszetą
krawędzią w grafie, która ma najmniejszą wagę i która łączy dwie różne składo­
we. W algorytmie Prima zbiór A tworzy pojedyncze drzewo. Krawędź bezpiecz-
na dodawana do A jest zawsze tą krawędzią w grafie, która ma najmniejszą wagę
i która łączy drzewo wyznaczone przez A z wierzchołkiem spoza tego drzewa.

Algorytm Kruskala
Algorytm Kruskala jest bezpośrednio oparty na schemacie obliczania minimal~
nego drzewa rozpinającego z pod.rozdz. 24.1. W tym algorytmie krawędzią

568
24.2. ALGORYTMY KAUSKALA J PRIMA

dodawaną do rozrastającego się lasu jest krawędź (u, v) o najmniejszej wadze


spośród krawędzi łączących różne drzewa w lesie. Niech C 1 i C2 oznaczają dwa
drzewa, które są połączone krawędzią (u, v). Ponieważ (u, v) jest krawędzią
lekką łączącą C 1 z innym drzewem, z wniosku 24.2 wynika, że (u, v) jest krawę­
dzią bezpieczną dla C 1• Algorytm Kruskala jest algorytmem zachłannym, po-
nieważ w każdym kroku do lasu jest dodawana krawędź o najmniejszej moż­
liwej wadze.
Nasza implementacja algorytmu Kruskala jest podobna do implementacji
algorytmu obliczania spójnych składowych z pod.rozdz. 22.1. W tym rozwiąza­
niu używamy struktury danych dla rozłącznych zbiorów do pamiętania kilku
rozłącznych zbiorów wierzchołków. Każdy taki zbiór zawiera wierzchołki jed-
nego drzewa w lesie. Operacja FIND-SET(u) zwraca reprezentanta zbioru za-
wierającego u. Testując, czy FIND-SET(u) jest równe FIND-SBT(v),możemy
sprawdzić, czy wierzchołki u oraz v należą do tego samego drzewa. Łączenie
dwóch drzew jest wykonywane za pomocą procedury UNION.

MST-KRUSKAL(G, w)
1 A+-0
2 for każdy wierzchołek ve flGJ
3 do MAKE-SET(v)
4 posortuj krawędzie z E niemalejąco względem wag w
5 for każda krawędź (u, v)eE, w kolejności niemalejących wag
6 do if F!ND-SET(u) # FIND-SET(v)
7 tben A-Au{(u, v)}
8 UN!ON(u, v)
9 return A

Działanie algorytmu K.ruskala ilustruje rys. 24.4. W wierszach 1-3 zbiór


A jest inicjowany jak.o pusty i zostaje utworzonych IV I drzew jednowierzchoł­
kowych. W wierszu 4 krawędzie ze zbioru E są sortowane niemalejąco wzglę­
dem wag. W pętli for w wierszach 5-8, dla każdej krawędzi (u, v), sprawdza się,
czy końce u, v tej krawędzi należą do tego samego drzewa, Jeśli tak, to krawędź
(u, v) nie może być dodana do lasu, ponieważ spowodowałaby powstanie cyk-
lu. Taka krawędź jest porzucana. W przeciwnym razie wierzchołki u i v należą
do różnych drzew i w wierszu 7 krawędź (u, v) jest dodawana do A, a w wierszu
8 oba te drzewa zostają połączone w jedno drzewo.
Czas działania algorytmu Kruskala dla grafu G = (V, E) zależy od sposo-
bu implementacji struktury danych dla zbiorów rozłącmych. Przyjmiemy
asymptotycznie najszybszą znaną implementację. Jest nią las zbiorów roz-
łącznych z rozdz. 22.3 z łączeniem według rangi i z kompresją ścieżek. Inicja-
cja zajmuje czas O(V), a czas potrzebny do posortowania krawędzi w wier-
szu 4 wynosi O(Elg E). W trakcie działania algorytmu jest wykonywanych

569
ROZDZIAŁ 24. MINIMALNE DRZEWA ROZPINAJĄCE

,;•v-~'-;:;,>;:-, d

(a) o
'

(c) o

(e) a (fJ a 11

(g} a li (h}
7
8
• •
Rys. 24.4. Driałarue
algorytmu K.ruskaJa na grafie z rys. 24.l. Krawędzie zacieniowane nalezą do
rozrastającego się lasu A. Krawędzie są rozpatrywane w porządku niemalejll,(:ych wag. Strzałlr:a
wskazuje krawędź rozpatrywaną w danym kroku algorytmu. Jeśli krawędź łączy dwa różne drzewa
w lesie, to jest dodawana do lasu, powodując tym samym scalenie tych drzew w jedno drzewo

O(E) operacji na lesie zbiorów rozłącznych, które w sumie :zabierają czas


O(Ea.(E, V)), gdzie a: jest odwrotnością funkcji Ackennanna zdefiniowaną
w pod.rozdz. 22.4. Ponieważ a:(E, V)= O(lgE), całkowity czas działania al-
gorytmu Kruskala wynosi O(ElgE).

Algorytm Prima
Podobnie jak algorytm Kruskala, algorytm Prima jest szczególnym przypad-
kiem schematu obliczania mJnimalnego drzewa rozpinającego z pod-
rozdz. 24.1. Algorytm Prima jest podobny do algorytmu Dijkstry dla probie-

570
24.2. ALGORYTMY KRUSICALA I PRIMA

~ l) , ul

r (I)

'

lys. 24.4. cd.

mu najkrótszych ścieżek w grafie (patrz podroz.dz. 25.2). W algorytmie Prima


krawędzie ze zbioru A tworzą zawsze pojedyncze drzewo. Jak widać na
rys. 24.5, początkowo takie drzewo składa się z dowolnie wybranego wierz-
chołka-korzenia r, a następnie rośnie do chwili, w której rozpina wszystkie
wierzchołki z V. W każdym kroku krawędź lekka łącząca wierzchołek
z A z wierzchołkiem z V - A jest dodawana do drzewa. Z wniosku 24.2 wy-
nika, że stosując tę zasadę, do drzewa dodajemy tylko krawędzie bezpieczne
dla A. Dlatego z chwilą zakończenia działania algorytmu krawędzie z A tworzą
minimalne drzewo rozpinające. Ta strategia jest zachłanna, ponieważ w każ­
dym kroku drzewo jest rozszerzane o krawędź, której waga wnosi najmniej do
wagi tego drzewa.
Kluczem do efektywnej implementacji algorytmu Prima jest t.apewnienie
szybkiego wyznaczania nowej krawędzi dodawanej do drzewa tworzonego
przez krawędzie ze zbioru A. W algorytmie opisanym dalej zarówno spójny
graf G, jak i korzeń r, od którego rozpoczyna się budowanie minimalnego
drzewa rozpinającego, są danymi wejściowymi. W czasie wykonywania algory-
tmu wszystkie wierzchołki spoza rozrastającego się drzewa znajdują się w ko-
lejce priorytetowej Q. Dla kai.dego wierzchołka v kluczem key[v] wyznaczają­
cym pozycję wierzchołka v w kolejce jest minimalna waga spośród wag kra-
wędzi łączących v z wierzchołkami drzewa. Przyjmujemy, że key(v] = oo, jeśli

571
ROZDZIAŁ 24. MINłMALNE DRZEWA ROZPINAJĄCE

b
' 9 '
,,, 14
' (b)
'
o
b g h f
I 2 I
' 2

8
d

(C) 14 e (d)
'
(,b'-,1 O
_::\,v--,,-{,ct[)

,,, ' (0 '

(g) e {h)
'

(i)

Rys. 14.5. Dziełsnie algorytmu Prima na grafie z rys. 24.L Wierzchołkiem-korzeniem jest a. Krawę­
dzie rozrastającego się drzewa są, zacieniowane, a wierzchołki w drzewie są pokolorowane na
czarno. W każdym kroku algorytmu wierzchołki z drzewa wyznaczają pr.zekrój grafu, a krawędż
lekka krzyżująca się z pr.zekrojem jest dodawana do drzewa. Dla przykłedu, w kroku drugim
ke:ide z dwóch krawędzi (b, c) i (a, h) może zostać dodana do drzewa,ponieważ obie są krawędzia­
mi lekkimi krzyżującymi się z przekrojem

572
24.2. ALGORYTMY KRUSKALA I PRIMA

takiej krawędzi nie ma. W zmiennej n:[v]jest pamiętany „ojciec" wierzchołka


v w obliczanym drzewie. Podczas wykonywania algorytmu zbiór A z procedury
GENERIC-MST jest pamiętany niejawnie.
A - {(v, •[v]): VE V - {r} - Q}
W chwili zakończ.enia działania algorytmu kolejka priorytetowa Q jest pusta;
minimalnym drzewem rozpinającym A w G jest więc

A - {(v, •[v]): VE V- {r))

MST-PRIM(G, w, r)
1 Q~V[G]
2 for każdy uEQ
3 do key[u] +- oo
4 key[rJ~ o
5 n(rJ +- NIL
6 while Q ;" 0
7 do u+- EXTRACT-MIN(Q)
8 for każdy vEAdj[u]
9 do if VEQ i w(u, v) < key[v]
10 then n[v] +- u
11 key[v] ~ w(u, v)

Działanie algorytmu Prima ilustruje rys. 24.5. W wierszach 1-4 jest inicjo-
wana kolejka priorytetowa Q. Początkowo są w niej zawarte wszystkie wierz-
chołki, a kluc7.em każdego wierzchołka, poza korzeniem r, jest oo. Kluczem
korzenia r jest O. W wierszu 5 pole n:[r]jest inicjowane na NIL, ponieważ korzeń
r nie ma ojca. W trakcie wykonywania algorytmu zbiór V - Q zawiera wierz-
chołki budowanego drzewa. Wierzchołek u E Q incydentny z krawędzią lekką
krzyżującą się z przekrojem (V - Q, Q) jest wyznaczany w wierszu 7 (z wyjąt­
kiem pierwszej iteracji, w której u = r w wyniku wykonania wiersza 4 ). Wierz-
chołek u usuwany z Q jest jednocześnie dodawany do zbioru V - Q wierzchoł­
ków drzewa. W wierszach 1-8 są aktualizowane wartości pól key i n dla każ­
dego wierzchołka v spoza drzewa, który sąsiaduje z u. Podczas aktualizacji jest
zachowany niezmiennik: key[v] = w(v, x[v]) i (v, n:[v])jest krawędzią lekką łą­
czącą v z pewnym wierzchołkiem w drzewie.
Szybkość działania algorytmu Prima zależy od tego, jak jest zaimplemen-
towana kolejka priorytetowa Q. Jeśli Q jest zaimplementowana jako kopiec
binarny (patrz rozdz. 7), to możemy zastosować procedurę BUILD-HEAP do
inicjacji w wierszach 1-4 w czasie O(V). Pętla główna jest wykonywana IVI
razy. Ponieważ każda operacja EXTRACT-MIN zabiera czas O(lg V), łączny
czas wszystkich wywołań EXTRACT~MIN wynosi O(Vlg V). Ponieważ suma

573
ROZDZIAŁ 24. MINIMALNE DRZEWA ROZPINAJĄCE

długości wszystkich list sąsiedztwa jest równa 21EI, czas wykonania pętli for
w wierszach 8-11 wynosi ogółem O(E). Test przynależności do Q w wierszu
9 wewnątrz pętli for może zostać zaimplementowany w czasie stałym przez
związanie z każdym wierzchołkiem jednego bitu informującego o tym, czy
wierzchołek należy do Q, i aktualizowanie tej informacji przy usuwania wierz-
chołka z kolejki. Przypisanie w wierszu 11 pociąga za sobą ukryte wykonanie
na kopcu operacji DECREASE-KEY,która moze być zaitnplementowana w cza-
sie O(lgV). A zatem całkowity czas wykonania algorytmu Prima wynosi
O(Vlg V+ Elg V) = O(Elg V). Czas ten jest asymptotycznie taki sam, jak
czas wykonania algorytmu Kruskala.
Asymptotyczny czas działania algorytmu Prima można jednakże popra-
wić, stosując kopce Fibonacciego. W ro2.dziaie 21 pokazaliśmy, że jeśli IVl
elementów zorganizujemy w kopiec Fibonacciego, to możemy operację
EXTRACT-MIN wykonać w czasie zamortyzowanym O(ig V), a operację DE-
CREASB-KEY(do implementacji wiersza 11) w czasie zamortyzowanym 0(1).
Dlatego, jeśli do implementacji kolejki priorytetowej Q użyjemy kopca Fibo-
nacciego, to czas działania algorytmu Prima zmaleje do O(E + Vlg V).

ZADANIA
24.2-1. W wyniku wykonania algorytmu Kruskala możemy otrzymać różne
drzewa rozpinające dla tego samego grafu G zależnie od tego, w jakiej
kolejności są przetwarzane krawędzie o tych samych wagach. Pokaż, że
dla każdego minimalnego drzewa rozpinającego T grafu G można w al-
gorytmie Kruskala tak uporządkować krawędzie, żeby w wyniku jego wy-
konania otrzymać drzewo T.
24.2-2. Przypuśćmy, że graf G = (V, E) jest reprezentowany przez macierz
sąsiedztwa. Podaj prostą implementację algorytmu Prima działającą w tym
wypadku w czasie O(V 2).
24.2-3. Czy dla grafu rzadkiego G = (V, E), w którym IEI = 0(V), implemen-
tacja algorytmu Prima z użyciem kopca Fibonacciego jest asymptotycznie
szybsza od implementacji z użyciem kopca binarnego? A jak rzecz się ma
w przypadku grafu gęstego, w którym IEI = 0(V 2)? Jaki związek musi
zachodzić między JEI i ]VI, żeby implementacja z użyciem kopca Fibonac-
ciego była szybsza od implementacji z użyciem kopca binarnego?
14.2-4. Załóżmy, że wagi wszystkich krawędzi w grafie są liczbami całkowity~
mi z zakresu od 1 do ]VI. Jak szybkim można uczynić algorytm Kruskala
w tym wypadku? Jak szybkim można uczynić ten algorytm, gdy wagi kra-
wędzi są liczbami całkowitymi z zakresu od 1 do W, dla pewnej stałej W?
24.2-5. Załóżmy, że wagi wszystkich krawędzi w grafie są liczbami całkowity~
mi z zakresu od 1 do ]VI. Jak szybkim można uczynić algorytm Pritna
w tym wypadku? Jak szybkim można uczynić ten algorytm, gdy wagi kra-
wędzi są liczbami całkowitymi z zakresu od 1 do W, dla pewnej stałej W?

574
PROBLEMY

24.2-6. Opisz efektywny algorytm obliczania takiego drzewa rozpinającego


w grafie nieskierowanym G, że największa waga krawędzi w tym drzewie
jest najmniejsza spośród największych wag krawędzi ze wszystkich drzew
rozpinających G.
* 24.2-7. Załóżmy, że wagi. krawędzi w grafie są dane z rozkładem jednostajnym
na prawostronnie otwartym przedziale [O, 1). Który algorytm, Kruskala
czy Prima, można uczynić szybszym w tym wypadku?
* 24.2-8. Załóżmy, że dla grafu G minimalne drzewo rozpinające zostało już
obliczone. Jak szybko można zaktualizować to drzewo.jeśli do G dodamy
nowy wierzchołek wraz z incydentnymi krawędziami?

Problemy
24--1.Drugie w kolejności minimalne drzewo rozpinające
Niech G = (V, E) będzie spójnym grafem nieskierowanym z funkcją wagową
w:E-+R i załóżmy, że ]El~ JVI.
(a) Niech T będzie minimalnym drzewem rozpinającym grafu G. Udowodnij,
że istnieją krawędzie (u, v)ETi (x, y)łTtakie, że T-{(u, v)}u{(x, y))
jest drugim w kolejności minimalnym drzewem rozpinającym G.
(b) Niech T będzie minimalnym drzewem rozpinającym G. Dla każdych
dwóch wierzchołków u, ve V niech max(u, v] będzie krawędzią o naj-
większej wadze na jedynej ścieżce między u i v w drzewie T. Opisz al-
gorytm, który dla danego drzewa T oblicza max[u, v] w czasie O(V 2)
dla wszystkich u, v e V.
(c) Podaj efektywny algorytm obliczania w grafie G drugiego w kolejności
minimalnego drzewa rozpinającego.

24--2. Minimalne drzewa rozpinające w grafach rzadkich


Dla bardzo rzadkiego grafu można uzyskać lepszy czas działania niż
O(E + VlgV) - czas działania algorytmu Prima z kopcami Fibonacciego.
W tym celu przetwarzamy wstępnie graf G, żeby zmniejszyć liczbę wierzchoł­
ków, a następnie dla zredukowanego grafu wykonujemy algorytm Prima. Pro-
cedura MST-REDUCE dostaje na wejściu graf ważony G, redukuje go do mniej-
szego grafu, obliczając jednocześnie pewne krawędzie konstruowanego mini-
malnego drzewa rozpinającego T. Zakładamy, że początkowo dla każdej kra-
wędzi (u, v)eEmamy orig[u, v] = (u, v) i w[u, v]jest wagą tej krawędzi.

MST-REDUCE(G, 7)
I for każdy vE V(GJ
2 do mark[v] - FALSE

575
3 MAKB-SET(v)
4 for każdy uc V[G]
5 do if mark[u] = FALSE
6 tben wybierz veAdj[u] taki, że w[u, v] jest najmniejsze
7 UNION(u, v)
8 T- Tu {orig[u, v]}
9 mark[u] +- mark[v] +- TRUE
10 V[G']- {FINO-SET(v): VE V[G])
Il E[G']-0
12 for każda krawędź (x, y)cE[G]
13 do u+-FIND-SET(x)
14 v +- FINO-SET(y)
15 if (u, v}EE[G']
16 thenE[G'] -E[G'] u {(u, v)}
17 orig[u, v]+- orig[x, y]
18 w[u, v] - w[x, y]
19 else if w[x, y] < w[u, v]
20 then orig{u, v] +- orig[x, y]
21 w[u, v]-w[x, y]
22 zbuduj listy sąsiedztwa Adj dla G'
23 return G' i T

(a) Niech T będzie zbiorem krawędzi zwracanym przez procedurę MST-RE-


DUCE i niech T' będzie minimalnym drzewem rozpinającym w grafie G'
obliczonym w tej procedurze. Udowodnij, że Tu {orig[x, y]: (x, y) e T'}
jest minimalnym drzewem rozpinającym w grafie G.
(b) Uzasadnij, że JV[G']I,; JVl/2.
(c) Pokaż, jak zaimplementować procedurę MST-R.EDUCE, żeby działała
w czasie O(E). (Wskazówka: Wykorzystaj proste struktury danych).
(d) Przypuśćmy, że wykonujemy k razy procedurę MST-REDUCE, biorąc
jako graf wejściowy dla kolejnego wykonania MST-REDUCE graf obli-
czony w wykonaniu popI7.Cdnim i gromadząc wszystkie krawędzie w T.
Udowodnij, że łączny czas k wykonań procedury MST-REDUCE wyno-
si O(kE).
(e) Przypuśćmy, że pok-krotnym wykonaniu procedury MST-RBDUCE uru-
chamiamy algorytm Prima dla grafu otrzymanego w ostatnim wykonaniu
algorytmu MST-REDUCE. Pokaż, jak dobrać k, żeby całkowity czas działa­
nia algorytmu wynosił O(Elg lg V). Uzasadnij, że Twój dobór k minimali-
zuje całkowity asymptotyczny czas działania.
(ł) Dla jakich wartości !El(w zależności od IVDalgorytm Prima ze wstępnym
przetwarzaniem jest asymptotycznie lepszy od algorytmu Prima bez wstęp,­
nego przetwarzania?

576
UWAGI DO ROZDZIAŁU

Uwagido rozdziału

Książka Tarjana [188] zawiera przegląd i wspaniałe rozwinięcie tematyki doty-


czącej problemu minimalnego drzewa rozpinającego. Historia problemu mini-
malnego drzewa rozpinającego została opisana przez Grahama i Helia w (92J.
Tarjan przypisuje O. Bonivce autorstwo pierwszego algorytmu obliczania
minimalnego drzewa rozpinającego. Algorytm Bonivki pochodzi z 1926 r.
Algorytm znany jak.o algorytm Kruskala został podany [131] przez jego twórcę
w 1956 r. Algorytm powszechnie znany jak.o algorytm Prima został rzeczywi-
ście podany przez Prima [163], ale już wcześniej odkrył go V. Jarnik. w 1930 r.
Powodem, dla którego algorytmy zachłanne służące do obliczania mini-
malnych drzew rozpinających są poprawne, jest to, że zbiór lasów w grafie jest
matroidem grafowym (patrz rozdz. 17.4).
Aktualnie najszybszym znanym algorytmem dla problemu minimalnego
drzewa rozpinającego, dla IEI = O(Vlg V), jest algorytm Prima zaimplemen-
towany z kopcami Fibonacciego. Dla rzadszych grafów Frrrlman i Tarjan [75]
podali algorytm działający w czasie O(EP(IEI, IVI)), gdzie P(IEI, IVl)-
-min{i:lg''IVI s, IEI/IVIJ. Ponieważ IEI > IVI, ich algorytm działa w czasie
O(Elg*V).
Rozdział 25

ścieżki
Najkrótsze
z jednymźródłem

Przypuśćmy, że kierowca chce przejechać najkrótszą trasą z Chicago do Bos~


tonu. W jaki sposób można znaleźć taką trasę, jeżeli dysponujemy mapą samQ..
chodową Stanów Zjednoczonych, na której zaznaczono odległości między każ~
dą parą sąsiednich skrzyżowań dróg.
Jednym ze sposobów jest sporządzenie wykazu wszystkich możliwych tras
z Chicago do Bostonu, zsumowanie odległości poszczególnych odcinków na
każdej trasie i wybranie trasy najkrótszej. Łatwo jednak zauważyć, że jeśli
nawet pominiemy w naszych rozważaniach trasy z cyklami, to i tak pozostanie
wiele milionów możliwości, z których większość nie jest warta rozważenia. Dla
przykładu, trasa z Chicago do Bostonu przez Houston jest w oczywisty sposób
złym wyborem, ponieważ Houston znajduje się około 1600 km na południowy
zachód od Chicago, natomiast Boston leży na wschód od Chicago.
W tym i następnym ro7.d.ziale pokażemy, w jaki sposób efektywnie roz-
wiązywać takie problemy. W problemie najkrótszych ścieżek jest dany ważony
graf skierowany G = ( V, E) z funkcją wagową w: E-+ R przyporządkowującą
krawędziom wagi o wartościach rzeczywistych. Wagą ścieżki p = (v 0, v1, ••• , V1:)
jest suma wag tworzących ją krawędzi:

l<{p)= L' w(v,_,, v;J


i=l

Wagę najkrótszej ścieżki z wierzchołka u do wierzchołka v defmiujemy jako

min{w(p): u4v), jeśli istnieje ścieżka z u do v


ii(u, v) ={ w przeciwnym razie
<Xl,

Najkrótszą ścieżką z wierzchołka u do wierzchołka v jest każda ścieżka p z u do


v, dla której w(p) = ii(u, v).

578
ROZDZIAŁ 25. NAJKRÓTSZE $CJE2KI Z JEDNYM 2RóDŁEM

W przykładzie omawianym we7.eśniej mapę samochodową możemy mode-


lować za pomocą grafu. w którym wier1.ehołki reprezentują skrzyżowania
dróg, a krawędzie odcinki dróg między skrzyżowaniami. Wagami krawędzi są
długości tych odcinków. Naszym celem jest znalezienie najkrótszej ścieżki
z wierzchołka reprezentującego pewne skrzyżowanie dróg w Chicago do wierz-
chołka reprezentującego pewne skrzyżowanie dróg w Bostonie.
Wagi krawędzi można interpretować inae7.ejniż odległości. Wagi krawędzi
reprezentują często czas, koszt, karę lub inne wielkości, które narastają liniowo
wzdłuż ścieżki i które chcemy minimalizować.
Algorytm przeszukiwania wszerz, opisany w podro:zdz.23.2, znajduje naj-
krótsze ścieżki w grafach bez wag lub - inaczej mówiąc - w grafach, w których
waga każdej krawędzi jest jednostkowa. Ponieważ wiele pojęć dotyczących
przeszukiwania wszerz pojawi się podczas omawiania problematyki najkrót-
szych ścieżek, 7.aehęcamy do przypomnienia sobie materiału z podrozdz. 23.2
przed przystąpieniem do dalszego czytania tego rozdziału.

Warianty
W tym rozdziale skupimy się na problemie najkrótuycb ścieżek z jednym źród­
łem, w którym: dany jest graf G = (V, E) i wyróżniony wierzchołek se V nazy-
wany źródłem; dla każdego wierzchołka v e V należy znaleźć najkrótszą. ścieżkę
z s do v. Wiele innych problemów można rozwiązać, wykorzystując algorytmy
dla problemu z jednym źródłem. Należą do nich następujące warianty omawia-
nego problemu.

Najkrótsze ścieżki z jednym wiencholk:iem.docelowym.Należy znaleźć najkrót-


szą ścieżkę z każdego wierzchołka v do danego wierzchołka docelowego t.
Odwracając zwrot każdej krawędzi, możemy zredukować ten problem do
problemu z jednym źródłem.

Najkrótsza ścieżka między parą wierzchołków. Należy znaleźć najkrótszą ścież­


kę z wierzchołka u do v dla danej pary wierzchołków u i v. Jeśli rozwiąże­
my problem najkrótszych ścieżek ze źródłem w wierzchołku u, to także
rozwiążemy ten problem. Podkreślmy, że dla problemu najkrótszej ściCżki
między parą wierzchołków nie jest znany żaden algorytm.działający w naj-
gorszym przypadku asymptotycznie szybciej niż najlepszy znany algorytm
dla problemu z jednym źródłem.

Najkrótsze ścieżki między wszystkimi parami wierzchołków. Dla każdej pary


wierzchołków u, v należy znaleźć najkrótszą ścieżkę z u do v. Ten problem
można rozwiązać, wykonując dla każdego wier1.ehołka w grafie algorytm
dla problemu z jednym źródłem. Rozwiązuje się go jerlnak zazwyczaj

579
ROZDZIAŁ 25. NAJKRÓTSZE SC!EiK1 Z JEDNYM 2R0DŁEM

inaczej, a jego struktura jest sama w sobie interesująca. Problem najkrót-


szych ścieżek między wszystkimi parami wierzchołków omówimy szczegó-
łowo w rozdz. 26.

Krawędzie z ujemnymi wagami


W pewnych zastosowaniach problemu najkrótszych ścieżek z jednym źródłem
mogą pojawić się krawędzie z ujemnymi wagami. Jeśli żaden cykl o ujemnej
wadze nie jest osiągalny ze źródła s, to dla każdego wierzchołka vE V waga
najkrótszej ścieżki b(s, v) jest dobrze zdefmiowana, nawet jeżeli jej wartość jest
ujemna. Jednakże jeśli cykl o ujemnej wadze jest osiągalny ze źródła s, to wagi
najkrótszych ścieżek nie są dobrze zdefiniowane. Żadna ścieżka z s do jakiego-
kolwiek wierzchołka na takim cyklu nie może być najkrótsza - zawsze można
znaleźć ścieżkę krótszą, rozszerzając ścieżkę „najkrótszą" właśnie o ten cykl.
Jeśli na pewnej ścieżce z s do v znajduje się cykl o ujemnej wadze, to definiuje-
my b(s, v) = - oo.
Na rysunku 25.l jest pokazany wpływ ujemnych wag na wagi najkrótszych
ścieżek. Ponieważ jest dokładnie jedna ścieżka z s do a (ścieżka (s, a)),
ó(s, a) = w(s, a) = 3. Podobnie, istnieje dokładnie jedna ścieżka z s do bi dlate-
go ó(s, b) = w(s, a)+ w(a, b) = 3 + (-4) = -1. Istnieje nieskończenie wiele
ścieżek z s doc: (s, c), (s, c, d, c), (s, c, d, c, d, c) itd. Ponieważ cykl (c, d, c)
ma wagę 6 + (-3) = 3 > O, najkrótszą ścieżką z wierzchołka s doc jest (s, c)
o wadze ó(s, c) = 5. Podobnie, najkrótszą ścieżką z wierzchołka s do d jest
(s, c, d) o wadze ó(s, d) = w(s, c) + w(c, d) = 11. Analogicznie, jest nieskoń­
czenie wiele ścieżek z wierzchołka s do e: (s, e), (s, e,f, e), (s, e,f, e,f, e) itd.

I,
" -4
3
I,
2 '
«=~_"@
1· 6 ,/
' 5 .l
.l

Rys. 25.1. Graf skierowany z ujemnymi wagami na krawędziach. Liczba wewnątrz ka:ż.dego wierz-
chołka jest wagą. najkrótszej ścieżki ze źródła s do tego wierzchołka. Ponieważ wierzchołki e oraz
/tworzą. cykl o ujemnej wadze i jest on osiągalny ze środka s, wagi najkrótszych ścieżek prowadzą­
cych do tych wierzchołków wynoszą - ro. Ponieważ wierzchołek g jest osiągalny z wierzchołka,
którego waga najkrótszej ścieżki jest - ro, waga najkrótszej ścieżki do g wynosi taki.e - ro. Wierz-
chołki h, i oraz j nie są osiągalne ze źródła s i dlatego wagi ich najkrótszych ścieżek wynoszą ro,
chociai: wierzchołki te leżą. na cyklu o ujemnej wadze

580
ROZDZIAŁ 25. N.AJKROTSZE ŚCIEżKI Z JEDNYM 1:RóDŁEM

Ponieważ jednak cykl (e,f, e) ma wagę 3 + (-6) = -3 < O, nie istnieje naj-
krótsza ścieżka z wierzchołka s do e. Przechodząc cykl (e, f, e) (o ujemnej
wadze) dowolnie wiele razy, możemy znajdować ścieżki z s do e o dowolnie
małych wagach i stąd ó(s, e) = -oo. Podobnie ó(s,j) = -oo. Ponieważ wierz-
chołek g jest osiągalny z wierzchołka/, możemy także znajdować ścieżki o do-
wolnie małych ujemnych wagach z wierzchołka s dog, stąd ó(s, g) = -oo.
Wierzchołki h, i oraz.j tworzą takż.e cykl o ujemnej wadze. Jednakż.e te wierz-
chołki nie są osiągalne z si dlatego ó(s, h) = ó(s, i) = ó(s, 1) = oo.
W pewnych algorytmach dla problemu najkrótszych ścieżek, na przykład
w algorytmie Dijkstry, zakłada się, że wszystkie wagi na krawędziach w grafie
wejściowym są nieujemne (tak jak: w przykładzie z mapą samochodową). W in-
nych rozwiązaniach, na przykład w algorytmie Bellmana-Forda, dopuszcza się
ujemne wagi na krawędziach i otrzymuje się poprawne wyniki, jeżeli tylko
żaden cykl o ujemnej wadze nie jest osiągalny ze źródła. Zazwyczaj, jeśli cykl
o ujemnej wadze istnieje, to algorytm wykrywa go i informuje o jego istnieniu.

Reprezentacja ścieżek
najkrótszych
Często chcemy nie tylko obliczyć wagi najkrótszych ścieżek, ale także wyzna-
czyć należące do nich wierzchołki. Najkrótsze ścieżki reprezentujemy podobnie
jak drzewa przeszukiwania wszerz w podrozdz. 23.2. Dla danego grafu
G = (V, E), dla każ.dego wierzchołka VE V pamiętamy poprzednikn:[v],który
jest albo innym wierzchołkiem albo równy NIL. Algorytmy służące do oblicza-
nia najkrótszej ścieżki, które omawiamy w tym rozdziale, nadają atrybutom
n takie wartości, że ciąg poprzedników zaczynający się od wierzchołka v, czyta-
ny w odwrotnym porządku, jest najkrótszą ścieżką u źródła s do wierzchołka
v. Dlatego do wypisania najkrótszej ścieżki ze źródła s do wierzchołka v, dla
którego n[v] =I=NIL, można zastosować procedurę PRINT-PATH(G, s, v) z pod-
rozdz. 23.2.
Jednakże w trakcie wykonywania algorytmu obliczania najkrótszej ścieżki
wartości n nie muszą określać najkrótszych ścieżek. Podobnie jak w algorytmie
przeszukiwania wszerz, będziemy badali JM)dgrafpoprzednikówG,.= (VI<,E,.)
indukowany przez wartości n:.Także tutaj definiujemy zbiór wierzchołków V„
jako zbiór tych wierzchołków grafu G, których poprzedniki są różne od NIL,
plus wierzchołek s:

V,~ {ve V: n[v] # NIL} u {s)

Zbiorem krawędzi skierowanych E„ jest zbiór krawędzi indukowany przez


wartości n dla wierzchołków z V,.:

E, ~ {(n[v], v)eE: vE V. - {s)}

581
ROZDZIAŁ 25. NAJKRÓTSZE $CIEżKI Z JEDNYM ŻRÓDŁEM

Udowodnimy, że wartości obliczane przez algorytmy z tego rozdziału


11:

mają tę własność, że końcowy graf G„ jest „drzewem najkrótszych ścieżek"


- nieformalnie, drzewem ukorzenionym zawierającym najkrótsze ścieżki ze
źródła s do każdego wierzchołka osiągalnego z s. Drzewo najkrótszych ścieżek
jest podobne do drzewa przeszukiwania wszerz z podrozdz. 23.2 z tą różnicą,
że zawiera ono najkrótsze ścieżki względem wag krawędzi, a nie ich liczby.
Uściślając, niech graf G = (V, E) będzie ważonym grafem skierowanym z funk-
cją wagową w:E _. R. Załóżmy, że graf G nie zawiera cykli o ujemnych wa-
gach, które są osiągalne z wierzchołka źródłowego se V. Tak więc najkrótsze
ścieżki są dobrze zdefiniowane. Drzewem najkrótszych ścieżek o korzeniu
ws nazywamy podgraf skierowany G' = (V', E'), w którym V' c: V, E' c: E,
taki że:

I. V' jest zbiorem wierzchołków w grafie G osiągalnych z s.


2. G' jest drzewem z korzeniem; sjest korzeniem drzewa.
3. Dla kaniego wierzchołka v e V jedyna ścieżka z s do v w grafie G' jest
najkrótszą ścieżką z s do v w grafie G.

' o

X y X y
(,) (b) (c)

Rys. 25.2. (a) Ważony graf skierowany. W wierzchołklli:h znajdują się wagi najkrótszych ścieżek z s.
(b) Krawędzie zacieniowane tworzą drzewo najkrótszych ścieżek z.e źródła s. (c) Jeszcz.e jedno
drzewo najkrótszych ścieżek o tym samym korzeniu

Może być wiele najkrótszych ścieżek prowadzących do danego wierzchołka.


Także drzewo najkrótszych ścieżek nie musi być jedyne. Na rysunku 25.2 jest
na przykład pokazany ważony graf skierowany i dwa drzewa najkrótszych
ścieżek o tym samym korzeniu.

Zawartość rozdziału

Algorytmy dla problemu najkrótszych ścieżek z jednego źródła opisane w tym


rozdziale działają z wykorzystaniem metody relaksacji. Podro7.dział 25.1 rozpo-
cz.niany od pokazania pewnych ważnych, ogólnych własności najkrótszych
ścieżek. Następnie pokażemy pewne fakty dotyczące algorytmów działających
z wykorzystaniem metody relaksacji. W podrozdziale 25,2 przedstawimy algo-

582
25.1. NAJKRÓTSZE $CIE2KI I RELAKSACJA

rytm Dijkstry służący do rozwiązywania problemu najkrótszych ścieżek z jed-


nym źródłem przy założeniu, że wagi na krawędziach są nieujemne. W pod-
rozdziale 25.3 omówimy algorytm Bellmana-Forda, który ma zastosowanie
w ogólniejszym przypadku - dopuszczającym ujemne wagi na krawędziach.
Algorytm Bellmana-Forda umożliwia wykrycie cykli o ujemnych wagach osią­
galnych ze źródła. W podrozdziale 25.4 podamy liniowy algorytm obliczania
najkrótszych ścieżek z pojedynczego źródła w grafach skierowanych·bez cykli.
Na koniec, w podrozdz. 25.5, pokażemy, w jaki sposób można 2'.astosować
algorytm Bellmana-Forda do rozwią2ania specjalnego przypadku „programo-
wania liniowego".
W naszych rozważaniach przyjmujemy pewną konwencję dotyc7.ąeą „aryt-
metyki z nieskończonościami". Zakładamy, że dla każdej liczby rzeczywistej
a 'F-- oo zachodzi a+ oo = oo +a= oo. Także dla poprawności dowodów
w razie występowania cykli o ujemnych wagach zakładamy, że dla każdej licz-
by rzeczywistej a 'F-oo zachodzi a + ( - oo) = (- oo) + a = - oo.

25.1. Najkrótsześcieżki i relaksacja


Do zrozumienia algorytmów obliczania najkrótszej ścieżki z pojedynczego
źródła pomocne będzie zrozumienie wykorzystywanych w nich metod i po-
znanie własności najkrótszych ścieżek. Podstawową metodą stosowaną w al-
gorytmach z tego rozdziału jest metoda relaksacji. Polega ona na wielokrot-
nym zmniejszaniu górnego ograniczenia na rzeczywiste wagi najkrótszych
ścieżek, aż te ograniczenia staną się rzeczywistymi wagami najkrótszych ścid­
żek. W tym rozdziale opiszemy zastosowanie tej metody oraz podamy kilka
jej własności.
Czytając ten rozdział po raz pierwszy, można pominąć dowody twierdzeń
- zapoznając się tylko z ich sformułowaniami -i przejść bezpośrednio do opisu
algorytmów w podrozdz. 25.2 i 25.3. Należy jednak zwrócić szczególną uwagę
na lemat 25. 7, który jest istotny dla zrozumienia algorytmów z tego rozdziału.
Przy pierwszym czytaniu można także opuścić lematy dotyczące grafów po-
przedników i drzew najkrótszych ścieżek (lematy 25.8 i 25.9), skupiając się za
to na wcześniejszych lematach odnoszących się do wag najkrótszych ścieżek.

Optymalna podstruktura najkrótszej ścieżki


W algorytmach obliczania najkrótszej ścieżki charakterystyczne jest wykorzys-
tywanie własności, że najkrótsza ścieżka między dwoma wierzchołkami za.wie-
ra w sobie inne najkrótsze ścieżki. Własność optymalnej pod.struktury jest nie-
zmiernie ważna w programowaniu dynamicznym (rozdz. 16) i w metodach
zachłannych (rozdz. 17). W rzeczywistości algorytm Dijkstry jest algorytmem

583
ROZDZIAŁ 25. NAJKRÓTSZE $CIEżKI Z JEDNYM ŻRÓDŁEM

zachłannym, a algorytm znajdowania najkrótszej ścieżki


Floyda-Warshalla
między wszystkimi parami wierzchołków (patrz rozdz. 26) jest algorytmem
programowania dynamicznego. W następującym lemacie sprecyzowano włas­
ność posiadania przez najkrótsze ścieżki optymalnej podstruktury.

LEMAT25.1. (Podścleżld najkrótszych ściet.ek sąnajkrótszymi ścieżkami)


Niech dla danego ważonego grafu skierowanego G = ( V, E) z funkcją wagową
w:E-+ R najkrótszą. ścieżką z wierzchołka v1 do wierzchołka v..,będzie p = (v 1,
v2, ••• , v,.) i dla każdych i, j takich, że 1 ~ i ~j ~ k, niech p 11 = (v 1, v1+ 1, ••• , v1)
będzie pod.ścieżką p z wierzchołka v1 do wierzchołka vl' Wtedy PiJ jest najkrót-
szą ścieżką z V; do vi'

DoWOD
Jeśli rozłoiyroy ścieżkę p na v1 4 v, 4 v1 4 vk>to w(p) = w(p11) + w(py) +
+ w(pJJ. Załóżmy teraz, że istnieje ścieżka pj 1 z wierzchołka v1 do v1 o wadze
w(p[1) < w(pi). Wtedy v1 4 v, 4 v1 4 v..,jest ścieżką z wierzchołka v1 do v..,,
której waga w(p11) + w(plj) + w(p_.J jest mniejsza od w(p), co przeczy założeniu,
że p jest najkrótszą. ścieżką z v1 do vk.


Przy okazji omawiania przeszukiwania wszerz (podrozdz. 23.2) pokazali-
śmy prostą. własność najkrótszych odległości w grafach bez wag (lemat 23.1).
Następujący wniosek z lematu 25.1 uogólnia tę własność na grafy z wagami.

WNIOSEK25.2.
Niech G = (V, E) będzie ważonym grafem skierowanym z f1mkcją wagową
w: E-+ R. Przypuśćmy, że najkrótszą ścieżkę p ze źródła s do wierzchołka
v można rozłożyć nas Ęu-+ v dla pewnego wierzchołka u i pewnej ścieżki p'.
Wtedy waga najkrótszej ścieżki z s do v wynosi 6(s, v) = 6(s, u) + w(u, v).

DoWOD
Z lematu 25.1 wynika, że podścieżka p' jest najkrótszą. ścieżką ze źródła s do
wierzchołka u. Stąd

ó(s, v) - w(p)
- w(p') + w(u, v)
- ó(s, u)+ w(u, v)

W następnym lemacie jest podana prosta, ale użyteczna własność wag
najkrótszych ścieżek.

584
25.1. NAJKRÓTSZE $CIEżKl l RELAKSACJA

LEMAT 25.3.
Niech G = (V, E) będzie ważonym grafem skierowanym z funkcją wagową
w:E-+ R i źródłem s. Wtedy dla każdej krawędzi (u, v)eE zachodzi zależność
ó(s, v),; ó(s, u) + w(u, v).

DOWÓD
Najkrótsza ścieżka p ze źródła s do wierzchołka v nie może mieć większej wagi
niż waga każdej innej ścieżki z s do v. W szczególności ścieżka p nie może mieć
wagi większej niż waga ścieżki składającej się z najkrótszej ścieżki ze źródła
s do wierzchołka u i krawędzi (u, v).

Relaksacja
W algorytmach z tego rozdziału jest zastosowana metoda relaksacji (lub osła­
biania ograniczeń). Dla każdego wierzchołka ve V utrzymujemy atrybut d[v],
którego wartość jest zawsze górnym ograniczeniem wagi najkrótszej ścieżki
ze źródła s do wierzchołka v. Wielkość d[v] nazywamy oszacowaniem wagi
najkrótszej ścieżki. Następująca procedura nadaje wartości początkowe atry-
butom n: id.

INITIALIZE-SINGLE-S0URCE{G, s)
1 for każdy wierzchołek ve V[G]
2 do d[v]+- oo
3 x[v]+- NIL
4 d[s]-o

Po fazie inicjowania mamy x{v]= NIL dla każdego ve V, d[v] = O dla v = s


oraz d[v] = oo, dla ve V - s.
Relaksacja J) krawędzi (u, v) polega na sprawdzeniu, czy przechodząc przez
wierzchołek u, można znaleźć krótszą od dotychcz.as najkrótszej ścieźki do v,
i jeśli taka możliwość istnieje, na zaktualizowaniu d[v] oraz x{v].Podczas relak-
sacji może zostać zmniejszona wartość oszacowania wagi najkrótszej ścieżki
d[v] i może się zmienić poprzednik n:[v].Relaksacja krawędzi (u, v) jest dokony-
wana za pomocą procedury RELAX.

ii Może wydawać się dziwne, że termin reJaksacja jest używany do okreśJenia operacji pole-
gającej na uściśJeniu górnego ograniczenia na wagę ścieżki Użycie tego terminu jest historyczne.
Na wynik wykonania reJaksacji można spojrzeć, jak na osłabienie żądania d[u] ,;,"d[u] + w(u, v),
które Uak wynika z lematu 2S.3) musi być spełnione, jeśli d[u] = ~s, u) i d[u] = i5(s,11).Oznaczato,
że jeśli d[v] ,;,"d[u] + w(u, v), to żadna akcja nie musi być już podjęta, żeby spełnić to żądanie
i w tym sensie nastąpiło jego osłabienie.

585
ROZDZIAŁ 25. NAJKRÓTSZE $CIE.ŻKI Z JEDNYM 1:R0DŁEM

llELAX(u, V, w)
I if d[v] > d[u] + w(u, v)
2 thend[v] -d[u] + w(u, v)
3 11:[v]+-u

Na rysunku 25.3 widać dwa przykłady relaksacji krawędzi. W przykładzie


pierwszym oszacowanie wagi najkrótszej ścieili zmniejsza się, natomiast
w przykładzie drugim żadne oszacowanie się nie zmienia.

u 2 ' 2 '
9 •O •O
R.El..AX(u,v) RELAX(u,v)

u '
'
o 2 ·•
2

(b)
(a)
Rys. 25.3. Relaksacja krawędzi (u, 11).Osmcowanie najkrótsztj ścieżki każdego wierzchołka jest
pokazane wewnątrz tego wierzchołka. (•) Ponieważ tuż prz.ed wykonaniem relaksacji d[v] >
> d[u] + w(u, v). wartość d[v] mmiejsza. się. (b) Tutaj przed relaksacją d[v] .:s;d[u] + w(u, v). zatem
w wyniku działania procedury Rm.Axnie zmienia się wartość d[v]

W każdym z algorytmów omawianych w tym ro:ułziale jest wywoływana


procedura INITJALIZE-SINGLE-SOURCE, a następnie są wielokrotnie wykony-
wane relaksacje krawędzi. Podkreślmy, że relaksacja jest jedynym środkiem
zmiany poprzedników i oszacowań wag najkrótszych ścieżek. Różnice mię­
dzy algorytmami z tego rozdziału dotyczą liczby i kolejności relaksacji po-
szczególnych krawędzi. W algorytmie Dijkstry i w algorytmie dla acyklicz-
nych grafów skierowanych relaksacja każdej krawędzi odbywa się tylko raz.
W algorytmie Bellmana-Forda relaksacje tej samej krawędzi są powtarzane
wielokrotnie.

Własności relaksacji
Poprawność algorytmów z tego rozdziału wynika z ważnych własności relak-
sacji, które zebraliśmy w następnych kilku lematach. Większość z tych lema-
tów opisuje wynik wykonania ciągu relaksacji krawędzi ważonego grafu skie-
rowanego przy założeniu, że została wykonana procedura inicjująca INITIALI·
ZE-SINGLE-SOURCE. Z wyjątkiem lematu 25.9 wszystkie pozostałe lematy mają
zastosowanie do dowolnego ciągu kroków relaksacji, a nie tylko takiego,
w wyniku którego otrzymuje się najkrótsze ścieżki.

586
25.1, NAJKRÓTSZESCIE2Kł ł RELAKSACJA

LEMAT 25.4.
Niech G = (V, E) będzie ważonym grafem skierowanym z funkcją wagową
w:E-+ R i niech (u, v) EE. Wtedy bezpośrednio po wykonaniu RELAX(u, v, w)
zachodzi zależność d[v] ~ d[u] + w(u, v).

DOWÓD
Jeśli tuż przed wykonaniem procedury RELAX(u, v, w) zachodzi nierówność
d[vJ > d[uJ + w(u. v), to po jej wykonaniu mamy d[vJ = d[uJ + w(u, v).
Jeśli natomiast przed relaksacją było d[v] ~ d[u) + w(u, v), to ani d[u], ani d[v]
nie zmieniają się i dlatego po wykonaniu relaksacji nadal zachodzi
d[vJ ,;; d[uJ + w(u, v).

LEMAT25.5.
Niech G = (V, E) będzie ważonym grafem skierowanym z funkcją wagową
w:E-+ R. Niech sE V będzie wierzchołkiem źródłowym i załóżmy, że została
wykonana procedura inicjująca INITIALIZE-SINGLE-SoURCE(G,s). Wtedy dla
każdego wierzchołka v EV zachodzi zależność d[v] ;i:, ó(s, v) i warunek ten
jest niezmiennikiem dowolnego ciągu relaksacji krawędzi grafu G. Ponadto,
kiedy tylko d[v] osiągnie swoje dolne ograniczenie ó(s, v), nigdy więcej nie
ulega zmianie.

DOWÓD
Niezmiennik d[v] ;i:, ó(s, v) jest oczywiście prawdziwy bezpośrednio po fazie
inicjowania, ponieważ d[s] = O ;i:: ó(s, s) (zauważmy, że ó(s, s) jest równe - oo,
jeśli s należy do cyklu o ujemnej wadze, lub jest równe O w przeciwnym razie),
a d[v] = oo implikuje d[vJ;,, ó(s, v) dla karoego ve V- {s). Pokażemy przez
doprowadzenie do sprzeczności, że warunek d[v] ;i:: ó(s, v) jest nie201iennikiem
dla dowolnego ciągu kroków relaksacji. Niech v będzie pierwszym wierzchoł­
kiem, dla którego w wyniku wykonania relaksacji krawędzi (u, v) otrzymujemy
d[v] < ó(s, v). Wtedy tuż po relaksacji krawędzi (u, v) mamy

d[uJ + w(u, v) = d[vJ


< ó(s, v)
,;; ó(s, u) + w(u, v) (z lematu 25.3)

co pociąga za sobą d[u] < ó(s, u). Ale ponieważ relaksacja krawędzi (u, v) nie
zmienia wartości d[u], więc ta nierówność musiała być prawdziwa tuż przed
relaksacją (u, v), co przeczy naszemu wyborowi v jako pierwszego wierzchołka,
dla którego d[v] < ó(s, v). Wnioskujemy stąd, że niezmiennik d[v] ;i:: ó(s, v) jest
utrzymany dla wszystkich v E V.

587
ROZDZIAŁ 25. NAJKRÓTSZE $CIEżKI Z JEDNYM l:RÓOŁEM

żeby się przekonać, że wartość d[v] nigdy się nie zmienia, jeżeli tylko
d[v] = J;(s,v), zauważmy, iż po osiągnięciu wartości swojego dolnego ogranicze-
nia d[v] nie może już zmaleć, ponieważ właśnie udowodniliśmy, że d[v] ~ J;(s,v).
Nie może też wzrosnąć, ponieważ relaksacja nie zwiększa wartości d.

WNIOSEK25.6.
Załóżmy, że w ważonym grafie skierowanym G = (V, E) z funkcją wagową
w:E - R nie istnieje ścieżka ze źródła se V do danego wierzchołka v e V.
Wtedy po fazie inicjowania za pomocą procedury INITIALIZB-SINGLE-SOUR
CE(G,s) mamy d[v] = J;(s,v) i równość ta jest niezmiennikiem dowolnego ciągu
relaksacji krawędzi grafu G.

Dowon
Z lematu 25.5 wynika, że zawsze zachodzą zależności oo = ó(s, v) .,e::;d[v]. Tak
więc d[v] = co=/i(s, v).


Następujący lemat jest podstawowy w dowodzeniu poprawności algoryt-
mów dla problemu najkrótszych ścieżek omawianych dalej w tym rozdziale.
Podaje on warunki wystarczające dla relaksacji, które gwarantują, że oszaco-
wania wag najkrótszych ścieżek dążą do ich rzeczywistych wag.

LEMAT25.7.
Niech G = (V, E) będzie ważonym grafem skierowanym z funkcją wagową
w:E - R, niech se V będzie wierzchołkiem źródłowym i niech s ~ u - v będzie
najkrótszą ścieżką w grafie G dla pewnych wierzchołków u, ve V. Przypuśćmy,
że została wykonana procedura inicjująca INITIALIZE-SINGLE-SOURCE(G, s),
a następnie został wykonany ciąg kroków relaksacji zawierający wywołanie
procedury RELAX(u,v, w). Jeśli w dowolnej chwili przed wywołaniem procedu-
ry RELAX(u, v, w) zachodzi d[u] = D(s, u), to po wykonaniu tej procedury
zawsze zachodzi d[v] = J;(s,v).

DoWOD
Z lematu 25.5 wynika, że jeśli d[u] = D(s,u) w pewnym punk.cie przed wykona-
niem relaksacji krawędzi (u, v), to ta równość pozostaje prawdziwa po wykona-
niu tego kroku. W szczególności, po wykonaniu relaksacji krawędzi (u, v) mamy

d[v] <; d[u] + w(u, v) (z lematu 25.5)


= li(r, u)+ w(u, v)
= li(s, v) (z wniosku 25.2)

588
25.1. NAJKRÓTSZE ŚClEżKI I RELAKSACJA

Z lematu 25.5 wynika, że b(s, v) ogranicza d[v] z dołu. Stąd wnioskujemy, że


d[v] = b(s, v) i ta równość od tego czasu się nie zmienia.

Drzewo najkrótszychścieżek
Dotychczas pokazaliśmy, że relaksacja powoduje monotoniczną zbieżność
oszacowań wag naJk:rótszych ścieżek do ich rzeczywistych wag. Chcielibyśmy
także pokazać, że kiedy w wyniku wykonania ciągu relaksacji są już policzone
rzeczywiste wagi najkrótszych ścieżek, graf poprzedników G„jest drzewem naj-
krótszych ścieżek dla grafu G. Rozpoczniemy od następującego lematu, z któ-
rego wynika, że graf poprzedników jest zawsze drzewem o korzeniu w źródle.

LEMAT 25.8.
Niech G = (V, E) będzie ważonym grafem skierowanym z funkcją wagową
w:E-+ R i wierzchołkiem źródłowym se V. Załóżmy, że graf G nie ma cykli
o ujemnych wagach, które są osiągalne ze źródła s. Wtedy po fazie inicjowania
za pomocą procedury lNITIALIZE-SINGLE-SoURCE(G,s) graf poprzedników G„
jest drzewem z korzeniem ws, a własność ta jest niezmiennikiem każdego ciągu
kroków relaksacji wykonywanych na krawędziach grafu G.

DOWÓD
Początkowo jedynym wierzchołkiem w grafie G„ jest źródło si lemat jest oczy-
wiście prawdziwy. Rozważmy graf poprzedników powstający w wyniku wyko-
nania pewnego ciągu kroków relaksacji. Udowodnimy najpierw, że graf G„jest
acykliczny. Załóżmy przeciwnie, że pewien krok relaksacji powoduje utworze-
nie cyklu w grafie G,.. Niech tym cyklem będzie c = (v 0 , v1, ••• , vk), gdzie
vk = v0 • Wówczas x[v;] = v,_1, dla i= I, 2, ... , k, i możemy założyć (bez straty
ogólności), że krawędzią, dla której wykonanie relaksacji spowodowało po-
wstanie cyklu w grafie G1r,jest (vk_1, vJ.
Zauważmy, że wszystkie wierzchołki na cyklu c są osiągalne ze źródła s.
Dlaczego? Poprzednik każdego wierzchołka na cyklu c jest różny od NIL. Dla-
tego z każdym wierzchołkiem na cyklu c zostało związane pewne skończone
oszacowanie najkrótszej ścieżki właśnie wtedy, kiedy została mu przypisana
wartość n: różna od NIL. Z lematu 25.5 wynika, że każdy wierzchołek na cyklu
c ma skończoną wagę najkrótszej ścieżki, co implikuje, że wierzchołki na cyklu
c są osiągalne ze źródła s.
Zbadamy oszacowania wag najkrótszych ścieżek dla wierzchołków z cy-
klu c tuż przed wywołaniem RELAX(vk_1, vk, w) i pokażemy, że c jest
cyklem o ujemnej wadze. Otrzymamy w ten sposób sprzeczność z założeniem,
że graf G nie ma cykli o ujemnych wagach, osiągalnych ze źródła. Tuż przed
wywołaniem RELAX mamy n:[vJ = v1_ 1 dla i= 1, 2, ... , k- 1. Stąd dla

589
ROZDZIAŁ 25. NAJKRÓTSZE $CIEżKI Z JEDNYM ŻRĆDŁEM

i = 1, 2. ..., k - 1 ostatnia aktualizacja d(vJ polegała na wykonaniu przypisa-


nia d[viJ+- d[v,_1] + lll{v1, v1_ 1). Jeśli d[v1_ 1] zmieniło swoją wartość od tego
czasu, to ta wartość mogła tylko zmaleć. Dlatego tuż przed wywołaniem
RELAX(vk-1•V.tł w) zachodzi

d[v,J;, d[v,_,J+ w(v,_., v,) dla każdego i- I, 2, ..., k - ł (25.l)

Ponieważ n:[vk]jest zmieniane w wyniku tego wywołania, bezpośrednio przed


tym wywołaniem zachodzi takle ostra nierówność

d[v,J > d[v,_,J + w(v,_,, vJ

Dodając stronami tę nierówność z k - l nierównościami (25.1), otrzymujemy


ograniczenie na sumę oszacowań wag najkrótszych ścieżek dla wierzchołków
na cyklu c:

•L d[v,] > I• (d[v,_,] + w(v,_,,v,))


I= 1 I= 1

• •
- I d[v,_,J+ I w(v,_,,v,)
J=l l=l

Ale

•L d[v,J- I• d[v,_,J
i=l i=l

ponieważ każdy wierzchołek z cyklu c pojawia się tylko raz w każdej sumie.
Stąd otrzymujemy


O> I w(v,_,, v,)
I= l

Zatem suma wag krawędzi na cyklu jest ujemna - sprzeczność z założeniem.


Udowodniliśmy w ten sposób, że G„ jest acyklicznym. grafem skierowa-
nym. żeby pokazać, że jest to drzewo z korzeniem w s wystarczy udowodnić
(patrz zad. 5.5-3), że dla ka2:dego wierzchołka ve V„ istnieje w grafie G„ do-
kładnie jedna ścieżka ze źródła s do wierzchołka v.
Musimy najpierw pokazać, że dla każdego wierzchołka z V,..istnieje w G„
ścieżka ze źródła s. Wier7.Chołk:ami w V,..są wierzchołki, dla których wartość
n: jest różna od NIL, plus wierzchołek. s. Istnienie ścieżek, o których jest mowa
powyżej, można udowodnić indukcyjnie. Szczegóły pozostawiamy czytelnik.o-
wi jako zadanie 25.1-f,.

590
25.1. NAJKRÓTSZE $CIEŻKI I RELAKSACJA

Dopełności dowodu lematu brakuje dowodu faktu, że dla każdego wierz-


chołka vE V„ istnieje w grafie G„ co najwyżej jedna ścieżka ze źródła s do
wierzchołka v. Załóżmy przeciwnie, że istnieją dwie ścieżki proste ze źródła
s do pewnego wierzchołka v: p 1, którą można rozłożyć na s""' u""' x-+ z""' v,
i p2, którą można rozłożyć nas""' u""' y-+ z""' v, gdzie x =I=-y (patrz rys. 25.4).
Ale wtedy x[z] = x i x[z] = y, co pociąga za sobą x = y - sprzeczność. Wnios-
kujemy zatem, że w grafie G„ istnieje dokładnie jedna ścieżka ze źródła s do
wierzchołka v i dlatego G„ jest drzewem o korzeniu ws. +

Rys. 25.4. Ilustracja tego, że w Gwjesl dokładnie jedna ścieżka z J do v. Je&lisą dwie ścieżki, p 1
(s .....u .....x .....z--+ v) i p 2 (s .....u .....y .....z .....v), gdzie x #- y, to n[z} = x i n(z] = y - sprzeczność

Pokażemy teraz, że jeśli po wykonaniu ciągu kroków relaksacji wszystkie wie-


rzchołki mają przypisane swoje rzeczywiste wagi najkrótszych ścieżek, to graf
poprzedników G„ jest drzewem najkrótszych ścieżek,

LEMAT 25.9.
Niech G = (V, E) będzie ważonym grafem skierowanym z funkcją wagową
w:E-+ R i wierzchołkiem źródłowym sE V. Załóżmy, że graf G nie zawiera
cykli o ujemnych wagach, które są osiągalne ze źródła s. Jeśli po wykonaniu
procedury inicjującej INITIALIZE-SINGLE-SOURCE(G, s), a następnie po wyko-
naniu dowolnego ciągu kroków relaksacji na krawędziach grafu G zachodzi
d[v] = ó(s, v) dla wszystkich vE V, to podgraf poprzedników G,..jest drzewem
najkrótszych ścieżek o korzeniu w s.

DOWÓD
Musimy udowodnić, że graf G„ ma wszystkie trzy własności drzewa najkrót-
szych ścieżek. Aby udowodnić pierwszą własność, musimy wykazać, że V„ jest
zbiorem wszystkich wierzchołków osiągalnych ze źródła s. Z definicji waga
najkrótszej ścieżki ó(s, v) jest skończona wtedy i tylko wtedy, gdy wierzchołek
v jest osiągalny ze źródła s. Dlatego wierzchołki osiągalne z ssą dokładnie tymi
ze skończonymi wartościami d. Ale z wierzchołkiem vE V-{s} została związa­
na skończona wartość d[v] wtedy i tylko wtedy, gdy x[v] "FNIL.Dlatego wierz-
chołki z V„ są dokładnie tymi, które są osiągalne ze źródła s.
Druga własność wynika bezpośrednio z lematu 25.8.
Pozostaje do udowodnienia ostatnia własność drzewa najkrótszych ście­
żek: dla każdego v E V,rjedyna ścieżka s .!,.v w grafie G„jest najkrótszą ścieżką

591
ROZDZIAŁ 25. NAJKRÓTSZE $CIE2KI Z JEDNYM 2:RODŁEM

ze źródła s do wierzchołka v w grafie G. Niech p = (v 0 , v1, ••• , v.t-), gdzie


v0 =si V.t- = v. Dla i= 1, 2, ... , k zachodzi d[vJ = ó(s, vJ i d[vJ ~ d[v 1_ 1] +
+ w(v1_ 1, vJ, co daje w(v1_ 1, v1)" ó(s, vJ- ó(s, v1_ 1). Sumując wagi krawędzi
ścieżki p, otrzymujemy


w(p) = L w(v,_,, vj
!ce t


,; L (o(s, vJ - o(s, v,_,))
J= 1

= o(s, v,) - o(s, v,,)


= o(s, v,)
Sumowanie w drugim wierszu jest sumowaniem teleskopowym. Czwarty
wiersz wynika stąd, że ó(s, vo) = ó(s, s) = O. Dlatego w(p) ::!:'.;ó(s, V,t-),Ponieważ
ó(s, vJ jest dolnym ograniczeniem wagi każdej ścieżki ze źródła s do wierzchoł­
ka vk wnioskujemy, że w(p) = ó(s, vk). Stąd wynika, że p jest najkrótszą ścieżką
ze źródła s do wiem:hołka v = vk'

ZADANIA
25.1-1. Znajdź dwa drzewa najkrótszych ścieżek w grafie z rys. 25.2 inne niż te
przedstawione na rysunku.
25.1-2. Podaj przykład ważonego grafu skierowanego G = (V, E), z funkcją
wagową w: E _,. R i źródłem s, o następującej własności: dla każdej krawę­
dzi (u, v) EE istnieją dwa drzewa najkrótszych ścieżek o korzeniach w s,
z których jedno zawiera krawędź (u, v), a drugie nie zawiera tej krawędzi.
25.1-3. Uwzględnij w dowodzie lematu 25.3 przypadki, w których wagi naj-
krótszych ścieżek wynoszą oo lub - oo.
25.1-4. Niech G = (V, E) będzie ważonym grafem skierowanym z wierzchoł­
kiem źródłowym s. Załóżmy, że dla grafu G wykonano procedurę inicjują­
cą INITIALIZB-SINGLE-SOURCE(G, s). Udowodnij, że jeżeli w wyniku wy-
konania ciągu kroków relaksacji wartość n{s]jest różna od NIL, to graf G
ma cykl o ujemnej wadze.
25.1-5. Niech G = (V, E) będzie ważonym grafem skierowanym o nieujem-
nych wagach na krawędziach. Niech se V będzie źródłem i niech wartością
7t[v]będzie, jak zazwyczaj, poprzednik wierzchołka v na pewnej najkrótszej
ścieżce ze źródła s do v, jeśli v e V - {s} jest osiągalne z s, a NIL w przeciw-
nym razie. Podaj przykład takiego grafu G oraz wartości n, które dają cykl
w grafie G,.. (Z lematu 25.8 wynika, że takich wartości nie można uzyskać
w wyniku wykonania ciągu relaksacji krawędzi grafu G).

592
25.2. ALGORYTM DIJKSTRY

25.1-6. Niech G = (V, E) będzie ważonym grafem skierowanym z funkcją wa-


gową w: E-+ R. Załóżmy, że graf G nie ma cykli o ujemnych wagach.
Niech sE V będzie źródłem i załóimy, że została wykonana procedura
inicjująca INITIALIZE-SINGLE-SOURCE(G, s). Udowodnij, że dla każdego
wierzchołka vE V„ istnieje w grafie G'II,
ścieżka ze źr6dla s oraz że ta włas­
ność jest niezmiennikiem dla kai.dego ciągu kroków relaksacji.
25.1-7. Niech G = (V, E) będzie ważonym grafem skierowanym bez cykli
o ujemnych wagach, a sE V niech będzie źródłem. Załóżmy, że została
wykonana procedura inicjująca lNITIALIZE-SINGLB-S0URCE(G, s). Udo-
wodnij, że istnieje ciąg IVI- 1 kroków relaksacji w wynik.uktórego otrzy-
mujemy d[v] = 6(s, v) dla każdego vE V.
25.1-8. Niech G = (V, E) będzie dowolnym ważonym grafem skierowanym,
w którym cykl o ujemnej wadze jest osiągalny ze źr6dla s. Pokaż, że za-
wsze można skonstruować tak.i nieskończony ciąg krawędzi grafu G, że
relaksacja każdej krawędzi z ciągu 2JD.ieniaoszacowanie pewnej najkrót-
szej ścieżki.

25.2. AlgorytmDijkstry

Algorytm Dijkstry służy do rozwiązywania problemu najkrótszych ścieżek


z jednym źródłem w ważonym grafie skierowanym G = (V, E) w przypadku,
gdy wagi wszystkich krawędzi są nieujemne. W tym rozdziale zakładamy więc,
że w(u, v) ~ O dla każdej krawędzi (u, v) EE.
W algorytmie Dijkstry jest pamiętany zbiór S zawierający te wierzchołki,
dla których wagi najkrótszych ścieżek ze źródła s zostały już obliczone. To
znaczy, że dla każdego wierzchołka veS mamy d[v] = ó(s,v). Algorytm Dijks-
try polega na wielokrotnym powtarzaniu następujących operacji: wybrania
wierzchołka ue V - S o najmniejszym oszacowaniu wagi najkrótszej ścieżki,
dodania wierzchołka u do S, wykonania relaksacji krawędzi opuszczających
wierzchołek u. W przedstawianej przez nas implementacji wierzchołki ze zbioru
V - S znajdują się w kolejce priorytetowej Q. Kluczami, według których wie-
rzchołki są zorganizowane w kolejce, są wartości d. W tej implementacji zakła­
da się, że graf G jest reprezentowany przez listy sąsiedztwa.

DIJKSTRA(G, w, s)
1 INITIALIZE-SINGLE-SOURCE(G, s)
2 S+-0
3 Q - J,'[G]
4 whileQ,'0
5 do u -EXTRACT-MIN(Q)

593
ROZDZIAŁ 25. NAJKRÓTSZE $CIEżKI Z JEDNYM lRĆOŁEM

6 s-su{u}
7 for każdy wierzchołek veAdj[u]
8 do RELAX(u, v, w}

Algorytm Dijkstry dokonuje relaksacji krawędzi w sposób pokazany na


rys. 25.5. W wierszu 1 atrybutom d i n są nadawane wartości początkowe,
a w wierszu 2 zbiór Sjest inicjowany jak.o pusty. W wierszu 3 jest inicjowana
kolejka priorytetowa Q. Początkowo zawiera ona wszystkie wierzchołki ze
zbioru V - S = V - 0 = V. W każdej iteracji pętli wbile (wiersze 4-8) ze zbio~
ro Q = V - Sjest usuwany wierzchołek u z najmniejszym kluczem, a następnie
ujest wstawiany do zbioru S. (W pierwszej iteracji u = s}. Dlatego oszacowanie
wagi najkrótszej ścieżki dla wierzchołka u jest najmniejsze spośród oszacowań
dla wierzchołków z V - S. Następnie (wiersze 7~8}na każdej krawędzi (u, v)
opuszczającej wierzchołek u jest wykonywana relaksacja i jeśli ścieżka prowa~
dząca do v przez wierzchołek u ma mniejszą wagę, to oszacowanie d(v] oraz
poprzednik 1t[v]są aktualizowane. Zauważmy, że poza wierszem 3 wierzchołki
nie są nigdy wstawiane do kolejki Qi że każdy wierzchołek jest dokładnie raz

' o

X X y
(•) ' (b) (c)

X y
(d) (o) (0
Rys. 25.5. Ilustracja działania algorytmu Dijkstry. źródłem jest wierzchołek po lewej stronie. Osza-
cowania najkrótszych ścieżek znajdują się wewnątrz wierzchołków. Krawędzie mcieniowane wy-
znaczają poprndniki w drzewie G.: jeśli krawędź (u, v) jest zacieniowana, to n [vJ= u. Czarne
wierzchołki są elementami zbioru S, a białe znajdują się w kolejce priorytetowej Q = V- S. (a)
Sytuacja tuż przed wykonaniem pierwszej iteracji pętli whlle w wierszach 4-8. Wierzchołek 1.acie-
niowany ma najmniejszą wartość di jest wybierany w wierszu S jak.o wierzchołek u. (bKf) Sytuacja
po każdej kolejnej iteracji pętli wllile. Zacieniowany wierzchołek w każdej części jest wybierany
w wierszu S następnej iteracji jak.o wierzchołek: u. Wartości di n pokazane w części (f) są warto-
ściami końcowymi

594
25.2. ALGORYTM OIJKSTRY

usuwany z kolejki Q i wstawiany do zbioru S, tak więc liczba iteracji pętli while
(wiersze 4-8) wynosi IVI.
Ponieważ w algorytmie Dijkstry do zbioru S jest dodawany „najlżejszy"
lub „najbliższy" wierzchołek z V - S, mówimy, że w tym algorytmie jest za-
stosowana strategia zachłanna. Strategie zachłanne zostały szczegółowo omó-
wione w rozdz. 17, ale znajomość materiału z tamtego rozdziału nie jest po-
trzebna do zrozumienia algorytmu Dijkstry. W ogólności, stosując strategie
zachłanne, nie zawsze otrzymamy optymalne rozwiązania, ale algorytm Dijkst-
ry rzeczywiście oblicza najkrótsze ścieżki. Przekonamy się o tym, udowadnia-
jąc twierdzenie 25.10 i wniosek 25.11. Najważniejsze w dowodzie poprawności
algorytmu Dijkstry jest pokazanie, że dla każdego wierzchołka u dodawanego
do S mamy d[uJ - ó(s, u).

fwIERDZENIE 25.10. (Poprawność algorytmuDijkstry)


Jeśli wykonamy algorytm Dijkstry dla ważonego grafu skierowanego G =
= (V, E) z nieujemną funkcją wagową w i źródłem s, to po zakończeniu dzia-
łania algorytmu zachodzi równość d{u] = ó(s, u) dla każdego wierzchoł­
ka UE V.

DOWÓD
Udowodnimy, że d[uJ = ó(s, u) w chwili wstawiania wierzchołka u do zbioru S,
dla każdego u E V, i że ta równość nie zmienia się do końca działania al-
gorytmu.
Załóżmy przeciwnie. Niech u będzie pierwszym wierzchołkiem, dla którego
d[u] 'F-ó(s, u), gdy jest on wstawiany do S. Skoncentrujemy uwagę na sytuacji
na początku iteracji pętli while, w której wierzchołek u jest wstawiany do S;
uzyskamy sprzeczność z przyjętym założeniem, rozpatrując najkrótszą ścieżkę
z s do u. Ponieważ s jest pierwszym wierzchołkiem wstawianym do zbioru S
i d[sJ= ó(s, s), więc u 'F-s. Skoro u 'F s, to zbiór S nie jest pusty tuż przed
wstawieniem do niego wierzchołka u. W grafie G musi istnieć ścieżka ze źród­
ła s do u, w przeciwnym razie d[u] = ó(s, u) = oo (patrz wniosek 25.6), wbrew
założeniu, że d[u] 'F-ó(s, u). Ponieważ ze źródła s do u prowadzi co najmniej
jedna ścieżka, istnieje zatem najkrótsza ścieżka p z s do u. Ścieżka p łączy
wierzchołek. z S, mianowicie źródło s z wierzchołkiem u z V - S. Rozważmy
pierwszy wierzchołek y na ścieżce p, taki że yE V - S, i niech xe V będzie
poprzednikiem y na ścieżce p. Wtedy, jak widać na rys. 25.6, ścieżkę p można
rozłożyć na s !!; x -+ y !?.:;
u.
Pokażemy, że gdy wierzchołek. u jest dodawany do S, .zachodzi d[y] =
= ó(s, y). żeby udowodnić ten fakt, zauważmy, że xeS. Ponieważ u jest
pierwszym wierzchołkiem, dla którego d[u] =f. i5(s, u) przy wstawianiu do S,
więc w chwili wstawiania wierzchołka x do zbioru S, zachodziło d[x] = ó(s, x).
W tym samym czasie nastąpiła relaksacja krawędzi (x, y). Prawdziwość faktu

595
ROZDZIAŁ 25. NAJKRÓTSZE ŚCIE2KI Z JEDNYM lR0DŁEM

Rys. 25.6. Dowód twierdzenia 25.10. Tuż przed wstawieniem wierzchołka u do S zbiór Sjest niepu-
sty. Najkrótszą. ścieżkę p :re źródła s do wierzchołka u można podzielić nas 4x-+ y,... 4 u, gdzie
y jest pierwszym wierzchołkiem na ścieżce nie należącym do V-Si wierzchołek. xeS bezpośred­
nio poprzedza y. Wierzcholk::ix i y są różnymi wierzchołkami, ale może być s = x lub y = u.
Ścieżka p 2 może, ale nie musi, zawierać wierzchołków ze zbioru S

wynika zatem z lematu 25.7. Ponieważ wierzchołek y występuje przed wie-


rzchołkiem u na najkrótszej ścieżce ze źródła s do u i wagi wszystkich krawędzi
są nieujemne (w s7.Cugólności tych ze ścieżki pJ, ;,.a.chodził>(s, y) ~ ł>(s, u),
a stąd
d[y] = li(s, y)
~ ó(s, u) (25.2)
.; d[u] (z lematu 25.5)

Ponieważ jednak: oba wier7.Chołki u i y znajdowały się w zbiorze V - S w chwili


wyboru wierzchołka u w wierszu 5, mamy d[u] ~ d[y]. Tak więc obie nierów-
ności w (25.2) są w rzeczywistości równościami. Stąd otrzymujemy

d[y] = li(s, y) = li(s, u) = d[u]

W konsekwencji d[u] = ó(s, u), co jest sprzeczne z naszym wyborem wierzchoł­


ka u. Pokazaliśmy zatem, że w chwili wstawiania każdego wierzchołka u e V do
zbioru S, zachodzi d[u] = b(s, u). Z lematu 25.5 wynika zaś, że ostatnia rów-
ność pozostaje prawdziwa już do końca działania algorytmu.


WNIOSEK.25.11.
Jeśli wykonamy algorytm Dijkstry dla ważonego grafu skierowanego G =
= (V, E) z nieujemną funkcją wagową w i źródłem s, to po zakończeniu
jego działania graf poprzednik.ów G'II:jest drzewem najkrótszych ścieżek. z ko-

rzen1em ws.

DOWÓD
Bezpośredni wniosek z twierdzenia 25.1 i lematu 25.9,

596
25.2. ALGORYTM DIJKSTRY

Analiza
Jak szybki jest algorytm Dijkstry? Rozważmy najpierw przypadek, w którym
kolejka priorytetowa Q = V - Sjest zaimplementowana za pomocą tablicy
liniowej. W tej implementacji każda operacja EXTRACT-MIN zabiera czas
O(V). Ponieważ wykonywanych jest IV I takich operacji, łączny czas ich wyko-
nania wynosi O( V2).Każdy wierzchołek jest wstawiany do zbioru S dokładnie
raz, każda krawędź z listy sąsiedztwa Aąj[v] jest więc badana w pętli for
w wierszach 4-8 dokładnie raz w trakcie działania algorytmu. Łączna liczba
krawędzi na listach sąsiedztwa wynosi IE].Stąd wynika, że łączna liczba itera-
cji pętli for wynosi IEI.Każda pojedyncza iteracja jest wykonywana w czasie
stałym. Czas działania całego algorytmu wynosi zatem O(V2 + E) = O(Y1).
Dla grafów rzadkich lepiej implementować kolejkę priorytetową za po-
mocą kopca binarnego. Otrzymany w ten sposób algorytm jest cza.sami na-
zywany zmodyfikowanymalgorytm.emDijkstry. Każda operacja ExrRACT-
-MIN zabiera wtedy czas O(lg V). Jak poprzednio, jest wykonywanych IVI
takich operacji. Czas budowy kopca wynosi O(V). Przypisanie d[v] +- d[u] +
+w(u, v) w procedurze RELAX jest realizowane przez wywołanie DECREASE-
·KEY(Q, v, d[u] + w(u, v)), co zabiera czas O(Jg V) (patrz zad. 7.5-4). Takich
operacji jest co najwyżej IEI.Łączny czas wykonania tych operacji wynosi
zatem O((V + E)lgV), co jest równe O(Elg V), jeśli wszystkie wierzchołki są
osiągalne ze źródła.
W rzeczywistości możemy osiągnąć czas O(Vlg V+ E), implementując
kolejkę priorytetową za pomocą kopca Fibonacciego (patrz rozdz. 21). Zamor-
tyzowany koszt każdej z IVI operacji EXTRACT-MIN wynosi O(lg V), a każda
z ]Ej operacji DECREASE-KEYjest wykonywana w zamortyzowanym czasie
0(1 ). Historycznie rzecz biorąc, rozwój kopców Fibonacciego był motywowa-
ny obserwacją, że w zmodyfikowanym algorytmie Dijkstry potencjalnie wielo-
krotnie częściej wywołuje się DECREASE-KEY niż EXTRACT-MIN. Tak więc
każda metoda redukcji cza.su zamortyzowanego operacji DECREASE-KEYdo
o(lg V), bez wzrostu czasu zamortyzowanego operacji EXTRACT-MIN, prowa-
dziłaby do asymptotycznie szybszej implementacji algorytmu Dijkstry.
Algorytm Dijkstry wykazuje pewne podobieństwa zarówno do przeszu-
kiwania wszerz (patrz podrozdz. 23.2), jak i do algorytmu Prima obliczania
minimalnych drzew rozpinających (patrz podrozdz. 24.2). W przypadku prze-
szukiwania wszerz zbiór S odpowiada zbiorowi czarnych wierzchołków; po-
dobnie jak wierzchołki z S, które mają już obliczone swoje końcowe wagi
najkrótszych ścieżek, czarne wierzchołki w przeszukiwaniu wszerz mają ob-
liczone swoje najkrótsze odległości od źródła. W przypadku algorytmu Prima
podobieństwo polega na użyciu w obu algorytmach kolejki priorytetowej do
znajdowania „najlżejszego" wierzchołka spoza danego zbioru (zbioru S w al-
gorytmie Dijkstry i rozrastającego się drzewa w algorytmie Prima), dodawaniu

597
ROZDZIAŁ 25. NAJKRÓTSZE $CJEŻKI Z JEDNYM lRÓOŁEM

takiego wierzchołkado tego zbioru i odpowiednim poprawianiu wag wierz-


chołków pozostających poza tym zbiorem.

ZADANIA
25.:2-.1.Wykonaj algorytm Dijkstry dla grafu z rys. 25.2, najpierw przyjmując
za źródło wierzchołek s, a następnie wierzchołek y. W ten sam sposób jak
na rys. 25.5 pokaż po każdej iteracji pętli wbile wartości di 1t oraz wierz-
chołki zbioru S.
25.2-2. Podaj przykład prostego grafu skierowanego z ujemnymi wagami
na krawędziach, dla którego algorytm Dijkstry daje niepoprawne roz-
wiązanie. Dlaczego dla wag ujemnych dowód twierdzenia 25.10 nie jest
poprawny?
25.2-3, Przypuśćmy, że wiersz 4 w algorytmie Dijkstry został zmieniony na-
stępująco:

4 wbile IQI> I

Zmiana ta powoduje, że pętla whilejest wykonywana ]VI -1 razy zamiast


IV! razy. Czy ten algorytm jest poprawny?
25.2-4. Dany jest graf skierowany G = (V, E), w którym z kaWą krawędzią
jest związana liczba rzeczywista r(u, v) z przedziału [O, 1]. Liczba ta re-
prezentuje niezawodność kanału komunikacyjnego z wierzchołka u do wie-
rzchołka v. Wielkość r(u, v) interpretujemy jako prawdopodobieństwo, że
kanał między wierzchołkami u i v nie zostanie uszkodzony. Zakładamy, że
prawdopodobieństwa są niezależne. Podaj efektywny algorytm znajdowa-
nia najbardziej niezawodnej ścieżki między danymi dwoma wierzchołkami.
25.2-S. Niech G = (V, E) będzie ważonym grafem skierowanym z funkcją wa-
gową w: E - { O, I, ..., W - 1} dla pewnej nieujemnej liczby całkowitej W.
Zmodyfikuj algorytm Dijkstry w taki sposób, żeby obliczał najkrótsze
ścieżki z danego źródła s w czasie O(WV + E).
25.U. Zmodyfikuj swój algorytm z zad. 25.2-5 w taki sposób, żeby działał
w czasie O((V + E)lgW}. (Wskazówka: Ile parami różnych oszacowań
wag najkrótszych ścieżek mogą mieć wierzchołki w zbiorze V - S w każdej
chwili obliczeń?)

25.3. AlgorytmBellmana-Forda
Algorytm Bellmaoa-Forda służy do rozwiązywania problemu najkrótszych ście­
żek z jednego źródła w ogólniejszym przypadku, w którym wagi na krawę­
dziach mogą być ujemne. Dla danego ważonego grafu skierowanego G =
= (V, E) ze źródłem s i funkcją wagową w:E - R algorytm Bellmana-Forda

598
25.3. ALGORYTM BELLMANA-FOADA

zwraca wartość logiczną wskazującą, czy istnieje lub nie cykl o ujemnej wadze
osiągalny ze źródła. Jeśli taki cykl istnieje, to algorytm informuje, że najkrót-
szych ścieżek w grafie G nie można obliczyć. Jeśli takiego cyklu nie ma, ta
algorytm oblicza najkrótsze ścieżki i ich wagi.
Podobnie jak w algorytmie Dijkstry, w algorytmie Bellmana-Forda wyko-
rzystuje się metodę relaksacji, zmniejszając stopniowo oszacowanie d[v] na
wagę najkrótszej ścieżki ze źródła s do każdego wierzchołka v e V, aż zostanie
osiągnięta rzeczywista waga najkrótszej ścieżki łi(s, v). Algorytm zwraca war-
tość logiczną TRUE wtedy i tylko wtedy, gdy graf nie zawiera cykli o ujemnych
wagach osiągalnych ze źródła.

BELLMAN-FORD(G,w, s)
1 INJTIALIZE-SINGLB-SoURCE(G, s)
2 for;- I to IV[G]l-1
3 do for każda krawędź (u, v)eE[G]
4 do RBLAX(u,v, w)
5 for każda krawędź (u, v) e E[G]
6 do if d[v] > d[u] + w(u, v)
7 then return F ALSE
8 return TRUE

Rysunek 25.7 ilustruje działanie algorytmu dla grafu z pięcioma wierzchoł­


kami. Po wykonaniu inicjacji algorytm przetwarza krawędzie grafu w IVI - 1
przebiegach. Każdy przebieg jest jedną iteracją pętli for z wierszy 24 i polega
na jednorazowej relaksacji każdej krawędzi. Na rysunkach 25.7(b)-{e) jest po-
kazany stan algorytmu po każdym z 4 przebiegów. Po wykonaniu wszystkich
IVI - 1 przebiegów w wierszach 5-8 sprawdza się, czy istnieje cykl o ujemnej
wadze, i zwraca właściwą wartość logiczną.
Algorytm Bellmana-Forda działa w czasie O(VE). Proces inicjowania
w wierszu 1 zajmuje czas 0(V), każdy z IVIprzebiegów w wierszach 2-4 zabiera
czas O(E), a pętla for w wierszach 5-7 jest wykonywana w czasie O(E).
Dowód poprawności algorytmu Belhnana-Forda rozpoczniemy od poka-
zania, że jeśli nie ma cykli o ujemnych wagach, to algorytm oblicza poprawne
wagi najkrótszych ścieżek dla wierzcholk.ów osiągalnych ze źródła. Dowód
lematu ułatwia intuicyjne zrozumienie algorytmu.

LEMAT25.12.
Niech G = ( V, E) będzie ważonym grafem skierowanym ze źródłem s i funkcją
wagową w: E ~ R. Zalóimy, że G niema cykli o ujemnych wagach osiągalnych
ze źródła s. Wtedy po zakończeniu działania algorytmu Bellmana-Forda za-
chodzi równość d[v] = ó(s, v) dla wszystkich wierzchołków v osiągalnych
ze źródła s.

599
ROZDZIAŁ 25. NAJKROTSZE $ClEŻKI Z JEDNYM 2:R0DŁEM

(•) (b) (c)

(d) (o)

Rys. 25.7. Działanie algorytmu Bellmana-Forda. Żrodłem.jest wienchołek z. Wartości dznajdują się
wewnątrz wierzchołków, a krawędzie zacieniowlllle wymaczają wartości n. W tym szczególnym
przykładzie w każdym przebiegu relaksacja krawędzi odbywa się w porządku leksykograficznym:
(u, 11),(11,x), (u, y), (11,u), (x, 11),(x, y), (Y, 11),(y, z), (z, u), (z, x). (a) Sytuacja tuż przed pierwszym
przebiegiem. (b)-<e)Sytuacja po ka:alym kolejnym przebiegu. Wartości di n w części (e) są war-
tościami końcowymi. W tym przykładzie algorytm Bellmana-Forda zwraca wartość TRUE

Dowóo
Niech v będzie wierzchołkiem osiągalnym ze źródła si niech p = (v 0 , v1, •••• V1c
będzie najkrótszą ścieżką z s do v, gdzie v0 =si v1c = v. Ścieżka p jest ścieżką
prostą, i dlatego k ~ IVI- 1. Udowodnimy przez indukcję, że po i-tym przebie-
gu zachodzi d[vJ = ó(s, vJ dla każdego i= O, I, ... ,ki równość ta pozostaje od
tej chwili niezmienna. Ponieważ jest co najwyżej IVI- 1 przebiegów, wystarcza
to do dowodu lematu.
Po fazie inicjowania d[vJ = ó(s, vJ = O. Z lematu 25.5 wynika, że równość
ta jest utrzymywana do końc.a działania algorytmu. W kroku indukcyjnym
załóżmy, że d[v 1_ 1] = ó(s, v1_ 1) po (i - 1)-szym przebiegu. W i-tym przebiegu
następuje relaksacja krawędzi (v1_ 1, vJ. Na podstawie lematu 25.7 wnioskuje-
my, że d[vJ = ó(s, vJ po i-tym przebiegu i we wszystkich kolejnych krokach
algorytmu, co kończy dowód lematu.

WNIOSEK
25.13.
Niech G = (V, E) będzie ważonym grafem skierowanym ze źródłem si funkcją
wagową w:E-t R. WówCLas dla każdego wierzchołka ve V istnieje ścieżka ze

onn
25.3_ ALGORYTM BELLMANA-FORDA

źródła
s do v wtedy i tylko wtedy, gdy po zakończeniu wykonywania algoryt-
mu Bellmana-Forda dla grafu G zachodzi zależność d[v] < oo.

DOWÓD
Dowód jest podobny do dowodu lematu 25.12 i pozostawiamy jego przepro-
wadzenie jako zadanie dla czytelnika (zob. zad. 25.3-2).

rw1ERDZENIE25.14. (Poprawność algorytmu Bellmana-Forda)



Niech G = (V, E) będzie ważonym grafem skierowanym ze źródłem si funkcją
wagową w: E--+ R. Załóżmy, że algorytm Bellmana-Forda został wykonany dla
grafu G. Jeśli graf G nie ma cykli o ujemnach wagach osiągalnych ze źródła s,
to algorytm zwraca wartość TRUE, d[v] = ó(s, v) dla każdego wierzchołka vE V
i graf poprzedników Gnjest drzewem najkrótszych ścieżek o korzeniu ws. Jeśli
natomiast graf G ma cykl o ujemnej wadze osiągalny z s, to algorytm zwraca
wartość FALSE.

DOWÓD
Załóżmy, że graf Gnie zawiera cykli o ujemnych wagach, które są osiągalne ze
źródła s. Najpierw udowodnimy, że po zakończeniu działania algorytmu
d[v] = ó(s, v) dla wszystkich wierzchołków vE V. Jeśli wierzchołek v jest osią­
galny ze źródła s, to powyższe stwierdzenie natychmiast wynika z lematu
25.12. Jeśli wierzchołek v nie jest osiągalny z s, to nasze stwierdzenie wynika
z wniosku 25.6. Z powyższego faktu i lematu 25.9 wynika, że graf poprzed-
ników Gn jest drzewem najkrótszych ścieżek. Teraz pokażemy, że algorytm
Bellmana-Forda zwraca wartość TRUE. Po zakończeniu działania algorytmu
dla każdej krawędzi (u, v)E E zachodzi

d[v] - J(s, v)
~ ó(s, u) + w(u, v) (z lematu 25.3)
- d[u] + w(u, v)

a więc żaden z testów w wierszu 6 nie spowoduje zwrócenia wartości FALSE;


zostaje więc zwrócona wartość TRUE.
Załóżmy teraz, że cykl c = (v 0, v1, ••• , v,.) o ujemnej wadze, gdzie v0 = v,.,
jest osiągalny ze źródła s. Wtedy

•I w(v,_,, vJ < O (25.3)


I= l

Załóżmy przeciwnie, że algorytm Bellmana-Forda zwraca wartość TRUE. Tak


więc d[vJ ~ d[v;_ 1] + w(v;_ 1, vJ dla i= 1, 2, ... , k. Sumując te nierówności
stronami po wszystkich wierzchołkach cyklu, otrzymujemy

601
ROZDZIAŁ 25. NAJKRÓTSZE $CIEŻKI Z JEDNYM 2R0DŁEM

•L d[vJ.; L• d[v,_,] + L• w(v,_,, v;J


i=1 /c=l /=,l

Podobnie jak w dowodzie lematu 25.8, każdy wierzchołek z cyklu c pojawia się
dokładnie raz w każdej z dwóch pierwszych sum. Zatem

•L d[vJ - L• d[v,_,]
J=,1 1""1

Ponadto z wniosku 25.13 wynika, że d[vJ jest skończone dla i= l, 2, ... , k.


Tak więc


O~ L w(v,_ 1, vJ
I= 1

co przeczy nierówności (25.3). Zatem algorytm Belhnana-Forda zwraca war-


tość TRUE, jeśli graf Gnie ma cyklu o ujemnej wadze osiągalnego ze źródła s,
i zwraca wartość FALSE w przeciwnym razie.

ZADANIA
25.3-1. Wykonaj algorytm Bellmana-Forda dla grafu z rys. 25.7, przyjmując
wierzchołek y za źródło. W każdym przebiegu wykonuj relaksacje krawę­
dzi w porządku leksykograficznym. Podawaj wartości d i n po każdym
przebiegu. Na koniec zmień wagę krawędzi (v, v) na 4 i wykonaj algorytm
ponownie, przyjmując tym razem za źródło wierzchołek z.
25.J..2. Udowodnij wniosek 25.13.
25.J..3. Dany jest ważony graf skierowany G = ( V, E} bez cykli o ujemnych
wagach. Dla każdej pary wierzchołków u, ve V niech m.,,0 będzie najmniej-
szą liczbą krawędzi na najkrótszej ścieżce (w sensie wag, a nie liczby kra-
wędzi) z wierzchołka u do v. Niech m będzie największą liczbą ze wszyst-
kich m„ 0 • Zaproponuj prostą modyfikację algorytmu Bellmana-Forda,
'
która pozwoli kończyć obliczenia po m + 1 przebiegach.
25.3-4. Zmodyfikuj algorytm Bellmana-Forda tak, żeby dla wszystkich wierz-
chołków v, dla których istnieje cykl o ujemnej wadze na pewnej ścieżce ze
źródła s do v, atrybutowi d[v] była przypisywana wartość - co.
25.J..5. Niech G = (V, E) będzie ważonym grafem skierowanym z funkcją wa-
gową w:E--+ R. Podaj algorytm, który w czasie O( VE) obliczy dla każdego
wierzchołka ve V wartość ó·(v) = min..,y{ó(u, v)}.
* 25.3-6. Załóimy, że ważony graf skierowany G = (V, E) ma cykl o ujemnej
wadze. Podaj algorytm wypisujący wierzchołki takiego cyklu. Wykaż, że
Twój algorytm jest poprawny.

602
25.4. NAJKRÓTSZE $CIE2KI Z JEDNYM 2R0DŁEM W ACYKLICZNYCH GRAFACH ...

25.4. Najkrótsześcieżki z jednymźródłem w acyklicznych


grafachskierowanych

Wykonując relaksacje krawędzi ważonego dagu G = (V, E) zgodnie z porząd­


kiem topologicznym jego wierzchołków, najkrótsze ścieżki z pojedynczego 7Ió-
dła można obliczyć w czasie @(V+ E). Najkrótsze ścieżki w dagach są zawsze
dobrze zdefmiowane. Nawet jeśli są ujemne wagi w grafie, to cykl o ujemnej
wadze nie może istnieć.
Na początku algorytmu sortujemy dag topologicznie (patrz podrozdz. 23.4),
uzyskując liniowe uporządkowanie jego wierzchołków. Jeśli istnieje ścieżka
z wierzchołka u do wierzchołka v, to u poprzedza v w porządku topologicznym.
Następnie wszystkie wierzchołki przeglądamy dokładnie raz w porządku topolo-
gicznym. Podczas przetwarzania wierzchołka wykonujemy relaksację wszystkich
wychodzących z niego krawędzi. Poniżej przedstawiamy algorytm DAG-SHOR-
TEST-PATHSsłużący do obliczania najkrótszej ścieżki w dagach.

DAG-SHORTEST-PATHS(G,w, s)
1 uporządkuj topologicz.nie wierzchołki G
2 INITIALIZE-SINGLE-SOURCE(G,s)
3 for każdy wierzchołek u, w porządku topologicznym
4 do for każ<ly wierzchołek vEAdj[u]
5 do RELAX(u, V, w)

Przykładowe działanie algorytmu jest pokazane na rys. 25.8.


Decydującymi dla czasu działania algorytmu są czasy wykonania wiersza
I i pętli for w wierszach 3-5. Jak wiadomo z podrozdz. 23.4, sortowanie topo-
logiczne może być wykonane w czasie @(V+ E). W pętli for w wierszach 3-5,
podobnie jak w algorytmie Dijkstry, jest wykonywana jedna iteracja dla każ­
dego wierzchołka. Dla każdego wierzchołka każda krawędź wychodząca z tego
wierzchołka jest badana dokładnie raz. Jednak.że w przeciwieństwie do algoryt-
mu Dijkstry obliczenia związane z jedną krawędzią są wykonywane w czasie
0(1). Czas działania algorytm.u wynosi zatem @(V+ E), czyli jest liniowy
względem rozmiaru listowej reprezentacji grafu.
Z następującego twierdzenia wynika, że procedura DAG-SHORTEST-PATHS
poprawnie oblicza najkrótsze ścieżki.

TwIERDZENIE 25.15.
Niech G = (V, E) będzie ważonym grafem skierowanym i niech s będzie źród­
łem w grafie G. Jeśli graf Gnie ma cykli, to po zakończeniu działania procedu-
ry DAG-SHORTEST-PATH dla grafu G zachodzi d[v] = ó(s, v) dla wszystkich
wierzchołków vE V i graf poprzedników G„jest drzewem najkrótszych ścieżek.

603
ROZDZIAŁ 25. NAJKRÓTSZE ŚCłE2KI Z JEDNYM :ŻR0DŁEM

6 I 6 I

(•) (b)

(c)

6 I

(0

(g)

Rys. 25.8. Ilustracja działania algorytmu obliczania najkrótszych ścieżek w acyklicznym grafie skie-
rowanym. Wierzchołki są uporządkowane topologicznie od strony lewej do prawej. h6dłem jest
wierzchołek s. Wartości d są pokanne wewnątrz wierzchołków, a zacieniowane krawędzie wy-
znacza.ją wartości n. (a) Sytuacja przed pierwszą iteracją pęili for w wierszach 3-5. (b}(g) Sytuacja
po kaid ej iteracji pętli (or w wierszach 3-5. W każdej iteracji wierzchołek pomalowany w tej iteracji
na czarno pełni rolę wierzchołka v. Wartości pokazane w cz.ęści (g) są wartościami końcowymi

Dowón
Pokażemy najpierw, że po zakończeniu działania procedury d[v] = b(s, v) dla
wszystkich v e V. Jeśli wierzchołek v nie jest osiągalny ze źródła s, to z wniosku
25.6 wynika, że d[v] = b(s, v) = oo. Załóimy zatem, że wierzchołek v jest osią­
galny ze źródła si że p = (v 0, v1, ••• , vk) jest najkrótsr.ą ścieżką, gdzie v0 = s
i V.1:= v. Ponieważ wierzchołki są przetwarzane w porządku topologicznym,
relaksacje krawędzi ze ścieżki p są wykonywane w kolejności (v0 , v1), (vi, vJ, ...,
(v.t-i• v.1:).Korzystając z lematu 25.7, można pokazać indukcyjnie (jak wdowo-
dzie lematu 25.12), że po zakończeniu działania procedury d[vJ = ó(s, vJ dla
i= 1, 2, ... , k. Na koniec z lematu 25.9 otrzymujemy, że G.,_jest drzewem
najkrótszych ścieżek. •

604
25.4. NAJKRÓTSZE SCIE2KI Z JEDNYM ŻR0DŁEM W ACYKLICZNYCH GRAFACH ...

Interesujące
jest zastosowanie omówionego algorytmu do wyznaczania
ścieżek krytycznych w analizie sieci PERTt. Krawędzie reprezentują prace do
wykonania, a wagi reprezentują czasy wykonania poszczególnych prac. Jeśli
krawędź (u, v) wchodzi do wierzchołka v, a krawędź (v, x) wychodzi z wierz-
chołka v, to praca (u, v) musi zostać zakończona przed rozpoczęciem pracy (v,
x). Ścieżka w takim dagu reprezentuje ciąg prac, które muszą być wykonane
właśnie w tej kolejności. Ścieżką krytyczną nazywamy najdłuższą ścieżkę w da-
gu. Taka ścieżka odpowiada najdłuższemu przedziałowi czasu potrzebnemu do
wykonania uporządkowanego ciągu zależnych od siebie prac. Waga ścieżki
krytycznej jest ograniczeniem dolnym na łączny czas potrzebny do wykonania
wszystkich prac. Ścieżkę krytyczną można znaleźć w jeden z następujących
sposobów:
• zamieniając
wagi na krawędziach na ujemne i wykonując procedurę DAG-
-SHORTEST-PATH, lub
• wykonując procedurę DAG-SHORTEST-PATHS, zamieniając w wierszu 2 pro-
cedury INITIALIZE-SINGLE-SOURCE 00 na - 00 i zamieniając ,,>" na ,, <"
w procedurze RELAX.

ZADANIA

25.4-1. Wykonaj algorytm DAG-SHORTEST-PATHS dla grafu skierowanego


z rys. 25.8, przyjmując wierzchołek r za źródło.
25.4-2. Załóżmy, że zmieniamy wiersz 3 w algorytmie DAG-SHORTEST-PATH
następująco:

3 for pierwsze IV I - 1 wierzchołki w por.ządku topologicznym

Wykaż, że
algorytm jest nadal poprawny.
25,4-3. Defmicja sieci PERT podana uprzednio jest trochę nienaturalna. Natu-
ralniej byłoby reprezentować prace przez wierzchołki, a zależności między
pracami przez krawędzie; tzn. krawędź (u, v) oznaczałaby, że praca u musi
zostać wykonana przed pracą v. Wagi byłyby wtedy przypisane do wierz-
chołków, a nie do krawędzi. Zmodyfikuj procedurę DAG-SHORTEST-PAT
w taki sposób, żeby w czasie liniowym znajdowała najdłuższą ścieżkę w acy-
klicznym grafie skierowanym z wagami przypisanymi do wierzchołków.
25.4-4. Podaj efektywny algorytm, który znajduje liczbę wszystkich ścieżek
w acyklicznym grafie skierowanym. Przeanalizuj swój algorytm i skomen-
tuj jego praktyczne zastosowanie.

t PERTjest mul Review Technit[ue.MetodaPERTjest


skrótem od ang. Program EIJQ/uation.
jedną z nowoczesnych metod organizowania i planowania pr:redsięw.rięć, w których bierze udział
wielu kooperantów (przyp. tłum.).

605
ROZDZIAŁ 25. NAJKRÓTSZE $CIEżKI Z JEDNYM 2RóDŁEM

różnicowe i najkrótsze
25.5. Ograniczenia ścieżki
Ogólne zadanie programowania liniowego polega na optymalizacji funkcji li~
niowej z uwzględnieniem pewnego zbioru nierówności liniowych. W tym roz-
dziale zbadamy specjalny przypadek programowania liniowego, który można
sprowadzić do znajdowania najkrótszych ścieżek z jednym źródłem. Otrzyma-
ny w rezultacie problem najkrótszych ścieżek można następnie rozwiązać za
pomocą algorytmu Bellmana-Forda i tym samym otrzymać rozwiązanie wyjś­
ciowego zadania programowania liniowego.

Programowanie liniowe
W ogólnym sformułowaniu zadania programowania liniowego dane są: macierz
A wymiaru m x n, m-elementowy wektor b oraz n-elementowy wektor c. Nale-
ży znaleźć n-elementowy wektor x, który maksymalizuje fimkcję celu L' c,x1,
1=1
przy m ograniczeniach danych jako Ax ~ b.
Wiele problemów można wyrazić jako programy liniowe i dlatego dużo
wysiłku poświęcono algorytmom do rozwiązywania problemu programowania
liniowego. W praktycznych zastosowaniach zadanie programowania liniowego
rozwiązuje się bardzo szybko za pomocą algorytmu sympleks 1l. Jednak dla
pewnych, wymyślnie skonstruowanych danych wejściowych metoda sympleks
może wymagać czasu wykładniczego. Ogólne zadanie programowania liniowe-
go można rozwiązać w czasie wielomianowym, stosując algorytm. elipsoidalny,
który w praktyce zachowuje się bardzo wolno, lub algorytm Karmarkara, któ-
ry w praktyce często jest konkurencyjny dla algorytmu sympleks.
Ponieważ aparat matematyczny potrzebny do zrozumienia i analizy al-
gorytmów dla ogólnego zadania programowania liniowego wybiega poza ramy
tej książki, pomijamy ogólny przypadek w naszych rozważaniach. Z kilku
powodów jest ważne, żeby rozumieć strukturę zadań programowania linio-

ii Algorytm sympleks znajduje rozwiązanie optymalne zadania programowania liniowego,


badając ciąg punktów w obszau.e dopuszczalnym - obszarze przestrzeni n-wymiarowej, którego
punkty spełniają nierówność A.r .::o;b. Zasada działaNa algorytmu jest oparta na spostrzeżeniu,
że rozwiązanie, które maksymalizuje funkcję celu, znajduje się w pewnym „punkcie ekstremal-
nym" lub „wierzchołku" obszaru dopuszczalnego. W algorytmie sympleks wędrujemy od wie-
rzchołka do wierzchołka obszaru dopuszczalnego dopóty, dopóki dalsze poprawianie wartości
funkcji celu jest jeszcze możliwe. ,,Sympleksem" nazywamy wypukłą oloczkę (patrz podroz.dz.
35.3) d + I punktów w przestrzeni d-wymiarowej (np. trójkąt na płaszczyźnie i czworościan
w przestrzeni trójwymiarowej). Jak zauważył Dantzig [53], jest możliwe przedstawienie operacji
przemiem:zarria się z jednego wierzchołka do drugiego jako operacji na sympleksie otrzymanym
w wyniku interpretacji „dualnej" WY.jściowego zadania programowania liniowego - stąd nazwa
,,metoda sympleks".

606
25.5. OGRANICZENIA RÓŻNICOWE I NAJKRÓTSZE $CIEŻKI

wego. Po pierwsze, jeśli dany problem może być sformułowany jako zadanie
programowania liniowego o ro2JI1iarze wielomianowym, oznacza to, że istnieje
wielomianowy algorytm dla tego problemu. Po drugie, istnieje wiele specjal-
nych przypadków programowania liniowego, dla których istnieją szybsze al-
gorytmy. Na przykład, jak pokazujemy w tym podrozdziale, problem najkrót-
szych ścieżek z jednym źródłem jest specjalnym przypadkiem programowania
liniowego. Do innych problemów, które można sformułować jako zadanie
programowania liniowego, należą: problem najkrótszej ścieżki między poje-
dynczą parą wierzchołków (zad. 25.5-4) oraz problem maksymalnego prze-
pływu (zad. 27.1-8).
Czasami tak naprawdę nie dbamy o funkcję celu; chcemy tylko znaleźć
rozwią:ianie dopuszczalne, tzn. jakikolwiek wektor x, który spełnia nierówność
b, lub stwierdzić, że nie ma rozwiązań dopuszczalnych. Skoncentrujemy
Ax ,:;;;;
się na takim właśnie problemie istnienia rozwiązań dopuszczalnych.

Układ ograniczeń różnicowych

W układzie ograniczeń różnicowych każdy wiersz macierzy programowania li-


niowego A zawiera jedną wartość 1 i jedną wartość -1, a wszystkie pozostałe
elementy macierzy A są zerami. Tak więc ograniczenia dane za pomocą nie-
równości Ax,:;;;;b są zbioren1 składającym się z m ograniczeń różnicowych
z n niewiadomymi, w którym każde ogranic7.enie jest prostą nierównością li-
niową postaci

i, j :t;, n i 1 ,:;;;;
gdzie 1 ,:;;;; m.
k ,:;;;;
RozwaZTIJydla przykładu problem znalezienia 5-elementowego wektora
x = (x), który spełnia nierówność

l -l o o o o
l o o o -1
x,
-l
o l o o -l l
o o x,
-1 l o x, <;
5
-l o o l o 4
o o -l l o x,
-l
o o -l o 1
x,
-3
o o o -1 l -3

Ten problem jest równoważny problemowi znalezienia niewiadomych X; dla


i= 1, 2, ... , n, które spełniają następujących 8 ograniczeń różnicowych:

607
ROZDZIAŁ 25. NAJKRÓTSZE SCIE2Kt Z JEDNYM ŻRÓDŁEM

X 1 -X ~0
2
Xi -x 5 :E;-l
Xi-Xs1'l
x 3 -x 1 :E;5 (25.4)
X4 -X 1 :E;4
X4-x 3 :s,;-l
x 5 -x 3 :E; -3
x 5 -x 4 :E; -3

Jednym z rozwiązań tego problemu jest x = (-5,


-3, O, -1, -4), co można
stwierdzić bezpośrednio, sprawdzając każdą nierówność. W rzeczywistości jest
więcej niż jedno rozwiązanie tego problemu. Innym rozwiązaniem jest x = (O,
2, 5, 4, 1). Te dwa rozwiązania są ze sobą powiązane: kaula składowa wektora
X jest o 5 większa niż odpowiadająca jej składowa x. Ten fakt nie jest zwykłym
zbiegiem okoliczności.

LEMAT 25.16,
Niech x = (x 1, x 2 , ... , xJ będzie rozwiązaniem układu ograniczeń różnicowych
Ax ~ b i niech d będzie dowolną. stałą. Wtedy x + d = (x 1 + d, x 2 + d, ...,
x~ + d) jest także rozwiązaniem układu Ax ~ b.

DOWÓD
Dla kaulych x 1 i xJ mamy (xJ + d) - (x 1 + d) = xJ - x,. Dlatego jeśli x spełnia
Ax .:is;b, to także x + d spełnia Ax ~ b.

Układy ograniczeń różnicowych pojawiają się w wielu różnych zastosowa-
niach. Na przykład niewiadome x 1 mogą odpowiadać czasom pojawiania się
pewnych zdarzeń. Każdy warunek może być rozumiany jako stwierdzenie, że
jedno zdarzenie nie może pojawiać się dużo później niż drugie zdarzenie. Zda-
rzenia mogą być na przykład pracami, które należy wykonać podczas budowy
domu. Jeśli kopanie fundamentów rozpoczyna się w chwili x 1 i zabiera 3 dni,
a zalewanie fundamentów betonem rozpoczyna się w chwili x 2, to wymagamy,
żeby x 2 ~ x 1 + 3 lub, równoważnie, żeby x 1 - x 2 .:is;- 3. Tak więc zależności
czasowe mogą być wyrażone jako ograniczenia różnicowe.

Grafy ograniczeń
Korzystnie jest interpretować układ ograniczeń różnicowych z punktu widze-
nia teorii grafów, Pomysł polega na tym, żeby macierz A wymiaru n x m,
z układu ograniczeń różnicowych Ax ~ b, interpretować jako macierz incy-
dencji (patrz zad. 23.1-7) grafu o n wierzchołkach i m krawędziach. Kaidy

608
25.5. OGRANICZENIA R0ŻN1COWE I NAJKRÓTSZE ŚCIEŻKI

wierzchołek v1 w grafie, dla i= 1, 2, ... , n, odpowiada jednej z n zmiennych x 1•


Każ.cłaskierowana krawędź grafu odpowiada jednej z m nierówności z dwiema
niewiadomymi.
Bardziej formalnie, dla danego układu ograniczeń różnicowych Ax ~ b
odpowiadającym mu grafem ograniczeń jest ważony graf skierowany G =
= (V, E), w którym


I

E= {(v,, v): xJ- x 1 ~ bkjest ograniczeniem}


u {(v0, v1), (v0 , v2), (v0, v3), ••• , (v0 , vn)}

Nowy wierzchołek v0 dołącza się, aby zagwarantować osiągalność każdego


innego wierzchołka ze źródła. Tak więc zbiór wierzchołków V składa się
z wierzchołków V;, dla każdej niewiadomej x 1, plus dodatkowy wierzchołek v0 •
Zbiór krawędzi E zawiera jedną krawędź dla każdego ograniczenia różnicowe­
go plus krawędzie (v0 , vJ dla wszystkich niewiadomych x 1• Jeśli xi - x 1 " bkjest
ograniczeniem różnicowym, to wagą krawędzi (vi, v) jest w(v1, v) = bk. Wagą
każdej krawędzi wychodzącej z v0 jest O. Na rysunku 25.9 widać graf ograni-
czeń dla układu ograniczeń różnicowych (25.4 ).
Z następującego twierdzenia wynika, że rozwiąz.anie układu ograniczeń
różnicowych można otrzymać, znajdując wagi najkrótszych ścieżek w odpo-
wiadającym mu grafie ograniczeń.

TwlERDZENIE 25.17.
Dla danego układu ograniczeń różnicowych Ax" b niech G (V, E) będzie =
odpowiadającym mu grafem ograniczeń. Jeśli graf Gnie zawiera cyk.li o ujem-
nych wagach, to
(25.5)
jest rozwiązaniem dopuszczalnym dla tego układu. Jeśli graf G zawiera cykl
o ujemnej wadze, to układ ograniczeń różnicowych Ax " b nie ma rozwiązania
dopuszczalnego.

DOWÓD
Najpierw pokażemy, że jeśli graf ograniczeń nie zawiera cykli o ujemnych
wagach, to wektor x z równania (25.5) jest rozwiązaniem dopuszczalnym. Roz-
ważmy dowolną krawędź (v1, v)eE. Z lematu 25.3 wynika, że ó(v0 , v) ~
" ó(v0, vJ + w(vi, v1) lub, równoważnie, ó(v0, vj) - ó(v0, vJ " w(vi, v). Zatem
x 1 = ó(v0 , V;) i x1 = ó(v0, v1) spełniają ograniczenie x1 - x 1 .!f w(v1, v1), które od-
powiada krawędzi (v1, v1).

609
ROZDZIAŁ 25. NAJKRÓTSZE SCIEżKl Z JEDNYM 2R0DŁEM

-3

o
Rys. 25.9. Graf ograniczeń odpowiadający układowi ograniczeń różnicowych vJ
(25.4). Wartość !S(vo,
jest pokazana w ka:idym wiem::hołku v„ Rozwiąuniem dopuszczalnym dla tego układu jest
x=(-5
. '.
-3 O -1 -4)
'

Teraz pokażemy, że jeżeli graf ograniczeń zawiera cykl o ujemnej wadze,


to układ ogranicuń różnicowych nie ma rozwiązania dopusrnlnego. Bez
straty ogólności, niech c = (v 1, v2, ••• , V.1,:-),
gdzie v1 = vk>będzie cyklem o ujem-
nej wadze. (Wierzchołek v0 nie może leżeć na cyklu c, ponieważ nie wchodzi do
niego żadna krawędź). Cykl c odpowiada następującym ograniczeniom
różnicowym:

X2 - X1 :i;,;;w(v1, vJ
X3 - X2 ,1' w(v2,V3}



xk - xk-i ,1' w{v.1,:-_i,
v,J
x 1 - xk ,1' w(v,t, v1}

Ponieważ każ.de rozwiązanie x musi spełniać każdą z tych k nierówności, to


x takż.e musi spełniać nierówność powstającą w wyniku zsumowania wszyst-
kich tych nierówności stronami. W S11miepo lewej stronie każda 1mienna x,
jest raz dodawana i raz odejmowana, a więc suma po lewej stronie wynosi O.
Suma po prawej stronie wynosi w(c). Dlatego O ,1' w(c). Ale ponieważ c jest
cyklem o ujemnej wadu, w(c) < O dla każdego rozwiązania x i O ,1' w(c) < O,
co jest niemożliwe.

Rozwiązywanie układów ograniczeń różnicowych

Z twierdzenia 25.17 wynika, że możemy zastosować algorytm Bellmaoa-Forda


do rozwiązania układu ograniczeń różnicowych. Ponieważ istnieją krawędzie

610
25.5. OGRANICZENIA RÓŻNICOWE I NAJKRÓTSZE ŚCIEŻKI

ze źródła v0 do wszystkich innych wierzchołków w grafie ograniczeń, kaidy


cykl o ujemnej wadze jest osiągalny z v0 • Jeśli algorytm Bellmana-Forda zwra-
ca TRUE, to wagi najkrótszych ścieżek dają rozwiązanie dopuszcr,alne dla ukła­
du wejściowego. Na przykład na rys. 25.9 wagi najkrótszych ścieżek wyznacza-
ją rozwiązanie dopuszczalne x = (-5, -3, O, -1, -4), a zgodnie z lematem
25.16 x = (d - 5, d - 3, d, d - l, d - 4) jest także rozwiązaniem dopuszczal-
nym dla każdej stałej d. Jeśli algorytm Bellmana-Forda zwraca FALSE, to nie
istnieje rozwiązanie dopuszczalne danego układu ogranicreń różnicowych.
Układowi ograniczeń różnicowych z m ograniczeniami i n niewiadomy-
mi odpowiada graf o n + 1 wier7.Cholk.ach i n + m krawędziach. Dlatego,
stosując algorytm Bellmana-Forda, możemy rozwiązać ten układ w czasie
O((n + l}(n + m}} = O(n2 + nm}. W zadaniu 25.5-5 należy wykazać, że rze-
czywisty czas działania algorytmu wynosi O(nm}, nawet jeśli m jest dużo
mniejsze od n.

ZADANIA
25.5-1. Znajdź rozwiązanie dopuszczalne lub ustal, że takiego rozwiązania nie
ma dla następującego układu ograniczeń różnicowych:

X1 -x 2 :;:,;; 1
X1- X 4 :;:,;; -4
X2 - x 3 :;:,;; 2
Xz - X5 :;:,;; 7
.x,;- Xi; :;:,;; 5
X3 - Xi;:;:,;; 10
X4 - x 2 :;:,;; 2
Xs - Xi :;:,;; -1
Xj - X~ :;:,;; 3
X6 - X 3 :;:,;; - 8

25.5-2. Znajdź rozwiązanie dopus7.ezalne lub ustal, że takiego rozwiązania nie


ma dla następującego układu ograniczeń różnicowych:

X1 - X2 :;:,;; 4
Xi - X5 :;:,;; 5
x2 - X 4 :;:,;; -6
X3 - X2 :;:,;; }
X4 - Xi :;:,;; 3
X4 - X 3 :;:,;; 5
X4-x 5 :;:,;; 10
X5 - X3 :;:,;;-4
X5 - X 4 :;:,;;- 8

611
ROZDZIAŁ 25. NAJKRÓTSZE $CtE2KI Z JEDNYM 2R0DŁEM

25.S..3. Czy każda


waga najkrótszej ścieżki z nowego wierzchołka v0 w grafie
ograniczeń może być dodatnia? Odpowiedź uzasadnij.
2S.S-4. Wyraź problem najkrótszych ścieżek. z jednego źródła jako program
liniowy.
25.S-5. Pokaż, jak można nieznacznie zmodyfikować algorytm Bellmana-For-
da, żeby jego czas działania wynosił O(nm), gdy algorytm ten zastosujemy
do rozwiązania układu ograniczeń różnicowych z m ograniczeniami i n
niewiadomymi.
25.5-6. Pokaż, w jaki sposób rozwiązać układ ograniczeń róZllicowych, stosu-
jąc algorytm podobny do algorytmu Bellmana-Forda, który działa na gra-
fie ograniczeń bez dodatkowego wierzchołka v0 •
* 25.5-7. Niech Ax ~ b będzie układem m ograniczeń różnicowych z n niewiado-
mymi. Pokaż, że algorytm Bellmana-Forda, wykonywany na odpowiada-
ją.cym układowi grafie ograniczeń, maksymalizuje L' X; przy ogranicze-
i= 1
niach Ax ~ b i X; ~ O dla wszystkich x 1•
* 25.5-8. Pokaż, że algorytm Bellmana-Forda, wykonywany na grafie ograni-
czeń dla układu ograniczeń różnicowych Ax ~ b, minimalizuje wielkość
(max{x 1} - min{x 1}) przy ograniczeniach Ax ~ b. Wyjaśnij, dlaczego ten
fakt jest przydatny, jeżeli algorytm Bellmana-Forda stosuje się do ustala-
nia kolejności wykonywania prac budowlanych.
25.5-9. Przypuśćmy, że każdy wiersz macierzy A programu liniowego Ax ~ b
odpowiada ograniczeniu różnicowemu z jedną 21Dienną. w jednej z dwóch
postaci: x 1 ~ bk lub - x 1 ~ h"" Pokaż, w jaki sposób zaadaptować algo-
rytm Bellmana-Forda, żeby rozwiązywał takie układy ograniczeń.
25.5-10. Przypuśćmy, że oprócz ograniczeń różnicowych uwzględniamy ogra-
niczenia-równania w postaci xi = xi + b1r..Pokaż, w jaki sposób zaadapto-
wać algorytm Bellmana-Forda, żeby rozwiązywał takie układy ograniczeń.
25.5-11. Podaj efektywny algorytm rozwiązywania układu ograniczeń róZllico-
wych Ax ~ b, kiedy wszystkie elementy wektora b są liczbami rzeczywi-
stymi, a wszystkie niewiadome x 1 muszą być liczbami całkowitymi.
* 25.5-12. Podaj efektywny algorytm rozwiązywania układu ograniczeń róZllico-
wych Ax ~ b, kiedy wszystkie elementy wektora b są liczbami rzeczywi~
stymi, a pewne, ale niekoniecznie wszystkie niewiadome x 1 muszą być licz~
bami całkowitymi.

Problemy
25-1. Poprawka Yena do algory1mu Belhnana-Forda
Załóżmy, że relaksacje krawędzi w algorytmie Bellmana-Forda odbywają się
w następującym porządku. Przed wykonaniem pierwszego przebiegu ustalamy

612
PROBLEMY


dowolny porządek v1, v2, ... , v1 na wierzchołkach wejściowego grafu G =
= (V, E). Następnie dzielimy zbiór krawędzi E na E1uE&, gdzie E,=
={(v,v 1)EE:i<j) i E,={(v„ v)EE:i>j}. Zdefmiujmy G1 =(V, E1)
i G, = (V, E,).

(a) Udowodnij, że G1 jest grafem acyklicznym, w którym porządek wierzchoł­


jest porządkiem topologicznym, a graf Gb jest grafem
ków (v 1, v2 , ••• , v,1-1>
acyklicznym, w którym porządek wierzchołków (v 1"1, v1vi_1, ... , v1) jest po-
rządkiem topologicznym.

Załóimy, że realizujemy każdy przebieg algorytmu Bellmana-Forda w na-


stępujący sposób. Odwiedzamy kolejno wierzchołki w porządku (v 1, v2,
..., v1vi), wykonując relaksacje krawędzi z E1 wychodzących z odwiedzanych
wierzchołków. Następnie odwiedzamy kolejno wierzchołki w porządku (v 1'1,
1

v1vi-i, ... , v1), wykonując relaksacje krawędzi z El>wychodzących z odwiedza-


nych wierzchołków.
(b) Udowodnij, że jeśli zastosujemy opisany schemat i graf Gnie zawiera cyk-
lu o ujemnej wadze osiągalnego z s, to po wykonaniu tylko n
Vl/21prze-
biegów zachodzi d[v] = 8(s, v) dla wszystkich wierzchołków ve V.
(c) Jaki jest wpływ zastosowania tego schematu na czas działania algorytmu
Bellmana-Forda.

2S-2. Zagnieżdżanie kostek


Powiemy, że tł-wymiarowa kostka o wymiarach (x 1, x 2, ... , x,J daje się zagnieź­
dzić w kostce o wymiarach (y 1, y 1 , ... , y,J, jeśli istnieje permutacja n indeksów
1, 2, ... , d taka, że x„c1> < y 1, x„c2J < y 2, ... , x,.(d) < Y,1,

(a) Uzasadnij, że relacja zagnieżdżania jest przechodnia.


(b) Opisz efektywną metodę ustalania, czy jedna d-wymiarowa kostka daje się
zagnieżdzić w drugiej, czy też nie.
(c) Załóimy, że dany jest zbiór składający się z n kostek d-wymiarowych
{B1, B 2, ••• , Bn}. Opisz efektywny algorytm ustalania najdluższ.ego ciągu
kostek (Bi,• B1,, ... , B1,) takiego, że kostka B1i daje się zagnieździć w B1,.,
dla j = 1, 2, ... , k - 1. Wyraź czas działania algorytmu w zależności od
n id.

25-3. Arbitraż
Arbitrażem nazywamy wykorzystanie różnic w kursach walut do zamiany jed-
nej jednostki danej waluty na więcej niż jedną jednostkę tej samej waluty. Dla
przykładu przyjmijmy, że za 1 dolara amerykańskiego można kupić 0,7 funta
brytyjskiego, za 1 funta brytyjskiego można kupić 9,5 franka francuskiego,

613
ROZDZIAŁ 25. NAJKROTSZE ŚCIE2KI Z JEDNYM 1:R0DŁEM

a za jednego franka francuskiego można kupić 0,16 dolara amerykańskiego.


Wtedy, wymieniając waluty, za 1 dolara amerykańskiego można kupić 1,064
dolara, osiągając zysk 6,4%.
Przypuśćmy, że ma.my n walut c1, c2 , ••• , c„i tabelę kursów walut Ro wy-
miarach n x n taką, że R[i,j]jest liczbą jednostek waluty cp które można kupić
za jednostkę waluty c1•

(a) Podaj efektywny algorytm ustalania, czy istnieje ciąg walut (c 1,, c,,,..., c4 )
taki, że
R[i 1, i2] • R[i.i, i3 ] ••• R[ik-t• ik] · R[ik1i1] > 1
Przeanalizuj czas działania algorytmu.
(b) Podaj efektywny algorytm wypisywania takiego ciągu Geśli tylko istnieje).
Przeanalizuj czas działania swojego algorytmu.

25-4. Algory1mskalujący Gabowadla problemunajkrótszyebścieżek z jednego


iróclla
Algorytm skalujący działa następująco. Początkowo rozważa się tylko najbar-
dziej znaczące bity odpowiednich wartości wejściowych (np. wag krawędzi).
Następnie początkowe rozwiązanie jest uściślane przez rozważenie dwóch naj-
bardziej znaczących bitów. Postępując tak dalej, rozważa się coraz więcej bi-
tów, za każdym razem uściślając bieżące rozwiązanie, aż do chwili, w której
wszystkie bity zostają zbadane i obliczone jest poprawne rozwiązanie.
Tutaj omówimy pewien algorytm obliczania najkrótszych ścieżek z jed-
nego źródła za pomocą skalowania wag krawędzi. Dany jest graf skierowany
G = (V, E) z nieujemnymi, całkowitymi wagami na krawędziach. Nie.eh
W= m°<u.v)ee{w(u, v)}. Naszym celem jest skonstruowanie algorytmu działa­
jącego w czasie O(Elg W).
W tym algorytmie kolejne bity binarnych reprezentacji wag krawędzi są
odsłaniane pojedynczo, od najbardziej do najmniej znaczącego. Niech k =
= flg(W + !Jlbędzie liczbą bitów w binarnej reprezentacji Wi niech dla i= I,
2, ..., k zachodzi wf.u, v) = Lw(u, v)/2'-~. Tak więc wf.u, v) jest „przeskalowa-
ną" wagą w(u, v), wyznaczoną przez jej i najbardziej znaczących bitów. (Zatem
w.Ju, v) = w(u, v) dla wszystkich (u, v)e E). Jeśli na przykład k = 5 i w(u,
v) = 25, co w reprezentacji binarnej wynosi (11001), to w3(u, v) = (110) =
= 6. Jeśli k = 5, w(u, v) = (00100) = 4, to w,(u, v) = (001) = I. 2.defmiujmy
f>/..u,v) jako wagę najkrótszej ścieżki z wierzchołka u do wierzchołka v dla funk-
cji wagowej w;. Tak więc lJ,,.(u,v) = l>(u,v) dla wszystkich u, ve V. Dla danego
źródła s w algorytmie skalującym najpierw są obliczane wagi najkrótszych
ścieżek lJ1(s, v), dla wszystkich ve V, następnie wagi lJ1 (s, v) itd., aż zostaną
obliczone wagi .!,(s, v). Przy zaloi.eniu IEI ;;, IVI - I zobaczymy, że obliczenie.!,
z.!,_, zajmuje czas O(E), a stąd cały algorytm działa w czasie O(kE) = O(Elg W).

614
PROBLEMY

(a) Przypuśćmy, że dla wszystkich wier:zchołków ve V zachodzi 6(s, v) ~ IEI.


Pokaż, że można w czasie O(E) obliczyć 6(s, v) dla wszystkich ve V..
(b) Pokaż, że t51(s, v) można obliczyć w czasie O(E) dla wszystkich vE V.

Skupmy teraz naszą uwagę na obliczaniu 61 z 61_ 1•

(c) Udowodnij, że dla i= 2, 3, ... , k albo wf..u, v) = 2w1_ 1(u, v), albo
w,{u,v) = 2w1_ 1(u, v) + 1. Następnie udowodnij, że

v) + JVJ-
2b,_,(s, v),; b,(s, v),; 2<1,_,(s, I
dla wszystkich v e V.
(d) Dla i= 2, 3, ... , ki wszystkich (u, v)e E definiujemy

Udowodnij, że dla i= 2, 3, ... , ki wszystkich u, ve V waga Wf...u,


v) krawę­
dzi (u, v) jest nieujemną liczbą całkowitą.
v) jako wagę najkrótszej ścieżki ze źródła s do
(e) z.definiujmy teraz 8/.._s,
wierzchołka v dla funkcji wagowej W1• Udowodnij, że dla i= 2, 3, ... , k
i wszystkich v e V zachodzi
b,(s, v) = o,(s, v) + 20,_,(s, v)
. ze
1
.

o,(s, v) <; JEJ.


(f) Pokaż, w jak.i sposób w czasie O(E) obliczać 6,(s, v) z 6 1_ 1(s, v) dla wszyst-
kich VE V. Wywnioskuj stąd, że dla wszystkich ve V wagę najkrótszej ścież­
ki ó(s, v) można obliczyć w czasie O(Elg W).

25-S. Algorytm Karpa wyznaczania cyklu o minimalnej średniej wadze


Niech G = (V, E) będzie grafem skierowanym z funkcją wagową w:E-+ R
i niech n = IVI. Sredoią wagę cyklu c = (ei, e2, ••• , e") składającego się z krawę­
dzi ze zbioru E definiujemy jak.o wielkość

I •
µ(c) = k ~ w(e,)
1 1

Niechµ•= mincµ{c), gdzie c przebiega po wszystkich skierowanych cyklach


w grafie G. Cykl c, dla którego µ(c) =µ·,nazywamy cyklem o minimalnej Śiedniej
wadze. Ten problem dotyczy pewnego efektywnego algorytmu obliczaniaµ•.

615
ROZDZ!AŁ 25. NAJKROTSZE SCIEżKI Z JEDNYM tR0DŁEM

Załóżmy bez straty ogólności, że każdy wierzchołek v E V jest osiągalny ze


źródła se V. Niech {J(s,v) będzie wagą najkrótszej ścieżki u źródła s do wierz-
chołka v i niech 6,1..s,
v) będzie wagą najkrótszej ścieżki ze źródła s do wierz-
chołka v składającej się z dokładnie k krawędzi. Jeśli nie ma ścieżki ze źródła
s do wierzchołka v o dokładnie k krawędziach, to 6,1..s, v) = co.

(a) Pokaż, że jeśli µ • = O, to graf G nie zawiera cykli o ujemnych wagach


i 6(s, v) = min 0 <k<,r-l {J,l..s,v) dla wszystkich ve V.
(b) Pokaż, że jeśli µ • = O, to

•.(s, v) - o,(s, v)
max ~---~-- ;,, 0
O<k<N-1 n- k
dla wszystkich wierzchołków ve V(Wskazówka: Wykorzystaj obie własno­
ści z cz.ęści (a)).
(c) Niech c będzie cyklem o wadze zerowej, a u i v niech będą dowolnymi
dwoma wierzchołkami z cyklu c. Przypuśćmy, że waga ścieżki z u do
v wzdłuż cyklu wynosi x. Udowodnij, że 6(s, v) = tS(s,u)+ x (Wskazówka:
Waga ścieżki z wierzchołka v do u wł.dłuż cyk.lu wynosi -x).
(d) Pokaż, że jeśli µ•=O, to istnieje wierzchołek v na cyk.lu o minimalnej
średniej wadze taki, że

o.(s, v) - o,(s, v) __
max 0
O<k<N-1 n- k

(Wskazówka: Pokaż, że najkrótszą ścieżkę prowadzącą do jakiegokolwiek


wierzchołka na cyklu o minimalnej średniejwadre można przedłużyć
wzdłuż cyklu do najkrótszej ścieżki prowadzącej do następnego wierzchoł­
ka na tym cyklu).
(e) Pokaż, że jeśliµ·= O, to

. o,(s,v) - J,!s, v) __O


min max
PEV O<k<,r-1 n- k
(f) Pokaż, że jeśli dodamy stałą t do wagi każdej krawędzi z grafu G, to µ•
wzrośnie o t. Wykorzystaj ten fakt do pokazania, że

• . •.(s, v) - o,(s, v)
µ = min max
... v D<k<n-1 n- k

(g) Podaj algorytm obliczaniaµ· w czasie O(VE).

616
UWAGI DO ROZDZIAŁU

Uwagido rozdziału

Algorytm Dijkstry [55} był opublikowany w 1959 r., ale w tej wersji nie była
używana kolejka priorytetowa. Algorytm Belhnana-Forda jest oparty na
dwóch oddzielnych algorytmach podanych przez Bellmana [22] i Forda [71].
Bellman opisał związek najkrótszych ścieżek z ograniczeniami różnicowymi.
Lawler [132] opisał liniowy algorytm dla problemu najkrótszych ścieżek w da-
gach i uważał to rozwiązanie za część środowiskowego folkloru. Gdy wagi
krawędzi są stosunkowo małe, można zastosować efektywniejszy algorytm
do rozwiązania problemu najkrótszych ścieżek z jednym źródłem. Ahuja,
Mehlhorn, Orlin i Tarjan [6] opisali algorytm, który działa w czasie
O(E + VJig W) dla grafów z nieujemnymi wagami na krawędziach, w któ-
rych W jest największą wagą krawędzi w grafie. Podali tak.że łatwy do zaprog-
ramowania algorytm działający w czasie O(E + Vlg W). Dla grafów z ujem-
nymi wagami na krawędziach algorytm pochodzący od Gabowa i Tarjana [77)
działa w czasie O(JVElg(VW)), gdzie W jest największą spośród wartości
bezwzględnych wszystkich wag krawędzi w grafie.
Papadimitriou i Steiglitz [l 54] omówili metodę sympleksów i algorytm
elipsoidalny, jak również inne algorytmy odnoszące się do programowania
liniowego. Algorytm sympleks dla programowania liniowego został odkryty
przez G. Danz.iga w 1947 r. Różne wersje metody sympleks pozostają najbar-
dziej popularnymi metodami rozwiązywania zadań programowania liniowego.
Autorem algorytmu elipsoidalnego jest L.G. Khachian. Ten algorytm pocho-
dzi z 1979 r.; powstał na podstawie wcześniejszej pracy N.Z. Shora, D.B. Jud.i-
na i A.S. Nemirovskiego. Karmarkar opisał swój algorytm w pracy [115].
Rozdział 26

Najkrótsześcieżki między
wszystkimiparamiwierzchołków

W tym rovlziale rozważymy problem znajdowania najkr6tszych ścieżek mię­


dzy wszystkimi parami wierzchołków w grafie. Taki problem pojawia się
przy tworzeniu tabeli odległości między wszystkimi parami miast uwzględnio­
nymi w atlasie samochodowym. Podobnie jak w rozdz. 25, dany jest ważony
graf skierowany G = (V, E) z funkcją wagową w:E-+ R, która przypisuje kra-
wędziom wagi o wartościach rzeczywistych. Dla każdej pary wierzchołków
u, ve V należy znaleźć najkrótszą (o najmniejszej wadze) ścieżkę z wierzchoł­
ka u do v, gdzie waga ścieżki jest sumą wag jej składowych krawędzi. Za-
zwyczaj żądamy, żeby wynik był dany w postaci tablicy: element tablicy
w u-tym wierszu i v-tej kolumnie powinien być wagą najkrótszej ścieżki z wie-
rzchołka u do v.
Problem najkrótszych ścieżek między wszystkimi parami wierzchołków
można rozwiązać, wykonując IVI razy algorytm dla problemu najkrótszych
ścieżek z jednym źródłem - po jednym razie dla każdego wierzchołka jako
źródła. W przypadku wszystkich wag nieujemnych można zastosować do tego
celu algorytm Dijkstry. Jeśli do implementacji kolejki priorytetowej zostanie
użyta tablica liniowa, to czas znalezienia wszystkich najkrótszych ścieżek wy-
nosi O(V' + VE) - O(V'). W przypadku użycia kopców binarnych do im-
plementacji kolejki priorytetowej otrzymany algorytm działa w czasie
O(VElg V), co jest pewnym usprawnieniem, jeśli graf wejściowy jest rzadki.
Alternatywnie, koleJ"kę priorytetową można zaimplementować za pomocą kop-
ców Fibonacciego, otrzymując algorytm działający w czasie O(v2 lg V+ VE).
Algorytm Dijkstry nie może być użyty, jeśli dopuszczamy wagi ujemne.
Zamiast niego jesteśmy zmuszeni wykorzystać wolniejszy algorytm Bellmana-
-Forda jeden raz dla każdego wierzchołka. Czas działania takiego algorytmu
wynosi O(V2 E), co dla grafów gęstych daje czas O(V"').W tym rozdziale opi-
szemy, jak lepiej rozwiązać ten problem. Zbadamy także związek problemu

618
ROZDZIAŁ 26. NAJKRÓTSZE ŚCIEżKI MIĘD2Y WS2YSTKIMI PARAMI ...

najkrótszych ścieżek między wszystkimi parami wierzchołków z mnożeniem


macierzy oraz przyjrzymy się strukturze algebraicznej tego problemu.
W przeciwieństwie do algorytmów z jednym źródłem, które zakładają
reprezentację listową grafu, większość algorytmów z tego rozdziału działa na
macierzach sąsiedztwa. (W algorytmie Johnsona dla grafów rzadkich są uży­
wane listy sąsiedztwa). Na wejściu jest dana macierz W wymiaru n x n
reprezentująca wagi krawędzi n-wierzchołkowego grafu G = (V, E); tzn.
W= (wy), gdzie

o, jeśli i= j
wy= waga krawędzi (i, j), jeśli i :I=j i (i, J)E E (26.1)
oo, jeśli i#j i (i,J)jE

Dopuszczamy ujemne wagi, ale chwilowo zakładamy, że graf wejściowy nie ma


cykli o ujemnych wagach.
Wynikiem działania wszystkich algorytmów z tego rozd.ziału jest tablica
D = (dq) wymiaru n x n, gd.zie dy jest wagą najkrótszej ścieżki z wierzchołka
i do wierzchołk:aj. Zatem, jeśli przez r5(i,J) oznaczymy wagę najkrótszej ścieżki
z wierzchołka i do wierzchołkaj (tak samo jak w rozdz. 25), to po zakończeniu
działania algorytmu d, = 3(i, J).
żeby rozwiązać problem najkrótszych ścieżek między wszystkimi parami
wierzchołków dla danej wejściowej macietzy sąsiedztwa, nie wystarczy tylko
znaleźć wagi najkrótszych ścieżek, ale trzeba tak.że obliczyć macierz popned-
Dik.ówII= (ny). Jeśli i= j lub nie istnieje ścieżka z i do j, to nlijest równe NIL.
W przeciwnym razie x!i jest poprzednikiem j na pewnej najkrótszej ścieżce z
i do j. Tak jak graf poprzedników G„ z roz.dz. 25 jest drzewem najkrótszych
ścieżek dla pewnego wierzchołka źródłowego, tak podgraf indukowany przez
i-ty wiersz macierzy II jest drzewem najkrótszych ścieżek o korzeniu i. Dla
każdego wierzchołka iE V defmiujemy podgraf poprzedników grafu G dla wie-
rzchołka i jako graf G.,,,,= (V.,,.
1, E.,,,
1), w którym

V,.,= {je V: n,# NIL} u {i}



I

E,.,= {(n,,j): jE V,.,i n,# NIL}


Jeśli ścieżek, to następująca procedura, która
G.,,•1 jest drzewem najkrótszych
jest zmodyfikowaną wersją procedury PRINT-PATH z ro7.dz. 23, wypisuje naj-
krótszą ścieżkę z wierzchołka i do wierzchołka j.

PRINT-ALL-PAIRS-SHORTEST-PATH(Il, i, j)
1 ifi=j
2 then wypisz i

619
ROZDZIAŁ 26. NAJKROTSZE $CIE2KI MIĘDZV W5ZYSTKIMI PARAMI. ..

3 else if n:IJ= NIL


4 tben wypisz "nie ma ścieżki z" i "do" j
5 else PRINT-ALL-PAIRS-SHORTEST-PATH{Il, i, n:11)
6 wypisz)

Żeby uwypuklić tylko istotne cechy algorytmów z tego ro7.działu, nie będziemy
omawiali ani sposobu tworzenia, ani własności macierzy popr:redników tak
obszernie, jak omawialiśmy podgrafy poprzedników w rozdz. 25. Zasadnicze
problemy z tym związane są poruszone w zadaniach.

Zawartość rozdziału

W podro7.dziale 26.1 przedstawimy algorytm programowania dynamicznego


dla problemu najkrótszych ścieżek między wszystkimi parami wierzchołków
oparty na mnożeniu macierzy. Stosując metodę „wielokrotnego podnoszenia
do kwadratu", możoa zaimplementować ten algorytm w taki sposób, żeby
działał w czasie 0(V3 lg V). Inny algorytm programowania dynamicznego, al-
gorytm. Floyda-Warshalla, omówimy w podro7.dz. 26.2. Algorytm Floyda-Wa-
rshalla działa w czasie 0(V3). W podrozdziale 26.2 opiszemy tak.że problem
znajdowania domknięcia przechodniego grafu skierowanego, który to problem
ma związek z problemem najkrótszych ścieżek między wszystkimi parami wie-
rzchołków. W podrozdziale 26.3 zaprezentujemy algorytm Johnsona. W prze-
ciwieństwie do innych algorytmów z tego ro7.działu, w algorytmie Johnsona
zakłada się, że graf wejściowy jest dany za pomocą list sąsiedztwa. Algorytm
Johnsona rozwiązuje problem. najkrótszych ścieżek w czasie O(V2 lg V+ VE).
Algorytm ten jest szybki dla dużych, rzadkich grafów. Na koniec, w podrozdz.
26.4, zbadamy strukturę algebraiczną nazywaną półpierścieniem domkniętym,
która umożliwia zastosowanie algorytmów znajdowania najkrótszych ścieżek
do rozwiązywania wielu innych problemów ścieżkowych, nie tylko związanych
z najkrótszymi ścieżkami.
2'.anim przejdziemy do dalszych części tego rozdziału, ustalimy pewne za-
sady dotyczące macierzy sąsiedztwa. Po pierwsze, ogólnie zakładamy, że wej-
ściowy graf G = (V, E) ma n wierzchołków, tak więc n= IV!.Po drugie, przyj-
mujemy, że macierze oznaczamy wielkimi literami, jak na przykład W i D,
a ich poszczególne elementy oznaczamy małymi literami z podwójnymi dol-
nymi indeksami, np. wy, d11• Pewne macierze będą miały górny indeks ujęty
w nawiasy do oznamenia iteracji, jak np. Jjrn) = (dlf>). Na koniec, dla danej
macierzy A wymiaru n x n zakładamy, że n jest wartością atrybutu rows[A].

620
26.1. NAJKRÓTSZE ŚCIEżKI I MNOŻENIE MACIERZY

26.1. Najkrótsześcieżki i mnożenie macierzy

W tym rozdziale przedstawiamy algorytm programowania dynamicznego dla


problemu najkrótszych ścieżek między wszystkimi parami wierzchołków w gra-
fie skierowanym G = (V, E). W każdej iteracji głównej pętli programu dyna-
micznego będzie wykonywana operacja, która jest bardzo podobna do mnoże­
nia macierzy. Na taki algorytm można więc patrzeć jak na wielokrotne mnoże­
nie macierzy. Rozpoczniemy od przedstawienia algorytmu działającego w cz.a-
sie E>(v4), a następnie poprawimy jego czas działania na 0(v3lg V). Zanim
przejdziemy dalej, przypomnijmy krótko etapy procesu tworzenia algorytmu
programowania dynamicznego podane w roz.dz. 16. Są one następujące.
1. Scharakteryzowanie struktury optymalnego rozwiązania.
2. Rekurencyjne zdefiniowanie kosztu optymalnego rozwiązania.
3. Obliczenie optymalnego kosztu metodą wstępującą.
(Etap 4, konstruowanie optymalnego rozwiązania na podstawie wyników
wcześniejszych obliczeń, został przeniesiony do zadań).

Struktura najkrótszejścieżki
Rozpoczniemy od scharakteryzowania optymalnego rozwiązania. Udowodni-
liśmy już (lemat 25.1), że wszystkie podścieżki każdej najkrótszej ścieżki są
najkrótszymi ścieżkami. Załóżmy, że graf jest reprezentowany przez macierz
sąsiedztwa W= (wlf). Rozważmy najkrótszą ścieżkę p z wierzchołka i do wie-
rzchołka} i przypuśćmy, że ścieżka p składa się z co najwyżej m krawędzi. Przy
założeniu, że w grafie nie ma cykli o ujemnych wagach, m jest skończone. Jeśli
i= j, to waga ścieżki p wynosi O i ścieżka nie zawiera żadnej krawędzi. Jeśli
wierzchołki i oraz} są różne, top można rozłożyć na i .!;k .-.+ j, gdzie p' zawiera
teraz co najwyżej m - I krawędzi. Ponadto z lematu 25.1 wynik.a, że p' jest
najkrótszą ścieżką z i do k. Dlatego, korzystając z wniosku 25.2, otrzymujemy
/J(i,1) - /J(i, k) + w,r

Rekurencyjnerozwiązanie problemu najkrótszychścieżek między


wszystkimi parami wierzchołków
Niech teraz djj> będzie najmniejszą wagą ścieżki z wierzchołka i do wierzchołka
j spośród tych, które zawierają co najwyżej m krawędzi. Gdym = O, to istnieje
ścieżka z i do j nie zawierająca krawędzi wtedy i tylko wtedy, gdy i= j. Zatem

d (O) -
,) - {Q, jeśli i= j
00, jeśli i;#; j

621
ROZDZIAŁ 26. NAJKRÓTSZE $CIE2KI MIĘDZY W5ZYSTKIMI PARAMI. ..

Dla m;;, 1 obliczamy dljl jako minimum z djj- 1> (wagi najkrótszej ścieżki
z i do j składającej się z co najwyżej m - 1 krawędzi) i najmniejszej wagi
spośród wag ścieżek z i do j składających się z co najwyżej m krawędzi, którą
otrzymuje się, przeglądając wszystkie możliwe poprzedniki k wierzchołka j.
A zatem rekurencyjnie defmiujemy

= min {dl:'- 11 + w/\:/} (26.2)


I ,;;k < n

Ostatnia równość zachodzi, ponieważ w11= O dla wszystkich j.


Jakie są rzeczywiste wagi najkrótszych ścieżek !J(i,J)? Jeśli w grafie nie ma
cykli o ujemnych wagach, to wszystkie najkrótsze ścieili są proste i mają co
najwyżej n - 1 krawędzi. ścieżka z wierzchołka i do wierzchołka j o więcej niż
n - 1 krawędziach nie może mieć mniejszej wagi niż najkrótsi.a ścieżka z wierz-
chołka i do j. Dla rzeczywistych wag najkrótszych ścieżek zachodzi z.a.tern

(26.3)

Obliczaniewag najkrótszychścieżek metodą wstępującą

Mając na wejściu macierz W= (wu), obliczamy ciąg macierzy Jj 1l, Dl 2l, ...,
=
1)(11- 11, w którym D("') (dljl) dla m = 1, 2, ..., n - 1. Ostatnia macierz D(n- l)
z.awiera rzeczywiste wagi najkrótszych ścieżek.. Zauważmy, że ponieważ
dj}l = wu dla wszystkich i, je V, mamy D11l = W.
Sercem omawianego algorytmu jest procedura EXTBND-SHORTBST~
-PATHS(D, W), która dla danych macierzy d"'- 11 i W oblicz.a macierz Dt'"l.
Innymi słowy, procedura EXTBND-SHORTEST-PATHS rozszerza o jedną kra-
wędź najkrótsze ścieżki policzone dotychczas.

EXTBND-SHORTBST-PATHS(D, W)
I n +- rows[D]
2 niech D' = (d;J) będzie macierzą wymiaru n x n
3 fori+-lton
4 doforjrl ton
5 dod; 1 +-oo
6 forkrl ton
7 + W.1,t)
do dij r min(d;J, d;.1;
8 return D'

622
26.1. NAJKRÓTSZE ŚCIEżKI I MNOŻENIE MACIERZY

Powyższa procedura oblicza macierz D' = (d; 1), którą na końcu zwraca jako
wynik. Macierz D' jest obliczana zgodnie z równaniem (26.2) dla wszystkich
i oraz j, przyjmując D za 1)1111-ll oraz D' za n<111>.(W tekście procedury są
pominięte górne indeksy, żeby macierze wejściową i wynikową uczynić nieza-
leżnymi odm). Z powodu trzech zagnieżdżonych pętli for czas działania proce-
dury wynosi 9(n 3).
Teraz możemy dostrzec związek z mnożeniem macierzy. Przypuśćmy, że
chcemy policzyć iloczyn C =A· B dwóch macierzy A i B wymiaru n x n. Wte-
dy, dla i, j = 1, 2, ... , n, liczymy


cy= L alk· bkJ (26.4)
k"' l

Zauważmy, że jeżeli zamienimy

d(m-1)--+ a
w~b
d(m)--+ C

min-+ +
+ ~-
w równaniu (26.2), to otrzymamy równanie (26.4). A zatem, jeśli wykonamy
te zmiany w procedurze EXTENDED-SHORTEST-PATHS, a także zamienimy
oo (jedność w operacji min) na O Gedność w operacji + ), otrzymamy zwykły
algorytm mnożenia macierzy, zajmujący czas 9(n 3 ).

MATRIX-MULTIPLY(A,
B)
1 n--+ rows[A]
2 niech C będzie macierzą wymiaru n x n
3 fori+-lton
4 doforj+-lton
5 do Cy+-0
6 fork+-1 ton
7 do cy--+ cu + aik • bkJ
8 return C

Wracając do problemu najkrótszych ścieżek., wagi najkrótszych ścieżek są


obliczane przez rozszerzanie najkrótszych ścieżek. krawędź po krawędzi.
Oznaczmy „iloczyn" macierzy zwracany przez procedurę ExrBNDED-
-SHORTEST-PATHs(A, B) przez A· B. Tak więc w procesie obliczania najkrót-
szych ścieżek jest obliczany ciąg n - 1 macierzy

623
ROZDZIAŁ 26. NAJKRÓTSZE $CIEżKI M1ĘD2Y WSZVSTKIMI PARAMI...

J>'łl = JjO). W =W
D(ll = I>'''·W = W'
Dl3J =D'''·W = W'



nn-1) = nn-l). W= Jf"-1

Jak. powiedzieliśmy, macierz n<11- 1> = W"- 1 zawiera wagi najkrótszych


ścieżek.. Procedura SLOW-ALL-PAIRS-SHORTBST-PATHS oblicza ciąg macierzy
4
w czasie 0(n ).

SLOW-ALL-PAIRS-SHORTBST-PATHS(W)
1 n+- rows[W]
2 n<1 >..-W
3 form+-2ton-l
4 111
do nt 111l +- EXTBND-SHORTBST-PATHs(D<-
1
>,W)
5 return nn- l)

-4 -5
7

o 3 8 -4 o 3 8 2 -4
o
""
1 7 3 o -4 1 7
Jj-1) = "" 4
""
o u,11"" o 5 11
4
""
2 -5
""
o ""
""
2 -1 -5 o -2
"" ""
"" "" "" 6 o 8
"" 1 6 o
o 3 -3 2 -4 o 1 -3 2 -4
3 o -4 I -) 3 o -4 1 -1
D',3) = 7 4 o 5 11 D',4) = 7 4 o 5 3
2 -I -5 o -2 2 -1 -5 o -2
8 5 1 6 o 8 5 1 6 o

RyL 26.1. Graf skierowany i cią,g


macierzy Jj*l obliczanych przez procedurę SL0W-ALL-PA11ts
-SHORTEST-PATHS. Można sprawdzić, ł.e D''1 .,. D-4)' W jest równe fi.'l j stąd n.i = D'4l dla
wszys.tkichm ;;i. 4

624
26.1. NAJKRÓTSZE $CIEŻKI I MNOŻENIE MACIERZV

Na rysunku 26.l jest pokazany graf i macierze D(ml obliczane przez procedurę
SLOW-ALL-PAIRS-SHOR TEST-PATHS.

Polepszenieczasudziałania
Naszym celem jednak nie jest policzenie wszystkich macierzy n<m): jesteśmy
tylko zainteresowani macierzą nc"- 1 ). Przypomnijmy, że przy braku cykli
o ujemnych wagach z równości (26.3) wynika, że J)(ml = D( 11- 1l dla wszystkich
m ~ n- 1. Macierz n<11- 1 > możemy otrzymać, wykonując tylko ng(n- 1)1
mnożeń macierzy, obliczając ciąg

n<l) -w
nc2) -W' -W·W
n(4> -W' - W'· W'
D(s>
-• W' - W'· W'

Ponieważ 2f11!(n
- 1ll ~ n - 1, wynik ostatniego iloczynu D(2fll(n- llł) jest rów-
ny D(11-1>.

Procedura FASTER-ALL-PAIRS-SHORTEST-PATHS oblicza powyższy ciąg


macierzy, wykorzystując przedstawioną właśnie metodę wielokrotnego podno-
szenia do kwadratu.

F ASTER-ALL-PAIRS-SHORTEST-PATHs(W)
1 n +- rows[W]
2 n<1>+- W
3 m+-1
4 whilen-l>m
5 do D<2m)
+- EXfEND-SHORTEST-PATHS(DCl, D(ml)
111

6 m+-2m
7 return nem)

W każdejiteracji pętli while w wierszach 4-6 obliczamy nc2m>= (DC"'l)


2 , rozpo-

czynając od m = 1. Na koniec każdej iteracji wartość m jest podwajana.


W ostatniej iteracji otrzymujemy macierz n<11- 1 >,obliczając w rzeczywistości
macierz JY2111 > dla pewnego m, takiego że n - 1 ~ 2m < 2n - 2. Z równo-
ści (26.3) otrzymujemy, że nc2 m>= Dc11- 1>. Przed wykonaniem sprawdzenia
w wierszu 4 wartość m jest podwajana, więc teraz n - l ~ m i warunek wejścia
do pętli nie jest spełniony. Procedura zwraca ostatnią obliczoną macierz.
Czas działania procedury FASTER-ALL-PAIRS-SHORTEST-PATHS wynosi
E>(n3 lgn), ponieważ każde z ng(n -1)1 mnożeń macierzy zabiera czas 0(n 3).

625
ROZDZIAŁ 26. NAJKRÓTSZE$CJEŻKI MIĘDZV W5ZYSTKIMI PARAMI...

Zauważmy, że procedura jest zapisana zwięźle; nie są używane żadne wyszuka-


ne struktury danych. Dlatego stała ukryta w notacji 0 jest mała.

ZADANIA
26.1-1. Wykonaj procedurę SLOW-ALL-PAIRS-SHORTEST-PATHS dla ważone­
go grafu skierowanego z rys. 262, wypisując odpowiednią macierz po każ­
dej iteracji pętli for. Następnie zrób to samo dla procedury FASTER-ALL-
·PAIRS-SHORTEST-PATHS.

1 2

-4 -8

lł.ys. 26.2. Ważony graf skierowany z zad. 26.1-1, 26.2-1 i 26.3-1

26.1-2. Dlaczego żąda się, żeby Wu= O dla wszystkich 1 :i::;;i~ n?


26.1-3. Jakiej macierzy w zwykłym mnożeniu macierzy odpowiada macierz

o 00 00 ••• 00

00 o 00... 00
D(O) = 00 00 o ... 00
• • • •
• • •
• •
00 00 00 ... o
która jest używana w algorytmach najkrótszych ścieżek?
26.1-4. Pokaż, jak wyrazić problem najkrótszych ścieżek z jednym źródłem
jako mnożenie macierzy przez wektor. Opisz związki między takim mnoże­
niem a algorytmem podobnym do algorytmu Bellmana-Forda (patrz pod-
rozdz. 25.3).
26.1-S. Załóżm.y, że za pomocą algorytmów z tego rozdziału cbre:roy także
znaleźć wierzchołki na najkrótszych ścieżkach. Pokaż, w jaki sposób z ma-
cierzy D obliczyć w czasie O(n3 ) macierz poprzedników TI .
26.1-6. Wierzchołki na najkrótszych ścieżkach można także obliczać w tym
samym czasie co wagi najkrótszych ścieżek. Zdefiniujmy njjl jako poprze-
dnik wierzchołka j na jakiejkolwiek ścieżce o minimalnej wadze z i do j,
zawierającej co najwyżej m krawędzi. Zmodyfikuj procedury ExTENDED-
·SHORTEST-PATHS oraz SLOW-ALL-PAIRS-SHORTEST-PATHS w taki spo-

626
262. ALGORYTM FLOYDA-WARSHALLA

sób, żeby oblic.zalymacierze n<1>,II( 2l, ..., nt11- 1>,tak samo jak są oblicza-
11- 1>.
ne macierze D 11l, D 12>,... , JJ1
26.1-7. Procedura FASTER-ALL-PAIRS-SHORTEST-PATHS w zaprezentowanej
implementacji wymaga zapamiętania flg(n - 1J1macierzy, każda o n2 ele-
mentach. Zatem łącznie rozmiar potrzebnej pamięci wynosi 8(n 2 lg n). Zmo-
dyfikuj tę procedurę w taki sposób, żeby rozmiar potrzebnej pamięci wyno-
sił tylko 0(n 2 ). W tym celu użyj tylko dwóch macierzy wymiaru n x n.
26.1-8. Zmodyfikuj procedurę FASTER-ALL-PAIRS-SHORTEST-PATHS w taki
sposób, żeby wykrywała istnienie cykli o ujemnych wagach.
26.1-9. Podaj efektywny algorytm znajdowania minimalnej długości cyklu
(liczonej w liczbie krawędzi) o ujemnej wadze.

26.2. AlgorytmFloyda-Warshalla
W tym podro7.dziale zastosujemy metodę programowania dynamicznego do
rozwiązania problemu najkrótszych ścieżek między wszystkimi parami wierz-
chołków w grafie skierowanym G = (V, E). Otrzymany algorytm, znany jako
algorytm Floyda-Warsballa, działa w czasie 0(V 3 ). Tak jak poprzednio, dopu-
szczamy występowanie krawędzi z ujemnymi wagami, ale zakładamy, że w gra-
fie nie ma cykli o wagach ujemnych. Podobnie jak w pod.rozdz. 26.1, algorytm
otrzymamy, stosując się do reguł programowania dynamicznego. Po zbadaniu
własności otrzymanego algorytmu przedstawimy podobną metodę obliczania
domknięcia przechodniego grafu skierowanego.

Strukturanajkrótszejścieżki
W algorytmie Floyda-Warshalla wykorzystujemy inną cechę struktury naj-
krótszej ścieżki niż ta, która znalazła zastosowanie w algorytmach najkrót-
szych ścieżek z mnożeniem macierzy. W prezentowanym algorytmie bierze się
pod uwagę wewnętrzne wierzchołki najkrótszej ścieżki. Wewnętrznym wierz-
chołkiem najkrótszej ścieżki p = (v 1, v2, ... , v1) jest każ.dy wierzchołek ze ścież­
kip różny od v1 i v„tzn. każdy wier7.Chołek ze zbioru {v2, v3, ... , v1_ 1}.
Algorytm Floyda-Warshalla opiera się na następującej obserwacji. Niech
zbiorem wier7.Chołków grafu G będzie V= {l, 2, ..., n}. Dla pewnego k rozważ­
my podzbiór {1, 2, ..., k}, a dla kam.ej pary wierzchołków i, JE V rozważmy
wszystkie ścieżki z wierzchołka i do j, których wewnętrzne wierzchołki należą
do zbioru {1, 2, ..., k}. Niech p będzie taką ścieżką spośród nich, której waga
jest najmniejsza. (Ścieżka p jest prosta, ponieważ założyliśmy, że graf G nie
zawiera cykli o ujemnych wagach). W algorytmie Floyda-Warshallajest wyko-
rzystywany pewien związek między ścieżką p a najkrótszymi ścieżkami z i do j,
których wszystkie wewnętrzne wier7.Cholkinależą do zbioru {I, 2, ..., k- I}.

627
ROZDZIAŁ 26. NAJKRÓTSZE $CIEżKI M1ĘOZY WS2YSTKIMI PARAMI ...

Związek ten zależy od tego, czy k jest lub nie jest, wewnętrznym wierzchołkiem
' . .
na sc1ezcep.

• Jeśli k nie jest wewnętrznym wierzchołkiem na ścieżce p, to jej wszystkie


wewnętrzne wierzchołki należą do zbioru {1, 2, ... , k - 1}. Zatem najkrótsza
ścieżka z wierzchołka i do wierzcholkaj, której wszystkie wewnętrzne wierz~
chałki należą do zbioru {1, 2, ..., k - 1}, jest także najkrótszą ścieżką z i do
j, której wszystkie wewnętrzne wierzchołki należą do zbioru {I, 2, ..., k}.
• Jeśli k jest wewnętrznym wierzchołkiem ścieżki p, to dzielimy p na
i A.kA j, tak. jak pokazano na rys. 26.3. Z lematu 25.1 otrzymujemy,
że p 1 jest najkrótszą ścieżką z i do k, której wszystkie wewnętrzne wierz~
cholki należą do zbioru {l, 2, ... , k}. W rzeczywistości wierzchołek k nie
jest wewnętrznym wierzchołkiem na ścieżce p 1, zatem p 1 jest najkrótszą
ścieżką z i do k, której wszystkie wewnętrzne wierzchołki należą do zbioru
{I, 2, ... , k- l}. Podobnie, p 2 jest najkrótszą ścieżką z wierzchołka k do
wierzchołka j, której wszystkie wewnętrzne wierzchołki należą do zbioru
{1,2, ...,k-l}.

Wszystkie wierzchołki pośrednie Wszystkie wierzchołki pośrednie


należą do {I, 2, ..., k- 1} należą do {1, 2, ..., k- I}

~-~---··---~
p: wszystkie wierzchołki pośrednie
należą do {l, 2, ... , k}
Rys. 26.3. Ścieżka p jest najkrótszą ścieżką z wierzchola i do wierzchołka j, a k jest wewnętrznym
wierzchołkiem ścieżki p o największym numerze. Ścieżkap 1 , fragment ścieżki pod wierzchołka i do
wierzchołka k, ma wszystkie wewnętrzne wierzchołki w zbiorze{I , 2, ... , k - 1}.To samo zachodzi
dla ścieżki p 2 prowadząc,;::j z wierzchołka k do wierzchołka j

Rozwiązanie rekurencyjneproblemu najkrótszychścieżek między


wszystkimi parami wierzchołków
Na podstawie powyższych obserwacji :zdefiniujemy wzór rekurencyjny służący
do obliczania długości najkrótszych ścieżek, inny niż ten z podrozdz. 26.1.
Niech dl')będzie wagą najkrótszej ścieżki z wierzchołka i do wierzchołka j,
której wszystkie wewnętrzne wierzchołki należą do zbioru {1, 2, ..., k}. Kiedy
k = D, ścieżka z wierzchołka i do wierzchołka j bez wewnętrznych wierz.chał-

628
26.2. ALGORYTM FLOYDA-WARSHALLA

ków o numerach większych niż O nie ma w ogóle żadnych wewnętrznych wierz-


chołków. Tak więc taka ścieżka ma co najwyżej jedną krawędź i stąd djJ) = w,r
Macierz d\J1 definiujemy rekurencyjnie, jak następuje:

d\~l= { w,, jeśli k=O


(26.5)
•J •
m1n(du
1-1
, da
k-1
+ d11
k-1
), jeśli k ~ 1
Macierz Jj 11> = (djj>)jest poszukiwanym rozwiązaniem - d!jl = ó(i,J) dla wszys-
tkich i, j E V - ponieważ wszystkie wewnętrzne wierzchołki należą do zbioru
{I, 2, , n).

Obliczaniewag najkrótszychścieżek metodą wstępującą


Wykorzystując równanie rekurencyjne (26.5), następująca procedura oblicza
wstępująca wartości d)Jl w kolejności rosnących wartości k. Dane wejściowe
procedury stanowi macierz W wymiaru n x n zdefiniowana równaniem (26.1).
Wynikiem jej działania jest macierz wag najkrótszych ścieżek D(11l.

FLOYD-W ARSHALL( W)
1 n+- rows[JV]
2 n<0J +- W
3 for k +- 1 to n
4 do for i +- I to n
5 doforj+-1 ton
6 ..1łk) +-mm
uii • (d'-'
ii , d'-'
11 + d'-
1J ')
7 return n<n)

Na rysunku 26.4 widać pewien graf skierowany oraz macierze D(1l obliczane
w algorytmie Floyda-Warshalla.
Na czas działania algorytmu Floyda-Warshalla decydujący wpływ ma czas
wykonania potrójnie zagnieżdżonej pętli for w wierszach 3-6. Każde wykona-
nie wiersza 6 zabiera czas 0(1 ). Cały algorytm działa zatem w czasie 0(n 3 ).
Zapis algorytmu Floyda-Warshalla, tak jak ostatniego algorytmu z podrozdz.
26.1, jest bardzo zwięzły. Żadne skomplikowane struktury danych nie są wyko-
rzystywane. Dlatego stała ukryta w notacji 0 jest mała. Algorytm Floyda-
-Warshalla zachowuje się bardzo dobrze w praktyce dla grafów o umiarkowa-
nych rozmiarach.

Konstruowanienajkrótszejścieżki
Istnieje wiele różnych metod konstruowania najkrótszych ścieżek w algorytmie
Floyda-Warshalla. Jedną z nich jest obliczenie macierzy wag najkrótszych

·------------------;6°"29
ROZDZIAŁ 26. NAJKRÓTSZE $CIE2K1MIĘDZY W5ZYSTKIMI PARAMI...

o 3 8
"'I -4 NIL I I Nil, I
o 7 Nil, Nil, Nil, 2 2
= "' "'o n(OJ = NIL 3
D(l)1
"'2 _, "'o "'
4
4
NIL

4
Nil, NIL

"' 6
"'
o NIL
Nil,

NIL >«L
,
NIL NIL
ML
"' "' "'
o 3 8
"'I -4 ML I I Nil, I

"' o "'o 7 NIL Nil, ML 2 2


D(ll = n(lJ- 3
"'2 4
_, "'o -2
"' ML
I
ML
4
NIL NIL

I
'
"' "' 6 o
4
Nil, mL >aL
NIL
, NIL
"'
o 3 8 4 -4 NIL I I 2 I

"' o "'o I 7 NIL NIL NIL 2 2


=
D(ll
"'2 4
_, o' li [F2J ... NIL 3 NIL
4
2 2
I
' -2 4 I Nil,

o
"' "' "' 6 NIL mL NIL
' ,UL

o 3 8 4 -4 >«L I I 2 I
o I 7 NIL Nil, >«L 2 2
,Dfll = "' "' o II(3l "" >«L 2
"'2 4
_, o' li
-2
3 >«L 2
-I
6 o
4
>«L NIL
3
>«L
4 NIL
, NIL
I

"' "' "'


o 3 -I 4 -4 NIL I 4 2 I
3 o -4 I -I 4 Nil, 4 2 I
D(4l = o n(4) = 2
7
2 -I
4
_, o' -2
3 4
4
3
3
NIL
4 NIL
I
I
o 4
8
' I 6 4 3
' NIL

o
3
I
o -4 I -I
-3 2 -4

=
Nil,

4
3
NIL
4
4 '
2
I
I
o [F5) 2 I
D(5l "" 7
2 -I
4
o -2
3
_, ' 4
4
3
3
>«L
4 ML I
o
Rys. 26.4.
8
'I 6

Ciąg
4 3 4
' NIL

macierzy Jji'/ i II{klobliczany w algorytmie Floyda-Warshalla d1a grafu z rys. 26.1

ścieżek D, a następnie, wykorzystując macierz D, zbudowanie macierzy


poprzedników II. Tę metodę można zaimplementować w C'lasie O(n3)
(zad. 26.1-5). Mając obliczoną macierz poprzedników Il, można wypisać wszy-
stkie wierzchołki żądanej najkrótszej ścieżki za pomocą procedury PRINT-
-ALL-PAIRS-SHORTBST-PATH.

630
26.2. ALGORYTM FLOYDA,WARSHALLA

Macierz poprzedników II możemy tak.że obliczać na bieżąco, razem z ob-


liczaniem macierzy n< 1>.Mówiąc dokładniej, obliczamy ciąg macierzy n1°.>

l, gdzie Il = nt11
IJ11l, ..., rrt11 > i n-\'ljest poprzednikiem wierzchołka} na najkrót-
szej ścieżce z wierzchołka i, której wszystkie wewnętrzne wierzchołki należą do
zbioru {l, 2, ..., k).
Poprzednik n-!}> można określić rekurencyjnie. Gdy k = O,najkrótsza ścież­
ka z wierzchołka i do j nie ma w ogóle wewnętrznych wierzchołków. Stąd

n-lol= {NIL, jeżeli i=J lub wv= oo


(26.6)
•i i, jeżelii::1-jiwy<oo

Jeśli dla k ~ I weźmiemy ścieżkę i.-.,.k.-.,.j,to wtedy poprzednik j, który wy-


braliśmy, jest tym samym co poprzednik} wybrany na najkrótszej ścieżce z k,
której wszystkie wewnętrzne wierzchołki należą do zbioru {1, 2, ..., k- l}.
W przeciwnym razie na poprzednik: j wybieramy poprzednik na najkrótszej
ścieżce z i, której wszystkie wewnętrzne wierzchołki są w zbiorze {1, 2, ... ,
k-1}. Formalnie, diak~ 1, zachodzi
jł-1) • 'l" d(ł-1) ~ dll-1) + dlł-1)
n-\t)- n:,J JeSJ IJ """' il: kJ
(26.7)
•i - { lł-1)
1t"ij
• 'li
JeS
.Jfł-1)
UJJ > .Jft-1)
"'Ił
+ "'łJ
.Jft-1)

Problem włączenia obliczania macierzy n<t) do procedury FLOYD-WARS-


HALLjest przedmiotem zad. 26.2-3. Na rysunku 26.4 jest pokazany ciąg macie-
rzy n<tl, które otrzymujemy w wyniku wykonania naszego algorytmu dla grafu
z rys. 26.1. W tym zadaniu należy taki.e udowodnić, że graf poprzedników G„ 1
'
jest drzewem najkrótszych ścieżek o korzeniu w i. Jeszcze inny sposób kon-
struowania najkrótszych ścieżek jest podany w zad. 26.2-6.

Domknięcie przechodniegrafu skierowanego


Powiedmiy, że dla danego grafu skierowanego G = (V, E) o zbiorze wierzchoł­
ków V= {1, 2, ..., n} chcemy wiedzieć, czy istnieją ścieżki z i do j dla wszyst-
kich par i,je V. Domknięciem pruchodnim(ang. transitive c/osure) grafu Gna-
zywamy graf G' - (V, E'), w którym
E• = {(i, 1): istnieje ścieżka z wierzchołka i do wierzchołka j w G}

Jednym ze sposobów obliczania domknięcia przechodniego grafu w czasie


8(n 1) jest przypisanie każdej krawędzi z E wagi 1 i wykonanie algorytmu
Floyda-Warshalla. Jeśli istnieje ścieżka z wierrehołka i do wierrehołka j, to
otrzymujemy d/J< n. W przeciwnym razie dostajemy dlJ= oo.
Istnieje inny, podobny sposób obliczania domknięcia przechodniego
w czas.ie 0(n 1), który jednak w praktyce jest osrezędniejszy zarówno czasowo,

631
ROZDZIAŁ 26. NAJKRÓTSZE SCIEżKI MIĘDZY W5ZYSTKIMI PARAMI. ..

jak i pamięciowo. W tej metodzie operacje arytmetyczne min i + z algorytmu


Floyda-Warshalla zastępujemy operacjami logicznymi v i A, Dla i,j, k = 1,
2, ..., n defmiujemy ,1,>
= l, jeśli istnieje ścieżka z wierzchołka i do wierzchołka
j, której wszystkie wewnętrzne wierzchołki należą do zbioru {l, 2, ..., k}, zaś
t!'l = Ow przeciwnym razie. Domknięcie przechodnie a· = (V, E•) dostajemy,
włączając krawędź (i,J) do E• wtedy i tylko wtedy, gdy ttl = 1. Rekurencyjna
defmicja t!,l,analogiczna do równania rekurencyjnego (26.5), jest następująca:

,,I -
o,
- {O,
jeśli i i=j i (i, 1)łE
I, jeśli i= j lub (i, J)EE

i dla k ~ 1 zachodzi

tl'l = 11,-l) V (ti:-l) A tk~-ll) (26.8)

Macierze Ji,l) = (tj,>),tak jak w algorytmie Floyda-Warshalla, obliczamy w ko-


lejności rosnących wartości k.

TRANSITJVE-0..0SURE(G)
I n - IV[GJI
2 fori+-lton
3 dofor}+-1 don
4 dolfi=jlub(i,J)eE[G]
5 then tlJ> +-1
6 else tlJ1+- O
7 fork+-lton
8 dofori+-1 ton
9 doforj+-lton
1>v(t~- 1
10 dotl,l+-tt- >A(tk~-1 l)
I I return 7"''

Na rysunku 26.5 są pokazane macierze Ji,klobliczone za pomocą procedu-


ry TRANSITIVE-CLOSURE dla przykładowego grafu. Podobnie jak dla algoryt-
mu Floyda-Warshalla, czas działania procedury TRANSmVE-0..0SURE wynosi
0(n3). Jednakże na pewnych komputerach operacje logiczne na wartościach
jednobitowych są wykonywane szybciej niż operacje arytmetyczne na liczbach
całkowitych. Ponadto, ponieważ algorytm obliczania domknięcia przechodnie-
go używa tylko wartości logicznych, a nie całkowitoliczbowych, jego wymaga-
nia pamięciowe są o czynnik odpowiadający rozmiarowi słowa w pamięci
komputera mniejsze niż wymagania pamięciowe algorytmu Floyda-Warshalla.
W podrozdziale 26.4 przekonamy się, że związki między algorytmem Floy-
da-Warshalla a algorytmem obliczania domknięcia przechodniego nie są przy-

632
26.2. ALGORYTM FLOYDA-WARSHALLA

I 2

I ooo l ooo l ooo l ooo


J'IO) = OI l I J'lł) =
O I I I
J'll) = O I I I
J'lłl = o I I I
Ol I O oI I o O I I I o I I I
I O l I l o l I l o l l I l I l

l ooo
J(4).., l l l l
l l l I
l I I l

Rys. 26.5. Graf skierowany i macierze ~> oblic=e w algorytmie domknięcia przechodniego

padkowe. W obu algorytmach wykorzystuje się własności struktury algebraicz-


nej nazywanej półpierścieniem domkniętym.
ZADANIA

26.2-1. Wykonaj algorytm Floyda-Warshalla dla ważonego grafu skierowane-


go z rys. 26.2. Podawaj macierze n<kl otrzymywane po wykonaniu każdej
iteracji zewnętrznej pętli.
26.2-2. Algorytm Floyda-Warshalla w przedstawionej przez nas posta.ciwyma-
ga pamięci rozmiaru E>(n 3
), ponieważ obliczamy dl'l dla i, j, k = 1, 2, ... , n.

Pokaż, że następująca procedura, w której po prostu opuszczono wszystkie


górne indeksy, jest poprawna i wymaga pamięci tylko rozmiaru E>(n2).

FLOYD-WARSHALL'(W)
1 n+-- rows[W]
2 D+--W
3 fork+--1 ton
4 dofori+--1 ton
5 doforj+--lton
6 dii +--min(dii' dlk + d„j)
7 return D

26.2-3. Uzupełnij procedurę Floyda-Warshalla w taki sposób, żeby obliczała


także macierze filkJ zgodnie z równaniami (26.6) i (26. 7). Podaj ścisły do-
_________________________ _--
..,_ ...
633
ROZDZIAŁ 26. NAJKRÓTSZE ŚCłEżKI MIĘDZY WSZVSTKIMI PARAMI ...

wód tego, że graf poprzedników G..,1 jest drzewem najkrótszych ścieżek


o korzeniu w i, (Wskazówka: Żeby udowodnić, że graf Gw•I jest acykliczny,
= I, to d!1l ~ d!~- l) + w 1i' Następnie zaadaptuj
pokaż najpierw, że jeśli 7t\'>
dowód lematu 25.8).
26.2-4. Załóżmy, że "DDieniamy równanie (26.7) w następujący sposób:
,-,, jeśli dl1-1> < d~- 1>+ di~-1 >
k)_ 7[J1 '
7[b - { 7[(k-1) jeśli dj)-ll ~ d~-l) + dt- 1>
kJ •

Czy nowa, alternatywna definicja macierzy poprzedników TI jest poprawna?


26.2-5. W jaki sposób wynik działania algorytmu Floyda-Warshalla może być
użyty do wykrywania istnienia cyk.lu o ujemnej wadre?
26.2-6. Innym sposobem konstruowania najkrótszych ścieżek w algorytmie
Floyda-Warshallajest użycie wartości 4'11>
dla i,j, k = 1, 2, ... , n, gdzie 4'1'>
jest wewnętrmym wierzchołkiem o największym numerze na najkrótszej
ścieżce z i do j. Podaj rekurencyjną formulę dla rt,j}l,"DDodyfikuj procedurę
FLOYD-WARSHALLw taki sposób, żeby obliczała wartości 4'!,l, i napisz od
nowa procedurę PruNT-ALL-PAIRS-SHORTEST-PATHtak, żeby wypisywała
wierzchołki najkrótszej ścieżki, dostając na wejściu macierz 4>= (rt,!j>).
Czym macierz 4>przypomina tablicę s z problemu wymna:i.ania łańcucha
macierzy z podrozdz. 16.l?
26.2-7. Podaj algorytm obliczania w czasie O( VE) domknięcia przechodniego
grafu skierowanego G = (V, E).
26.2-8. Załóżmy, że domknięcie przechodnie acyklicznego grafu skierowanego
można obliczyć w czasie f(V, E), gdzie f(V, E) - ll(V + E), a/ jest
funkcją niemalejącą. Pokaż, że domknięcie przechodnie dowolnego grafu
skierowanego G = (V, E) można obliczyć w czasie O(f(V, E)).

26.3. AlgorytmJohnsonadla grafów rzadkich


Algorytm Johnsona znajdowania ścieżki między wszystkimi parami wierzchoł­
ków działa w czasie O(V' lg V+ VE). Dla grafów rzadkich jest on asympto-
tycznie szybszy, zarówno od algorytmu polegającego na kolejnym podnoszeniu
macierzy do kwadratu, jak i od algorytmu Floyda-Warshalla. Algorytm John-
sona albo zwraca macierz wag najkrótszych ścieżek, albo informuje, że graf
wejściowy ma cykl o ujemnej wadze. W algorytmie Johnsona jako podpro-
gramy są używane algorytm Dijkstry i algorytm Bellmana-Forda, które zostały
opisane w rozdz. 25.
W algorytmie Johnsona jest wykorzystywana metoda zmieniających się
wag. W metodzie tej, jeśli wszystkie wagi krawędzi w w grafie G = (V, E) są
nieujemne, to najkrótsze ścież.ki między wszystkimi parami wierzchołków znaj-

634
26.3. ALGORYTM JOHNSONA DLA GRAFÓW RZADKICH

dujemy, wykonując algorytm Dijkstry z każdego wierzchołka oddzielnie. Wy-


korzystując kopce Fibonacciego do implementacji kolejki priorytetowej, otrzy-
mujemy algorytm obliczania najkrótszych ścieżek między wszystkimi parami
wierzchołków, który działa w czasie O(V1 lg V+ VE). Jeśli graf G ma cykl
o ujemnej wadze, to obliczamy nowy zbiór nieujemnych wag krawędzi, który
umożliwia użycie algorytmu Dijkstry. Nowy zbiór wag krawędzi W musi mieć
dwie ważne własności.
1. Dla wszystkich par wierzchołków u, v E V najkrótsza ścieżka z wierzchołka
u do wierzchołka v dla funkcji wagowej w jest tak.że najkrótszą ścieżką
między wierzchołkami u i v dla funkcji wagowej W.
2. Dla wszystkich krawędzi (u, v) nowa waga W(u, v) jest nieujemna.
Jak się za chwilę przekonamy, wstępne przetworzenie grafu G w celu obliczenia
nowej funkcji wagowej W można wykonać w czasie O(VE).

Zachowywanie najkrótszychścieżek przy zmianie wag


Jak wynik.a z następującego lematu, łatwo jest 7Jllienić wagi krawędzi w taki
sposób, żeby zachodziła własność pierws:za. Oznacnny przez O wagi najkrót-

szych ścieżek przy funkcji wagowej w, a przez O - wagi najkrótszych ścieżek
przy funkcji wagowej W.

LEMAT26.1. (Zmiana wag nie powoduje zmiany najkrótszych ścieżek)


Dany jest ważony graf skierowany G = (V, E) o funkcji wagowej w: E--+ R.
Niech h: V--+ R będzie dowolną funkcją odwzorowującą wierzchołki w zbiór
liczb rzeczywistych. Dla każdej krawędzi (u, v)e E definiujemy

w(u, v) - w(u, v) + h(u) - h(v) (26,9)

Niech p = <v0 , v1, ••• , v") będzie ścieżką z wierzchołka v0 do wierzchołka v".
-
Wówczas w(p) = O(v0, v") wtedy i tylko wtedy, gdy W(p)= O(v0, v,:). Ponadto
graf G ma cykl o ujemnej wadze przy funkcji wagowej w wtedy i tylko wtedy,
gdy ma on cykl o ujemnej wadze przy funkcji wagowej W.

Dowoo
Rozpoczniemy od wykazania, że

w(p) - w(p) + h(v 0) - h(vJ (26.10)


Mamy

w(p) -
•L w(v,_,, vj
i"' 1

635
ROZDZIAŁ 26. NAJKRÓTSZE SCIEżKI MIĘDZY WSZVSTKIMI PARAMI. ..


= L (w(v,_,, v;J+ h(v,_,) - h(v;J)
I"' 1

=
•L w(v,_,, v;J+ h(v,) - h(v,)
! "' 1

= w(p) + h(v,,)- h(v,)

Trzecia równość wynika z tego, że w drugim wierszu mamy sumę teleskopową.


Udowodnimy teraz nie wprost, że jeśli w(p) = ó(v0, v,1),to »'(p) = ó(v0, vJ. -
Przypuśćmy, że istnieje krótsza ścieżka p' z v0 do vk przy funkcji wagowej W.
Wówczas W(p') < W(p). Z równości (26.10) wynika, że

w(p') + h(v,) - h(v;) = >O{p')


< w(p)
= w(p) + h(v0) - h(v;)

co daje w(p') < w(p). Otrzymujemy sprzeczność z założeniem, że p jest najkrót-


szą ścieżką między wierzchołkami u i v przy funkcji wagowej w. Dowód w dru-
gą stronę jest podobny.

Na koniec pokaźemy, że graf G ma cykl o ujemnej wadze przy funkcji


wagowej w wtedy i tylko wtedy, gdy ma on cykl o ujemnej wadze przy funkcji
wagowej W. Rozważmy dowolny cykl c = (v 0, Vu ... , v.,), w którym v0 = vk.
Z równości (26.10) wynika, że

w(c) = w(c) + h(v0) - h(v,)

= w(c)
i stąd cykl c ma ujemną wagę przy funkcji wagowej w wtedy i tylko wtedy, gdy
jego waga jest ujemna przy funkcji wagowej W.

Otrzymywanie nieujemnych wag
Naszym następnym celem jest zapewnienie drugiej własności: chcemy, żeby
waga W(u, v) była nieujemna dla wszystkich (u, v)EE. Dla ważonego grafu
skierowanego G = (V, E) z funkcją wagową w: E-+ R tworzymy nowy graf
G' = (V', E'), w którym V'= Vu {s} dla pewnego nowego wierzchołka sf V
i E' = Eu {(s, v): vE V}. Rozszerzamy funkcję wagową w tak, że w(s, v) = O
dla wszystkich vE V. Zauważmy, że ponieważ do wierzchołka s nie dochodzi
ani jedna krawędź, żadna najkrótsza ścieżka, oprócz tych o początku ws, nie

636
26,3. ALGORYTM JOHNSONA DLA GRAFOW RZADKICH

zawiera s. Ponadto graf G' nie ma cyk.li o ujemnych wagach wtedy i tylko
wtedy, gdy Gnie ma cykli o ujemnych wagach. Na rysunku 26.6a jest przed-
stawiony graf G' odpowiadający grafowi G z rys. 26.1.

[)
2
5 - 2
o l

l l
o o -5 3
2 2 13

-4 -5 [)
o
7 ,o o

2
o
(a) (h)

5
2
4
(c) (d) (e)

2 2
4
10 (gl

Rys. 26.6. Ilustracja działania algorytmu Johnsona dla grafu z rys. 26.1. (a) Graf G z początkową
funkcją wagową 111. Nowy wierzchołek sjest czarny. Wewnątrz kaxdego wierzchołka v mamy
h(v) = ó(s, v). (b) Waga każdej krawędzi (u, v) została zmieniona na w(u, v) = w(u, v) + h(u)- h(v).
(c){g} Wynik działania algorytmu Dijk:stry dla każdego wierzchołka z G jako źródła przy funkcji
wagowej W. W kai.dej części wierzchołek źródłowy u jest czarny. Wewnątrz każdego wierzchołka
v znajdują się wartości S(u, v) i ó(u, v), oddzielone ukośną kreską. Wartość d.., = ó(u, v)jest równa
-
ó(u, v) + h(v) - h(u)

637
ROZDZIAŁ 26. NAJKRÓTSZE $CIEżKI MIĘDZY WSZVSTKIMI PARAMI...

Przypuśćmy teraz, że
grafy G i G' nie mają cykli o ujemnych wagach.
Zdefiniujmy h(v) = t5(s,v) dla wszystkich ve V'. Z lematu 25.3 otrzymujemy, że
h(v).; h(u) + w(u, v) dla wszystkich krawędzi (u, v)e E'. Dlatego, jeśli zdeftniu-
jemy nowe wagi W zgodnie z równaniem (26.3), to otrzymamy w(u, v) =
= w(u, v) + h(u) - h(v) ~ O;zachodzi więc druga własność. Na rysunku 26.6b
jest pokazany graf G' z rys. 26.6a ze z.mienionymi wagami.

Obliczanienajkrótszychścieżek między wszystkimi


paramiwierzchołków
W algorytmie Johnsona obliczania najkrótszych ścieżek między wszystkimi
parami wierzchołków są stosowane jak.o podprogramy algorytmy Bellmana-
-Forda (podrozdz. 25.3) i Dijkstry (podrozdz. 25.2). Zakłada się, że krawędzie
grafu są pamiętane za pomocą list sąsiedztwa. Algorytm zwraca, jak zazwyczaj,
macierz D = (diJ)wymiaru IVI x IVI,w której dy= ó(i,J), lub informuje, że graf
wejściowy ma cykl o ujemnej wadze. (żeby indeksy odnoszące się do macierzy
D miały sens, zakładamy, że wierzchołki są ponumerowane od 1 do IVI}.

lOHNSON(G)
1 oblicz G', gdzie V[G1 = V[G] u {s} i E[G1 = E[G] u {(s, v): ve V[G]}
2 if BELLMAN-FORD(G', W, s) = FALSE
3 then wypisz „graf wejściowy zawiera cykl o ujemnej wadze"
4 else for każdy wierzchołek ve V[G1
5 do przypisz h(v) wartość ó(s, v) obliczoną.
w algorytmie Bellmana-F orda
6 for każda krawędź (u, v)eE[G1
7 do w(u, v) - w(u, v) + h(u) - h(v)
8 for każdy wierzchołek ue V[G]
9
-
do wywołaj DIJKSTRA(G,W, u), aby obliczyć t5(u,v)
dla każdego ve V[G]
10 for każdy wierzchołek ve V[G)
Il do dw -i(u, v) + h(v) - h(u)
12 return D

W procedurze JOHNSON zapisaliśmy precyzyjnie wszystkie kroki algorytmu,


o których mówiliśmy wcześniej. W wierszu 1 jest tworzony graf G'. W wier-
szu 2 jest wykonywany algorytm Bellmana-Forda dla grafu G' z funkcją wago-
wą w. Jeśli graf G', a stąd i graf G, ma cykl o ujemnej wadze, to w wierszu 3 jest
wypisywana informacja o tym fakcie. W wierszach 4-11 zakładamy, że graf G'
nie zawiera cykli o ujemnych wagach. W wierszach 4-5, dla wszystkich ve V',
wartością h(v) staje się waga najkrótszej ścieżki t5(s,v) obliczona w algorytmie
Bellmana-Forda. W wierszach 6-7 są obliczane nowe wagi W. Dla każdej pary

638
* 26.4. OGÓLNY SCHEMAT ROZWIĄZYWANIA PROBLEMÓW $CIEŻKOWYCH ...

wierzchołków u, v E V w pętli for w wierszach 8-11 jest obliczana waganajkrót-



szej ścieżki 6(u, v). Odbywa się to za pomocą algorytmu Dijkstry wykony-
wanego jeden raz dla każdego wierzchołka z V. W wierszu 11 każdemu ele-
mentowi macierzy d.,_ 0
jest przypisywana poprawna długość najkrótszej ścież­
ki ó(u, v), obliczana zgodnie z równaniem (26.10). Na koniec, w wierszu 12,
jest zwracana wypełniona macierz D. Rysunek 26.6 ilustruje działanie algo-
rytmu Johnsona.
Łatwo się można przekonać, że czas działania algorytmu Johnsona wynosi
O(V2lg V+ VE), jeśli kolejka priorytetowa używana w algorytmie Dijkstry
jest zaimplementowana za pomocą kopców Fibonacciego. Stosując prostszą
implementację za pomocą kopca binarnego, otrzymujemy czas działania
O(VElg V), który dla grafów rzadkich jest nadal asymptotycznie lepszy niż
czas działania algorytmu Floyda-Warshalla.

ZADANIA
26.3-1. Zastosuj algorytm Johnsona do znalezienia najkrótszych ścieżek mię­
dzy wszystkimi parami wierzchołków w grafie z rys. 26.2. Wypisz wartoś­
ci h i W obliczane w tym algorytmie.
26.3-2. W jakim celu jest dodawany nowy wierzchołek s do V, w wyniku czego
otrzymujemy V'?
26.3-3. Załóżmy, że w(u, v) ~ O dla wszystkich krawędzi (u, v)eE. Jaki jest
związek między funkcjami wagowymi w i W?

* 26.4. Ogólny schematrozwiązywania problemów


ścieżkowych w grafachskierowanych
W tym podrozdziale zdefiniujemy półpierścień domknięty - strukturę alge--
braiczną, która posłuży do opisania pewnego ogólnego schematu rozwiązywa­
nia problemów ścieżk.owych w grafach skierowanych. Przedyskutujemy też
związki półpierścieni domkniętych z operacjami na ścieżkach skierowanych.
Następnie przedstawimy kilka przykładów półpierścieni domkniętych i pewien
schemat obliczania informacji o ścieżkach między wszystkimi parami wierz-
chołków. Zarówno algorytm Floyda-Warshalla, jak i algorytm oblicmnia
domknięcia przechodniego z podrozdz. 26.2 są zgodne z tym schematem.

Definicja pólpierścienia domkniętego


Półpierścieniem domkniętymnazywamy system (S, El), 0, O, I), w którym Sjest
zbiorem elementów, EB (operator sumowania) i 0 (operator rozszerzania) są
operacjami binarnymi nad zbiorem S, a O i l są elementami zbioru S speł­
niającymi następujące warunki:

639
ROZDZIAŁ 26. NAJKRÓTSZE $CIEżKI MIĘDZY WSZVSTKIMI PARAMI. ..

I. (S, EB,il) jest monoidem.


• Zbiór Sjest zamknięty ze względu na EB, czyli aEBbeS dla wszystkich
a,beS.
• Operacja EB jest łączna, czyli a EB(b EBc) = (a EBb) EBc dla wszystkich
a, b, ceS.
• Ojest jednością operacji EB,czyli a EBO= OEBa= a dla wszystkich aeS.
Podobnie, (S, 0, I) jest monoidem.
2. Ojest elementem zerowym operacji 0, czyli a 0 O= O0 a = Odla wszyst-
kich aeS.
3. Operacja EBjest pnemienna, czyli a EBb = b EBa dla wszystkich a, be S.
4. Operacja EBjest idempotentna, czyli a EBa= a dla wszystkich aeS.
5. Operacja 0 jest rozdzielna względem EB, czyli a 0 (b EBc) - (a 0 b)
9 (a 0 c) i (b EBc) 0 a - (b 0 a) 9 (c 0 a) dla wszystkich a, b, ceS.
6. Jeśli a1, a 2, a3, ••• jest przeliczalnym ciągiem elementów ze zbioru S, to
a 1 EBa 2 EBa3 EB... jest jednoznacznie określone i należy do zbioru S.
7. Łączność, przemienność i idempotentność stosują się takź'.e do sum nieskoń­
czonych. (Stąd wynika, że każdą sumę nieskończoną można zapisać w taki
sposób, żeby każdy jej składnik występował dokładnie raz, a kolejność su-
mowania była dowolna).
8. Operacja 0 jest rozdzielna względem sum nieskończonych: a 0 (b 1 EBb2 EB
9b,EB ...)- (a0b,)EB(a0b,)9(a0b,)9 ... i (a, 9a,9a,e ...)0b-
- (a, 0 b) 9 (a, 0 b) 9 (a, 0 b) EB...

Rachunekna ścieżkach w grafach skierowanych


Chociaż operacje w półpierścieniu domkniętym wydają się abstrakcyjne, mają
one związek z rachunkiem na ścieżkach w grafie skierowanym. Załóżmy, że
=
dany jest graf skierowany G (V, E} i funkcja etykietująca 1: V x V-+ S
odwzorowująca wszystkie uporządkowane pary wierzchołków w pewną
przeciwdziedzinę S. Etykietę krawędzi (u, v)eE oznaczamy przez l(u, v).
Ponieważ l jest zdefiniowana na dziedzinie V x V, przyjmuje się zazwyczaj, że
l(u, v) = O,jeżeli (u, v) nie jest krawędzią w grafie G (za chwilę zobaczymy
dlaczego).
Użyjemy łącznego operatorarozszerzania 0 w celu rozszerzenia etykieto·
wania krawędzi na etykietowanie ścieżek. Etykietą ścieżki p = (v 0, v1>..., vk) jest
.l(p) = .l(v„ v,) 0 .l(v,, v,) 0 ... 0 .l(v,~,, v,)
Jedność operacji 0, czyli I, służy za etykietę pustej ścieżki.
Nasze rozważania dotyczące zastosowań półpierścieni domkniętych hę·
dziemy ilustrować na przykładzie ścieżek z nieujemnymi wagami na krawę--

640
* 26.4. OGÓLNY SCHEMAT ROZWIĄZYWANIA PROBLEMÓW $CIEŻKOWYCH ...

ciziach. Przeciwdziedziną Sjest R> 0 u {oo}, gdzie R>0 jest zbiorem nieujem-
nych liczb rzeczywistych, a A(i, J) = Wg dla wszystkich i, je V. Operator roz-
szerzania 0 odpowiada operatorowi arytmetycznemu + i dlatego etykietą
ścieżki p = (v 0 , v1, ••• , vk) jest

l(p) - ,(v,, v;J0 l(v,, v,) 0 ... 0 l(v,_,, v,)


-w, v,, • +w....
., .•,
+ ... +w, ..
·-····
- w(p)

Nie jest niespodzianką, że rolę I, jedności operacji 0, pełni O,jedność operacji


+. Pustą ścieżkę oznaczamy przez e, a jej etykietą jest ,l.(e)= w(e) = O= T.
Ponieważ operator rozszerz,ania jest łączny, możemy 7.definiować w natu-
ralny sposób etykietę konkatenacji dwóch ścieżek. Konkatenację dwóch ścieżek
P 1 = (vJI v2, ..., vk) i p 2 = (vk+I• vk+2, ..•, v1) nazywamy ścieżkę

a etykietą ich konkatenacji jest

A(p1 o pJ = A(v1, v2) 0 A(v2, v3) 0 ... 0 A(vk-i• v.J 0 l(v,1:,vk+i>0


A(v.1:+i•vk+ 2)0 ... 0 l(v 1_ 1, vJ

- (l(v,, v;J0 l(v,, v,) 0 ... 0 l(v,_,, vJ) 0 (J.(v~ v, + ,) 0


l(vk+ 1, vk+J 0 ... 0 l(v 1_ 1, vJ)

Operator sumowania EB,który jest zarówno przemienny, jak i łączny, jest


używany do sumowania etykiet ścieżkowych. Semantyka operacji sumowania
jest ściśle związana z konkretnym zastosowaniem.
Naszym celem będzie obliczenie, dla wszystkich par i,je V, sumy wszyst-
kich etykiet ścieżek od i do J:

1,-$l(p)
;.!.j
(26.11)

Wymagamy, żeby operacja EB była łączna i przemienna, ponieważ kolejność,


w jakiej sumujemy etykiety ścieżek, nie powinna mieć znaczenia. Ponieważ
przyjmujemy, że etykietą uporządkowanej pary (u, v) jest O,jeśli para (u, v) nie
jest krawędzią w grafie, etykietą każ.dej „ścieżki" zawierającej nie istniejącą
krawędź jest O.
W przypadku najkrótszych ścieżek operacją sumowania jest operacja bra-
nia minimum (min). Jednością operacji min jest oo i oo jest faktycznie anihila-
torem operacji+: a+ oo = co +a= oo dla wszystkich aER> 0 u{oo}. Nie

641
ROZDZIAŁ 26. NAJKRÓTSZE SClfŻKI MIĘDZY WSZVSTKIMI PARAMI ...

występujące krawędzie mają wagę oo, a jeśli jakakolwiek ścieżka zawiera kra-
wędź z wagą oo, to wagą całej ścieżki jest też oo.
Dodatkowo chcemy, żeby operacja sumowania była idempotentna, ponie-
waż na podstawie równości (26.11) widzimy, że operacja EBpowinna wyzna-
czać etykietę całego zbioru ścieżek. Jeśli p jest ścieżką, to {p}u {p}= {p};jeśli
sumujemy ścieżkę p z samą sobą, to wynikową etykietą powinna być etykieta
p: ,\(p}EB2(p) = .l(p).
Rozpatrujemy ścieżki, które nie muszą być ścieżkami prostymi. Tak.ich
ścieżek w grafie może być nieskończenie, ale przeliczalnie wiele. (Każda ścież­
ka, zarówno prosta, jak i nie, skJada się ze skończonej liczby krawędzi). Dlate-
go operacja EBpowinna stosować się do przeliczalnej liczby etykiet ścieżk.o­
wych. Oznacza to, że jeśli a1, a2, a3, ... jest przeliczalnym ciągiem elementów
z przeciwdziedziny S, to etykieta a 1 EBDi EBa3 EB... powinna być jednoznacznie
określona i należeć do zbioru S. Nie powinno mieć znaczenia, w jakiej kolejno-
ści etykiety ścieżk.owe są sumowane i dlatego łączność i przemienność powinny
zachodzić dla sum nieskończonych. Ponadto, jeśli sumujemy tę samą etykietę
ścieżk.ową a przeliczalnie wiele razy, powinniśmy w wyniku zawsze dostać
a i dlatego idempotentność powinna zachodzić dla sum nieskończonych.
Wracając do naszego przykładu najkrótszych ścieżek, sprawdźmy,
czy operacja min jest stosowalna do nieskończonego ciągu wartości

z R~ u {oo}. Na
0 przykład, czy wartość min {1/k} jest dobrze zdefiniowana?
A:"'1
Odpowiedź btzmi „tak.", jeśli przyjmiemy, że operacja min zwraca w rzeczy-
wistości kres dolny zbioru jej argumentów. W takim przypadku otrzymujemy

min{l/k} = O.
A:""1
Żeby policzyć etykiety rozgałęziających się ścieżek, potrzebujemy rozdziel-
ności operacji rozszerzania 0 względem operacji sumowania EB.Załóżmy, że
mamy ścieżki u Ą.v, v Ą.x i v 4y, jak na rys. 26.7. Z rozdzielności wynika, że
możemy zsumować etykiety ścieżek p 1 o p 2 i Pi o p 3, obliC"lając albo (A{p
1) 0
0 .l(p,)}al (.l(p,) 0 ,l{p,)), albo ,l{p,) 0 (.l(p,) EB2(p,)).

Pz

P,

Rys. 26.7. Zastosowanie rozdzielności 0 względem @. Żeby zsumować etykiety ścieżek p 1 o p 2


i p 1 o p1 , możemy obliczyć (l(p 1) 0 ,l(pJ Ea(..t(p1) 0 ).(p3)) albo A(p1) 0 ().(p:Jm..t(pJ)

642
* 26.4. OGÓLNY SCHEMAT ROZWIĄZYWANIA PROBLEMÓW SCIEŻ'.KOWYCH ...

Rys. 26.B. RozdzieJność operacji 0 względem nieskończonych, ale przeliczalnych,sumowań EB.Cykl


c powoduje, że jest nieskończenie, ale przeliczalnie wieJe, ścieżek z wierzchołka v do wierzchołka x.
Musimy mieć mo:i:liwość zsumowania ścieżek p 1 o Pi, p 1 o co Pv p 1 o co co Pv ...

Ponieważ w grafie może być nieskończenie, ale przeliczalnie wiele ścieżek,


operacja 0 powinna być rozdzielna względem sum nieskończonych tak samo
jak względem sum skończonych. Na rysunku 26.8 mamy ścieżki u Ą. v i v Ą.x
i cykl v ~ v. Musimy mieć możliwość sumowania ścieżek p 1 o p 2, Pi o co p 2,
Pi o co co p 2, •••• Dzięki rozdzielności operacji 0 względem nieskończonych,
ale przeliczalnych sum otrzymujemy

(l(p,) O l(p,)) <'Il(l(p,) O l(c) O l(p,)) <'Il(l(p,) O l(c) 0 ,l(c) O l(p,)) <'Il...
- l(p,) 0 (l(p,) <'Il(l(c) O l(p,)) <'Il(l(c) O l(c) O l(p,)) al ...)
- l(p,) O (I <'Ilc <'Il(c 0 c) <'Il(c O c O c) al ...) O l(p,)
Do oznaczenia etykiety cyklu, po którym możemy przechodzić dowolną
liczbę razy, wprowadzimy specjalny symbol. Załóżmy, że mamy cykl c o ety-
kiecie ,l.(c)= a. Cykl c możemy przejść zero razy -dostając etykietę l(t:) = I,
jeden raz - dostając etykietę l(c) = a, dwa razy - dostając etykietę
J.(c)0 J.(c) = a 0 a itd. Etykieta, którą otrzymujemy, przechodząc cykl c nie-
skończenie wiele razy, jest domknięciem a zdefmiowanym tak:

a' - I <'Ila <'Il(a O a) <'Il(a O a O a) <'Il(a 0 a O a O a) al ...


Tak więc na rys. 26.8 chcemy obliczyć l(p,) O (l(c))' O l(p,).
W przykładzie z najkrótszymi ścieżkami dla każdej nieujemnej liczby rze-
czywistej aeR~ 0 u {oo} otrzymujemy

a' - min{ka)
k'"O

-o
Powyższą własność można zinterpretować następująco. Ponieważ wszystkie cy-
kle mają nieujemne wagi, żadna najkrótsza ścieżka nie musi zawierać w całości
jakiegokolwiek cyklu.

Przykłady półpierścieni domkniętych

Z jednym przykładem półpierścienia domkniętego już się z.apoznaliśmy, a mia-


nowicie z S 1 = (R;;,0 u {oo}, min, +, oo, O), którego używaliśmy w rozwiązaniu

643
ROZDZIAŁ 28. NAJKRÓTSZE $CIEżKI MIĘDZY WSZVSTKIMI PARAMI. ..

problemu najkrótszych ścieżek w grafach z nieujemnymi wagami na krawę­


dziach. (Jak.już wcześniej wspomnieliśmy, operacja min w rzeczywistości zwra-
ca kres dolny zbioru jej argumentów). Pokazaliśmy także, że a· = Odla wszyst-
kich a eR'" 0 u {oo}.
Wykazaliśmy jednak, że nawet jeśli są w grafie krawędzie o ujemnych
wagach, to algorytm Floyda-Warshalla poprawnie oblicza wagi najkrótszych
ścieżek, o ile nie pojawiają się cykle o ujemnych wagach. Dodając właściwą
operację domykania i rozszerzając zbiór etykiet do Ru { - oo, + oo}, możemy
znaleźć półpierścień domknięty, w którym można poradzić sobie z cyklami
o ujemnych wagach. Przyjmując min jak.o EBi + jako 0, można sprawdzić, że
domknięciem aeRu{-oo, +oo} jest

'-{O, jeśli a~O


a - -oo, jeśli a<O

Przypadek drugi odpowiada sytuacji, w której, przechodząc nieskończenie wie-


le razy cykl o ujemnej wadze, możemy przyporządkować wagę - oo każdej
ścieżce zawierającej ten cykl. Tak więc, półpierścieniem domkniętym używa­
nym w algorytmie Floyda-Warshalla z ujemnymi wagami na krawędziach jest
s, = (Ru{-oo, +oo}, min,+, +oo, O) (patrz zad. 26.4-3).
W problemie obliczania domknięcia przechodniego jest używany półpierś­
cień domknięty S 3 = ({O, 1}, v, A, O, 1), gdzie ).(i,J) = 1, jeśli (i,;)eE, oraz
).(i,J) = O w przeciwnym razie. W tym przypadku mamy o·= 1• = 1.

Algorytm obliczania etykiet na ścieżkach skierowanych


oparty na programowaniudynamicznym
Załóżmy, że dany jest graf skierowany G = (V, E) i funkcja etykietująca
).: V x V-+ S. Wierzchołki grafu są ponumerowane od 1 do n. Dla każdej pary
wierzchołków i, je V należy obliczyć

Etykietę /1,Jotrzymuje się w wyniku zsumowania etykiet na wszystkich ścież­


kach z i do j za pomocą operacji EB.W problemie najkrótszych ścieżek należy
na przykład obliczyć

I"= J(i, 1) = min {w(p)}


1!..j

Powyższyproblem możemy rozwiązać za pomocą algorytmu progra-


mowania dynamicznego, który jest bardzo podobny do algorytmu Floyda-

644
* 26.4. OGÓLNY SCHEMAT ROZWIĄZYWANIA PROBLEMÓW $CIEŻKOWYCH ...

-Warshalla i algorytmu obliczania domknięcia przechodniego. Niech Q!1>


będzie zbiorem ścieżek z wierzchołka i do wierzchołka j, których wszystkie
wierzchołki wewnętrzne należą do zbioru {1, 2, ... , k}. Zdefmiujmy

l!l'- EB,(pl
,•O!'
Zauważmy analogię z defmicją d~) w algorytmie Floyda-Warshalla i z definicją
tjJ>w algorytmie obliczania domknięcia przechodniego. Wartości /~l możemy
zdefiniować rekurencyjnie:

(26.12)

Rekurencja (26.12) przypomina rekurencje (26.5) i (26.8), ale z dodatkowym


czynnikiem (/t- 1 J)•. Ten czynnik reprezentuje sumę wszystkich cykli, które
przechodzą przez wierzchołek k i w których wszystkie pozostałe wierzchołki
należą do zbioru {1, 2, ..., k-1}. (Jeśli zakładamy, że w algorytmie Floyda-
-Warshalla nie napotykamy cykli o ujemnych wagach, to (ct- 1 i)• jest równe O,
co odpowiada I - wadze pustego cyklu. W algorytmie obliczania domknięcia
przechodniego pusta ścieżka z k do k daje nam (1t- 1 i)• = 1 = I. Tak więc
w obu tych algorytmach możemy pominąć czynnik (llr\- 1>)•, ponieważ jest
jednością operacji 0). Wartościami brzegowymi w definicji rekurencyjnej są

li'' - {l(i,J), jeśli i# j


J r Elll(i, J), jeśli i - j
co można wytłumaczyć, jak następuje. Etykietą ścieżki (i, j) złożonej z jednej
krawędzi jest po prostu A(i,;) (co jest równe O,jeśli (i,;) nie jest krawędzią ze
zbioru E). Jeśli na dodatek i= j, to I jest etykietą pustej ścieżki z i do i.
Algorytm COMPUTE-SUMMARJES jest algorytmem programowania dyna-
micznego, który oblicza wartości IjJ1 w kolejności rosnących wartości k. Wy-
nikiem jego działania jest macierz Ll11l = (/jjl).

COMPUTE-SUMMARIES(J\., V)
I n~ IVI
2 fori,.__l ton
3 doforj,.__1 ton
4 doifi=j
5 thenIJY'~ T Elll(i, j)
6 else !jJ1- A(i,;)
7 fork,.__1 ton
8 dofori,.__lton

645
ROZDZIAŁ 26. NAJKROTSZE $C1E2KI MIĘDZY WSZVSTKtMI PARAMI. ..

9 doforjrlton
10 do I!j>~ ilJ-1>Ell(ill-1>0 (/~- 1>)•O i(\-1>)
11 retun1 Lin>

Czas działania powyższego algorytmu zależy od czasów obliczania operacji


0, EBi*. Jeśli czasy te oznaczymy przez T0 , Te i T., to czas działania algoryt-
mu COMPUTE-SUMMARIES wynosi 9(n 3 (T 0 +Te+ T.)), co jest równe 9(n 3),
jeśli każda z tych trzech operacji może zostać wykonana w czasie stałym.

ZADANIA
26.4-1. Sprawdź,żeS1 =(R:i- 0 u{oo},min, +,oo,O)iS 3 =({0, l}, v, A,0,
l) są półpierścieniami domkniętymi.
26,4-2. Sprawdź, że S2 = (Ru { - oo, + oo}, min, +, + oo, O) jest półpierś­
cieniem domkniętym. Co jest wartością wyrażenia a + ( - oo) dla a e R,
a co wartością wyrażenia ( - co) + ( + oo)?
26.4-3. Napisz procedurę COMPUTE-SUMMARIES w taki sposób, żeby operacje
były wykonywane w półpierścieniu S2, otrzymując w ten sposób imple-
mentację algorytmu Floyda-Warshalla. Co powinno być wartością wyra-
żenia - co + oo?
26.4-4. Czy system S4 = (R, +,·,O, 1) jest półpierścieniem domkniętym?
26.4-5. Czy w algorytmie Dijkstry może zostać użyty dowolny półpierścień
domknięty? Jaka jest odpowiedź na powyższe pytanie w przypadku algo-
rytmów Bellmana-Forda i FASTBR-ALL-PAIRS-SHORTEST-PATHS?
26.4-6. Firma przewozowa z USA chce wysiać z Castroville do Bostonu samo-
chód ciężarowy z ładunkiem karczochów obciążony tak mocno, jak to jest
tylko możliwe. Na każdej drodze w USA istnieje ograniczenie na maksy-
malną wagę samochodów ciężarowych, które mogą się po niej poruszać.
Należy wyznaczyć najkrótszą dopus.zczalną drogę przeja.7.duciężarówki.
Wyraź powyższy problem za pomocą grafu skierowanego i odpowiedniego
półpierścienia domkniętego, a następnie podaj efektywny algorytm obli-
czania najkrótszej możliwej drogi.

Problemy
26-1. Domknięcie
przechodnie grafu dynamicznego
Załóżmy, że chcemy utrzymywać domknięcie przechodnie grafu skierowanego
G = (V, E), kiedy do zbioru E są dodawane nowe krawędzie. Oznacza to, że
po dodaniu każdej krawędzi do zbioru E należy zaktualizować bieżące do-
mknięcie przechodnie tak:, żeby została uwzględniona nowo dodana krawędź.
Załóżmy, że początkowo graf G nie ma żadnych krawędzi i że domknięcie
przechodnie reprezentujemy za pomocą macierzy logicznej.

646
PROBLEMY

(a) Pokaż, w jaki sposób w czasie O(V2) zaktualizować domknięcie przechod-


nie G = (V, E ) grafu G = (V, E) po dodaniu nowej krawędzi do grafu G.
0 0

(b) Podaj przykład grafu G i krawędzie, żeby aktualizacja domknięcia prze-


chodniego G po dodaniu krawędzi e wymagała co najmniej O(V2) kroków.
(c) Opisz efektywny algorytm aktualizacji domknięcia przechodniego grafu G
podczas dodawania do tego grafu nowych krawędzi. Dla każdego ciągu n
operacji dołączania nowych krawędzi Twój algorytm powinien działać
"
w czasie Lt 1 = O(v3), gdzie t1 jest czasem aktualizacji domknięcia prze-
i=t
chodniego po dołączeniu i-tej krawędzi. Udowodnij, że Twój algorytm
działa rzeczywiście w tym czasie.

26-2. Najkrótsze ścieżki w grafach ,;-gęstych


Graf G = (V, E) nazywamy 1::-gęstym, jeśli IE'l= 0(V 1 +•) dla pewnej stałej t
z zakresu O < E :E;;I. Stosując kopce rzędu d (patrz problem 7-2) w algorytmach
najkrótszych ścieżek dla grafów e-gęstych, otrzymujemy algorytmy, których
czasy działania są takie same jak przy zastosowaniu kopców Fibonacciego,
jednak. bez używania tak. skomplikowanej struktury danych.

(a) Jak.ie są asymptotyczne czasy wykonania operacji INSERT, EXTRACT-MIN


i DECREASE-KEY wyrażone jako funkcje zależne od d i liczby elemen-
tów n w kopcu d-arnym? Jak.ie są te czasy, gdy przyjmiemy d = 0(n") dla
pewnej stałej O< ce:E;;17 Porównaj czasy wykonania poszczególnych opera-
cji z ich kosztami zamortyzowanymi w implementacji z użyciem kopców
Fibonacciego.
(b) Pokaż, w jaki sposób obliczyć w czasie O(E) najkrótsze ścieżki z jednego
źródła w E-gęstym grafie skierowanym G = (V, E), nie zawierającym kra-
wędzi z ujemnymi wagami? (Wskazówka; Określ zależność d od s).
(c) Pokaż, w jaki sposób rozwiązać w czasie O(VE) problem najkrótszych
ścieżek między wszystkimi parami wierzchołków w s-gęstym grafie skiero-
wanym G = (V, E), nie zawierającym krawędzi z ujemnymi wagami.
(d) Pokaż, w jaki sposób rozwiązać w czasie O(VE) problem najkrótszych
ścieżek między wszystkimi parami wierz.chołków w 1::-gęstym grafie skiero-
wanym G = (V, E), który może zawierać krawędzie z ujemnymi wagami,
ale nie ma cykli o ujemnych wagach.

26-3. Minimalne drzewo rozpinające w półpierścieniu domkniętym


Niech G = (V, E) będzie spójnym grafem nieskierowanym z funkcją wagową
w; E--> R. Niech zbiorem wierzchołków będzie V= { 1, 2, ... , n}, gdzie n = IVI.
Załóżmy też, że wszystkie wagi w(i,J) są parami różne. Niech Tbędzie jedynym
(patrz zad. 24.1-6) minimalnym drzewem rozpinającym w grafie G. Pokażemy,
w jaki sposób wyznaczyć drzewo T, wykorzystując pewien półpierścień do-

647
ROZDZIAŁ 26. NAJKROTSZE SCIEżKI MIĘDZY WS2YSTKłMI PARAMI ...

mk.nięty.
Omawiane rozwiązanie pochodzi od B.M. Maggsa i S.A. Plotkina.
Określmy najpierw dla kaid.ej pary wierzchołków i,je V wagę minimaksową

m 11= min max w(e)


1!.J kraw. eep

(a) Uzasadnij krótko, że S =(Ru { - oo, oo}, min, max, oo, - oo) jest półpier­
ścieniem domkniętym.

Ponieważ Sjest półpierścieniem domkniętym, możemy zastosować proce-


durę COMPUTE-SUMMARIES do wyznacu:nia w grafie G wag minimaksowych
mlJ. Niech mj~l będzie wagą minimaksową obliczaną po wszystkich ścieżkach
z i do j, których wewnętrzne wierzchołki należą do zbioru {l, 2, ... , k}.
(b) Ułóż równanie rekurencyjne dla mril, gdy k ~ O.
(c) Niech T. = {(i,J)EE: w(i,J) = m,). Udowodnij, że krawędzie z T. tworzą
drzewo rozpinające w grafie G.
(d) Pokaż, że T,,.= T. (Wskazówka: Zastanów się, co jest wynikiem dodania
krawędzi (i,J) do druwa Ti usunięcia innej krawędzi u: ścieżki w Tłączą­
cej i zj. Rozważ także efekt usunięcia krawędzi (i,J) z drzewa Ti zastąpie­
nia jej inną krawędzią).

Uwagido rozdziału
Książka Lawlera [132] zawiera sporo materiału dotyczącego problemu najkrót-
szych ścieżek. między wszystkimi parami wierzchołków, chociaż nie ma tam
analizy rozwiązań problemu dla grafów rzadkich. Lawler podaje, że algorytm
wykorzystujący mnożenie macierzy należy do folkloru w tej dziedzinie. Algo-
rytm Floyda-Warsballa pochodzi od Floyda [68], który w swoim rozwiązaniu
wykorzystał twierdu:nie Warshalla [198], określające sposób obliczania do-
mknięcia przechodniego macierzy logicznych. Półpierścień domknięty jest
omówiony w książce Abo, Hopcrofta, Ullmana [4]. Algorytm Johnsona został
zaczerpnięty z pracy [114].
Rozdział 27

Maksymalnyprzepływ

Jak można za pomocą grafu skierowanego modelować mapę samochodową


w celu znajdowania najkrótszej drogi z jednego punktu do drugiego, tak i moż­
na interpretować graf skierowany jak.o „sieć przepływową" i wykorzystywać ją
do znajdowania odpowiedzi na pytania dotyczą.ce przemieszczania się „cze-
goś" w takiej sieci. Wyobraźmy sobie materiał krążący w pewnym systemie od
źródła, w którym jest wytwarzany, do ujścia, w którym jest zużywany. Żródło
wytwarza materiał ze stałą szybkością i z tą samą szybkością jest on zużywany
w ujściu. Intuicyjnie, w każdym punkcie tego systemu „przepływ" odpowiada
szybkości, z jaką materiał przemieszcza się przez ten punkt. Sieci przepływowe
mogą być używane do modelowania przepływu cieczy w rurociągach, części na
liniach montażowych, prądu w sieciach elektrycznych, informacji w sieciach
komunikacyjnych itp.
Każdą krawędź skierowaną w sieci możemy interpretować jako kanał, któ-
rym coś płynie. Każdy kanał ma ustaloną przepustowość, wyznaczającą maksy-
malną szybkość, z jaką następuje przepływ w tym kanale (np. I OOO litrów cieczy
na godzinę w rurociągu lub prąd o natężeniu 20 amperów w przewodzie elekt-
rycznym). Wierzchołki różne od źródła i ujścia są punktami, w których zbiegają
się kanały. Przepływ odbywa się tylko przez takie wierzchołki i nie jest w nich
zatrzymywany. Szybkość wpływania do wierzchołka musi być taka sama jak
szybkość wypływania. Taką własność nazywamy własnością „zachowania prze-
pływu". Jeżeli rozważamy na przykład przepływ prądu elektrycznego, to włas­
ność zachowania przepływu jest zgodna z prądowym prawem Kirchhoffa.
Problem maksymalnego przepływu jest najprostszym problemem poja-
wiającym się w sieciach przepływowych. Należy znaleźć największą szybkość,
z jaką może następować przepływ ze źródła do ujścia bez naruszenia ogra-
niczeń na przepustowości kanałów. Jak się przekonamy, jest wiele efektywnych
algorytmów służących do rozwiązania tego problemu. Ponadto podstawowe

649
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

metody stosowane w tych algorytmach mogą być zaadaptowane do rozwiązy­


wania innych problemów sieciowych.
W tym rozdziale przedstawimy dwie ogólne metody rozwiązywania prob-
lemu maksymalnego przepływu. W podrozdziale 27.1 wprowadzimy formalnie
pojęcia sieci i przepływu, a następnie sformułujemy problem maksymalnego
przepływu. W podrozdziale 27 .2 opiszemy klasyczną metodę znajdowania ma-
ksymalnego przepływu, pochodzącą od Forda i Fulkersona. Metodę tę można
zastosować do obliczania maksymalnego skojarzenia w nieskierowanych gra-
fach dwudzielnych, co omówimy w pod.rozdz. 27.3. W podrozdziale 27.4 za-
prezentujemy metodę przedprzepływów, która jest podstawą wielu najszyb-
szych algorytmów służących do rozwiązywania problemów dotyczących prze-
pływów w sieciach. W podrozdziale 27.5 omówimy pewną implementację tej
metody, która działa w czasie O(V 3). Chociaż algorytm ten nie jest najszyb-
szym znanym algorytmem dla problemu maksymalnego przepływu, ilustruje
on jednak metody stosowane w najszybszych z tych algorytmów i jest w prak-
tyce dość efektywny.

27.1. Sieci przepływowe


W tym podro7.dziale podamy grafową definicję sieci przepływowych, zapoz-
namy się z ich własnościami oraz precyzyjnie zdefmiujemy problem maksymal-
nego przepływu.

Sieci przepływowe i przepływy


Siecią przepływową (krótko: siecią) G = (V, E) nazywamy graf skierowany,
w którym każda krawędź (u, v)eE ma nieujemną przepustowość c(u, v) ~ O.
Jeśli (u, v)f:E, to przyjmujemy, że c(u, v) =O.W sieci wyróżniamy dwa wierz-
chołki: źródło si ujście t. Dla wygody przyjmujemy, że każdy wierzchołek sieci
leży na pewnej ścieżce ze źródła do ujścia. Oznacza to, że dla każdego wierz-
chołka VE V istnieje ścieżka s,....v-+t. Graf G jest więc spójny i stąd
IE]~ IVI -1. Na rysunku 27.1 jest przedstawiona przykładowa sieć.
Możemy teraz 7.defmiować przepływ bardziej formalnie. Niech G = (V, E)
będzie siecią (z funkcją przepustowości c). Niech s będzie źródłem w sieci,
a t ujściem. Przepływem w sieci G nazwywamy każdą funkcję o wartościach
rzeczywistych/: V x V-+ R spełniającą poniższe trzy warunki.

• Warunek przepustowości: Dla wszystkich u, ve V zachodzi/(u, v) ,:s;c(u, v).


• Warunek skośnej symetryczności: Dla wszystkich u, ve Vzachodzi/(u, v) =
= -f(v, u).
• Warunek zachowania przepływu: Dla każdego uE V - {s, t} zachodzi

650
27.1. SIECI PRZEPŁYWOWE

Edmonton Saskatoon
12
Vancouver \b Winnipeg

>

Calgary Regina
(,)

\ \\\b
., . 12/12
1
·½0
"

--
S •;


V
o ,t
"' ,1•
~
:f.-.,
C:•."-

~.l '

•• l I/ 14
y
~.

(b)

Rys. 27.1. (a) Sieć G = (V, E) modelująca


problem transportu powstały w kanadyjskiej spółce
,,Szczęśliwy Krążek" produkującej krążki hokejowe. Fabryka w Vancouver jest źródłem s, w któ-
rym produkuje się krą.ili hokejowe. Magazyn w Winnipeg jest ujic:iem t, do którego transportuje
się krążki. Krążki są. transportowane w kontenerach. Towar nie jest wysyłany bezpośrednio do
Winnipeg, ale wędruje prt.ez punkty przeładunkowe, które majdują. się w kilku miastach. Z miasta
u do miasta v można każdego dnia przewieźc tylko c(u, v) kontenerów. Przy każ.dej krawędzi
zaznaczono jej przepustowość. (b) Przepływ/ w G o wartości I.fi = 19. Pokazano tylko dodatnie
przepływy netto. Jeśli/(u, v) > O, to krawędź (u, v) ma etykietę/(u, v}/c(u, v). (Kreska ukośna nie
jest znakiem dzielenia. Separuje ona przepływ netto od przepustowości). Jeśli/ (u, v) :i,;:O, to etykie-
tą krawędzi (u, v) jert tylko jej przepustowość

'f,f(u, v) ~ O
,,v
Wielkośćf(u, v), która może być dodatnia lub ujemna, nazywamy pneplywem
netto z wierzchołka u do wierzchołka v. Wartość przepływu/ definiuje się jako

Iii ~ I,,Yf(s, v) (27.1)

Oznacza to, że wartością przepływu jest łączny przepływ netto opuszczający


żródło. (Tutaj I·! oznacza wartość przepływu, a nie wartość bezwzględną lub
moc zbioru). W problemie maksymalnego pnepływu jest dana sieć G oraz źród­
ło s i ujście t. Należy znależć przepływ o maksymalnej wartości z s do t.
Zanim zapoznamy się z przykładowym problemem maksymalnego prze-
pływu, omówmy krótko trzy wymienione wan1nki, jakie musi spełniać każdy

651
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

przepływ. Warunek przepustowości oznacza, że przepływ netto z jednego wie-


rzchołka do drugiego nie może przekraczać przepustowości krawędzi. Waru-
nek skośnej symetryczności oznacza zaś, że przepływ netto z wierzchołka u do
wierzchołka v ma wartość przeciwną do przepływu netto w odwrotnym kierun-
ku. Tak więc przepływ z u do u wynosi O, ponieważ dla każdego ueVmamy
f(u, u)= -f(u, u), a stąd/(u, u)= O. Własność zachowania przepływu mówi,
że łącmy przepływ netto opUSZC'lający wierzchołek różny od źródła i ujścia jest
zerowy. Korzystając z warunku skośnej symetryczności, możemy zapisać wa-
runek zachowania przepływu, jak następuje:
Lf(u, v) = O
••Y
dla wszystkich ve V - {s, t}. Co oznacza, że łączny przepływ na wejściu do
wierzchołka jest zerowy.
Zauważmy także, że nie może istnieć przepływ netto różny od O między
u i v, jeśli między tymi wierzchołkami nie ma w sieci krawędzi. Jeśli ani
(u, v)łE, ani (v, u)łE, to c(u, v) = c(v, u)= O. Stąd i z warunku przepus-
towości mamy f(u, v) ~ O i f(v, u)~ O. Ale ponieważ z warunku skośnej
symetryczności f(u, v) = -f(v, u), to f(u, v) = f(v, u) = O. Tak więc niezero-
wy przepływ netto z wierzchołka u do wierzchołka v implikuje, że (u, v)eE
lub (v, u)eE.
Ostatnia własność przepływu, która nas interesuje, dotyczy dodatnich
przepływów netto. Dodatni przepływ netto na wejściu do wierzchołka v defi-
niujemy jako

L f(u, v) (27.2)
••Y
/l:M0P)> 0

Dodatni przepływ netto wypływający (lub na wyjściu) z wierzchołka definiuje


się symetrycznie. Jedna z interpretacji własności zachowania przepływu mówi,
że dodatni przepływ netto na wejściu do wierzchołka różnego od źródła i ujścia
jest równy dodatniemu przepływowi na wyjściu z tego wierzchołka.

Przykład sieci
Za pomocą sieci przepływowej można modelować problem transportowy
przedstawiony na rys. 27.1. Fabryka Spółki Szczęśliwy Krążek (źródło s) mieś­
ci się w Vancouver. Są tam wytwarzane krążki hokejowe. Magazyn Spółki
(ujście t) znajduje się w Winnipeg - tam krążki są składowane. Firma Szczęś­
liwy Krążek wydzierżawiła od firmy przewozowej ciężarówki do przewozu krą­
żków z fabryki do magazynu. Krążki są przewożone w kontenerach. Ponieważ
ciężarówki jeżdżą po z góry ustalonych trasach między miastami i mają ograni-

652
27.1. SJECIPRZEPŁYWOWE

czoną ładowność, firma Szczęśliwy Krążek może przesłać każdego dnia co


najwyżej c(u, v) kontenerów między każdą parą miast u i v z rys. 27.la. Firma
Szczęśliwy Krążek nie ma możliwości wpływania na trasy przejazdu ciężaró­
wek ani na ich ładowność, tak więc sieć z rys. 27.la nie może zostać zmieniona.
Firma chce znać maksymalną liczbę kontenerów p, które można przesłać jed-
nego dnia i wówczas produkować jednego dnia tylko taką liczbę krążków,
która może być przewieziona do magazynu.
Liczba kontenerów przewożonych różnymi drogami w sieci określa pewien
przepływ. Każdego dnia fabryka produkuje p kontenerów krążków i każdego
dnia p kontenerów musi przybyć do magazynu. Nie jest ważne, jak długo dany
krążek wędruje z fabryki do magazynu, ale jest ważne, żeby każdego dnia
p kontenerów opuściło fabrykę i tyle samo kontenerów przybyło do magazynu.
Z miasta u do miasta v można jednego dnia przewieźć co najwyżej c(u, v)
kontenerów. W ten sposób otrzymujemy ograniczenie na przepływ z u do v.
W ustabilizowanym przepływie towaru liczba krążków, która przybywa do
miasta-pośrednika w sieci przewozów, musi być równa liczbie krążków, które
opuszczają to miasto. W przeciwnym razie zaczną się gromadzić zapasy. Po-
wyższa własność jest własnością zachowania przepływu. Maksymalny prze-
pływ w naszej sieci wyznacza więc maksymalną liczbę kontenerów p, które
można wyekspediować z fabryki każdego dnia.
Na rysunku 27.lb jest pokazany możliwy przepływ w rozważanej przez
nas sieci, który jest reprezentowany w sposób naturalnie odpowiadający wysył­
ce krążków. Dla każdych dwóch wierzchołków u i v w sieci przepływ netto
f(u, v) odpowiada wysylaniu/(u, v) kontenerów dziennie z u do v. Jeślif(u, v)
wynosi O lub jest ujemny, to żaden kontener nie jest ekspediowany z u do v. Na
rysunku 27.lb są więc pokazane tylko krawędzie, dla których przepływ netto
jest dodatni. Na rysunku przepływ netto jest oddzielony ukośną kreską od
przepustowości krawędzi.
Związek między przepływem netto a ilością ekspediowanego towaru moż­
na zrozumieć lepiej, koncentrując się na wysyłce towaru między dwoma wierz-
chołkami. Na rysunku 27.2a widać pod.graf indukowany przez wierzchołki v1
i v2 z sieci z rys. 27.1. Na rysunku 27.2b pokazano sytuację odpowiadającą
wysyłaniu jednego dnia z v1 do v2 8 kontenerów: przepływ netto z v1 do v2
wynosi 8 kontenerów na dzień. Korzystając z własności skośnej symetryczno-
ści, możemy powiedzieć, że przepływ netto w odwrotnym kierunku z v2 do v1
wynosi -8 na dzień, chociaż żaden krążek nie jest przesyłany z v2 do v1 .
Ogólnie, przepływ netto z v 1 do v2 jest równy różnicy liczby kontenerów prze-
syłanych z v 1 do v 2 oraz liczby kontenerów przesyłanych z v2 do v1 . W przyję­
tym przez nas sposobie reprezentacji przepływów netto są pokazywane tylko
dodatnie przepływy, ponieważ wskazują one rzeczywistą ilość wyekspediowa~
nego towaru; tak więc tylko liczba 8 pojawia się na rysunku, natomiast nie ma
odpowiadającej jej liczby -8.

653
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

., ' '
"l' : ~l t,.' ""l
""'
-
o ~ --
o
~
-- "
o
00 M
--
o
~
~
-
o ;';
..
00

'
,' :v,. •
. I .

(a) (b) (c) (d) (el


Rys. 27.2. Kasowanie. (a) Wierzchołki 11
1 i 11
2 z c(11 2) = IO i c(11
1, 11 1) = 4. (h) W ten sposób
2, 11
zaznaczamy przepływ netto, gdy 8 kontenerów dziennie jest ekspediowanych z v1 do v2 • (c) Eks-
pedycja dodatkowych 3 kontenerów dziennie z 11 2 do v1. (d) Kasując przepływy w przeciwnych
kierunkach, sytuatję z (c) można reprezentować za pomocą dodatniego prmpływu netto tylko
w jednym kierunku. (e) Dodatkowych 7 kontenerów dziennie wysyłanych z 112 do 111

Przypuśćmy że
ekspediujemy także 3 kontenery z v2 do v1 . Ta do-
teraz,
datkowa wysyłka została zaznaczona na rys. 27 .2c. Mamy sytuację, w której
towar jest ekspediowany w obu kientnkach między v1 i v2 • Każdego dnia
8 kontenerów jest przesyłanych z v1 do v2 , a 3 kontenery z v2 do v 1 . Jakie są
wartości przepływów netto między tymi wierzchołkami? Przepływ netto z v1 do
v2 wynosi 8 - 3 = 5 kontenerów na dzień, natomiast przepływ netto z v2 do v1
wynosi 3 - 8 = - 5 na dzień.
Przedstawiona sytuacja jest w rezultacie równoważna z sytuacją
z rys. 27.2d, w której 5 kontenerów jest ekspediowanych z v1 do v2 , a żaden
kontener nie jest wysyłany z v2 do v1 • Wysyłka 3 kontenerów z v2 do v1 została
,,skasowana" przez 3 z 8 kontenerów wysyłanych z v1 do v2 • W obu przypad-
kach przepływ netto z v1 do v2 wynosi 5 kontenerów na dzień, ale w (d)
rzeczywiste wysyłki są dokonywane tylko w jednym kierunku.
W ogólności, stosując kasowanie można reprezentować wysyłkę towaru
między dwoma miastami przez dodatni przepływ netto dla co najwyżej jednej
z dwóch krawędzi między odpowiednimi wierzchołkami. Jeśli przepływ netto
z jednego miasta do drugiego jest nie większy niż O, to żadna wysyłka towaru
w tym kierunku nie ma miejsca. Oznacza to, że każdą sytuację, w której krążki
są ekspediowane w obu kien1nkacb między dwoma miastami, można prze-
kształcić za pomocą kasowania w sytuację równoważną, w której krążki węd­
rują tylko w jednym kierunku: w kierunku, w którym przepływ netto jest do-
datni. Przy takiej transformacji warunek przepustowości nie jest naruszany,
ponieważ redukcja ilości ekspediowanego towaru następuje w obu kierunkach.
Podobnie nie jest naruszona własność zachowania przepływu, ponieważ prze-
pływ netto między dwoma wierzchołkami pozostaje taki sam.
Kontynuując rozważania dotyczą.ce naszego przykładu, zobacł.l11y, jak.i
jest wynik przesłania dodatkowych 7 kontenerów dziennie z v2 do v1 • Nary-
sunku 27 .2e jest przedstawiona ta sytuacja zgodnie z umową, że prezentujemy

654
27.1. SIECI PRZEPŁYWOWE

tylko dodatnie przepływy netto. Przepływ netto z v1 do v 2 wynosi teraz


5 - 7 = -2, a przepływ netto z v 2 do v1 wynosi 7 - 5 = 2. Ponieważ przepływ
netto z v2 do v1 jest dodatni, reprezentuje on wysyłanie 2 kontenerów dziennie
z v2 do v1 . Przepływ netto z v1 do v2 wynosi -2 kontenery dziennie, a ponie-
waż nie jest dodatni, żaden krążek nie jest ekspediowany w tym kierunku.
Alternatywnie, na 5 z 7 dodatkowych kontenerów dziennie z v2 do v1 możemy
spojrzeć jak na te, których wysyłka jest skasowana przez 5 kontenerów wysyła­
nych dziennie z v1 do v2 , co daje 2 kontenery, które w rzeC'L)'wistości muszą być
wysyłane każdego dnia z v2 do v1 •

Sieci z wieloma źródłami i ujściami

W problemie maksymalnego przepływu zamiast jednego źrodła i jednego


ujścia, może pojawić się wiele źródeł i wiele ujść. Na przykład firma SZC'Zęśliwy
Krążek mogłaby mieć m fabryk {s1 , s 2 , ••• , sm}i n magazynów {t1 , t 2 , ••• , tn}
(patrz rys. 27.3a). Na szczęście nowy problem nie jest trudniejszy od po-
przedniego.
Problem maksymalnego przepływu w sieciach z wieloma źródłami i wielo-
ma ujściami można sprowadzić do zwykłego problemu maksymalnego prze-
pływu. Na rysunku 27.3b widać, w jaki sposób sieć z rys. 27.3a można prze-
kształcić w zwykłą sieć z jednym źródłem i jednym ujściem. Do sieci dodajemy
superźródlo s' oraz krawędź skierowaną (s, s 1) o przepustowości c(s, s1) = oo
dla każdego i= 1, 2, ..., m. Tworzymy tak.że nowe superujście t i dodajemy
krawędź (ti, t) o przepustowości c(tJ, t) = oo dla każdego i= 1, 2, ... , n. In-
tuicyjnie, każdy przepływ w sieci (a) odpowiada przepływowi w sieci (b} i vice
versa. Z pojedynczego superźródła s' wypływa tyle, ile potrzebują rzeczywiste
źródła, natomiast superujście t jest w stanie przyjąć tyle, ile łącznie wypływa
z rzeczywistych ujść. W zadaniu 27.1-3 należy formalnie udowodnić, że oba
problemy są równoważne.

Notacja
W naszych rozważaniach będziemy mieli do czynienia z kilkoma funkcjami
(takimi jak/), których argumentami są dwa wierzchołki sieci. W tym rozdziale
będziemy się posługiwać niejawną notacją swnowania, w której jeden z argu-
mentów lub oba mogą być zbiorami wierzchołków. W takim przypadku warto-
ścią wyrażenia jest suma wszystkich wartości, jakie otrzymujemy, zastępując
argumenty (zbiory) przez zawarte w nich elementy. Jeśli na przykład X i Y są
zbiorami wierzchołków, to

f(X, Y) - L Z:f(x, y)
:u;XyEY

655
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

,, .,,,:
,,.
O,.' '

Jo Jo
,, I ,, "'i:;,,,
,.,.,
.

,, ,,
3
,,":( ' J
,, ;I
~

s s .

r I ">?·
•z,,;

,, ' 6 ' 6
:t1,'
,',, (
,o );_',,
,, ,, 1ll

1 1 o
/3 /3

'• ,, [~
,, ,, 'it
' /J·,
1,

,, ' . JIA:·
'
.
(a) (b)

Rys. 27,3. Sprowadzanie problemu maksymalnego przepływu z wieloma źródłami i wieloma ujściami
do problemu z jednym źródłem i jednym ujściem. (a) Sieć przepływu z pięcioma źródłami S = {su
s2 , s 3 , s4 , s~} i trz.ema ujściami T= {ti, t 1 , t 3 }. (b) Siecrównoważna z jednym źródłem i z jednym
ujściem. Dodajemy super.źródło s' i krawędzie o nieograniczonych przepustowościach z s' do
wszystkich rzeczywistych żródeł. Dodajemy także superujście t' i krawędzie o nieograniczonych
przepustowościach z t' do wszystkich rzeczywistych ujść

Jeszcze innym przykładem użycia


niejawnej notacji sumowania może być wy-
rażenie opisujące warunek zachowania pr1.epływu zapisane jak następuje:
/(u, V) - Odla wszystkich ue V - {s, t). Dla wygody będziemy zazwyczaj po-
mijać nawiasy klamrowe (oznaczające zbiór), gdyby miały wystąpić w niejaw-
nej notacji sumowania; na przykład w równaniu f(s, V - s) =f(s, V) napis
V - s oznacza zbiór V - {s}.
Niejawna notacja sumowania często uprasZC'Za równania opisujące przepły­
wy. Następujący lemat, którego dowód jest pr7J"l)miotem.zadania 27.1-4, zawie-
ra kilka najczęściej pojawiających się tożsamości dotyczących przepływów.

LEMAT27.1.
Niech G = (V, E) będzie siecią i niech/ będzie pr1.epływem. w sieci G. Wówczas
są prawdziwe następujące równości:

/(X, X)= O dlaX.s:V

656
27.1. SIECI PRZEPŁYWOWE

f(X, Y) = -f(Y, X) dla X, Yc V

Dla X, Y, Z c: V takich, że X n Y = 0,

f(Xu Y, Z)= f(X, Z)+ f(Y, Z)



l
f(Z, Xu Y) =f(Z, X)+ f(Z, Y)

Jako przykład posługiwania się niejawną notacją sumowania udowodni-



my, że wartość przepływu jest równa łącznemu przepływowi netto na wejściu
do ujścia, czyli że

1/1= f(V, I) (27.3)

Intuicyjnie jest to prawda, ponieważ dla wszystkich wierzchołków różnych od


źródła i ujścia przepływ netto wynosi O (z własności zachowania przepływu).
Jedynym wierzchołkiem różnym od źródła, który może mieć niezerowy prze-
pływ netto odpowiadający niezerowemu przepływowi netto w źródle, jest ujś­
cie. Formalny dowód powyższego faktu jest następujący:

1/1= f(s, V) (z deftnicji)


= f(V, V) - f(V - s, V) (z lematu 27.1)
=f(V, V - s) (z lematu 27.1)
= f(V, I)+ f(V, V - s - t) (z lematu 27.1)
=f(V, I) (z zachowania przepływu)

W dalszej części tego rozdziału uogólnimy ten fakt (lemat 27.5).


ZADANIA

27.1-1. Dane są dwa wierzchołki u i v w pewnej sieci, w której c(u, v) = 5


i c(v, u)= 8. Przypuśćmy, że 3 jednostki przepływu są przesyłane z u do v,
a 4 jednostki są przesyłane z v do u. Ile wynosi przepływ netto z u do v?
Zilustruj przedstawioną sytuację tak jak na rys. 27 .2.
27.1-2. Wykaż, że funkcja/z rys. 27.lb jest przepływem.
27.1-3. Uogólnij własności przepływów oraz odpowiednie definicje na prob-
lem z wieloma źródłami i ujściami. Pokaż, że każdemu przepływowi w sieci
z wieloma źródłami i ujściami odpowiada przepływ o takiej samej wartości
w sieci z jednym źródłem i z jednym ujściem, otrzymywanej w wyniku
dodania superźródła i superujścia i na odwrót.
27.1-4. Udowodnij lemat 27.l.

657
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

27.1-S, Dla sieci G = (V, E) i przepływu/z rys. 27.lb znajdź parę podzbiorów
X, Ys; V, dla których f(X, Y) = -f(V- X, Y). Następnie znajdź parę
zbiorów X, Y c V, dla którycbf(X, Y) ;,6 -f(V - X, Y).
27.1-6. Dla danej sieci G = (V, E) niech/ 1 i / 1 będą funkcjami z V x V w R.
Sumą przepływów / 1 + / 1 nazywamy funkcję z V x V w R zdefiniowaną
następująco:

(J, +f,)(u, v) = f,(u, v) +f,(u, v) (27.4)

dla wszystkich u, ve V. Jeśli / 1 i / 1 są przepływami w sieci G, to które


z trzech warunków dla przepływu są spełnione prrez./ 1 + / 1 •
27.1-7. Niech/będzie przepływem w pewnej sieci i niech a będzie liczbą rze-
czywistą. Przez aj oznaczamy iloczyn skalara a: i przepływu/, który jest
funkcją z V x V w R zdefiniowaną następująco:

(•fXu, v) = • ·f(u, v)

Udowodnij, że przepływy w każdej sieci tworzą zbiór wypukły, pokazując,


1 + (1 - 11.'}/
że jeśli / 1 i / 1 są przepływami, to również 11./ 2 jest przepływem
dla każdego O ~ 11.~ 1.
27.1-8. Sformułuj problem maksymalnego przepływu jako zadanie programo-
wania liniowego.
27.1-9. Sieci przepływowe wprowadzone w tym podrozdziale umożliwiają mo-
delowanie przepływu tylko jednego materiału. Wielomaterialowa sieć prze-
pływowa modeluje przepływ p materiałów między zbiorem p wierubołków
źródłowych S = {s1 , s 2 , ••• , sJI}a zbioren1p ujść T= {t1 , t 1 , ... , t"}. Prze-
pływ netto i-tego materiału z u do v oznaczamy przez f/u, v). Dla i-tego
materiału jedynym żródłem jest s1, a jedynym ujściem jest t 1• Warunek
zachowania przepływu musi być spełniony niezależnie dla każdego mate-
riału: dla każdego materiału przepływ na wyjściu z każdego wierzchołka,
poza odpowiadającym temu materiałowi źródłem i ujściem, jest v:.rowy.
Suma przepływów netto wszystkich materiałów z u do v nie może prze-
kraczać c(u, v), zatem przepływy poszczególnych materiałów oddziałują na
siebie. Wartością przepływu każdego materiału jest przepływ na wyjściu ze
źródła dla tego materiału. Łączna wartość przepływu jest sumą wartości
przepływów dla wszystkichpmateriałów. Udowodnij, że istnieje wielomia-
nowy algorytm dla problemu znajdowania maksymalnego łącznego prze-
pływu w sieciach wielomaterialowych, formułując ten problem jako zada-
nie programowania liniowego.

658
272. METODA FOADA-FULKERSONA

27.2. MetodaForda-Fulkersona

W tym podrozdziale przedstawimy metodę Forda-Fulkersona rozwiązywania


problemu maksymalnego przepływu. Użyliśmy słowa metoda zamiast algo-
rytm, ponieważ rozwiązanie zaproponowane przez Forda i Fulkersona jest
podstawą kilku algorytmów o różnych czasach działania. W metodzie Forda-
-Fulkersona wykorzystuje się trzy ważne pojęcia, które znalazły istotne zasto-
sowania w wielu algorytmach i problemach związanych z przepływami wsie-
ciach. Należą do nich sieci residualne, ścieżki powiększające oraz przekroje. Są
to zasadnicze pojęcia w ważnym twierdzeniu o maksymalnym przepływie i mi-
nimalnym przekroju (tw. 27. 7), które charakteryzuje wartość maksymalnego
przepływu w kategoriach przekrojów sieci. Na mk:ońcr.enie tego rozdziału
przedstawimy jedną z implementacji metody Forda-Fulkersona i przeanalizu-
jemy jej czas działania.
Metoda Forda-Fulkersona jest metodą iteracyjną. Rozpoczynamy od
f(u, v) = O, dla wszystkich u, vE V, co daje początkową wartość przepływu
równą O. W każdej iteracji zwięks:zamy wartość przepływu, znajdując pewną
„ścieżkę powiększającą". Ścieżką powiększającą jest taka ścieżka ze źródła s do
ujścia t, po której możemy przesłać większy przepływ. Powtarzamy ten proces
dopóty, dopóki nie można już znaleźć żadnej ścieżki powiększającej. Twierdze-
nie o maksymalnym przepływie i minimalnym przekroju mówi, że po zakoń­
czeniu powyższego procesu otrzymany przepływ jest maksymalny. Procedura
FORD-FULKERSON-METHOD jest formalnym zapisem omawianej metody.

fORD-fULKERSON-METHOD(G, s, t)
1 inicjowanie/na O
2 whileistnieje ścieżka powiększająca p
3 do powiększ prupływ f wzdłuż p
4 return/

Sieci residualne
Intuicyjnie, dla danej sieci przepływowej i pewnego przepływu sieć residualna
składa się z krawędzi, które dopuszczają większy przepływ netto. Bardziej
formalnie, załóimy, że dana jest sieć G = (V, E) ze źródłem s i ujściem t.
Niech/ będzie pewnym przepływem w sieci G. Rozważmy parę wierzchołków
u, v E V. Dodatkowy przepływ z u do v, nie przekraczający przepustowości
c(u, v), nazywamy pnepustowością residualną dla (u, v), którą defmiujemy na-
stępująco:

<r(•, v) - c(u, v) - f(u, v) (27.5)

659
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

Dla przykładu, jeśli c(u, v) = 16 if(u, v) = 11, to możemy zwiększyć przepływ


z u do v o c1 (u, v) = 5, nie naruszając warunku przepustowości na krawędzi
(u, v). Gdy przepływ netto f(u, v) jest ujemny, przepustowość residualna
c1 (u, v) jest większa niż przepustowość c(u, v). Na przykład, jeśli c(u, v) = 16
i f(u, v) = -4, to przepustowość residualna cfu, v) wynosi 20. Możemy to
zinterpretować w następujący sposób. Przepływ netto z v do u wynosi 4. Może­
my go skasować, przesyłając 4 jednostki przepływu z u do v. Następnie, bez
naruszenia warunku przepustowości dla krawędzi (u, v), możemy przesłać 16
jednostek z u do v. Przesłaliśmy zatem dodatkowych 20 jednostek przepływu,
rozpoczynając od przepływu sieciowego f(u, v) = -4, zanim osiągnęliśmy
przepływ na krawędzi (u, v) równy jej przepustowości.
Dana jest sieć G = (V, E) oraz przepływ/ Siecią residualną dla sieci Gin-
dukowaną przez przepływ f nazywamy sieć G1 = (V, E1), w której

Er= {(u, v)e V x V:c,(u, v) > O}


Oznacza to, że każda krawędź w sieci residualnej, lub inaczej krawędź residual-
na, umożliwia dodatni przepływ netto.
Na rysunku 27.4a powtórzono sieć G i przepływ f z rys. 27.lb, a na
rys. 27 .4b przedstawiono odpowiadającą jej sieć residualną G1 . Zauważmy, że
(u, v) może być krawędzią residualną w Ep nawet jeśli nie jest krawędzią w E.
Innymi słowy, może tak się zdarzyć, że E1 ,;/;,E.Sieć residualna z rys. 27 .4b
zawiera kilka krawędzi, które nie występują w sieci pierwotnej, na przykład
(v1, s) i (v2 , v3). Taka krawędź (u, v) pojawia się w sieci Gft jeśli tylko (v, u)E E
oraz istnieje dodatni przepływ netto z v do u. Ponieważ przepływ netto f(u, v)
z u do v jest ujemny, przepustowość cJ.u, v) = c(u, v) - f(u, v) jest dodatnia
i (u, v)eE 1. Ponieważ krawędź (u, v) może pojawić się w sieci residualnej tylko
wtedy, kiedy co najmniej jedna z krawędzi (u, v) i (v, u) występuje w sieci
pierwotnej, otrzymujemy następujące ograniczenie na liczbę krawędzi w sieci
residualnej:

\E~,;,2\E\
Zauważmy, że sieć residualna G1 jest siecią przepływową o przepustowo-
ściach danych przez c . Z następującego lematu wynika związek między prze-
1
pływem w sieci residualnej a przepływem w sieci pierwotnej.

LEMAT27.2.
Niech G = (V, E) będzie siecią przepływową ze źródłem si ujściem t,f -prze-
pływem w sieci G, G1 - siecią residualną dla sieci G indukowaną przez/, a/'
-przepływem w sieci G1 . Wówczas suma przepływów f + f' zdefiniowana rów-
nością (27.4) jest przepływem w sieci Go wartości I/+ /'I= lfl + if'I.

660
27.2. METODA FORDA"FULKERSONA

DOWÓD
Musimy sprawdzić, cr.yf + f' spełnia warunki skośnej symetryczności, przepu-
stowości oraz zachowania przepływu. Żeby wykazać, że zachodzi warunek
skośnej symetryczności, zauważmy, że dla wszystkich u, vE V mamy

(f + /)(u, v) = /(u, v) + /'(u, v)

= -/(v, u) - /'(v, u)
= -(f(v, u) + /'(v, u))
= -(f + /')(v, u)

Żeby pokazać, że jest spełniony warunek przepustowości, zauważmy, że


cju, v) dla wszystkich u, ve V. Stąd i z równości (27.5) mamy
f'(u, v)::;;;;

(f + /')(u, v) = /(u, v) + /'(u, v)


,;,/(u, v) + (c(u, v) - /(u, v))
= c(u, v)
Pozostaje wykazać, że dla f + f' jest spełniona własność zachowania przepły­
wu. W tym celu zauważmy, że dla wszystkich uE V - {s, t} mamy

I,,Y(f + /)(u, v) = I (f(u, v) + /'(u, v))


,,Y
= I /(u, v) + I /'(u, v)
t>EY u,;;Y

=0+0
=0

Ostatecznie mamy

I/+ /'I = I,,Y (f + !1(s, v)

= I,,Y (f(s, v) + /'(s, v))

=I /(s, v) + I f'(s, v)
v,;;Y uc,Y

= 1/1+ 1/'I

661
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

$cieżki powiększające

Dla danej sieci G = (V, E) i przepływu/ ścieżką powiększającą p nazywamy


każdą ścieżkę ze źródła s do ujścia t w sieci residualnej G1 . Zgodnie z defmicją
sieci residualnej każda krawędź (u, v) na ścieżce powiększającej umożliwia pe·
wien dodatni przepływ netto między wierzchołkami u i v bez naruszenia warun·
ku przepustowości dla tej krawędzi.

12/12 12
V Ari,
..
\_\.\\Ó ' ls-'.<o
' ,, -
--
o et
" ~

,1•
s -
~ ~

8/13
11/14
_.v4:
3
ll
'
(a) (b)

12 : )13;,.
12/12 . ' -- I
\\\\Ó
'.\'l
/9.-'.<o
.v..,,·-"
' ,, - /9
:·t._-
'" '

~\,-.- ;'-_tf
·-,. I
~ ~

\_! ,. '

1
-</13
"
~

,1• 1, 3 y:·'
11/14
II . ·-·
(d)
(c)

Rys. 27.4. (a) Sieć przepływowa G i przepływ /z


rys. 27.lb. (b) Sieć residualna G1 z zacieniowaną
ścieżką powiększającą p; jej residualna przepustowość wynosi cJUJ) = c{v2 , v3) = 4. (c) Przepływ
w sieci G powiększony wzdłuż ścieżki p o jej przepustowość residualną. (d) Sieć residualna in-
dukowana przez przepływ z (c)

Zacieniowana ścieżka na rys. 27.4b jest ścieżką powiększającą. Traktując


sieć residualną G z rysunku jako sieć przepływową, możemy zwiększyć prze·
I
pływ o nie więcej niż 4 jednostki na każdej krawędzi z tej ścieżki, bez narusze.
nia warunku przepustowości. Jest to możliwe, ponieważ najmniejsza przepus·
towość residualna na tej ścieżce wynosi c,(.v 2 , v3 ) = 4. Największy możliwy
przepływ netto po krawędziach ścieżki powięksmjącej p nazywamy jej pnepus,.
towością residualną i definiujemy następująco:

cJp) =min{cfu, v): (u, v)jest nap)

Następujący lemat, którego dowód pozostawiamy jako zad. 21.2·1, precyzuje


dotyche7.asowerozważania.

662
27.2. METODA FORDA-FULKERSONA

LEMAT27.3.
Niech G = (V, E) będzie siecią przepływową, f - przepływem w sieci G,
ap - ścieżką powiększającą w sieci G!' Zdefiniujmy funkcję / 11: V x V-+ R
jak następuje:

cf(p), jeśli (u, v) jest na p


f,(u, v) = -c 1 (p), jeśli (v, u) jest na p (27.6)
o •
w przCCiwnym ralle

Wówczas / 11jest przepływem w sieci GI o wartości 1/,,1


= c1(p) > O.

Z następującego wniosku wynika, że dodając / 11 do f, dostajemy nowy
przepływ w sieci G, którego wartość jest bliższa wartości maksymalnej. Rysu·
nek 27.4c ilustruje wynik dodania/,, z rys. 27.4b do/z rys. 27.4a.

WNIOSEK27.4.
Niech G = (V, E) będzie siecią przepływową, f - przepływem w sieci G,
a p - ścieżką powiększającą w sieci G1. Niech J,,będzie funkcją zdefm.iowaną
równaniem (27.6). Zdefiniujmy funkcję/': V x V-+ R taką, że f' =f +/ 11•
Wówczas/' jest przepływem w sieci G o wartości 1/'I= 1/1+ 1/,1> 1/1.

DOWÓD
Natychmiastowy z lematów 27.2 i 27.3.


Przekrojew sieciach
W metodzie F orda-Fulkersona przepływ jest wielokrotnie powiększany wzdłuż
ścieżek powiększających, aż zostanie osiągnięty maksymalny przepływ. Twier·
dzenie o maksymalnym przepływie i minimalnym przekroju, które wkrótce
udowodnimy, mówi, że przepływ jest maksymalny wtedy i tylko wtedy, gdy
sieć residualna indukowana przez ten przepływ nie zawiera ścieżki powiększa.
jącej. Żeby udowodnić to twierdzenie, musimy najpierw t.definiować przekrój
w sieci i zbadać jego własności.
Niech G = ( V, E) będzie siecią. Każdy podział zbioru V na S i T = V - S
taki, że se Si teT, nazywamy przekrojem (S, T) w sieci G. (fa definicja jest
podobna do definicji „przekroju", której używaliśmy w rozdz. 24 poświęca·
nym minimalnym drzewom rozpinającym. Różnice polegają na tym, że tutaj
rozważamy przekrój w grafie skierowanym oraz żądamy, żeby seS oraz te T).
Jeśli f jest przepływem, to przepływ netto przez przekrój (S, T) definiujemy
jako /(S, T). Przepustowością przekroju (S, T) jest c(S, T).

663
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

12
ts:9o
~ t

,fy3 .i•
11/14
'
'
-s:r_,.
Rys. 27.5. Pnekrój (S, T) w sieci z rys. 27.l(b), gdzie S"" {s, Vu v2} i T = {vs,v„ 1}. Wierzchołki
należącedo Ssą czarne, a wierzchołki należące do Tsą białe. Przepływ netto pr:rezprzekrój (S, T)
wynosif(S, T) = 19, ajego p:tzepustowość wynosi c(S, T) = 26

Na rysunku 27.5 jest pokazany przekrój ({s, v1 , v2 }, {v3 , v4 , t}) w sieci


z rys. 27.lb. Przepływ netto przez ten przekrój wynosi

/(v 1, v,) + f(v,, v3 ) + f(v,, v.J = 12 + (-4) + 11


= 19
a jego przepustowość wynosi

c(v1 , v 3) + c(v2 , v4 ) = 12 + 14
=26
Zauważmy, że do przepływu przez przekrój mogą zostać włączone ujemne
przepływy krawędziowe między wierzchołkami, ale na przepustowość przekro-
ju składają się
tylko wartości nieujemne.
Z następnego lematu wynika, że wartość przepływu w sieci jest równa
przepływowi przez dowolny przekrój w sieci.

LEMAT27.5.
Niechf będzie przepływem w
sieci G ze źródłem si ujściem t, a (S, T) niech
będzie przekrojem w sieci G. Przepływem netto przez (S, T) jest wówczas
f(S, T) = 1/1,
nowoo
Korzystając z lematu 27.1, otrzymujemy

f(S, T) = f(S, V) - f(S, S)


=f(S, V)
=f(s, V)+f(S-s, V)

664
27.2. METODA FORDA-FULKERS0NA

-f(s, V)

- Ili

Bezpośrednim wnioskiem z lematu 27.5 jest równość (27.3}, którą już
udowodniliśmy wcześniej, mówiąca, że wartością przepływu jest przepływ net-
to wpływający
do ujścia.
Z lematu 27 .5 otrzymamy również wniosek o sposobie wykorzystania
przepustowości do otrzymania górnego ograniczenia na wartość dowolnego
przepływu.

WNIOSEK27.6.
Wartość dowolnego przepływu/w sieci G jest nie większa niż przepustowość
dowolnego przekroju w sieci G.

DOWÓD
Niech (S, T} będzie dowolnym przekrojem w sieci G i niech/ będzie dowol-
nym przepływem. Z lematu 27.5 i warunku przepustowości mamy

lfl -f(S, T)

- L L f(u, v)
-~,
<; I I c(u, v)
IRlS veT

- c(S, T)

Możemy już przeprowadzić dowód ważnego twierdzenia o maksymalnym
przepływie i minimalnym przekroju.

TwlERDZENIE27.7. (O maksymalnym przepływie i minimalnym przekroju}


Jeśli/jest przepływem w sieci G = (V, E) ze źródłem si ujściem I, to następują­
ce warunki są równoważne:

(l} Przepływ /w sieci G jest maksymalny.


(2} Sieć residualna G1 nie zawiera ścieżek powiększających.
(3) Dla pewnego przekroju (S, T) w sieci G zachodzi 1/1- c(S, T).

DOWÓD
(l} => (2): Załóżmy przeciwnie, że f jest przepływem maksymalnym w sieci G,
ale G1 ma ścieżkę powiększającą. Wówczas z wniosku 27.4 otrzymujemy, że

665
ROZDZIAŁ 27, MAKSYMALNY PRZEPŁYW

suma przepływów f + / 11, gdzie / 11jest zdefiniowane równaniem (27 .6), jest prze-
pływem w sieci G o wartości większej n.iż 1/1,co przeczy założeniu, że f jest
maksymalny.
(2)=- (3): Załóżmy, że sieć residualna GI nie zawiera żadnej ścieżki powięk­
szającej, tzn. G1 nie zawiera żadnej ścieżki z s dot. Niech

S = {ve V: istnieje ścieżka z s do v w G1 }

i niech T = V - S. Podział (S, T) jest przekrojem: w oczywisty sposób se S,


a t ,f:S, ponieważ nie istnieje ścieżka z s do t w sieci residualnej Gr Dla każdej
pary wierzchołków u i v takich, że ueS i ve T, mamy f(u, v) = c(u, v), ponie-
waż w przeciwnym przypadku (u, v)eE 1 i v byłby w zbiorze S. Stąd i z lema-
tu 27.5 otrzymujemy, że 1/1= f(S, T) = c(S, T).
(3)= (!): Z wniosku 27.6 otrzymujemy, że dla karoego przekroju (S, T), :r.a-
chodzi 1/1<; c(S, T). Z warunku J/1= c(S, T) wynika :r.atem, że/ jest prze-
pływem maksymalnym.


Podstawowyalgorytm Forda-Fulkersona
W metodzie Forda-Fulkersona w każdej iteracji znajdujemy dowolną ścieżkę
powiększającą p i zwiększamy przepływ/ wzdłuż p o przepustowość residual-
ną cJp). W następującej implementacji tej metody obliC7ATDymaksymalny
przepływ w grafie G = (V, E), aktualizując przepływ netto J1u,v] między każdą
parą wierzchołków u, v połączonych krawędzią w G 1l, Jeśli wierzchołki u i v nie
są połączone krawędzią w żadnym kien,nku, to przyjmujemy niejawnie, że
f[u, v] = O. W przedstawionej poniżej procedurze FORD-FULKERSON zakłada­
my, że przepustowość z u do v dana jest jako funkcja c(u, v), którą oblicza się
=
w czasie stałym. Przyjmujemy, że c(u, v) O, jeśli (u, v)łE, (:N typowych
implementacjach c(u, v) można otrzymać z informacji pamiętanych w wierz-
chołkach i na ich listach sąsiedztwa). Przepustowość residualna cf.u, v) jest
obliczana zgodnie ze wzorem (27.5). Wyrażenie c1 (p) w zapisie procedury jest
w rzeczywistości :zmienną pomocniczą, w której pamiętamy przepustowość re~
sidualną ścieżki p.

FORD-FULKERSON(G, s, t)
I for każda krawędź (u, v)eE[G]
2 dof1u,v]+-0
3 J1v,u]~ O

I)Będziemy używali nawiasów kwadratowych, gdy identyfikator - taki jak f - traktujemy


jako zmienną tablicową, natomiast nawiasy okrągłe omaczają, Zemamy do czynienia z funkcją.

666
27.2. METODA FOROA-FULKERSONA

4 while istnieje ścieżka p z s do t w sieci residualnej G1


5 do c1 (p)-min{c.,{u, v): (u, v) jest nap}
6 for każda krawędź (u, v) nap
7 do/[u, v] - flu, v] + cJp)
8 flv, u] - - flu, v]

Procedura FORD-FULK.ERSON jest po prostu uściśleniem wcześniejszego opisu


metody Forda-Fulkersona. Na rysunku 27.6 jest przedstawiony wynik działa­
nia każd.ej iteracji w przykładowym wykonaniu tej procedury. W wierszach 1-3
przepływ f jest inicjowany na O. W pętli wlille, w wierszach 4-8, raz za razem
jest znajdowana dowolna ścieżka powiększająca p w sieci residualnej GI i prze-
pływ f jest powiększany wzdłuZ p o przepustowość residualną cJp). Gdy nie
ma juZ ścieżek powiększających, przepływ/ jest maksymalny.

Analiza metody Forda-Fulkersona


Czas działania procedury FORD-FULKERSONzalefy od tego, w jaki sposób
jest wyznaczana ścieżka powiększająca w wierszu 4. Jeśli nie narzucimy żad­
nych ograniczeń na wybór ścieżki powiększającej, to moZe się Marzyć, Ze al-
gorytm będzie działał w nieskończoność: wartość przepływu będzie wzrastała,
ale nigdy nie osiągnie wartości przepływu maksymalnego. JeZeli jednak do
wyznaczania ścieżki powiększającej użyjemy przeszukiwania wszerz (pod-
rozdz. 23.2), to omawiany algorytm działa w czasie wielomianowym. Zanim
jednak przejdziemy do dowodów powyższych stwierdzeń, wykażemy, że
w przypadku przepustowości całkowitoliczbowych procedura FORD-FULKER-
SON zawsze oblicza przepływ maksymalny, niezależnie od tego, jak są wybie-
rane ścieżki powiększające.
Najczęściej w zastosowaniach praktycznych problemu maksymalnego
przepływu przepustowości można wyrazić za pomocą liczb całkowitych. Jeśli
przepustowości są liczbami wymiernymi, to moZna je przeskalować w taki
sposób, żeby otrzymać przepustowości całkowitoliczbowe. Zakładając działa­
nia na liczbach całkowitych, prosta implementacja procedury FORD-FULKER-
SON działa w czasie O(EJ]I), gdzie _rjest przepływem maksymalnym znaj-
dowanym przez tę procedurę. Wiersze 1-3 zajmują czas 0(E). Ponieważ w każ­
dej iteracji wartość przepływu rośnie co najmniej o jedną jednostkę, liczba
iteracji pętli wbile w wierszach 4-8 wynosi co najwyżej I]].
Dla efektywności działania pętli while jest waZne, w jaki sposób działamy
na strukturze danych używanej do implementacji sieci G = (V, E). Załóżmy, że
mamy strukturę danych odpowiadającą grafowi skierowanemu G' = (V, E'),
w którym E' = {(u, v): (u, v) e E lub (v, u) e E}. Krawędzie w sieci G są także
krawędziami w sieci G' i dlatego łatwo jest pamiętać przepustowości i prze~
pływy w tej strukturze danych. Dla danego przepływu/w sieci G krawędziami

667
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

4/12
(a)
<o

I
,, ,,
14 4/14 •
--.ji:

8 4/12
(b)
4

' I
,, ' ,,
IO
4
11/14 ·~··
-+

·,·"f,-

(c)
8 12/12

' 4

.
'. .l,'o· ł. '..

3 ' '

11/14
II

(d) 12/12

z
--
o I

3
II
' 11/14

(c)

,, /9
J

J
J;,
'
Rys. 27.6. Ilustracja działania podstawowego algorytmu Forda-Fulkenona. (a)-{d) Kolejne iteracje
pętli wllile. Z lewej strony każdego fragmentu rysunku jest pokazane sieć residualn.a G1 z wiersza
4 z mcicniowaną ścieżką powiększają.cąp. Po prawej stronie pokazany jest nowy przepływ/ otrzy-
many w wyniku dodania/, do j. Siecią residualną na rysunl:u (a) jest wejściowa sieć G. (e) Sieć
residualna bedana w ostalnim teście w pętli wblle. Nie zawiera ona ścieżek. powiększają.cych,
i d1etego przepływ /pokazany ne.rysunku (d) jest pnepływem maksymalnym

668
27.2. METODA FORDA·FULKERSONA

w sieci residualnej GI są wszystkie krawędzie (u, v) z G' takie, że c(u, v) -


- f[u, v] "F-O. Czas potr7.ebny na malezienie ścieżki w sieci residualnej wynosi
zatem O(E') = O(E), jeśli tylko do szukania takiej ścieżki zastosujemy prze-
szukiwanie w głąb lub wszerz. Kama iteracja pętli wbile jest więc wykonywana
w czasie O(E), co daje łą.cmy czas działania procedury FORD-FULKERSON
O(E1.(I).
Gdy przepustowości są całkowitoliczbowe i wartość optymalnego prze-
pływu 1/'I jest mała, czas działania algorytmu Forda-Fulk:ersona jest zado-
walający.

t I
' '

(,) (b)

• t

\
y

(c)

Rys. 27.7. (a) Sieć przepływowa, dla której procedura FORD·FUUU!lł.SON może działać w czasie
0(El/"I ), gdzie/' jest maksymalnym przepływem, którego wartością jest tutaj 2000000. Zazna-
czono ścieżkę powiększającą o przepustowości residualnej L (b) Sieć residualna otrzymana w wy-
niku powiększenia przepływu wzdłuż ścieżki z (a) . .zaznaczono kolejną ścieżkę powiększającą
o przepustowości residualnej I. (c) Wynikowa sieć residualna

Na rysunku 27.7a widać, co może się zdarzyć w prostej sieci, dla której lf'I
jest duże. Maksymalny przepływ w tej sieci ma wartość 2 OOOOOO:1 OOO OOO
jednostek przepływa ścieżką S-* u"'"* t, a następne 1 000000 -ścieżką S-* v "'"*t.
Jeśli pierwszą ścieżką powiększającą znajdowaną w tym algorytmie jest
S-* u-* v "'"*t (patrz rys. 27 .7a), to po pierwszej iteracji wartość przepływu
wynosi 1. Na rysunku 27.7b jest przedstawiona sieć residualna indukowana
przez ten przepływ. Jeśli w drugiej iteracji znalezioną ścieżką powiększającą
jest S-* V-* U-* t (rys. 27.7b), to wówczas wartość przepływu wzrośnie do 2.
Na rysunku 27.7c widać sieć residualną indukowaną przez ten przepływ. Mo-
żemy teraz kontynuować ten proces, wybierając ścieżkę powiększającą

669
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

s-+ u-+ v -+ t w iteracjach o numerach nieparzystych i ścieżkę powiększającą


s-+ v-+ u-+ t w iteracjach o nu.merach parzystych. W ten sposób wykonaliby-
śmy łącznie 2 OOO OOOpowiększeń, zwiększając za każdym razem wartość prze-
pływu tylko o I.
Czas działania procedury FoRD-FULKERSON można poprawić, jeśli ścież­
ka powiększająca p w wierszu 4 będzie znajdowana z użyciem przeszukiwania
wszerz, czyli wtedy, kiedy ścieżka powiększająca jest najkrótszą ścieżką z s do
t w sieci residualnej (długość ścieżki mierzymy tutaj liC'lbą krawędzi). Metodę
Forda-Fulkersona zaimplementowaną w ten sposób nazywamy algorytm.em
Enmondsa-Karpa.Udowodnimy teraz, że algorytm Edmondsa-Karpa działa
w czasie O(VE').
W analizie korzysta się z własności odległości wierzchołków od źródła
w sieci residualnej G 1 . W poniższym lemacie używamy notacji ó1(u, v) na ozna-
czenie odległości z u do v w sieci resid11alnej G1, czyli długości najkrótszej
ścieżki z u do v, gdy każda krawędź ma jednostkową długość.

LEMAT 27.8.
Jeślialgorytm Edmondsa-Karpa jest wykonywany dla sieci przepływowej
G = (V, E) o źródle si ujściu t, to dla każdego wierzchołka ve V - {s, t} po
każdym powiększeniu wartości przepływu odległość ó1 (s, v) w sieci residualnej
GI nie maleje.

DOWÓD
Załóżmy przeciwnie, że dla pewnego wierzchołka ve V - {s, t} istnieje taltie
powiększenie wartości przepływu, które powoduje, że ó1 (s, v) maleje. Niech
J będzie przepływem akurat przed tym powiększeniem i niech/' będzie prze-
pływem zaraz po wykonaniu powiększenia. WówC'las

Bez straty ogólności możemy założyć, że ó1,(s, v) ~ ó1,(s, u) dla wszystkich


ue V - {s, t} tak.ich, że ór(s, u)< ó1 (s, u). Równoważnie możemy przyjąć, że
dla wszystkich wierzchołków ue V - {s, t}

(27.7)

Weźmy teraz najkrótszą ścieżkę p' w sieci Gr postaci S"ł-U-+ v i rozważmy


wierzchołek u, który poprzedza v na tej ścieżce. Z wniosku 25.2 wynik.a, że
musi zachodzić ór(s, u)= ó1 ,(s, v) - 1, ponieważ (u, v) jest krawędzią z p',
o której wiadomo, że jest najkrótszą ścieżką z s do v. Stąd i z (27.7) mamy

670
27.2. METODA FORDA-FULKERSONA

Rozważmy teraz przepływ netto /między wierzchołkami u i v (tymi samy-


mi co wyżej) przed powiększeniem przepływu w sieci G1. Jeśli f[u, v] < c(u, v),
to mamy

•,(s, v) ,;; •,(s, u) + I (z lematu 25.3)


~ ó1 .(s, u) +l
- o,.(s, v)
co przeczy założeniu, że powiększenie przepływu 11Dniejszaodległość z s do v.
Musi więc zachodzić f[u, v] = c(u, v), co oznacza, że (u, v) ffE1. ścieżka
powiększająca p, która została wybrana w sieci G do otrzymania Gr• musi
I
zawierać krawędź (v, u) w kierunku z v do u, ponieważ (u, v)EEr (z założenia)
i (u, v)f/Ep co przed chwilą pokazaliśmy. Tak więc, powiększając prze-
pływ wWłuż ścieżki p, ,,wypychamy" go z powrotem po krawędzi (u, v),
a v pojawia się przed u na ścieżce p. Ponieważ p jest najkrótszą ścieżką z s
do t, jej podścieżki są także najkrótszymi ścieżkami (lemat 25.1), a stąd
ó1 (s, u)= fJ1 (s, v) + 1. W konsekwencji otrzymujemy

ó/s, v) - ó/s, u) - I
~ o1,(s, u) - 1
- o,,(s,v) - 2
< o,.(s, v)
co przeczy naszemu początkowemu założeniu.


W następnym twierdzeniu jest podane ograniczenie na liczbę iteracji w al-
gorytmie Edmondsa-Karpa.

TwlERDZENIE27.9.
Jeśli algorytm Edmondsa-Karpa jest wykonywany dla sieci G = (V, E) o źród­
le si ujściu t, to łączna liczba powiększeń przepływu w tym algorytmie wynosi
co najwy7.ej O(VE).

DOWÓD
Powiemy, że krawędź (u, v) w sieci residualnej GI jest krytyczna na ścieżce
powiększającej p, jeśli przepustowość residualna p jest równa przepustowości
residualnej (u, v), tzn. jeśli c1 (p) = c1 (u, v). Po powiększeniu przepływu wzdłuż
ścieżki powiększającej każda krawędź krytyczna na tej ścieżce znika z sieci
residualnej. Co najmniej jedna krawędź na każdej ścieżce powiększającej musi
więc być krytyczna.

671
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

Niech u i v będą wierzcholk:ami w V, które są połączone krawędzią z E. Ile


razy krawędź (u, v) może być krawędzią krytyczną w czasie wykonywania
algorytmu Edmondsa-Karpa? Ponieważ ścieżki powiększające są najkrótszymi
ścieżkami, więc gdy (u, v) jest krytyczna po raz pierwszy, mamy

b1 (s, v) - b1 (s, u) + l
Po powiększeniu przepływu krawędź (u, v) znika z sieci residualnej i nie
może pojawić się na innej ścieżce powiększającej, aż do cza.su, w którym prze-
pływ netto między wierzchołkami u i v zostanie zmniejszony. To może zdarzyć
się tylko wtedy, kiedy (v, u) znajdzie się na ścieżce powiększającej. Jeśli/' jest
przepływem w sieci G w chwili, gdy tak się dzieje, to

ó1.(s, u) - J1 .(s, v) + l
Z lematu 27.8 wynika, że b (s, v) ~ ()1 ,(s, v). Stąd otrzymujemy
1

J1 .(s, u) - J1 .(s, v) + l
~ a,(s, v) + 1
- ó1(s, u) + 2
W konsekwencji od chwili, w której krawędź (u, v) była krytyczna, do
chwili, kiedy ponownie staje się krytyczna, odległość wierzchołka u od źródła
rośnie co najmniej o 2. Początkowa odległość wierzchołka u od źródła s wynosi
co najmniej I i zanim stanie się on nieosiągalny ze źródła s (jeśli to w ogóle
nastąpi), jego odległość od s może wzrosnąć co najwyżej do IVI- 2. Zatem
krawędź (u, v) może stawać się krytyczna co najwyżej O( V) razy. Ponieważ jest
co najwyżej O(E) par wierzchołków, dla których istnieje krawędź między nimi
w grafie residualnym, łączna liczba krawędzi krytycznych pojawiających się
w czasie całego wykonania algorytmu Edmondsa-Karpa wynosi O(VE). Każ­
da ścieżka powiększająca ma co najmniej jedną kawędż krytyczną, co wystar-
cza do zakończenia dowodu twierdzenia.

Ponieważ każda iteracja algorytmu Forda-Fulkersona może zostać zaim-
plementowana w czasie O(E), kiedy ścieżka powiększająca jest znajdowana za
pomocą przeszukiwania wszerz, łączny czas wykonania algorytmu Edmond-
sa-Karpa wynosi O(VE 2 ). W podrozdziale 27.4 opiszemy pewną metodę umoż­
liwiającą osiągnięcie czasu O(V2E), która jest podstawą algorytmu z pod.rozdz.
27.5 działającego w czasie O(V3).

ZADANIA
27.2--1. Podaj przepływ przez przekrój ({s, v2 , v4 }, {v1 , v3 , t}) w sieci z rys.
27 .1b. Jaka jest przepustowość tego przekroju?

672
27.3. MAKSYMALNE SKOJARZENIA W GRAFACH DWUDZIELNYCH

27,2,-2. Zilustruj działanie algorytmu Edm.ondsa-Karpa dla sieci z rys. 27.la.


27.2--3. Jak.i jest minimalny przekrój odpowiadający maksymalnemu przepły­
wowi dla sieci z rys. 27 .6? Wskaż dwie ścieżki powiększające, występujące
w tym przykładzie, które zmniejszają dodatni przepływ netto między pew-
ną parą wierzchołków sieci.
27.2-4. Udowodnij, że dla każdej pary wierzchołków u i v oraz każdych funkcji,
przepustowościciprzepływuf,zachodzic1 (u,v) + c1 (v,u) = c(u,v) + c(v,u).
27.2-S. Przypomnij sobie konstrukcję z pod.rozdz. 27.1 przekształcającą sieć
przepływów z wieloma źródłami i ujściami w sieć przepływów z pojedyn-
czym źródłem i pojedynczym ujściem przez dodanie krawędzi z nieskoń­
czonymi przepustowościami. Udowodnij, że każdy przepływ w tak otrzy-
manej sieci ma skończoną wartość, jeśli przepustowości krawędzi w sieci
pierwotnej są skończone.
27.2-6. Załóżmy, że w sieci z wieloma źródłami i ujściami każde źródło s;
wytwarza p 1 jednostek przepływu, tak że f(s 1, V) = p 1• Załóżmy tak.że, że
każde ujście t; ,,przyjmuje" q1 jednostek, tak że f(V, t ) = q , gdzie
1 1
I:.;p 1 = I:.iqi. Pokaż, w jaki sposób przekształcić problem znajdowania
przepływu f spełniającego te dodatkowe warunki na problem znajdowania
maksymalnego przepływu w sieci z pojedynczym źródłem i pojedynczym
., .
UJSCtem.
27.1-7. Udowodnij lemat 27.3.
27.2-8. Pokaż, że maksymalny przepływ w sieci G = (V, E) można zawsze
znaleźć za pomocą ciągu co najwyżej IE!ścieżek powiększających. (Wska-
zówka: Najpierw znajdź maksymalny przepływ, a potem wyznacz ścieżki).
27.2--9. Spójnością krawędziową grafu nieskierowanego nazywamy minimalną
liczbę k krawędzi, których usunięcie „rozspójnia" graf. Na przykład spój-
ność krawędziowa drzewa wynosi 1, a spójność krawędziowa cyklu wy-
nosi 2. Pokaż, w jaki sposób można obliczyć spójność krawędziową grafu
nieskierowanego G = (V, E), wykonując algorytm obliczania maksymal-
nego przepływu dla co najwyżej IV I sieci przepływowych, z których każda
ma O(V) wierzchołków i O(E) krawędzi.
27.2-10. Pokaż, że algorytm Edmondsa-Karpa kończy swoje działanie po co
najwyżej IVIIEl/4iteracjach. (W.'l'kazówka:Dla każdej krawędzi (u, v) roz-
waż, w jaki sposób ó(s, u) i ó(u, t) zmieniają się między iteracjami, w któ-
rych (u, ,) jest krytyczna).

27.3. Maksymalne
skojarzenia
w grafachdwudzielnych
Pewne problemy kombinatoryczne można łatwo przedstawić jako problemy
maksymalnego przepływu. Przykładem jest tu problem maksymalnego prze-
pływu z wieloma źródłami i ujściami z podrozdz. 27 .1. Istnieją także problemy,

673
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

które wydają się odległe od problemu maksymalnego przepływu, ale w rzeczywi-


stości można te problemy do niego sprowadzić. W tym podro7.dziale przedsta-
wiamy jeden z nich: znajdowanie maksymalnego skojarzenia w grafie dwudziel-
nym (patrz podro7.dz. 5.4). Żeby rozwią711Ć ten problem, skorzystamy z własno­
ści całk:owitoliczbowości pr:zepływu gwarantowanej w metodzie Forda-Fulkerso-
na. Zobaczymy, że stosując metodę Forda-Fulkersona, maksymalne skojarzenie
w grafie dwudzielnym G = (V, E) można obliczyć w czasie O(VE).

Problem maksymalnego skojarzenia w grafie dwudzielnym


Niech G = (V, E) będzie grafem nieskierowanym. Skojarzeniem w grafie Gna-
zywamy każdy podzbiór krawędzi M c E taki, że dla wszystkich wierzchoł­
ków ve: V co najwyżej jedna krawędź z podzbioru M jest incydentna z v. Mó-
wimy, że wieI'7.Chołek ve: V jest skojarzony w podzbiorze M, jeśli pewna kra-
wędź z M jest incydentna z wierzchołkiem v. W przeciwnym razie o v mówimy,
że jest wolny. Maksymalnym skojaneoiem. nazywamy każde skojarzenie o ma-
ksymalnej liczności. Innymi słowy, skojarzenie M jest maksymalne, jeśli
IM]~ IM'Idla każdego innego skojarzenia M'. W tym podro7.dziale ograniczy-
my naszą uwagę do znajdowania maksymalnego skojarzenia w grafach dwu-
dzielnych. Założymy, że zbiór wierzchołków można podzielić na V= Lu R,
gdzie L i R są rozłączne, a wszystkie krawędzie z E prowadzą między L i R.
Rysunek 27.8 ilustruje pojęcie skojarzenia.
Problem znajdowania maksymalnego skojarzenia w grafie dwudzielnym
ma wiele praktycznych rntosowań. Rozważmy dla przykładu problem przy-
działu maszyn do prac, które mogą być wykonywane niezależnie. Zbiór L jest
zbiorem maszyn, R zbiorem prac do wykonania. Krawędź (u, v) z E reprezen-

l R l R
(•) (b)

Rys, 27.8. Graf dwudzielny G = (V, E), w którym V= L v R. (•) Skojarzenie o liczności 2. (b) Ma-
ksymalne skojattenie o liczności 3

674
27.3. MAKSYMALNE SKOJARZENIA W GRAFACH DWUDZIELNYCH

tuje możliwość wykonania pracy v przez maszynę u. Maksymalne skojarzenie


wiąże z każdą. maszyną. co najwyżej jedną. pracę w sposób, który maksymalizu-
je liczbę jednoc:ześnie wykonywanych prac.

Znajdowaniemaksymalnegoskojarzeniaw grafie dwudzielnym


Do znajdowania maksymalnego skojarzenia w nieskierowanym grafie dwu-
dzielnym G = (V, E) możemy zastosować metodę Forda-Fulkersona, otrzymu-
jąc w ten sposób algorytm działający w czasie wielomianowo zależnym od IV!
i IEI.Idea rozwiązania polega na skonstruowaniu sieci przepływowej, w której
przepływy odpowiadają skojarzeniom (patrz rys. 27.9). Dla grafu dwudziel-
nego G konstrujemy odpowiadającą mu sieć przepływową G' = (V', E') w na-
stępujący sposób. Niech źródło s i ujście t będą wierzchołkami nie należącymi
do V i niech V' = V u {s, t}. Jeśli V= Lu R jest podziałem zbioru wierzchoł­
ków G, to zbiorem krawędzi skierowanych w sieci G' jest

E' - {(s, u):ueL)


u {(u, v): ueL, veR i (u, v)eE)
u {(v, t):veR)

Każdej krawędzi przypisujemy jednostkową przepustowość.

o
l R L R
(,) (b)

RyL 27.9. SillCprzepływowa odpowiadająca grafowi dwudzielnemu. (•) Graf dwudzielny G = (V, E)
z rys. 27.8, w którym V,.. Lu R. Do mak~ymalnego skojarzenia należą krawędzie z.a.cieniowane.
(b) Odpowiadająca grafowi G sieć prmpływowa G', w której jest zaznaczony maksymalny
przepływ. Przepustowośc każdej krawędzi. jest jednostkowa. Prrepływ na krawędziach 2'Jlcienio-
wanych wynosi I, natomiast na pozostałych krawędzi.ach przepływ jest zerowy. Za.cieniowane
krawędzie prowadzące od L do R odpowiadają krawędziom z maksymalnego skojarzenia w grafie
dwudzielnym

675
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

Z następującego twierdzenia wynika, że każdemu skojarzeniu w grafie G


odpowiada bezpośrednio pewien przepływ w sieci G'. Mówimy, że przepływ/
w sieci G = (V, E) jest całkowitoliczbowy, jeśli/(u, v) jest liczbą calkowitą dla
każdego (u, v)e V x V.

LEMAT27.10.
Niech G = (V, E) będzie grafem dwudzielnym, w którym V= Lu R, i niech
G' = (V', E') będzie odpowiadającą mu siecią przepływową. Jeśli M jest skoja-
rzeniem w G, to istnieje całkowitoliczbowy przepływ/ w sieci G' o wartości
lfl = IMJ.Odwrotnie, jeśli/jest przepływem całkowitoliczbowym w sieci G', to
istnieje skojarzenie M w grafie Go mocy I.Ml= 1/1.

DOWÓD
Udowodnimy najpierw, że skojarzeniu M w grafie G odpowiada pewien cał­
kowitoliczbowy przepływ w sieci G'. Z.definiujmy / następująco. Jeśli
(u, v)c M, to /(s, u)= f(u, v) = f(v, t) = l i f(u, s) = f(v, u)= f(t, v) = -1.
Dla wszystkich pozostałych krawędzi (u, v)eE' definiujemy /(u, v) = O.
Intuicyjnie, każdej krawędzi (u, v)eM odpowiada 1 jednostka przepływu
w sieci G', która wędruje ścieżką s-+ u-+ v-+ t. Ponadto ścieżki indukowane
przez krawędzie z M są wierzchołkowo rozłączne, z wyjątkiem s i t. żeby
wykazać, że/ rzeczywiście spełnia warunki skośnej symetryczności, przepus-
towości i zachowania przepływu, wystarczy tylko zauważyć, że/można otrzy-
mać w wyniku powiększania przepływu wzdłuż każdej z tych ścieżek. Przepływ
netto przez przekrój (Lu {s}, Ru {t}) jest równy IMJ.Z lematu 27.5 otrzymu-
jemy więc, że wartość przepływu wynosi 1/1= IMJ.
Aby udowodnić odwrotną implikację, załóżmy, że/jest przepływem cał­
kowitoliczbowym w sieci G' i niech
M = {(u, v):ucL, vcR if(u, v) > O}
Ka:idy wierzchołek u e L ma tylko jedną krawędź wchodzącą, mianowicie (s, u),
a jej przepustowość wynosi I. Tak więc do każdego ueL wchodzi co najwyżej
1 jednostka dodatniego przepływu. Ponieważ dla każdego u e L przepływ/ jest
calkowitoliczbowy, 1 jednostka dodatniego przepływu wchodzi do u wtedy
i tylko wtedy, gdy istnieje dokładnie jeden wierzchołek veR taki, że/(u, v) = 1.
Tak więc co najwyżej jedna krawędź wychodząca z każdego wierzchołka ueL
przenosi dodatni przepływ. Symetryczne rozumowanie można przeprowadzić
dla każdego v e R. Dlatego zbiór M zdefmiowany powyżej jest skojarzeniem.
Pozostaje pokazać, że !Ml= l/J. W tym celu zauważmy, że dla każdego
skojarzonego wierzchołka ueL mamy f(s, u)= 1, a dla każdej kra-
wędzi (u, v)e E - M zachodzi/(u, v) = O. W konsekwencji z lematu 27 .1, włas­
ności skośnej symetryczności i z braku istnienia krawędzi re zbioru L do ujś­
cia t otrzymujemy

676
27.3. MAKSYMALNE SKOJARZENIA W GRAFACH DWUDZIELNYCH

IMI-f(L, R)
- f(L, V') - f(L, L) - f(L, s) - f(L, t)
- O - O + f(s, L) - O
-f(s, V1
- Iii
Jest zatem naturalne, że maksymalnemu skojarzeniu w grafie dwudzielnym

G odpowiada pewien maksymalny przepływ w sieci przepływowej G'. Maksy-
malne skojarzenie w grafie G można więc obliczyć, wykonując dowolny al-
gorytm obliczania maksymalnego przepływu w sieci G'. Jedynym słabym pun-
ktem tego rozumowania jest to, że użyty przez nas algorytm obliczania ma-
ksymalnego przepływu mógłby wyznaczyć przepływ, który nie jest całkowito­
liczbowy. Z następującego twierdzenia wynika, że jeśli zastosujemy metodę
Forda-Fulk:ersona, taki problem nie może się pojawić.

TwIERDZENIE17.11. (O przepływie całkowitoliczbowym)


Jeśli funkcja przepustowości c jest calk:owitoliczbowa, to maksymalny prze-
pływ f obliczany metodą Forda-Fulkersona jest całkowitoliczbowy.

DOWÓD
Dowód przebiega przez indukcję względem liczby iteracji. Jego przeprowadze-
nie pozostawiamy czytelnikowi jako zad. 27.3-2.

Udowodnimy teraz następujący wniosek z lematu 27.10.



WNIOSEK27.12.
Liczność maksymalnego skojarzenia w grafie dwudzielnym G jest równa war-
tości maksymalnego przepływu w odpowiadającej grafowi G sieci G'.

DOWÓD
Posłużymy się terminologią z lematu 27.10. Załóżmy, że M jest maksymalnym
skojarzeniem w grafie G i że odpowiadający mu przepływ /w sieci G' nie jest
maksymalny. Wówczas istnieje maksymalny przepływ /' w sieci G' taki, że
I/' I > )/1.Ponieważ przepustowości w G' są całkowitoliczbowe, z twierdzenia
27.11 wynika, że przepływ/' jest taicie calkowitoliczbowy. Tak więc przepływ
/' odpowiada skojarzeniu M' w grafie G o liczności IM'] = I/' I > 1/1= IM],
przecząc maksymalności M. W podobny sposób możemy pokazać, że jeśli
/jest przepływem maksymalnym w sieci G', to odpowiadające mu skojarzenie
jest maksymalnym skojarzeniem w grafie G.

677
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

Maksymalne skojarzenie w dwudzielnym grafie nieskierowanym G można


więc znaleźć, tworząc sieć przepływową G' i wykonując algorytm Forda-Ful-
kersona. Maksymalne skojarzenie M otrzymuje się bezpośrednio ze, znalezio-
nego całkowitoliczbowego, maksymalnego przepływu/ Ponieważ każde skoja-
rzenie w grafie dwudzielnym ma liczność co najwyżej min(L, R) = O( V), war-
tość maksymalnego przepływu w sieci G' wynosi O(V). Dlatego maksymalne
skojarzenie w grafie dwudzielnym można znależć w czasie O(VE).
ZADANIA
27.3-1. Wykonaj algorytm Forda-Fulkersona dla sieci z rys. 27.9b, pokazując
sieć residualną po każdym powiększeniu przepływu. Ponwneruj wierzchoł­
ki w L z góry w dół od I do 5, a w Rz góry w dół od 6 do 9. W każdej
iteracji wybieraj ścieżkę powiększającą, która jest leksykograficznie naj-
mniejsza.
27.3-2. Udowodnij twierdze.nie27.11.
27.3-3. Niech G = (V, E) będzie grafem dwudzielnym, w którym V= Lu R,
i niech G' będzie odpowiadającą mu siecią przepływową. Podaj dokładne
górne ograniczenie na długości wszystkich ścieżek powiększających znaj-
dowanych w sieci G' w czasie działania procedury FORD-FULK.ERSON.
* 27.3-4. Skojarzeniem doskonałym nazywamy skojarzenie, w którym ka7dy wie-
rzchołek jest skojarzony. Niech G = (V, E) będzie nieskierowanym grafem
dwodzielnym, w którym V= Lu R i ILI= IRI-Dla każdego X s V defi-
niujemy sąsiedztwo N(X) zbioru X jak.o zbiór wierzchołków sąsiadujących
z co najmniej jednym wierzchołkiem z X. Formalnie

N(X) = {ye V: (x, y)eE dla pewnego xeX)

Udowodnij twierdzenie Halla: w grafie G istnieje skojarzenie doskonałe


wtedy i tylko wtedy, gdy dla każdego podzbioru A ~ L zachodzi zależność
IAI.; IN{A)I.
* 27.3-5, Graf dwudzielny G = (V, E), w którym V= Lu R, nazywamy d-regu-
larnym, jeśli każdy wierzchołek: ve Vma stopień dokładnie d. W każdym
cl-regularnym grafie dwudzielnym ILI= IRI-Udowodnij, że każdy cl-regu-
larny graf dwudzielny ma skojarzenie o liczności !LI, pokazując, że mini-
malny przekrój w odpowiadającej grafowi G sieci przepływowej ma prze.-
pustowość ILI,

*27.4. Algorytmyprzedprzeplywowe
W tym podrox.dzialeprzedstawimy metodę przedprzepływową obliczania ma-
ksymalnego przepływu. Najszybsze znane obecnie algorytmy obliczania ma~

678
* 27.4. ALGORYTMY PRZEDPRZEPŁYWOWE

ksymalnego przepływu działają z wykorzystaniem tej metody. Również inne


problemy związane z przepływami, jak na przykład problem maksymalnego
przepływu o minimalnym koszcie, można rozwiązać efektywnie w ten sposób.
W tym podrozdziale przedstawimy schemat obliczania maksymalnego przepły­
wu wykorzystujący metody przed przepływów. Schemat ten pochodzi od Gold-
berga. Prosta implementacja tego schematu działa w C'lasie O(V2E). Tym sa-
mym uzyskujemy algorytm szybszy od algorytmu Edmondsa-Karpa działają­
cego w C'lasie O(VE 2 ). W podro7.dziale 27.5 dokonamy SZC'legółowej analizy
tego algorytmu i wyprowadzimy algorytm działający w czasie O(V3).
Metoda przedprzepływowajest bardziej lokalna niż metoda Forda-Fulker-
sona. Zamiast badać całą sieć residnalną G = (V, E) w celu malezienia ścieżki
powiększającej, w metodzie przed.przepływowej w każdym kroku jest przetwa-
rzany tylko jeden wierzchołek wraz z jego wierzchołkami-sąsiadami w sieci
residualnej. Ponadto, w przeciwieństwie do metody Forda-Fulk:ersona, w me-
todzie przedprzepływowej nie jest utrzymywana własność zachowania przepły­
wu. Wykorzystuje się natomiast pojęcie pnedprzeplywu, który jest funkcją
f: V x V-+ R, spełniającą warunki skośnej symetryC'lności, przepustowości
oraz słabszy warunek zachowania przepływu: f(V, u) ~ Odla wszystkich wierz-
chołków uE V - {s}. Ta ostatnia własność mówi, że wartość przepływu na
wejściu do wierzchołka jest nieujemna. Wielkość przepływu na wejściu do wie-
rzchołka u nazywamy nadmiarem dla u i definiujemy jako

e(u) =f(V, u) (27.8)

Powiemy, że wier7.ehołek uE V - {s, t} jest nadmiarowy, jeśli e(u) > O.


Ten ro7.dział rozpoczniemy od intuicyjnego wytłumaczenia metody przed.-
przepływowej. Prześledzimy dwie operacje stosowane w tej metodzie: ,.przesy-
łanie" (ang. pushing) przed.przepływu i „podnoszenie" (ang. lifting) wierzchoł­
ka. Na koniec opiszemy schemat obliczania maksymalnego przepływu działa­
jący z wykorzystaniem metody przed.przepływów oraz przeanalizujemy jego
poprawność i czas działania.

Rozważania intuicyjne
Metodę przed.przepływową można prawdopodobnie najlepiej zrozumieć, roz-
ważając przepływ cieczy w sieci G = (V, E) połączonych ze sobą rur o danych
przepustowościach. Stosując tę analogię do metody Forda-Fulkersona, mog-
libyśmy powiedzieć, że każda ścieżka powiększająca w sieci umożliwia przesia-
nie ze źródła do ujścia dodatkowego strumienia cieczy, który w żadnym punk-
cie się nie rozgałęzia. W metodzie Forda-Fulk:ersona kolejno, jeden po drugim,
są dodawane nowe strumienie aż do chwili, w której już żaden nowy strumień
nie może być dodany.

679
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

Jednak rozumowanie intuicyjne, umożliwiające wytłumaczenie metody


przedprzepływowej jest trochę inne. Jak poprzednio, krawędziom skierowa-
nym odpowiadają rury. Wierzchołki, które są miejscami łąe7.E:nia rur, mają
dwie interesujące własności. Po pierwsze, każdy wierzchołek jest wyposażony
w zbiornik o nieograniczonej pojemności, w którym można przechowywać
nadmiar przepływu. Po drugie, każdy wierzchołek, jego zbiornik. i wszystkie
przyłącza rur znajdują się na platformie, kt6rej wysokość rośnie z czasem dzia-
łania algorytmu.
Wysokości wierzchołków określają kieninki przesyłania przepływu: pne-
pływ „wędruje" tylko w d6l, tzn. od wierz.cholka położonego wyżej do wierz-
chołka położonego niżej. Może istnieć dodatni przepływ netto z wierzchoł­
ka położonego niżej do wierzchołka położonego wyżej, ale we wszystkich
operacjach przesyłania pr:zepływ jest zawsze pr:zesyłany w dół. Wysokości źró­
dła i ujścia są ustalone i wynoszą odpowiednio IV! i O. Wysokości wszystkich
pozostałych wierzchołków wynoszą początkowo O i rosną w czasie działania
algorytmu. Na początku p!7.Cpływ ze źrodła w kierunku ujścia jest tak duży,
jak to jest tylko możliwe. Innymi słowy, ze źródła wysyłamy tak dużo, żeby
wypełnić całkowicie każdą rurę wychodzącą ze źródła. Zatem wielkość po-
czątkowego przepływu ze źródła jest równa p!7.Cpustowości przekroju
(s, V - s). Przepływ po raz pierwszy docierający do wierzchołka trafia do
jego zbiornika, a stamtąd jest przesyłany w dół do wierzchołków położo­
nych niżej.
Może się zdarzyć, że jedynymi nie wypełnionymi całkowicie rurami wy-
chodzącymi z wierzchołka u są te, które prowadzą do wierzchołków leżących
na tej samej lub większej wysokości niż wysokość u. W tym przypadku, żeby
usunąć z wierzchołka u nadmiar przepływu, musimy zwiększyć wysokość tego
wierzchołka. Dokonujemy tego za pomocą operacji „podnoszenia". Wysokość
wierzchołka u wzrasta do wysokości o 1 większej od wysokości najniżsi.ego
sąsiada u, do którego prowadzi nie wypełniona całkowicie rura. Dlatego po
podniesieniu wierzchołka u pewien nadmiar przepływu można przesłać w dól
przez co najmniej jedną wychodzącą z niego rurę.
W końcu do ujścia dociera cały przepływ, który powinien tam wpłynąć,
Więcej nigdy tam nie dotrze, ponieważ przez rury nie można przesyłać więcej
niż wynosi ich przepustowość; wielkość pr:zepływu przez każdy przekrój jest
ciągle ograniczana przez jego pnepustowość. żeby z przedprzeplywu uzyskać
„legalny" przepływ, należy pr:zesłać nadmiar „cieczy" i.ebranej w zbiornikach
wierzchołków nadmiarowych z powrotem do źródła. Dokonuje się tego przez
podnoszenie wierzchołków powyżej wysokości źródła IVJ.(Pnesyłanie nad-
miaru z powrotem do źródła w rzeczywistości odbywa się przez kasowanie
przepływów powodujących nadmiar). Jak wkrótce zobaczymy, gdy wszystkie
zbiorniki zostają opróżnione, przedprzepływ jest nie tylko przepływem legal-
nym, ale także przepływem maksymalnym.

680
* 27.4. ALGORYTMY PRZEDPRZEPŁYWOWE

Podstawoweoperacje
Z przeprowadzonej dyskusji wynika, że w metodzie przedprzepływowej wy-
konywane są dwie podstawowe operacje: przesyłanie nadmiaru przepływu
z wierzchołka do jednego z jego sąsiadów (operacja PusH) i podnoszenie
wierzchołka (operacja LIFT). Stosowalność tych operacji zależy od wysokości
wierzchołków. To pojęcie zdefiniujemy teraz formalnie.
Niech G = (V, E) będzie siecią przepływową o źródle w s i ujściu w t,
a/ niech będzie przedprzepływem w sieci G. Funkcję h: V__.N nazywamy
funkcją wysokości, jeśli h(s) = IVI, h(t) = Oi
h(u),; h(v) + 1

dla każdej krawędzi residualnej (u, v)EE 1. Natychmiast otrzymujemy następu­


jący lemat.

LEMAT27.13.
Niech G = ( V, E) będzie siecią przepływową, niech f będzie przed przepływem
w sieci G, a h - funkcją wysokości na zbiorze V. Dla ka7..dych dwóch wierz-
chołków u, ve V, jeśli h(u) > h(v) + 1, to (u, v) nie jest krawędzią w grafie
residualnym.


Operację podstawową PUSH(u, v) można stosować tylko wtedy, gdy wierz-
chołek u jest wierzchołkiem nadmiarowym, c1(u, v) > Oi h(u) = h(v) + I. Ope-
racja ta zmienia przed.przepływ f w rozważanej sieci G = (V, E). Pseudokod
dla tej operacji jest zapisany poniżej. Zakładamy, że przepustowości są dane
przez obliczaną w stałym czasie funkcję c. Przepustowości residualne mogą być
wówczas obliczone w stałym czasie z c i f Nadmiar przepływu w wierzchoł­
ku u jest pamiętany w zmiennej e[u], a wysokość u w zmiennej h[u]. Wyrażenie
d1 (u, v) oznacza zmienną tymczasową służącą do pamiętania wielkości prze-
pływu, który można przesiać z u do v.

PUSH(u, v)
1 t> Stosujemy, gdy: u jest nadmiarowy, cr(u, v) > O i h[u] = h[v] + I
2 t> Działanie: Przesianie d1 (u, v) = min(e[u], c1 (u, v)) jednostek przepływu
zudov.
3 d1(u, v) - min(e[u], c1 (u, v))
4 /[u, v]- /[u, v] + d1 (u, v)
5 f[v, u] - -/[u, v]
6 e[u] - e[u] - dr(u, v)
7 e[v] - e[v] + d1 (u, v)

681
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

Operacja PUSHdziała w następujący sposób. Zakładamy, że zarówno nad-


miar e[u] w wierzchołku u, jak i przepustowość residualna krawędzi (u, v) są
dodatnie. Dlatego z wierzchołka u do v możemy przesłać do d1(u, v) =
1= min(e[u], c (u, v)) jednostek przepływu, pozostawiając e[u] nieujemne i nie
1
przekraczając przepustowości c(u, v). Ta wielkość jest obliczana w wierszu 3.
Przesłanie przepływu z u do v następuje przez aktualizację f w wienuch 4-5
i aktualizację e w wierszach 6-7. Stąd, jeśli funkcja f jest przed.przepływem
przed wykonaniem PUSH, to pozostaje przed.przepływem po wykonaniu tej
••
operac:i1.
Zauważmy, że żadna akcja w procedurze PUSH nie zależy od wysokości
wierzchołków u i v. Żądamy jedynie, żeby h[u] = h[v] + 1. Tak więc nadmiar
przepływu jest przesyłany w dół między wierzchołkami, których różnica wyso-
kości wynosi 1. Z lematu 27 .13 wynika, że nie istnieją krawędzie residualne
między dwoma wierzchołkami, których wysokości różnią się więcej niż o 1.
A zatem nic nie zyskamy, umożliwiając przesyłanie przepływu w dół między
wierzchołkami, których różnica wysokości jest większa niż 1.
Operację PuSH nazywamy operacją przesyłania. Powiemy, że operacja
przesyłania stosuje się do wierzchołka u, jeśli stosuje się do pewnej krawędzi
(u, v) wychodzącej z u. Operacja przesyłania jest nasycająca, jeśli krawędź (u, v)
zostaje nasycona po jej wykonaniu (tj. zachodzi c1 (u, v) = O); w przeciwnym
razie przesyłanie jest nienasycające. Krawędzie nasycone nie występują w sieci
residualnej.
Operację LIFT(u) wykonujemy, jeśli wierzchołek u jest nadmiarowy i gdy
z c1 (u, v) > O wynik.a, że h[u] " h[v] dla wszystkich wierzchołków v. Innymi
słowy, możemy podnieść nadmiarowy wierzchołek u, jeśli wysokość każdego
wierzchołka v, dla którego przepustowość residualna z u do v jest dodatnia, nie
jest mniejsza od wysokości u i dlatego przepływ nie może być przesłany
z u do v. (Pamiętajmy, że zgodnie z defmicją ani źródło s, ani ujście tnie mogą
być nadmiarowe. Tak więc ani s, ani tnie mogą być podnoszone).

L!Fr(u)
1 C> Stosujemy, gdy: u jest nadmiarowy i dla wszystkich ve V
(u, v) E E1 implikuje h[u] ,;; h[v]
2 t> Działanie: Zwiększenie wysokości u
3 h[u] +-1 + min{h[v]: (u, v)eE 1}

O wierzchołku u mówimy, że jest podnoszony,jeśli wykonujemy operację


LIFr(u). Należy zauważyć, że gdy u jest podnoszony, E1 zawiera co najmniej
jedną krawędź wychodzącą z u, tak że operacja minimum w zapisie operacji
LIFT jest stosowana do niepustego zbioru. Wynika to z nadmiarowości u.
Ponieważ e[u] > O, mamy e[u] =/[V, u] > O i skutkiem tego musi istnieć co
najmniej jeden wierzchołek v taki, że Jlv, u] > O.Ale wtedy

682
* 27.4. ALGORYTMY PRZEDPRZEPŁYWQWE

c1 (u, v) = c(u, v) - f[u, v]


= c(u, v) + f[v, u]
>0
z czego wynika, że (u, v)eE 1 • Tak więc operacja LIFT(u) nadaje u największą
możliwą wysokość przy zachowaniu własności funkcji wysokości.

Schemat algorytmu przedprzepływowego


W schemacie algorytmu przedprzeplywowego wykorzystuje się następujący
podprogram do konstruowania początkowego przedprzepływu w sieci.

INITIALIZE-PREFLOW(G, s)
1 for każdy wierzchołek ue V[G]
2 do h[u] -o
3 e[uJ-o
4 for każda krawędź (u, v)e E[G]
5 do/[u,v]-O
6 f[v, u]- O
7 h[sJ - IV[GJI
8 for każdy wierzchołek u e Adj[s]
9 do /[s, u] - c(s, u)
10 /[u, s] - - c(s, u)
li e[u]-c(s,u)

Za pomocą procedury INITIALIZE-PREFLOW jest tworzony przedprzepływ


zdefiniowany następująco:

c(u, v), jeśli u= s


f[u, v] = -c(v, u), jeśli v =s (27.9)
O w pozostałych przypadkach

Oznacza to, że każda krawędź wychodząca u źródła jest całkowicie wypełnio­


na, a przez żadną z pozostałych krawędzi nic nie przepływa. Dla każdego
wierzchołka v sąsiadującego u źródłem mamy początkowo e[v] = c(s, v). Na
początku algorytmu funkcja wysokości jest zdefiniowana następująco:

jeśli u= s
h[uJ = {~I, . .
w przeciwnym razie
Jest to rzeczywiście funkcja wysokości, ponieważ jedynymi krawędziami (u, v),
dla których h[u] > h[v] + 1, są te, dla których u= s. Krawędzie te są nasycone,
co oznacza, że nie mogą występować w sieci residualnej.

683
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

Następująca procedura stanowi ogólny schemat metody prz.edprzeplywowej


GENBRIC-PREFLOW-PuSH(G)
1 lNITIALIZE-PREFLOW(G, s)
2 while można zastosować operacje przesłania lub podniesienia
3 do wybierz jedną z tych operacji i wykonaj ją
w algorytmie GENERIC-PREFLOW-PUSH, po fazie inicjowania, w kolej-
nych iteracjach pętli while są wykonywane w dowolnym porządku operacje
PuSH i LIFT, gdy tylko można je zastosować. W następującym lemacie jest
mowa o tym, że jeśli w sieci istnieje wierzchołek nadmiarowy, to co najmniej
jedną z tych operacji można zastosować.

LEMAT27,14. (O stosowalności operacji podstawowychdo wierzchołków


nadmiarowych)
Niech G = (V, E) będzie siecią przepływową ze źródłem si ujściem t,f-przed-
przepływem, a h - funkcją wysokości dla f Jeśli u jest wierzchołkiem nad-
miarowym, to PUSH lub LIFT stosuje się do u.

DOW0D
Ponieważ h jest funkcją wysokości, dla każdej krawędzi residualnej (u, v) ma-
+
my h(u) ~ h(v) 1. Jeśli operacja PUSH nie stosuje się do u, to dla każdej
krawędzi residualnej (u, v) musi zachodzić h(u) < h(v) + I, z czego wynik.a, ie
h(u) :i::;h(v). Tak więc do u można zastosować operację LIFT.


Poprawność metody przedprzeplywów
Żeby udowodnić, że za pomocą algorytmu GENERIC-PREFLOW-PUSH
można
poprawnie rozwiązać problem maksymalnego przepływu, pokażemy najpierw,
że po zakończeniu działania algorytmu/jest przepływem maksymalnym. Na-
stępnie udowodnimy, że omawiany algorytm zawsze kończy swoje działanie.
Rozpoczniemy od pewnych obserwacji dotyczących funkcji wysokości h.

LEMAT27.15. (Wysokości wierzchołków nigdy nie maleją)


Dla każdego wierzchołka ue V podczas wykonywania algorytmu GENERIC-
-PREFLOW-PUSH dla sieci G = (V, E) wysokość h[u] nigdy nie maleje. Ponadto,
gdy operacja LIFT jest stosowana do wierzchołka u, jego wysokość h[u] rośnie
co najmniej o l.

DOWÓD
Ponieważ wysokości wierzchołków zmieniają się tylko w wyniku wykonywania
operacji LIFT, wystarczy udowodnić drugą część twierdzenia. Jeśli wierzchołek

684
* 27.4. ALGORYTMY PAZEOPRZEPŁYWOWE

jest podnoszony, to dla wszystkich wierzchołków takich, ze


(u, v)EE 1, mamy
h[u].; h[v]. Z tego wynika, że h[u] < I + min{h[v]: (u, v)eE 1}. Tak więc wyko-
nanie LIFT dla wierzchołka u powoduje zwiększenie h[u].


LEMAT27.16.
Niech G = (V, E) będzie siecią przepływową ze źródłem s i ujściem t. Podczas
wykonywania algorytmu GENERIC-PREFLOW-PUSH dla sieci G atrybut h za-
chowuje własności funkcji wysokości.

DOWÓD
Dowód przebiega przez indukcję względem liczby wykonywanych operacji
PUSH i LIFT. Po fazie inicjowania, jak już wcześniej zauważyliśmy, h jest
funkcją wysokości.
Udowodnimy, że jeśli h jest funkcją wysokości, to operacja LIFT pozo-
stawia hjako funkcję wysokości. Jeśli (u, v)EE 1 jest krawędzią residualną wy-
chodzącą z u, to po wykonaniu LIFT(u) mamy h[u] ~ h[v] + 1. Jeśli krawędź
residualna (w, u) wchodzi do u, to z lematu 27 .15 wynika, że jeśli przed wyko-
naniem operacji LIFT(u) było h{w] ~ h[u] + 1, to po jej wykonaniu zachodzi
h[w] < h[u] + 1. Tak więc po wykonaniu LIFT h nadal jest funkcją wysokości.
Rozważmy teraz operację PUSH(u, v). Za pomocą tej operacji możemy
dodać krawędź (v, u) do E1 i możemy usunąć krawędź (u, v) z E_rW pierwszym.
przypadku mamy h[v] = h[u] - 1 i dlatego h pozostaje funkcją wysokości.
W drugim przypadku usunięcie krawędzi (u, v) z sieci residualnej powoduje,
że ta krawędź nie wpływa już na h i dlatego funkcja ta jest nadal funkcją
wysokości.


W następującym. lemacie jest podana pewna ważna własność funkcji wy-
sokości.

LEMAT27.17.
Niech G = (V, E) będzie siecią przepływową ze źródłem si ujściem t,f- przed-
przepływem w sieci G, a h-funkcją wysokości na V. Wówczas w sieci residual-
nej G1 nie istnieje ścieżka ze źródła .vdo ujścia t.

DOWÓD
Załóżmy przeciwnie i niech p = (v 0 , v1, vk) będzie ścieżką z s do t w sieci G1,
••• ,
na której v0 =si vt = t. Bez straty ogólności możemy przyjąć, że p jest ścieżką
prostą i stąd k < IVI.Dla i= O, 1, ... , k - l krawędź (v;, v1 + 1)E E1 . Ponieważ
h jest funkcją wysokości, h(v 1) ~ h(v 1 + 1) + I dla i= O, 1, ... , k - I. Łącząc te
nierówności wzdłuż ścieżki p, otrzymujemy h(s) .::;,;; h(t) + k. Ale ponieważ

685
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

h(t) = O, otrzymujemy h(s) ,;; k < IVI,czyli sprzeczność, bo h jest funkcją wy-
sokości, stąd = IYI,
a

Możemy
h(s)

teraz udowodnić, że jeśli koń­


algorytm GENERIC-PREFLOW-PuSH

czy swoje działanie, to obliczony przedprzepływ jest przepływem maksymalnym.

TwlERDZENIE27,18. (Poprawność metody przedpruplywów)


Jeśli algorytm GENERIC-PREFLOW-PuSH wykonywany dla sieci przepływowej
G = (V, E) ze źródłem s i ujściem t kończy swoje działanie, to przedprzepływ
f obliczany w tym algorytmie jest przepływem maksymalnym.

Dowón
Jeśli algorytm kończy swoje działanie, to nadmiar w każdym wierzchołku
z V·- {s, t} musi wynosić O, ponieważ z lematów 27.14 i 27.16 oraz z tego, że
f jest zawsze przed.przepływem wynik.a, że nie ma wierzchołków nadmiaro-
wych. Dlatego f jest przepływem. Ponieważ h jest funkcją wysokości, z lematu
27.17 otrzymujemy, że w sieci residualnej nie istnieje żadna ścieżka z s do t.
Zatem z twierdzenia o maksymalnym przepływie i minimalnym przekroju
otrzymujemy, że/jest przepływem maksymalnym.

Analiza metody przedprzepływów
żeby udowodnić, że algorytm przedprzepływów rzeczywiście kończy swoje
działanie, podamy ograniczenia na liczbę operacji wykonywanych w tym al-
gorytmie. Oddzielnie policzymy ograniczenia na liczbę operacji dla każdego
z trzech typów operacji - podnoszenia, przesłania nasycającego i przesłania
nienasycającego. Znając te ograniczenia, nie napotkamy już trudności przy
konstruowaniu algorytmu działającego w cz.asieO(V 2 E). Przed rozpoczęciem.
analizy liczby operacji udowodnimy jeden ważny lemat.

LEMAT27.19.
Niech G = (V, E) będzie siecią przepływową ze źródłem s i ujściem t i niech
f będzie przedprzepływem w G. Wówczas dla każdego nadmiarowego wierz-
chołka u istnieje ścieżka prosta z u do s w sieci residualnej G1 .

Dowoo
Niech U= {v: istnieje prosta ścieżka z u do v w sieci G1} i załóżmy przeciwnie,
że sf U. Niech U =
V - U.
Pokażemy, że dla każdej pary wierzchołków v e U i we "tł zachodzi zależ­
ność /(w, v),;; O.Dlac,.ego? Jeśli/(w, v) > O,to f(v, w) < O,z czego wynika, że
cf..v, w)= c(v, w) -f(v, w)> O i istnieje krawędź (u, v)eE 1 . Dlatego także

686
* 27.4. ALGORYTMY PRZEDPRZEPŁYWOWE

istnieje ścieżka prosta u -to v-. w w sieci Gf' co jest sprzecme z naszym wy-
borem w.
Musi zatem zachodzić /(U-, U)~ O, ponieważ każdy składnik w niejaw-
nym sumowaniu jest niedodatni. Dlatego z równości (27.8) i lematu 27.1 wnio-
skujemy, że

e(U) = f(V, U)
=f(U, U)+ f(U, U)
=f(U, U)

"o
We wszystkich wierzchołkach z V - {s} nadmiary przepływu są nieujemne.
Ponieważ założyliśmy, że U c V - {s},dla każdego wierzchołka ve U musimy
więc mieć e(v) = O. W szczególności e(u) = O, co przeczy naszemu założeniu
o tym, że wierzchołek u jest nadmiarowy.

W następującym lemacie jest podane ograniczenie na wysokości wierzchoł­



ków. Jako wniosek z tego lematu otrzymujemy ograniczenie na łączną liczbę
operacji LIFT.

LEMAT 27,20.
=
Niech G (V, E) będzie siecią przepływową ze źródłem si ujściem t. W każdej
chwili podczas wykonywania algorytmu GENERIC-PREFLOW-PUSHdla sieci
Gdla każdego wierzchołka ueVzachodzi h[u] ~ 21Vl-1.

DoWóD
Wysokości źródła s i ujścia t nigdy się nie zmieniają, ponieważ zgodnie z de-
finicją wierzchołki te nie mogą być nadmiarowe. Tak więc zawsze h[s] = ]VI
ih[t]=O.
Ponieważ tylko wierzchołki nadmiarowe są podnoszone, rozważmy do-
wolny nadmiarowy wierzchołek ueV-{s, t}. Z lematu 27.19 wiemy, że ist-
nieje ścieżka prosta p z u do s w sieci Gr Niechp = (v 0, v1, ••• , v1;),gdzie v0 = u,
v.,=s i k~ IVl-1, ponieważ p jest prosta. Dla i= O, 1, ..., k-1 mamy
(v;, v1+ 1)eE 1 i dlatego (z lematu 27.16) zachodzi h{v,]~ h[v;+il + 1. Łącząc
te nierówności wzdłuż ścieżki p, otrzymujemy h[u] = h[vcJ~ h[v1;]+ k.:;;;
,;; h[s] + (IVI- I)= 21VI-1.

WNIOSEK27 .21. (Ograniczenie na liczbę operacji podnoszenia)
Niech G = (V, E) będzie siecią przepływową ze źródłem s i ujściem t. Liczba
operacji podnoszenia wykonywanych dla jednego wierzchołka podczas wyko-

687
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

nywania algorytmu GENERIC-PREFLOW-PUSHdla sieci G jest wówczas nie


większa niż 21V I - 1 i stąd liczba wszystkich operacji podnoszenia jest nie
większa niż (2IVI - lXIVI -2) < 21VI'.

DOWÓD
Tylko wierzchołki z V - {s, t}, których jest IV! - 2 mogą być podnoszone.
Niech uE V - {s, t}. Operacja LIFT(u) zwiększa h[u]. Początkową wartością
h[u] jest O, a z lematu 27.20 wynika, że może ona wzrosnąć do co najwyżej
21VI- 1. Tak. więc każdy wierzchołek uE V - {s, t} jest podnoszony co naj-
wyżej 21VI - 1 razy, a łączna liczba wykonywanych operacji podnoszenia jest
nie większa niż (21VI- 1x1v1- 2) < 21v12 •

Lemat 27.20 zastosujemy także do znalezienia ograniczenia na liczbę prze-
słań nasycających.

LEMAT 27.22. (Ograniczenie na liczbę przesiań nasycających)


Podczas wykonywania algorytmu GENERJC-PREFLOW-PuSHdla dowolnej sie-
ci przepływowej G = (V, E) liczba przesłań nasycających jest nie większa
niż 21VIJEI.

DOWÓD
Dla każdej pary wierzchołków u, vE V rozważmy nasycające przesłania
z u do v i z v do u. Jeśli jest wykonywane co najmniej jedno takie przesłanie, to
co najmniej jedna z krawędzi (u, v) i (v, u) jest rzeczywistą krawędzią z E.
Załóżmy teraz, że wystąpiło przesłanie z wierzchołka u do v. Żeby można
wykonać na tej krawędzi operację PUSH w przyszłości, wcześniej tak.a operacja
musi zostać wykonana z wierzchołka v do u, co nie może się zdarzyć, zanim
h[v] nie wzrośnie co najmniej o 2. Podobnie h[u] musi wzrosnąć co najmniej
o 2 między kolejnym.i nasycającym.i operacjami PuSH z v do u.
Rozważmy ciąg A liczb całkowitych postaci h[u] + h[v], odpowiadający
ciągowi operacji PUSH między u i v. Jaka jest długość tego ciągu? Kiedy jest
wykonywana pierwsza operacja PuSH, w dowolnym. z kierunków między u i v,
musi zachodzić h[u] + h[v] ~ 1. Wynika stąd, że pierwszy element ciągu A jest
nie mniejszy niż 1. Z lematu 27.20 otrzymujemy, że gdy jest wykonywana
ostatnia operacja PUSH, zachodzi h[u] + h[v] <a:(21VI-1) + (21VI- 2)-
= 41V1- 3. Ostatnia liczba w ciągu A jest zatem nie większa niż 41VI- 3.
Używając argumentu z poprzedniego podrozdziału, widzimy, że w ciągu A mo-
że występować co najwyżej co druga liczba całkowita z przedziału [1, 41VI - 3].
Tak więc w A występuje co najwyżej ((41VI- 3) - 1)/2 + 1 - 2IVI - 1 liczb
całkowitych. (Dodajemy 1, żeby mieć pewność policzenia elementów z obu
końców ciągu A). Łączna liczba nasycających operacji PUSH między wierz-

688
* 27.4. ALGORYTMY PRZEDPRZEPŁYWOWE

chałkami u i v wynosi zatem co najwyżej 21Vl- I. Mnożąc tę liczbę przez


liczbę krawędzi w sieci, dostajemy, że łączna liczba wszystkich nasycających
operacji PUSH wynosi co najwyżej (2IVI- l)IEI < 21VIIEI.

W poniższym lemacie jest podane ograniczenie na liczbę przesłań nienasy-
cających w algorytmie GENERIC-PREFLOW-PUSH.

LEMAT27.23. (Ograniczenie na liczbę pnesłań nienasycających).


Podczas wykonywania algorytmu GENERIC-PREFLOW-PUSH dla dowolnej sie-
ci przepływowej G = (V, E) liczba nienasycających przesłań jest nie większa
niż 41Vl'(IV I + IEI).
Dowon
Zdefiniujmy funkcję potencjału tl>= I:..ah[v], gdzie X c V jest zbiorem wierz-
chołków nadmiarowych. Początkowo cl>= O. Zauważmy, że podniesienie wie-
rzchołka u zwiększa wartość cl>co najwyżej o 21VI,ponieważ zbiór, po którym
sumujemy, nie zmienia się i wierzch olek u nie może być podniesiony powyżej
maksymalnej możliwej wysokości, która na podstawie lematu 27.20wynosi co
najwyżej 21Vj. Również nasycająca operacja PUSH z wierzchołka u do wierz-
chołka v zwiększa tl>co najwyżej o 21VI, ponieważ wysokość żadnego wierz-
chołka się nie zmienia, a tylko wierzchołek v, którego wysokość jest nie więk­
sza niż 21VI,może stać się nadmiarowy. Na koniec zauważmy, że nienasycają­
ca operacja PUSH z u do v zmniejsza cl>co najwyżej o 1. Jest tak, ponieważ po
wykonaniu PUSH wierzchołek u nie jest dłużej nadmiarowy, a wierzchołek
v jest nadmiarowy, nawet jeśli wcześniej nie był, i h[v] - h[u] = -1.
Tak więc podczas wykonywania algorytmu łączna wartość, o jaką może
wzrosnąć cl>,jest nie większa niż 41V!2 (!VI + IEI), co wynika z wniosku 27.22
i lematu 27.23.

Jesteśmy już na etapie, w którym możemy dokonać analizy algorytmu GENE-



RIC-PREFLOW-PUSH, a stąd także każdego algorytmu pracującego z wykorzys-
taniem metody przed.przepływów.

TwIERDZENIE27.24.
Liczba podniesień (operacji LIFT) i przesłań (operacji PUSH)w schemacie GE-
NERIC-PREFLOW-PUSH wykonywanym dla dowolnej sieci G = (V, E) jest nie
większa niż O( V 2 E).

Dowoo
Natychmiastowy z wniosku 27.21 oraz lematów 27.22 i 27.23.

689
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

WNIOSEK27.25.
Schemat GENERIC-PREFLOW-PUSHmożna zaimplementować w taki sposób,
żeby działał w czasie O(V 2E) dla każdej sieci G = (V, E).

DOWÓD
Celem zadania 27.4-1 jest podanie implementacji algorytmu GENERIC-PREF-
LOW-PUSH,w której wykonanie operacji LIFT zabiera czas O(V), a wykonanie
operacji PUSH zabiera czas 0(1). Stąd natychmiast otrzymujemy nasz wniosek .


ZADANIA
27.4-1. Podaj implementację algorytmu GENERIC-PREFLOW-PUSHdziałającą
w czasie O(V 2E), w której wykonanie operacji LIFT zabiera czas O(V),
a wykonanie operacji PUSH zabiera czas 0(1).
27.4-2. Udowodnij, że w algorytm.ie GENERIC-PREFLOW-PUSH łączny czas
spędzany na wykonywaniu wszystkich O(V 2) operacji podnoszenia wynosi
tylko O( VE).
27.4-3. Załóżmy, że w sieci przepływowej G = (V, E) został znaleziony ma-
ksymalny przepływ za pomocą algorytmu GENERIC-PREFLOW-PUSH.Za-
proponuj szybki algorytm znajdowania minimalnego przekroju w sieci G.
27.4-4. Podaj efektywny algorytm przed.przepływów służą.cy do znajdowania
maksymalnego skojarzenia w grafach dwudzielnych. Przeanalizuj swój
algorytm.
27.4-5. Przypuśćmy, że przepustowości wszystkich krawędzi w sieci przepły­
wowej należą do zbioru {l, 2, ..., k}. Przeanalizuj czas działania algoryt-
mu GENERIC-PREFLOW-PUSHw zależności od V, E oraz k. (Wskazówka:
Ile razy nienasycająca operacja PUSH może być wykonywana na tej samej
krawędzi, zanim krawędź ta zostanie nasycona?)
27.4-6. Pokaż, że jeśli wiersz 7 w procedurze INJTIALIZE-PREFLOWzamieni-
my na
h[s1~ IV[GJI - 2
to algorytm GENERIC-PREFLOW-PUSHpozostaje poprawny, a jego asymp-
totyczny czas działania się nie zmieni.
27.4-7. Niech ó1 (u, v) będzie odległością (liczbą krawędzi) z wierzchołka u do
v w sieci residualnej Gf· Pokaż, że algorytm GENERIC-.PREFLOW-PUSH
zachowuje następujące własności: jeśli h[u] < IVI, to h[u].::;,;;ó1(u, t), i jeśli
h[u];. IVI, to h[u] - IVI <; b1 (u, s).
* 27.4-8. Podobnie jak w zadaniu poprzednim, niech ó1 (u, v) będzie odległością
między wierzchołkami u i v w sieci residualnej Gp Pokaż, w jaki sposób
można zmodyfikować algorytm GENERIC-PREFLOW-PUSH,żeby była za-
* 27.5. ALGORYTM „PODNIES I PRZESU/\1NA POCZĄTEK'"

chowywana następująca własność: jeśli h[u] < IVI,to h[u] = ó1 (u, t), i jeśli
h[u] ~ IVI, to h[u] - IVI = D1(u, s). W Twojej implementacji łączny czas
potrzebny do zachowania tej własności powinien wynosić O(VE).
27.4-9. Pokaż, że liczba nienasycających przesłań wykonywanych przez GE-
NERIC-PREFLOW-PUSHna sieci G = (V, E) wynosi co najwyżej 41Vl2 IEI
dla ]V] ;,4.

*27.5. Algorytm „podnieś i przesuń na początek"


W metodzie przed.przepływów operacje podstawowe (LIFT i PUSH) mogą być
wykonywane w dowolnej kolejności. Jednakże, wybierając uważnie kolejność
wykonywania operacji podstawowych i zarządzając efektywnie strukturą da-
nych reprezentującą sieć, problem maksymalnego pr7.epływu można rozwiązać
szybciej niż w czasie O(V 2 E) z wniosku 27 .25. W tym podrozdziale zbadamy
algorytm typu „podnieś i przesuń na początek", oparty na metodzie przed.-
przepływów, którego czas działania O(V3) jest asymptotycznie co najmniej tak
dobry jak O(V 2E).
N owy algorytm operuje na liście zawierającej wierzchołki sieci. Lista jest
przeglądana od początku w celu znalezienia wierzchołka nadmiarowego. Zna-
leziony wierzchołek nadmiarowy u jest następnie „rozładowywany", tzn. na
u są wykonywane operacje PUSH i LIFT tak długo, jak długo nadmiar w u jest
dodatni. Ilekroć wierzchołek zostaje podniesiony, jest on przesuwany na po-
czątek listy (stąd nazwa „podnieś i przesuń na początek"), a algorytm rozpo-
czyna przeglądanie listy od początku.
W dowodzie poprawności i analizie algorytmu „podnieś i przesuń na po-
czątek" wykorzystuje się pojęcie krawędzi „dopuszczalnych" - to jest tych
krawędzi w sieci residualnej, przez które można przesiać przepływ. Po udowo-
dnieniu pewnych własności sieci złożonych z krawędzi dopuszczalnych zapoz-
namy się z operacją rozładowywania, a następnie zaprezentujemy i przeanali-
zujemy sam algorytm „podnieś i przesuń na początek".

<rawędzie i sieci dopuszczalne


Jeśli G = (V, E) jest siecią przepływową o źródle s i ujściu t, f - przedprzep-
ływem w G, a h - funkcją wysokości, to o krawędzi (u, v) mówimy, że jest
krawędzią dopuszczalną, gdy c1 (u, v) > Oi h(u) = h(v) + l. W przeciwnym razie
(u, v) jest niedopuszczalna. Siecią dopuszczalną nazywamy sieć G1,h = (V, E1,h),
w której E 1. h jest zbiorem krawędzi dopuszczalnych.
Sieć dopus7.czalna składa się tylko z tych krawędzi, przez które można
przesiać przepływ. Z następującego lematu wynika, że sieć dopuszczalna jest
skierowanym grafem acyklicznym (dagiem).

691
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

LEMAT27.26. (Sieć dopu!aczalna jest acykliczna)


Jeśli G = (V, E) jest siecią przepływową, / - przed.przepływem w sieci G,
a h -funkcją wysokości na sieci G, to sieć dopuszczalna G1,,. = (V, E1 ,h) jest
acykliczna.

DOWÓD
Załóżmy przeciwnie i niech p = (v 6 , v1, ••• , v,1;),gdzie v0 = V,1; i k > O, będzie
cyklem w sieci G1, h· Ponieważ każda krawędź z p jest dopuszczalna, mamy
h(v 1~ 1} = h(v 1) + 1 dla i= 1, 2, ... , k. Sumując po cyklu, dostajemy
•Lh(v,_,)- •
L(h(v,) + I)
jo,1 /;1

-
•L h(v.l + k
i"' 1

Ponieważ każdy wierzchołek występuje dokładnie raz w każdej sumie, otrzy-


mujemy O = k - sprzeczność.

Z kolejnych dwóch lematów dowiadujemy się, w jaki sposób



operacje
PUSH i LIFf zmieniają sieć dopuszczalną.

LEMAT27.27.
Niech G = (V, E) będzie siecią przepływową,/- przed.przepływem w sieci G,
a h - funkcją wysokości. Jeśli wiem:holek u jest nadmiarowy, a (u, v) jest
krawędzią dopuszczalną, to do (u, v) stosuje się operacja PUSH. Operacja
PUSH(u, v) nie tworzy żadnej nowej krawędzi dopuszczalnej, ale może spowo-
dować, że (u, v) przestanie być dopuszczalna.

DOWÓD
Zgodnie z definicją krawędzi dopuszczalnej jest możliwe przesłanie przepływu
z u do v. Ponieważ u jest nadmiarowy, stosuje się do niego operacja PUSH(u, v).
Jedyną nową krawędzią residualną, która może powstać w wyniku przesłania
przepływu z u do v, jest krawędź (v, u). Ponieważ h(v) = h(u) - 1, kra-
wędź (v, u) nie może zostać krawędzią dopuszczalną. Jeśli operacja PUSH jest
nasycająca, to po jej wykonaniu c1 (u, v) = Oi (u, v) przestaje być dopuszczalna .


LEMAT27.28.
Niech G = (V, E) będzie siecią przepływową, f - przed.przepływem w sieci G,
a h - funkcją wysokości. Jeśli wierzchołek u jest nadmiarowy i żadna z krawę­
dzi wychodzących z u nie jest dopuszczalna, to do wierzchołka u stosuje się
operacja LIFT(u). Po wykonaniu operacji podniesienia LIFT co najmniej jedna

692
* 27.5. ALGORYTM „PODNIEŚ I PRZESUŃ NA POCZĄTEK"

z krawędzi wychodzących z wierzchołka u jest dopuszczalna, ale każda z kra-


wędzi wchodzących do u jest niedopuszczalna.

DOWÓD
Jeśli wierzchołek u jest nadmiarowy, to na mocy lematu 27.14 albo operacja
PUSH, albo operacja LIFT stosuje się do u. Jeśli wśród krawędzi wychodzących
z u nie ma krawędzi dopuszczalnych, to żaden przepływ nie może opuścić u,
a więc do u stosuje się operacja LIFI(u). Po wykonaniu tej operacji zachodzi
h[u]= 1 + min{h[vJ: (u, v)EE1}. A zatem, jeśli v jest wierzchołkiem, dla które-
go jest osiągane minimum w powyższym wyrażeniu, to krawędź (u, v} staje się
dopuszczalna. Stąd, po wykonaniu podniesienia, co najmniej jedna krawędź
wychodząca z u jest dopuszczalna.
Pokażemy teraz, że po wykonaniu podniesienia żadna z krawędzi wcho-
dzących do u nie może być dopuszczalna. Załóżmy przeciwnie, niech v będzie
wierzchołkiem, dla którego krawędź (v, u) jest dopuszczalna po podniesieniu.
Wtedy h[v] - h[u] + l i dlatego zachodzi h[v] > h[u] + l tuż przed wykona-
niem podniesienia. Ale z lematu 27 .13 wynika, że między wierzchołkami, któ-
rych wysokości różnią się o więcej niż 1, nie istnieją krawędzie residualne.
Ponadto podnoszenie wierzchołka nie zmienia sieci residualnej. Tak więc (v, u)
nie występuje w sieci residualnej i dlatego nie może występować w sieci dopusz-
czalnej - sprzeczność z założeniem.


Listy sąsiadów
W algorytmie „podnieś i przesuń na początek" są wykorLystywane listy sąsia­
dów. Dla danej sieci przepływowej G = (V, E} listą sąsiadów N[uJ, dla wierz-
chołka u E V, nazywamy jednokierunkową listę sąsiadów u w sieci G. Wierz-
chołek v występuje więc na liście N[u], jeśli (u, v)EE lub (v, u)EE. Pierwszy
wierzchołek na liście N[uJ jest wskazywany przez head[N[u]]. Wierzchołek z li-
sty występujący po v jest wskazywany przez next-neighbor[v].Jeśli v jest ostat-
nim wierzchołkiem na liście, to wskaźnik ten ma wartość NIL.
W algorytmie „podnieś i przesuń na początek" po każdej liście krążymy
cyklicznie. Porządek wierzchołków na liście jest dowolny, ale pozostaje jednak
niezmienny w trakcie działania algorytmu. Dla każdego wierzchołka u pole
current[u]wskazuje na aktualnie rozważany wierzchołek z listy N[u]. Począt­
kową wartością current[u]jest head[N[uJJ.

Rozładowywanie nadmiarowych wierzchołków

Rozładowywanie nadmiarowego wierzchołka u polega na przesłaniu


do wie-
rzchołków sąsiednich nadmiaru przepływu przez krawędzie dopuszczalne.

--------------------------~
693
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

W razie potrzeby w celu umożliwienia przekształcenia krawędzi wychodzących


z u w krawędzie dopuszczalne wierzchołek u jest podnoszony. Rozładowywa­
nie jest wykonywane za pomocą procedury DISCHARGE.

DISCHARGE(u)
1 while e[u] > O
2 do v +- current[u]
3 ifv=NIL
4 then LIIT(u)
5 current[u]+-head[N[u]]
6 elseif c1(u, v) > O i h[u] = h[v] + 1
7 then PUSH(u, v)
8 else current[u]+- next-neighbor[v]

Na rysunku 27.10 jest pokazanych kilka iteracji pętli while z wierszy 1-8,
która jest wykonywana dopóty, dopóki nadmiar przepływu w u jest dodatni.
W każdej iteracji jest wykonywana dokładnie jedna z trzech operacji, zależna
od aktualnie rozważanego wierzchołka v z listy sąsiadów N[u].
1. Jeśli v jest równe NIL, to została wyczerpana lista N[u]. W wierszu 4 wierz-
chołek u jest podnoszony, a potem w wierszu 5 wskaźnik current[u]jest
przesuwany na początek listy N[u]. (Lemat 27.29 mówi, że w tej sytuacji
operacja podniesienia LIFf stosuje się do u).
2. Je.śli v jest różny od NIL i (u, v) jest krawędzią dopuszczalną (co sprawdza się
w wierszu 6), to w wierszu 7 zostaje przesłany pewien (a być może cały)
nadmiar z u do v.
3. Jeśli v jest różny od NIL, ale krawędź (u, v) nie jest dopuszczalna, to w wier-
szu 8 wskaźnik current[u]jest przesuwany do następnego elementu na liś­
cie N[u].
Zauważmy, że jeżeli procedura DISCHARGE jest wywoływana dla nadmia-
rowego wierzchołka u, to ostatnią operacją wykonywaną przez DISCHARGE
musi być przesłanie przepływu z wierzchołka u. Dlaczego? Procedura kończy
swoje działanie tylko wtedy, gdy e{u] przyjmuje wartość O. Z drugiej strony, ani
operacja podnoszenia, ani przesuwanie wskaźnika current[u],nie wpływa na
wartość e[u].
Musimy być pewni, że kiedy w procedurze DISCHARGE jest wywoływana
procedura PUSH lub procedura LIFT, operacja ta jest stosowalna. W następ­
nym lemacie udowodnimy ten fakt.

LEMAT 27.29.
Jeśli w wierszu 7 procedury DISCHARGE jest wywoływana procedura PUSH, to
jest ona stosowalna do krawędzi (u, v). Jeśli w wierszu 4 procedury DISCHAR-

694
* 27.5. ALGORYTM „PODNIEŚ l PRZESUŃ NA POCZĄTEK"

GEjest wywoływana procedura LIFT, to operację podnoszenia można zastoso-


wać do wierzchołka u.

DOWÓD
Testy w wierszach 1 i 6 zapewniają, że operacja PUSl'I jest wykonywana tylko
wtedy, gdy jest stosowalna. To dowodzi pierwszej części lematu.
Żeby udowodnić drugą część lematu, wystarczy tylko pokazać, stosownie
do testu z wiersza I i lematu 27.28, że żadna z krawędzi wychodzących z u nie
jest dopuszczalna. Podczas kolejnych wywołań procedury D1SCHARGE(u)
wskaźnik current[u]przebiega po liście N[u]. Każde przeglądanie listy rozpo-
czyna się od jej pierwszego elementu i kończy, gdy current[u]= NIL. W tym
ostatnim wypadku wierzchołek u jest podnoszony, a wskaźnik current[u]zo-
staje przesunięty na początek listy i rozpoczyna się nowe przeglądanie listy.
Rozważmy jeden taki przebieg. żeby wskaźnik current[u]mógł przesunąć się
po liście do następnego wierzchołka po v, krawędź (u, v) musi zostać uznana za
niedopuszczalną w teście w wierszu 6. Tak więc po przejściu listy każda kra-
wędź wychodząca z u musiała być w tym przejściu uznana za niedopuszczalną.
Dlaczego? Z lematu 27.27 wiemy, że w wyniku wykonania operacji PUSH nie
może zostać utworzona krawędź dopuszczalna. Zatem jakakolwiek krawędź
dopuszczalna może zostać utworzona jedynie w wyniku wykonania operacji
podnoszenia. Ale wierzchołek u nie jest podnoszony podczas przechodzenia
listy N[u], a zgodnie z lematem 27.28 krawędzie wchodzące do ka7.dego innego
wierzchołka v podnoszonego w tym przejściu nie są dopuszczalne. Tak więc po
zakończeniu przebiegu wszystkie krawędzie wychodzące z wierzchołka u są
niedopuszczalne, co kończy dowód lematu.

Algorytm „podnieś i przesuń na początek"
Omawiany przez nas algorytm operuje na liście L zawierającej wszystkie wierz-
chołki z V - {s, t}. Wierzchołki na liście są uporządkowane topologicznie,
stosownie do bieżącej sieci dopuszczalnej. (Z lematu 27.26 wiemy, że sieć dopu-
szczalna jest dagiem).
W przedstawionym poniżej formalnym zapisie algorytmu „podnieś i prze-
suń na początek" (procedura LIFT-TO-FRONT) zakładamy, że dla wszystkich
wierzchołków u listy sąsiadów zostały już utworzone. Przyjmujemy także, że
next[u] wskazuje na wierzchołek występujący po u na liście [.,, Je7.eli u jest
ostatnim elementem na liście, to - jak zazwyczaj - next[u] = NIL.

LIFr-TO-FRONT(G, s, I)
1 INITIALIZE-PREFLOW(G,s)
2 L +- V[G] - {s, t}, w dowolnym porządku
------------------------"""
695
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

6
5 I 2 3 4
..
, ~.-- ..-·-··",.,....................
4 <ł'
(a) 3 X
'
X
'
X X
'
2 •

I

' ' '
o

6
5 5 6 7
4
."" '

'
(b) 3
2
X
• X


I
' '
o •."z·~
·.Q.

6
5 8 9
4
(c) 3 X
' '
X

2 :'t' •
I 8,i,
'
.z
o ił

Rys. 17.10. Rozładowywanie wierzchołka. Wysłanie całego nadmiaru przepływu z wierzchołka y jest
wykonywane w 15 iteracjach pętli wbile w procedurn: DISCHARGE.Na rysunku widać tylko sąsia­
dów y oraz krawędzie wychodzące i wchodzące do y. Liczba wewnątrz wierzchołka jesl jego
nadmiarem na początku pierwsn:j iteracji ilustrowanej w tym fragmencie, a każdy wierzchołek
majduje się na poziomie odpowiadającym jego wysokości w tej fazie algorytmu. Z prawej strony
mamy listy są.siadów N(y) pokazane na początku każdej iteracji. Numer danej iteracji majduje się
u góry. Zmienna current[y]wskazuje sąsiada y, który jest zacieniowany.(•) Początkowo wy znaj-
duje się 19 jednostek nedmiaru przepływu, które należy wyslaC z y, a cwrent[y] = s. Ponieważ
żadna z krawędzi wychodzących z y nie jest dopuszczalna, w iteracjach I, 2 i 3 wskażnik. c1,1rrent[y
tylko przesuwa się po liście i żadna inna akcja nie jest podejmowana. W iteracji 4 C11Trmt[y] = NlL
(co jest zaznaczone zacieniowanym kółkiem występującym za ostatnim elementem listy). Teraz
y zostaje podniesiony, a currenl[y]przesuwa się na początek listy. (h) Po podniesieniu wierzchołek
y ma wysokość l. W iteracjach 5 i 6 napotykamy krawędzie (y, s) i (y, x), które nie są dopuszcza].
ne, ale w kolejnej iteracji, 8 jednostek przepływu zostaje przesłanych z y do z. Ponieważ wstała
wykonana operacja Pum, wskażnik. CllrTenify]nie prn:suwa się po liście. (c) Ponieważ w iteracji
7 krawędź (y, z) została nasycona, w iteracji 8 zostaje wykryte, ie nie jest ona dłużej dopuszczalna.
W iteracji 9 cun-ent[y]= NIL i dlatego wierzchołek y jest ponownie podnoszony, a CllrT.tnt[y]prze.
suwa się na początek listy. (d) W iteracji 10 krawędź (y, s) nie jest dopuszczalna, ale za to 5 jedno-
stek przepływu zostaje prz.esłanych z y do x w iteracji 11. (e) Ponieważ current{y]nie został przem-

696
* 27.5. ALGORYTM „POONIES I PRZESUl'il NA POCZĄTEK"·

6
5
4
GR. IO
-----
II
_,
"!.v~ '
(d / J -, X

-
C
- la-_, - -
o
I CD''
• •
a;.

12 13 14

( C)
'
'
-

6
5
@ ------- )4)\'!.--·· {)
15
4
26
\,,-· '
(f) J
? '"' "
'I G) \ I
'
\)
~ •

6
5 @--___! l!,"14

4
(g)
-'
- l
I G)
u '
8

nięty w iteratji Il, w iteracji 12 zoslaje stwierdzone, ;i:eta krawędź nie jest dłużej dopuszczalna.
Podobnie w iteracji 13 stwierdza się, t.e (y, z) jest niedopuszczalna. W iteracji 14 y jest podnoszony,
a curre11t(y]przesuwa się na początek listy.(() W iteracji 15, 6 jednostek przepływu jest przesyła­
nych z y do s. (g) W wierzchołku y nie ma ju;i:nadmiaru przepływu i procedura DISCHAROE kończy
działanie. W tym przypadku zarówno na początku, jak i na końcu działanią procedury DISCHAROE
wskaźnik current wskazuje na początek listy. Tak nie musi być jednak w każdym przypadku

697
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

3 for każdy wierzchołek ue V[G] - {s, t}


4 do current[uJ+- head[N[u]]
5 u+- head[L]
6 wbile u "F NIL
7 do old-height+-h[u]
8 DISCHARGE(u)
9 if h [u]> old-height
10 then przesuń u na początek listy L
11 u+- next[u]

Algorytm LIFT-TO-FRONT działa następująco. W wierszu 1 przedprzepływ


i wysokości są inicjowane tak samo jak w algorytmie GENERIC-PREFLOW-
-PUSH. W wierszu 2 jest inicjowana lista L. Zawiera ona wszystkie możliwe
nadmiarowe wierzchołki ustawione w dowolnej kolejności. Po wykonaniu
wierszy 3-4 wskaźnik current[u]wskazuje na pierwszy element listy sąsiadów
N[u] dla każdego wierzchołka u.
W pętli while, w wierszach 6-11, przeglądamy listę Li rozładowujemy
wierzchołki (patrz rys. 27.11). Przechodzenie po liście rozpoczynamy od jej
pierwszego wierzchołka (wiersz 5). W każdej iteracji pętli while aktualnie roz-
ważany wierzchołek z listy L jest rozładowywany w wierszu 8. Jeśli u zostaje
podniesiony w wyniku wykonania DISCHARGE, to w wierszu 1Ojest przesuwa-
ny na początek listy. żeby stwierdzić, czy wierzchołek został podniesiony,
w wierszu 7 w zmiennej old-heightjest zapamiętywana wysokość wierzchołka u
przed rozładowywaniem, a następnie zapamiętana wysokość jest porównywa-
na z wysokością u po rozładowaniu (wiersz 9). W wierszu 11 jest przygotowy-
wana kolejna iteracja pętli white. Następnym badanym wierzchołkiem będzie
wierzchołek następny po u na liście L. Jeśli u został wcześniej przesunięty na
początek listy, to kolejnym przetwarzanym jest wierzchołek występujący po u
.
na noweJ pozyCJI.
..
żeby wykazać, że algorytm LIFT-TO-FRONT oblicza przepływ maksy-
malny, pokażemy, że jest on pewną implementacją algorytmu GENERIC-
-PREFLOW-PUSH. Po pierwsze zauważmy, że operacje PUSH i LIFr są wykony-
wane tylko wtedy, gdy są stosowalne. Wynika to z lematu 27.29, który
gwarantuje wykonywanie operacji PUSH i LIFr w procedurze DISCHARGE tył~
ko wtedy, gdy są one stosowalne. Wystarczy zatem pokazać, że po zakoń­
czeniu działania algorytmu LIFT-TO-FRONT nie można wykonać żadnej z pod-
stawowych operacji PUSH i LIFT. Zauważmy, że jeżeli wierzchołek u osiąga
koniec listy L, każdy wierzchołek z listy L musiał zostać rozładowany bez
podnoszenia. Z lematu 27.30, który wkrótce udowodnimy, wynika że wierz~
chałki na liście L są uporządkowane topologicznie w stosunku do bieżącej
sieci dopuszczalnej. Tak więc każda operacja PUSH powoduje przesłanie nad~
miaru przepływu do wierzchołka położonego bliżej końca listy (albo do s,

698
* 27.5. ALGORYTM „POONIE$ I PRZESUN NA POCZĄTEK"

albo do t). Dlatego, jeśli wskaźnik do wierzchołka u osiąga koniec listy, nad-
miar w każdym wierzchołku wynosi O i żadna operacja podstawowa nie jest
stosowalna.

LEMAT 27.30.
Niech G = (V, E) będzie siecią przepływową ze źródłem s i ujściem t. Na-
stępujący warunek jest niezmiennikiem pętli wbile w algorytmie LIFT-TO-
-FRONT wykonywanym dla sieci G: porządek wierzchołków na liście L jest
porządkiem topologicznym dla sieci dopuszczalnej Gr,;,= (V, Er,;,).

DOWÓD
Bezpośrednio po fazie inicjowania w wierszu 1 mamy h[s] = \VI i
h[v} = O
dla wszystkich vE V - {s}. Ponieważ IV]~ 2 (V zawiera co najmniej 2 wierz-
chołki: s i t), i.adna krawędź nie może być dopuszczalna. Tak więc Er,;,= 0
i każdy porządek wierzchołków z V - {s, t} jest porządkiem topologicznym
w sieci Gf,h·
Pokażemy teraz, że niezmiennik z lematu jest zachowywany w każdej itera-
cji pętli while. Z lematu 27.27 wiemy, że operacje PUSH mogą tylko spowodo-
wać, iż niektóre krawędzie przestaną być dopuszczalne. Nowe krawędzie dopu-
szczalne mogą powstać tylko w wyniku wykonania operacji podnoszenia. Z le-
matu 27.28 mamy, że po podniesieniu dowolnego wierzchołka u nie istnieją
krawędzie dopuszczalne wchodzące do u, ale mogą istnieć krawędzie dopusz-
czalne wychodzące z u. Tak. więc, przesuwając wierzchołek u na początek li-
sty L, mamy pewność, że każda krawędź wychodząca z wierzchołka u zacho-
wuje porządek topologiczny.

Analiza
Pokażemy teraz, że algorytm Livr-To--FRONT działa w czasie O(V ) dla każdej
3

sieci G = (V, E). Ponieważ omawiany algorytm jest implementacją algorytmu


GENERIC-PREFLOW-PUSH,możemy skorzystać z wniosku 27.21, który określa
ograniczenie O( V) na liczbę wykonywanych operacji podnoszenia dla jednego
wierzchołka. Łączna liczba operacji podnoszenia jest więc nie większa niż
O(V 2 ). Pozostawiamy jak.o zad. 27.4-2 wykazanie, że ograniczenie na łączny
czas spędzany na wykonywaniu operacji podnoszenia wynosi O(VE). Skorzys-
tamy także z lematu 27 .22 określającego ograniczenia na liczbę nasycających
operacji PusH.

TwIERDZENIE 27 .31.
Dla każdej sieci przepływowej G = (V, E) czas działania algorytmu LIFT-TO·
·FRONT wynosi O(V 3 ).

699
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

DOWÓD
Fazą w algorytmie LIFI'-TO-FRONT nazwijmy czas między kolejnymi dwiema
operacjami podnoszenia. Ponieważ może być co najwyżej O( V 2) operacji
podnoszenia, liczba faz wynosi co najwyżej O(V 2 }. W każdej fazie procedura
DISCHARGBjest wywoływana co najwyżej IV] razy. Uzasadnienie tego faktu
jest następujące. Jeśli w procedurze DISCHARGEnie wykonujemy podnoszenia,
to kolejne wywołanie tej procedury zachodzi dla wierzchołka bliższego końca
listy, a długość listy jest mniejsza od IVI.Jeśli w DISCHARGEjest wykonywane
podnoszenie, to następne wywołanie DISCHARGE odbywa się już w innej
fazie. Ponieważ w każdej fazie mamy co najwyżej !VI wywołań DISCHARGE,
a liczba faz wynosi co najwyżej IV]2 , łączna liczba wywołań DISCHARGE
w wierszu 8 algorytmu LIFT-TO-FRONT wynosi O(V 3 ). Tak więc łączna praca
wykonywana w pętli wbile w algorytmie LIFT-TO-FRONT, oprócz pracy wy-
konywanej we wszystkich wywołaniach procedury DISCHARGE, wynosi co
najwyżej O( V 3 ).
Pozostaje do oszacowania łączna praca wykonywana we wszystkich wy-
wołaniach DISCHARGE. W każdej iteracji pętli whilew procedurze DISCHARGE
wykonywana jest jedna z trzech operacji. Przeanalizujemy ilość pracy wykony-
waną przez każdą z tych operacji. Rozpoczynamy od operacji podnoszenia
(wiersze 4-5). Pozostawiamy jak.o zad. 27.4-2 pokazanie, że łączny czas wyko-
nania wszystkich O(V 2 ) operacji podnoszenia jest nie większy niż O(VE).
Rozważmy teraz operację z wiersza 8, polegającą na przesunięciu wskaź­
nika cu"ent[u]. Tę operację wykonujemy O(degree(u))razy między kolejnymi
podnoszeniami kłlmego wierzchołka u (gdzie degree(u) jest stopniem wierz-
chołka u). Wobec tego łączna liczba przesunięć wskaźnika cu"ent[u} wynosi
O(V·degree(u)). Z lematu o uściskach dłoni (zad. 5.4-1) wynika, że łączna
liczba przesunięć wskaźników na wszystkich listach sąsiadów wynosi O( VE).
Trzecim typem operacji wykonywanym przez DISCHARGBjest operacja
PUSH (wiersz 7). Wiemy już, że łączna liczba nasycających operacji PUSH wy-
nosi O(VE). Zauważmy, że ponieważ w wyniku wykonania nienasycającej ope~
racji PUSH nadmiar zostaje zredukowany do O, DISCHARGEkończy swoje dzia-
łanie bezpośrednio po wykonaniu nienasycającej operacji PUSH. Tak więc
w jednym wywołaniu DISCHARGE może zostać wykonana co najwyżej jedna
nienasycająca operacja PUSH. Jak. już zaobserwowaliśmy, DISCHARGEjest wy-
woływana O(V 3 ) razy i stąd łączny czas wykonywania nienasycających opera-
cji PUSH wynosi O( V3 ).
Czas działania algorytmu l.JFf-TO-FRONT wynosi zatem O(V 3 + VE), co
daje ograniczenie O(V 3). +
ZADANIA
27.S-1. Przedstaw działanie algorytmu LIFf~TO-FRONT dla sieci przepływowej
z rys. 27.la w taki sam sposób, jak to zrobiono na rys. 27.11. Przyjmij, że

700
PROBLEMY

początkowym uporządkowaniem wierzchołków na liście L jest (vi, v2,


v3, v4), a listy sąsiadów wyglądają następująco:

N[viJ = (s, v2, v3)


N[v:J= (s, Vi, v3, v4 )
N[vJ = (vi, v2, v4 , t)
N[vJ - (u,, v,, t)

* 27.5-2. Rozważmy implementację algorytmu przed.przepływów, w której wie-


rzchołki nadmiarowe są pamiętane w kolejce typu FIFO. W tej implemen-
tacji zawsze jest rozładowywany wierzchołek z czoła kolejki, a każdy wierz-
chołek, który w wyniku tego rozładowywania staje się nadmiarowy, jest
umieszczany na końcu kolejki. Po rozładowaniu wierzchołek z czoła kolejki
jest z niej usuwany. Algorytm kończy swoje działanie, gdy kolejka zostaje
opróżniona. Pokaż, że ten algorytm obliczania maksymalnego przepływu dzia-
ła w czasie O( V3 ).
27.S-3. Pokaż, że schemat algorytmu przed.przepływowego pozostaje popraw-
ny, jeśli procedura LIFT aktualizuje h[u], obliczając po prostu h[u] +-
+- h[u] + I. Jak ta zmiana wpływa na analizę czasu działania algorytmu
LIFT-TO-FRONT?
* 27.5-4. Pokaż, że jeśli zawsze jest rozładowywany najwyższy nadmiarowy wie-
rzchołek, to metodę przed.przepływów można zaimplementować tak, żeby
jej czas działania wynosił O(V 3 ).

Problemy
27-1. Problem ucieczki
Kratownicą n x n nazywamy graf nieskierowany składający się z n wierszy
i n kolumn wierzchołków, jak pokazano na rys. 27.12. Wierzchołek w i-tym
wierszu ij-tej kolumnie oznaczamy przez (i,J). Każdy wierzchołek kratownicy
ma czterech sąsiadów, z wyjątkiem wierzchołków brzegowych (i, J), dla któ-
rych i= 1, i= n,j= l lubj= n.
Problem ucieczki dla kratownicy definiuje się jak następuje: Na kratownicy
n x n danych jest m ~ n2 punktów początkowych. Należy stwierdzić, czy ist-
nieje m wierzchołkowo rozłącznych ścieżek prowadzących z punktów począt­
kowych do dowolnych m różnych punktów brzegowych. Na przykład dla kra-
townicy z rys. 27.12a problem ucieczki ma rozwiązanie, natomiast dla kratow~
nicy z rys. 27.12b rozwiązania nie ma.

701
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

6
L, y
5 X
'X
4 N,
• '
y X y
(,) 3
I
2
'I '
l
o
16

6
L, y
5
N,
X
'
(b)
4
3
I

y
'
X
X

y
1 16 I
2
z 'I '
I . g.. 10 t
o '7

6 S/\4
5
'
-N
L,
N,
y X
'
' X
4 I

(c) 3 "" X y y
7/16 I
2
' 'I
l 1
10
o

Rys. 27.11. Ilustracja działania LIFT-TO-FRONT. (a) Przepływ w sieci przed wykonaniem pierwszej
iteracji pętli wblle.Na początku 26 jednostek przepływu opuszcza żródlo s. Po prawej stronie jest
pokazana początkowa lista L = (x, y, z). Na poez\tkU u= x. Pod każdym wierzchołkiem z listy
L :znajduje się jego lista sąsiadów. Rozładowywany jest wier7.Chołek x. Wierzchołek x jest pod-
noszony na wysokość I; 5 jOOnostek nadmiaru przepływu jest przesyłanych do y, a 7 pozostałych
jednostek nadmiaru przepływu jest przesyłanych do ujścia. Ponieważ x został podniesiony jest więc
przesuwany na początek listy L, co w tym przypadku nie zmienia struktury listy. (b) Następnym
rozładowywanym wierzchołkiem z listy L jest y. Sposób rozładowywania y w takiej sytuatji jest
zilustrowany na rysunku 27.10. Wierzch.olek y, po podniesieniu, zostaje przesunięty na początek
listy L. (c) Następnym wierzchołkiem na liście L po y jest teraz x. Ponownie jest on rozłado­
wywany i 5 jednostek przepływu jest przesyłanych do 1. W tym wypadku x nie jest podnoszony,
nie zmienia on więc swojej pozycji na liście L. (d) Następnym wierzchołkiem po x na liście L jest
wierzchołek z; teraz on jest rozładowywany. Zostaje podniesiony na wysokość l i wszystkie 8 jed-
nostek nadmiaru zostaje przesianych dot. Wierzchołek z został podniesiony, jest on więc przesu-

702
PROBLEMY

6 ?,/\4
5 '
-20 L, y X
'
4 N,
• X ·x·
(d) J X y y
2 , 12/16
' '~ '
I o 7
IO t
o 8 12

6
, ~/\4

(<)
5
4
3
-00 L:
N· X

y
' "'
j
X
X

y
2 (
I
7 ' ',
12/16
o 8~

wany na początek listy L. (e) Teraz y występuje po z na liście L i jest rozładowywany. Ale
ponieważ y nie jest nadmiarowy, następuje natychmiastowy powrót z D1sCHARGE, a y nie zmienia
swojej pozycji na L. Następnie jest rozładowywany x. Ponieważ także nie ma nadmiaru, pozostaje
na tym samym miejscu na liście L. W ten sposób zostaje osiągnięty koniec listy i algorytm LIFT·
-To-FRONT kończy działanie. Nie ma już wierzchołków nadmiarowych i przedprrepływ _jestprze-
pływem maksymalnym

(a) Rozważ sieć przepływową, w której zarówno wierzchołki, jak i krawędzie


mają określone przepustowości. Oznacza to, że każdy dodatni przepływ na
wejściu do wierzchołka musi spełniać warunek przepustowości. Pokaż, że
problem znajdowania maksymalnego przepływu w sieci z przepustowościa­
mi zarówno na wierzchołkach, jak i na krawędziach można sprowadzić do
zwykłego problemu maksymalnego przepływu w sieci o porównywalnym
rozmiarze.
(b) Opisz efektywny algorytm rozwiązywania problemu ucieczki, a następnie
przeanalizuj jego czas działania.

27-2. Minimalne pokrycie ścieżkowe


Pokryciem ścieikowym grafu skierowanego G = (V, E) nazywamy dowolny
zbiór P wierzchołkowo rozłącznych ścieżek, taki że każdy wierzchołek z V na-
leży do dokładnie jednej ścieżki z P. Ścieżki mogą się zaczynać i kończyć
w dowolnym z wierzchołków, a ich długości też mogą być dowolne, nawet

703
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

(•) (b)

Rys. 27.12. Kratownice w problemie ucieczki. Czarne punkty są punk1ami początkowymi, pozostałe
wierzchołki kratownicy są białe. (•) Kratownica, dla któraj problem ucieczki ma rozwiązanie.
Zacieniowane ścieżki prowadzą z wierzchołków początkowych do brzegu kratownicy. (b) Kratow-
nica, dla której problem ucieczki nie ma rozwiązania

zerowe. Minimalnym pokryciem śdeżkowym grafu G nazywamy pokrycie ścież­


kowe zawierające najmniejszą mozliwą liczbę ścieżek.
(a) Podaj efektywny algorytm obliciania minimalnego pokrycia ścieżk.owego
acyklicinego grafu skierowanego G = (V, E). (Wskazówka: Przyjmując, że
V= {l, 2, ... , n}, zbuduj graf G' = (V', E'), w którym
V' = {xo,x 1, ••. , x"}U {yo,Y1, ... , Yn} ·
E' - {(x0 , x;J: ie V) u {(y,,y.): ie V) u {(x„ Yi): (i,J)eE)
i wykonaj dla niego algorytm obliczania maksymalnego przepływu).
(b) Czy Twój algorytm działa dla grafów skierowanych zawierających cykle?
Odpowiedź uzasadnij.

27-3. Eksperymenty kosmiczne


Profesor Spock jest konsultantem NASA. NASA planuje wiele wypraw kos-
micznych i musi zdecydować, jakie eksperymenty wykonywać i w jakie oprzy-
rządowanie wyposażyć statek kosmiczny w ciasie każdego lotu. Przy każdej
wyprawie NASA rozważ zbiór eksperymentów E = {E1, Ei, ..., E'"} oraz spon-
sora eksperymentu El' który zgodził się wpłacić do kasy NASA PJdolarów za
wynik.i eksperymentu. Do przeprowadzenia eksperymentów ze zbioru E są po-
trzebne urządzenia ze zbioru J = {11, 12, ••• , In}-Do wykonania eksperymentu EJ
są potrzebne wszystkie urządzenia ze zbioru RJ!,;: J. Koszt umieszczenia i trans-
portu urządzenia lk na statku kosmicznym wynosi ck dolarów. Zadaniem pro-
fesora Spocka jest znalezienie efektywnego algorytmu umożliwiającego okreś­
lenie eksperymentów, które należy wykonać, i urządzeń, które należy zabrać
na pokład statku kosmicznego, żeby zmaksymalizować zysk netto z jednego

704
PROBLEMY

lotu w kosmos (zysk ten jest różnicą między łącznymi wpływami za przeprowa-
dzenie eksperymentów, a łącznym kosztem umieszczenia i transportowania
wszystkich potrzebnych urządzeń).
Rozważmy następującą sieć G. Sieć ta zawiera wierzchołek źródłowy s,
wierzchołki / 1, / 2, ••• , In, wierzchołki Ei, Ei, ..., Em oraz wierzchołek-ujście t.
Dla k = 1, 2, ... , n istnieje krawędź (s, lk) o przepustowości c1c,a dla j =
= 1, 2, ... , m istnieje krawędź (E.J,t) o przepustowości Pp Jeśli dla k =
= 1, 2, ... , n i j = 1, 2, ... , m zachodzi /kE Rp to istnieje krawędź (lk, E) o nie-
skończonej przepustowości.

(a) Pokaż, że jeżeli E1 E T dla przekroju (S, n


w sieci G o skończonej przepus-
towości, to lk E T dla każdego !,:E R1.
(b) Pokaż, w jaki sposób wyznaczyć maksymalny zysk netto, znając minimal-
ny przekrój w sieci G i wartości Pr
(c) Podaj efektywny algorytm wyznaczania eksperymentów do wykonania
i niezbędne do ich przeprowadzenia urz.ądzenia. Przeanalizuj czas działania

algorytmu w zależności odm, n i r = L IR).
)"' 1

27-4. Aktualizowanie maksymalnego przepływu


Niech G = (V, E) będzie siecią przepływową o źródle w s, ujściu w t i cał­
kowitoliczbowych przepustowościach. Zalóimy, że mamy dany pewien maksy-
malny przepływ w sieci G.
(a) Przypuśćmy, że przepustowość pojedynczej krawędzi (u, v)EE zostaje
zwiększona o 1. Podaj algorytm aktualizowania maksymalnego przepływu
działający w czasie O(V + E).
(b) Przypuśćmy, że przepustowość pojedyncuj krawędzi (u, v)EE zostaje
zmniejszona o 1. Podaj algorytm aktualizowania maksymalnego przepły­
wu działający w czasie O(V + E).

27-5. Obliczanie maksymalnego przepływu za pomocą skalowania


Niech G = (V, E) będzie siecią przepływową o źródle w s, ujściu w t i cał­
kowitoliczbowej przepustowości c(u, v) na każdej krawędzi (u, v)EE. Niech
C = max(u,u)EE c(u, v).
(a) Uzasadnij, że przepustowość minimalnego przekroju w sieci G wynosi co
najwyżej CIEi.
(b) Pokaż, że dla danej liczby całkowitej K można w czasie O(E) znaleźć ścieżkę
powiększającą o przepustowości co najmniej K, o ile tak.a ścieżka istnieje.

Następująca metoda, która jest modyfikacją metody Forda-Fulkersona,


może zostać użyta do obliczania maksymalnego przepływu w sieci G.

705
ROZDZIAŁ 27. MAKSYMALNY PRZEPŁYW

MAX-FLOW-BY-SCALING(G, s, t)
l C +- max(u,tt)eE c(u, v)
2 zainicjuj przepływ f na O
3 K<+-2 L!11Cj
4 while K~ I
5 do while istnieje ścieżka powiększająca p o przepustowości co najmniej K
6 do powiększ przepływ f wzdłuż p
7 K-K/2
8 return/
(c) Uzasadnij, że MAx-FLOW-BY-SCALING zwraca maksymalny przepływ.
(d) Pokaż, że przepustowość residualna dowolnego minimalnego przekroju
w sieci G wynosi co najwyżej 2KIE! za każdym razem, kiedy jest wykony-
wany wiersz 4.
(e) Uzasadnij, że wewnętrzna pętla while w wierszach 5-6 jest wykonywana
O(E} razy dla każdej wartości K.
(f) Pokaż, że algorytm MAX-FLOW-BY-SCALING może zostać zaimplemento-
wany tak, żeby działał w czasie O(E 2 lg C).

27-6. Maksymalny przepływ z górnymi i dolnymi ograniczeniami pr.tepustowości


Przypuśćmy, że każda krawędź (u, v) w sieci przepływowej G = (V, E), oprócz
górnego ograniczenia c(u, v) na przepływ krawędziowy z wierzchołka u do v,
ma także dolne ograniczenie b(u, v). Omacza to, że każdy przepływ /w sieci
musi spełniać warunki b(u, v) ~f(u, v)::::;;
c(u, v). W takiej sieci może się zda-
rzyć, że nie istnieje żaden dopuszczalny przepływ.

(a) Udowodnij, że jeśli/ jest przepływem w sieci G, to 1/1<; c(S, T) - b(T, S)


dla każdego przekroju w sieci G.
(b) Udowodnij, że jeżeli w sieci istnieje maksymalny przepływ, to jego wartość
jest równa minimalnej wartości z c(S, T) - b<.,T,S) po wszystkich prze-
krojach (S, T) w sieci.
Niech G = (V, E) będzie siecią przepływową z funkcjami ci b wyznaczają­
cymi ograniczenia, odpowiednio górne i dolne, na przepływ na krawędziach.
Niech s i t będą źródłem i ujściem w sieci G. Skonstruuj zwykłą sieć prze-
pływową G' = (V', EJ z funkcją przepustowości c', źródłem s' i ujściem t',
jak następuje:
V'= Vu {s', t'}
E' - Eu {(s', v):vEV} u {(u, t'): u EV} u {(s, t),(t, s)}
Przepustowości krawędzi określamy w następujący sposób. Dla każdej krawę­
dzi (u, v)e E przyjmujemy c'(u, v) = c(u, v) - b(u, v). Dla każdego wierzchoł-

706
PROBLEMY

ka ue V przyjmujemy c'(s', u)= b(V, u) i c'(u, t') = b(u, V). Przyjmujemy także
c'(s, t) = c'(t, s) = oo.

(c) Udowodnij, że w sieci G istnieje przepływ dopuszczalny wtedy i tylko wte-


dy, gdy w sieci G' istnieje przepływ maksymalny taki, że wszystkie krawę­
dzie wchodzące do ujścia t' są nasycone.
(d) Podaj algorytm, który znajduje maksymalny przepływ w sieci z górnymi
i dolnymi ograniczeniami lub stwierdza, że przepływ dopuszczalny nie ist-
nieje. Przeanalizuj czas działania swojego algorytmu.

Uwagi do rozdziału
Książki Evena [65], Lawlera (132], Papadimitriou i Steiglitza [154] oraz Tarja-
na [188] są dobrym źródłem informacji na temat przepływów w sieciach i po-
krewnych algorytmów. Praca Goldberga, Tardos i Tarjana [83] zawiera szeroki
przegląd algorytmów dla problemów dotyczących przepływów w sieciach.
Metoda Forda-Fulkersona pochodzi od Forda i Fulkersona [71], którzy
jako pierwsi zbadali wiele problemów dotyczących przepływów sieciowych,
włączając w to problemy maksymalnego przepływu i skojarzenia w grafach
dwudzielnych. W wielu wczesnych implementacjach tej metody ścieżki powięk­
szające były znajdowane za pomocą przeszukiwania wszerz. Edmonds i Karp
udowodnili [63], że taka strategia znajdowania ścieżek prowadzi do algoryt-
mów wielomianowych. Pomysł przedprzeplywów pochodzi od Karzanova
[119]. Metoda przedprzeplywów opisana w tym rozdziale pochodzi od Gold-
berga [82]. Najszybszy obecnie algorytm działający z wykorzystaniem tej me-
tody pochodzi od Goldberga i Tarjana [85]. Jego czas działania wynosi
O(VElg(V 2/E)). Najlepszy znany teraz algorytm dla problemu maksymalnego
skojarzenia w grafach dwudzielnych został odkryty przez Hopcrofta i Karpa.
Jego czas działania wynosi O(J V E).
_______ Część VII

Wybrane
zagadnieni
----------------------------
Wprowadzenie
Część ta stanowi wybór zagadnień algorytmicznych, będący rozszerzeniem
i uzupełnieniem materiału przedstawionego wcześniej w tej książce. Wprowa-
dzimy tu nowe modele obliczeń, jak układy kombinacyjne czy obliczenia
równoległe. Zajmiemy się też wyspecjalizowanymi działami, takimi jak geo-
metria obliczeniowa lub teoria liczb. W dwóch ostatnich rozdziałach poruszy-
my kwestię niektórych ze znanych ograniczeń w projektowaniu efektywnych
algorytmów i wprowadzimy metody umożliwiające częściowe przezwyciężanie
tych ograniczeń.
W rozdziale 28 przedstawimy nasz pierwszy model obliczeń równoległych:
sieci porównujące. Z grubsza rzecz biorąc, sieć porównująca to algorytm,
w którym można wykonywać wiele porównań jednocześnie. W rozdziale tym
pokażemy, jak zbudować sieć porównującą sortującą n liczb w czasie O(lg 2 n).
W rozdziale 29 opiszemy inny model obliczeń równoległych: układy kom-
binacyjne. Pokażemy tam, że dwie n-hitowe liczby można dodać w czasie
O(lgn) za pomocą układu kombinacyjnego zwanego sumatorem równoległym.
Wyjaśnijmy także, jak pomnoiyć dwie n-bitowe liczby w czasie O(lg n).
W rozdziale 30 wprowadzimy ogólny model obliczeń równoległych, znany
pod nazwą PRAM. W rozdziale tym przedstawiamy podstawowe metody sto-
sowane przy konstruowaniu algorytmów równoległych, między innymi metodę
przeskakiwania, obliczenia prefiksowe i metodę cykli Eulera. Większość opisy-
wanych metod wyjaśniamy na przykładach prostych struktur danych, w tym
list i drzew. W rozdziale tym omówimy także ogólne zagadnienia związane
z obliczeniami równoległymi, takie jak pojęcie sekwencyjnej efektywności al-
gorytmu równoległego czy kwestię jednoczesnego dostępu do wspólnej pamię­
ci. Udowodnimy twierdzenie Brenta o efektywnym symulowaniu układu kom-
binacyjnego na maszynie równoległej. Rozdział zamkniemy opisem sekwencyj-
nie efektywnego algorytmu probabilistycznego dla problemu ustalania kolej-
----------
710
WPROWADZENIE

ności na liście oraz bardzo szybkiego deterministycznego algorytmu łamania


symetrii na liście.
W rozdziale 31 zajmiemy się efektywnymi algorytmami działającymi na
macierzach. Zaczniemy od algorytmu Strassena służącego do mnożenia dwóch
macierzy wymiaru n x n w czasie O(n 2 •81 ). Następnie przedstawimy dwie ogól-
ne metody - rozkłady LU i LUP - rozwiązywania układu równań liniowych
metodą eliminacji Gaussa w czasie O(n 3 ). Pokażemy też, że algorytmu Stras-
sena Il).Ożna użyć do szybszego rozwiązywania układów równań liniowych
i że (asymptotycznie) można równie szybko odwracać macierze, jak mnożyć.
Ro7..dział zakończymy pokazując, jak obliczać rozwiązanie przybliżone meto-
dą najmniejszych kwadratów, jeśli układ równań liniowych nie ma dokład-
• •
nego rozw1ązarua.
W rozdziale 32, dotyczącym operacji na wielomianach, pokażemy, że zna-
ną metodę przetwarzania sygnałów - szybkie przekształcenie Fouriera (FFT)
- można zastosować do pomnożenia dwóch wielomianów stopnia n w czasie
O(nlgn). Omówimy także efektywne implementacje FFT, w tym równoległy
układ arytmetyczny.
W rozdziale 33 przedstawimy kilka algorytmów dotyczących teorii liczb.
Dokonawszy przeglądu pojęć elementarnej teorii liczb, omówimy algorytm Eu-
klidesa obliczania największego wspólnego dzielnika. Następnie przedstawimy
algorytmy rozwiązywania modularnych równań liniowych i podnoszenia licz-
by do potęgi modulo inna liczba. W dalszej części rozdziału opiszemy inte-
resujące zastosowanie algorytmów dotyczących teorii liczb: kryptosystem
z kluczem jawnym RSA. Owego kryptosystemu można używać nie tylko do
szyfrowania wiadomości tak, by przeciwnik nie mógł ich odczytać, ale także do
składania podpisów cyfrowych. Dalej przedstawimy metodę Millera-Rabina
probabilistycznego sprawdzania, czy dana liczba jest pierwsza. Metodę tę moż­
na zastosować do efektywnego znajdowania dużych liczb pierwszych, stano-
wiącego podstawowy wymóg w systemie RSA. Na koniec opiszemy heurystykę
„ro" Pollarda, służącą do rozkładania liczb na czynniki, i omówimy aktualny
stan wiedzy na temat rozkładu liczb.
W rozdziale 34 zajmiemy się problemem znajdowania wszystkich wystą­
pień danego napisu zwanego wzorcem w drugim napisie zwanym tekstem. Pro-
blem ten często pojawia się w programach związanych z redagowaniem tek·
stów. Najpierw opiszemy eleganckie podejście do tego problemu, zapropono-
wane przez Rabina i Karpa. Następnie, po omówieniu efektywnego rozwiąza­
nia z zastosowaniem automatu skończonego, przedstawiamy algorytm Knut-
ha-Morrisa-Pratta, który swoją efektywność zawdzięC7.8. pomysłowemu wstęp­
nemu przetworzeniu wzorca. Rozdział zakończymy opisem heurystyki wyszu-
kiwania wzorca pochodzącej od Bayera i Moore'a.
Tematem rozdziału 35 jest geometria obliczeniowa. Po omówieniu pod-
stawowych obiektów i operacji w geometrii obliczeniowej pokażemy, jak z.a

711
CZĘ$C VII. WYBRANEZAGADNIENIA

pomocą metody „zamiatania" efektywnie rozstrzygać, czy dany zbiór odcin-


ków zawiera przecięcia. Dwa pomysłowe algorytmy znajdowania wypukłej
otoC'Zkizbioru punktów - algorytmy Grahama i Jarvisa - również ilustrują siłę
metody v.amiatania. Rozdział zakończymy omówieniem efektywnego algoryt-
mu znajdowania pary najmniej odległych punktów w danym zbiorze punktów
na płaszczyźnie.
Rozdział 36 dotyczy problemów NP-zupełnych. Do NP-zupełnych zalicza
się wiele interesujących problemów obliczeniowych, dla których nie są znane
algorytmy rozwiązujące je w czasie wielomianowym. W rozdziale tym przed-
stawimy metody dowodzenia NP-zupełności. Udowodnimy NP-zupełność kil-
ku klasycznych problemów: sprawdzania czy graf ma cykl Hamiltona, spraw-
dzania czy formula logiczna jest spełnialna i sprawdzania czy dany zbiór liczb
zawiera podzbiór, którego suma jest równa v.a.danej wartości. Udowodnimy
też, że słynny problem komiwojażera jest NP-zupełny.
W rozdziale 37 pokażemy, jak za pomocą algorytmów aproksymacyjnych
znajdować w sposób efektywny przybliżone rozwiązania problemów NP-zupeł­
nych. Dla niektórych problemów NP-zupełnych stosunkowo łatwo jest obli-
czyć rozwiązania przybliżone bliskie optymalnym, dla innych jednak nawet
najlepsze wane algorytmy aproksymacyjne sprawują się coraz gorzej w miarę
wzrostu ro2I11iaruproblemu. Są wreszcie i takie problemy, dla których kosztem
przedłużenia czasu obliczeń można uzyskiwać coraz lepsze rozwiązania przy-
bliżone. W rozdziale tym opiszemy owe możliwości na przykładzie problemu
pokrycia wierzchołkowego, problemu komiwojażera, problemu pokrycia zbio-
ru i problemu sumy podzbioru.
Rozdział 28

Siecisortujące

W części II rozważaliśmy algorytmy sortowania dla komputerów sekwencyj-


nych (maszyn ze swobodnym dostępem do pamięci RAM), które mogą w jed-
nej chwili wykonywać tylko jedną operację. W tym rozdiiale zajmiemy się
algorytmami sortowania dla modelu obliczeń opartego na sieciach porównują­
cych, w których może być wykonywanych jednocześnie wiele porównań.
Sieci porównujące różnią się od modelu RAM w dwóch ważnych aspek-
tach. Po pierwsze, wykorzystując sieci możemy wykonywać tylko porównania.
Dlatego algorytm taki jak sortowanie przez zliczanie (patrz podrozdz. 9.2) nie
może zostać zaimplementowany z wykorzystaniem sieci porównującej. Po dru-
gie, w przeciwieństwie do modelu RAM, w którym operacje są wykonywane
sekwencyjnie, stosując sieci porównujące, wiele operacji można wykonać w tej
samej chwili lub „równolegle". Jak się pI7.Ckonamy, ta właściwość umożliwia
posortowanie n liczb z wykorzystaniem sieci porównującej w czasie mniejszym
niż liniowy.
W podro:zdziale 28.1 :zdefiniujemy sieci porównujące i sortujące. Podamy
również naturalną definicję „czasu działania" sieci porównującej za pomocą
głębokości sieci. W podro:zdziale 282 udowodnimy „zasadę zero-jedynkową",
która znacznie ułatwia analizę poprawności sieci sortujących.
Skonstruujemy efektywną sieć sortującą, będącą w istocie równoległą wer-
sją algorytmu sortowania przez scalanie z podrozdz. 1.3.1. Będziemy ją two-
rzyć w trzech krokach. W podro:zdziale 28.3 opiszemy konstrukcję bitonicznej
sieci sortującej, która będzie jej podstawowym składnikiem. W podrozdziale
28.4 zmodyfikujemy nieco bitoniczną sieć sortującą, aby otrzymać sieć scalają­
cą, która scala dwa uporządkowane ciągi w jeden ciąg uporządkowany. Wresz-
cie w podro:zdziale 28.5 zbudujemy z sieci scalających sieć sortującą ciąg n war-
tości w czasie 00g 2 n).

713
ROZDZIAŁ 28. SIECI SORTUJĄCE

28.1. Sieciporównujące
Sieci sortujące są sieciami porównującymi, które zawsze sortują wartości na
wejściu. Rozpoczniemy więc naszą prezentację od sieci porównujących i ich
własności. Sieć porównująca składa się tylko z przewodów i komparatorów.
Komparator, pokazany na rys. 28.la, jest urządzeniem z dwoma wejściami
x i y oraz dwoma wyjściami x' i y', ,,obliczającym" następującą funkcję:

x' = min(x, y)
y' = max(x, y)

x -'---~1•--~
7

3
3
'- x'
7
=min(x,y)
y - '-----~-'--~~ y' = max(x,y)

(,) (b)

Rys. 28.1. {a) Komparator z wejściami x i y oraz wyjściami x' i y'. (b) Ten sam komparator
przedstawiony jako pionowy odcinek. Na wejściu komparatora znajdują. się wartości x = 1, y = 3,
a na wyjściu x' = 3, y' = 1

Graficzna reprezentacja komparatora na rys. 28.la jest dla naszych celów


zbyt obszerna, przyjmiemy więc konwencję przedstawiania komparatorów ja~
ko pojedynczych pionowych odcinków, takich jak na rys. 28,lb, Wejścia kom~
paratora znajdują się po lewej stronie, a wyjścia po prawej, przy czym mniejsza
wartość pojawia się na górnym przewodzie, a większa na dolnym. Pojedynczy
komparator „sortuje" więc ciąg składający się z dwóch liczb pojawiających się
• • ••
na Jego we.isc1u.
Będziemy zakładać, że każdy komparator działa w czasie 0(1). Mówiąc
inaczej, przyjmujemy, ie czas między podaniem wartości x i y na wejścia kom~
paratora a pojawieniem się wartości x' i y' na jego wyjściach jest stały.
W tym rozdziale będziemy przyjmować, że każda sieć porównująca zawie~
ran wejść a 1, a 2 , ... , an, na które są podawane wartości do posortowania, oraz
n wyjść b 1 , b2 , ..• , bn, z których odczytujemy wynik. Będziemy także mówić
o ciągu wejściowym (a 1 , a 2 , .•• , an) oraz ciągu wyjściowym (b 1 , b 2 , ••• , bn)
w odniesieniu do wartości na wejściu i wyjściu.
Na rysunku 28.2 jest przedstawiona sieć porównująca składająca się z kom"
paratorów połączonych za pomocą przewodów, Sieci porównujące o n wej-
ściach będziemy przedstawiać jako n poziomych linii z komparatorami w po~
staci pionowych odcinków. Należy zaznaczyć, że pojedyncza linia nie reprezen"
tuje jednego przewodu, lecz raczej ciąg przewodów łączących wiele komparato-
rów. Na przykład najwyższa linia na rys. 28.2 reprezentuje trzy przewody:
wejściowy a 1 łączący wejście z komparatorem A, przewód łączący górne wyj-

714
28.1. SIECI PORÓWNUJĄCE

ście komparatora A z wejściem komparatora C oraz przewód wyjściowy b 1


górnego wyjścia komparatora C. Wejścia każdego komparatora są połączone
z jednym z n wejść a 1 , a 2 , ... , a" całej sieci albo z wyjściem innego kom-
paratora. Podobnie wyjścia każdego komparatora są połączone z jednym
z n wyjść b 1 , b 2 , .•• , b" całej sieci albo z wejściem innego komparatora. Od
połączeń w sieci wymagamy, by ich graf był acykliczny: żadna ścieżka pro-
wadząca z wyjścia pewnego komparatora do wejścia innego nie może przejść
dwa razy przez ten sam komparator, wyjście komparatora nie może być
połączone bezpośrednio z jego wejściem itp. Dzięki temu możemy zawsze
przedstawić sieć porównującą tak jak na rys. 28.2 - z wejściami sieci po lewej
stronie i jej wyjściami po prawej stronie; dane „przepływają" w takiej sieci od
strony lewej do prawej.
Wartości wyjściowe pojawiają się na wyjściu komparatora dopiero wtedy,
gdy otrzyma on na swym wejściu obie wartości. Załóżmy na przykład, że na
wejściu sieci z rys. 28.2a pojawia się w chwili O ciąg (9, 5, 2, 6). Wówczas tylko
komparatory A i B mają ustalone wartości na swych wejściach. Przyjmując, że
obliczenie wartości wyjściowych komparatora trwa jednostkę czasu, wartości

,, 9 ,, 9
'
5 A C 5 9

2 E 2 2

6 B D
,, 6 6

Głębokość l 1
(a) (b)

,, 9 5 2 ,, ,, 9
' 2 2

2
9

2
6

5
5

2
9

2
6

5
'
6

,, 6 6 9 ,, 6 6 9 9

Głębokość I I 2 2 Głębokość I 1 2 2 3
(cl (d)

Rys. 28.2. (a) Sieć porównująca o 4 wajściach i 4 w}'jściach, która jest jednocześnie siecią sortują.cą.
W chwili O wypisane wartości znajdują się na wejściach. (b) W chwili I przetworzone dane wejś­
ciowe znajdują się na w}'jściach komparatorów A i B, które mają głębokość l w sieci. (c) W chwili
2 wartości majdują się na wyjściach bramek Ci D, mających glebokość 2 w sieci. Na wyjściach b 1
i b„ znajdują się już końcowe wartości, lecz na wyjściach b1 i b 3 jeszcze nic. (d) W chwili 3 wypisane
wartości znajdują się na wyjściu komparatora E. Teraz już i na wyjściach b1 i b 3 znajdują się
ostateczne wartości

715
ROZDZIAŁ 28. SIECI SORTUJĄCE

na wyjściach komparatorów A i B ustalają się w chwili I; odpowiednie wyniki


są pokazane na rys. 28.2b. Należy zaznaczyć, że wartości na wyjściach kom-
paratorów A i B pojawiają się jednocześnie lub „równolegle". W chwili 1 kom-
paratory C i D mają ustalone wartości na wejściach Oecz nadal nie ma ich
komparator E). W chwili 2 wyznaczają one wartości na swych wyjściach, jak
na rys. 28.2c. Komparatory C i D także działają równolegle. Górne wyjście
komparatora Coraz dolne wyjście komparatora D są podłączone odpowiednio
do wyjść b1 i b4 • Na tych dwóch wyjściach sieci końcowe wartości pojawiają się
więc już w chwili 2. W międzyczasie w chwili 2 „kompletuje" wartości na
swych wejściach komparator Ei w chwili 3 pojawiają się odpowiednie wartości
na jego wyjściach (patrz rys. 28.2d). Te wartości są więc też na wyjściach b2
i b 3 , co daje końcowy ciąg wyjściowy sieci (2, 5, 6, 9).
Przy powyższym założeniu, że wartości na wyjściach komparatora ustalają
się po upływie jednostki czasu, możemy zdefmiować „czas działania" sieci
porównującej, tzn. czas jaki upływa od podania wszystkich wartości na wej-
ściach do chwili, w której na wszystkich wyjściach ustalą się końcowe wartości.
Mówiąc nieformalnie, wielkość ta jest równa największej możliwej liczbie kom-
paratorów, przez które może „przejść" informacja wejściowa od pewnego wej-
ścia do wyjścia. Bardziej formalnie głębokość sieci zdefiniujemy następująco.
Wejście sieci ma głębokość O. Jeśli wejścia pewnego komparatora
mają głębokości dx i d.,, to wyjścia tego komparatora mają głębokość
max(dx, d.,) + l. Głębokości wejść i wyjść są dobrze zdefiniowane, ponieważ
komparatory są tak połączone, że w sieci nie występują cykle. Głębokość kom-
paratora zdefmiujemy jako głębokość jego wyjść. Na rysunku 28.2 są przed-
stawione głębokości komparatorów. Głębokość całej sieci porównującej defi-
niuje się jak.o największą głębokość wyjścia sieci lub, równoważnie, jako naj-
większą głebokość komparatora w sieci. Na przykład sieć na rys. 28.2 ma
głębokość 3, bo komparator E ma głębokość 3. Każdy komparator potrzebuje
jednostkowego czasu na ustalenie wartości na wyjściach. Jeśli wartości na wejś­
ciu sieci pojawią się w chwili O, to na wyjściach komparatora o głębokości
d wartości ustalą się w chwili d. Głębokość siecijest więc czasem, po którym na
wszystkich jej wyjściach ustalą się końcowe wartości.
Sieć sortująca jest siecią porównującą, której ciąg wyjściowy jest niemale-
jący (tm. b 1 ~ b 2 ~ ••• ~ bn) dla każdego ciągu wejściowego. Oczywiście nie
każda sieć porównująca jest siecią sortującą. Aby się przekonać, że sieć na
'
rys. 28.2 jest siecią sortującą, zauważmy, że w chwili 1 najmniejsza spośród
4 wartości wejściowych znajduje się albo na górnym wyjściu komparatora A,
albo na górym wyjściu komparatora B. W chwili 2 musi się ona znaleźć na
górnym wyjściu komparatora C. Podobnie największa z 4 wartości wejścio­
wych majduje się w chwili 2 na dolnym wyjściu komparatora D. Jedyne co
pozostaje dla komparatora E to zagwarantowanie, że dwie środkowe wartości
zostaną ułożone we właściwej kolejności, co odbywa się w chwili 3.

716
28.1. SIECI PORÓWNUJĄCE

Sieć porównująca jest podobna do procedury, która ustala kolejność wy-


konywanych porównań, lecz w przeciwieństwie do procedury jej fizyczny roz-
miar zależy od liczby wejść i wyjść. Dlatego też będziemy raczej opisywać
,,rodziny" sieci porównujących. Celem tego rozdziału jest na przykład zapro-
jektowanie rodziny SORTER złożonej z efektywnych sieci sortujących. Pojedyn-
cze egzemplarze sieci z rodziny sieci porównujących określamy za pomocą
nazwy rodziny oraz liczby wejść sieci (równej liczbie wyjść); na przykład sieć
o n wejściach i n wyjściach należącą do rodziny SORTER będziemy oznaczać
przez SORTER [n].

ZADANlA

28.1-1. Podaj wartości, jakie pojawiają sie na wszystkich wejściach i wyjściach


komparatorów sieci z rys. 28.2, jeśli na wejściu podamy ciąg <9, 6, 5, 2).
28.1-2. Niech n będzie dokładną potęgą 2. Pokaż, jak skonstruować sieć poró-
wnującą o n wejściach oraz n wyjściach i głębokości lg n, w której na
górnym wyjściu będzie pojawiać się wartość najmniejsza, a na dolnym
wyjściu - wartość największa dla dowolnego ciągu wejściowego.
28.1-3. Profesor Nielsen twierdzi, że jeśli dodamy gdziekolwiek komparator
do sieci sortującej, to sieć nadal będzie poprawnie sortowała ciągi wejś­
ciowe. Wykaż, Ze profesor nie ma racji, dodając komparator do sieci na
rys. 28.2 w tak.i sposób, że nowa sieć nie będzie poprawnie sortować wszys-
tkich permutacji.
28.1-4. Udowodnij, że każda sieć sortująca o n wejściach ma głębokość co
najmniej lg n.
28.1-5. Udowodnij, że liczba komparatorów w każdej sieci sortującej jest
!l(n lg n).
28.l-4'i. Udowodnij, że sieć porównująca na rys. 28.3 jest w istocie siecią sor-
tującą. Opisz związek jej struktury z algorytmem sortowania przez wsta-
wianie (patrz podrozdz. I. I).
28.1-7. Sieć sortującą o n wejściach składającą się z c komparatorów można
reprezentować jako ciąg c par liczb calk.owitych z przedziału od 1 do n.

a,--~~---~-~------
a,
b,
b,
a, b,
---h,
a, ----h,
a, _____ b,

a, ------h,
°'-------- -------- b,

Rys. 28.3. Sieć sortująca oparta na algorytm.ie sortowania przez wstawianie

717
ROZDZIAŁ 28. SIECI SORTUJĄCE

Jeżeli dwie pary zawierają wspólną liczbę, to kolejność odpowiednich


komparatorów w sieci ustalamy według kolejności par na liście, Zaprojek-
tuj algorytm (sekwencyjny) działający w czasie O(n + c), obliczający głę­
bokość sieci zadanej w powyższej reprezentacji.
28.1-8. Przypuśćmy, że oprócz zwykłych komparatorów możemy także uży­
wać komparatorów „odwróconych", w których na dolnym wyjściu poja-
wia się mniejsza, a na górnym większa z liczb wejściowych, Zaproponuj
metodę umożliwiającą przekształcenie dowolnej sieci sortującej składającej
się ze zwykłych oraz odwróconych komparatorów na sieć o takiej samej
liczbie komparatorów, ale bez komparatorów odwróconych. Wykaż, że
zaproponowana przez Ciebie metoda jest poprawna.

28.2. Zasadazero-jedynkowa
Zasada :zero-jedynkowa mówi, że jeśli sieć sortująca działa poprawnie dla wszy-
stkich ciągów składających się tylko z zer i jedynek, to poprawnie sortuje
wszystkie ciągi wartości. (W art ości mogą być liczbami całkowitymi, rzeczywi-
stymi lub należeć do dowolnego zbioru liniowo uporządkowanego), Dzięki
zasadzie zero-jedynkowej, konstruując sieci sortujące i inne sieci porównujące,
będziemy mogli się skupić na funkcjonowaniu tych sieci dla ciągów składają­
cych się tylko z wartości O albo 1. Jeśli skonstruujemy sieć sortującą i udowod-
nimy, że poprawnie sortuje wszystkie ciągi zero-jedynkowe, to wystarczy od-
wołać się do zasady zero-jedynkowej, aby ustalić poprawność tej sieci dla do-
wolnych ciągów.
Dowód zasady zero-jedynkowej opiera się na pojęciu funkcji niemalejącej
(monotonicznie rosnącej; patrz podrozdz. 2.2).

LEMAT28.1.
Jeśli sieć porównująca dla ciągu wejściowego a= (a 1, a 2 ,a,,) wyznacza ciąg
.•. ,
wyjściowy b = (b 1 , b 2 , ... , b,.), to dla dowolnej funkcji niemalejącej/ta sama
sieć z ciągiem f(a) = (f(a 1), f(a 2 ), ••• , f(a,J) na wejściu wyznacza ciąg wyjś­
ciowy f(b) - <f(b,), f(b,), ..., f(b.))

DOWÓD
Udowodnimy najpierw, że jeśli/jest funkcją niemalejącą, to dla wartościf(x)
i f(y) na wejściu pojedynczy komparator wyznacza na wyjściu wartości
f(min(x, y)) if(max(x, y)). Następnie posłużymy się indukcją w celu udowod-
nienia lematu.
Załóżmy, że na wejściu komparatora są liczby x i y. Na górnym wyjściu
komparatora pojawia się wartość min(x, y), a na dolnym -wartość max(x, y).
Niech teraz na wejściu komparatora będą liczby f(x) i f(y), tak jak na

718
28.2. ZASADA ZERO-JEDYNKOWA

rys, 28,4. Na górnym wyjściu pojawia się wówczas wartość min(f(x), f(y)),
a na dolnym - wartość max(f(x), f(y)). Funkcja f jest niemalejąca, więc
x ~ y pociąga za sobą f(x) ~f(y). W rezultacie prawdziwe są następujące
tożsamości:

min(f(x), f(y)) - f(min(x, y))

rnax(f(x), f(y)) - f(max(x, y))

Rys. 28.4. W)'tlik działania komparatora z dowodu lematu 28.L Funkcjajjest niemalej:µ:a

Stąd wynika, że jeśli na wejścia


komparatora będą podane wartościf(x) if(y),
to na wyjściach pojawią się odpowiednio: f(min(x, y)) i f(max(x, y)).
Użyjemy teraz indukcji względem głębokości każdego połączenia sieci po-
równującej w celu wykazania faktu mocniejszego niż teza lematu: przyjmijmy,
że na pewnym połączeniu pojawia się wartość a;, gdy na wejście sieci jest
podawany ciąg a, wówczas dla ciągu wejściowego f(a) na tym połączeniu poja-
wia się wartość f(a 1). Stwierdzenie to dotyczy także wyjść, jego dowód będzie
więc jednoC'.leśnie dowodem tezy lematu.
Początek indukcji jest trywialny: wejście sieci jest na głębokości O.Jeśli na
wejścia sieci jest podany ciąg f(a), to oznacza, że na i-tym wejściu jest wartość
f(aJ. Aby wykonać krok indukcyjny, rozwaimy komparator o głębokości
d ~ 1. Oznacza to, że wyjście komparatora ma głębokość d, wejścia tego kom-
paratora mają więc głębokość istotnie mniejszą niż d. Z założenia indukcyj-
nego wynika zatem, że jeśli na wejściach komparatora pojawiają się wartości a1
i aj dla ciągu wejściowego a, to dla ciągu f(a) na wejściu sieci na wejściach
komparatora pojawiają się wartości J(a 1) oraz f(aJ). Korzystając z wcześniej
wykazanego faktu, wnioskujemy, że na wyjściach tego komparatora pojawiają
się wartości f(min(a 1, aJ)) i f(max(a 1, aj)). Jeśli na wejście sieci jest podany
ciąg a, to na wyjściach tego komparatora pojawiają się wartości min(ai, ai)
i max(a 1, ai); lemat został więc udowodniony.

Przykład wykorzystania lematu 28,l jest pokazany na rys. 28.5, na którym
widać wynik zastosowania niemalejącej funkcjif(x) = fx/1] do ciągu wejścio­
wego i sieci sortującej z rys. 28.2. Wartość na każdym wejściu jest wynikiem
zastosowania funkcjifdo wartości z odpowiedniego wejścia na rys. 28.2.
Jeśli sieć porównująca jest siecią sortującą, to z lematu 28.1 wynika na-
stępujące ważne twierdzenie.

719
ROZDZIAŁ 28. S1ECJSORTUJĄCE

3 I I
"1
9
' 2 2
bi "1
' bi

., ' 9 6
' b, ., 3
' 3 3 b,
6 I I 3 3
a, 2 2
' b, a, b,

a, 6 6

(•)
9 9 b, a, 3 3

(b)
' ' b,

Rys. 28.5. (a) Sieć sortująca z rys. 28.2 z ciągiem (9, S, 2, 6) na wejściu.. (b) Ta sama sieć po
r
zastosowaniu funkcji niemalejącej /(x) = x/11do liczb na wejściu. Wartość na kairlym wejściu
jest wynik.iem mstosowania funkcji f do wartości na odpowiednim wejściu w części (a)

TwIERDZENIE28.1. (Zasada zero-jedynkowa)


Jeśli sieć porównująca o n wejściach poprawnie sortuje wszystkie 2n ciągi zer
i jedynek, to sortuje poprawnie dowolne ciągi liczb.

DOWÓD
Załóżmy przeciwnie, że sieć sortuje poprawnie wszystkie ciągi zero-jedynkowe,
ale istnieje pewien ciąg liczb, dla którego nie działa właściwie. Mówiąc inaczej,
istnieje ciąg wejściowy (a 1 , a2 , ••• , an) zawierający elementy a1 oraz aj takie, że
a; < aj, ale w ciągu wyjściowym sieci a1 znajduje się przed a1• Zdefiniujmy
niemalejącą funkcję/ następująco:

o, jeśli x ~ a;
f(x) ={
1, jeśli x > a1
Jeśli ciągiem wejściowym sieci jest (a 1 , a2 , ... , an), to aJ znajduje się w ciągu
wyjściowym przed a1, z lematu 28.1 wynika więc, że jeśli na wejściu sieci znaj-
duje się ciąg (f(a 1),f(a 2), ... ,f(a,;J), to wtedy w ciągu wyjściowymf(a1 ) będzie
przed/(a 1
). Stanowi to jednak sprzeczność z faktem, że sieć poprawnie sortuje
ciąg zero-jedyokowy (f(a 1),f(a 2 ), •••,f(a,)), ponieważf(a1) = I, af(a 1) = O.

ZADANIA
28.2-1. Udowodnij, że w wyniku zastosowania funkcji niemalejącej do ciągu
posortowanego otrzymamy ciąg posortowany.
28.2-2, Udowodnij, że sieć porównująca poprawnie sortuje n-elementowy ciąg
(n, n - 1, ... , 1) wtedy i tylko wtedy, gdy poprawnie sortuje wszystkie
n - 1 ciągów zero-jedynkowych (1, O, O, ..., O, O), (I, I, O, ... , O, O), ...,
(I, 1, I, ... , I, O).
28.2-3. Użyj zasady zero-jedynkowej do wykazania, że sieć porównująca
przedstawiona na rys. 28.6 jest siecią sortującą.

720
28.3. BITONICZNA SIEĆ SORTUJĄCA

28.2-4. Sformułuj i udowodnij odpowiednik zasady zero-jedynkowej dla mo-


delu drzew decyzyjnych. (Wskazówka: Zadbaj o właściwe potraktowanie
równości).

Rys. 28.6. Sieć sortująca dla ciągów 4-clementowych

28.2-5. Udowodnij, że sieć sortująca o n wejściach musi zawierać co najmniej


jeden komparator między i-tą a (i+ 1)-szą linią dla i= 1, 2, ... , n - 1.

--- ....·-·--· --------------·-·-" ----------


28.3. Bitonicznasieć sortująca

Pierwszym krokiem podczas konstruowania sieci sortującej będzie zaprojek-


towanie sieci porównującej, która sortuje wszystkie ciągi bitoniczne,czyli ciągi,
które albo najpierw są nierosnące, a potem niemalejące, albo najpierw niemale-
jące, a potem nierosnące. Ciągi (1, 4, 6, 8, 3, 2) oraz (9, 8, 3, 2, 4, 6) są
bitoniczne. Zero-jedynkowe ciągi bitoniczne mają bardzo prostą postać: albo
Qil 10" albo JiQit", dla pewnych i, j, k ~ O. Oczywiście ciąg niemalejący lub
nierosnący jest także bitoniczny.
Bitoniczna sieć sortująca, którą zbudujemy, będzie siecią porównującą,
sortującą bitoniczne ciągi zer i jedynek. Zadanie 28.3-6 polega na wykazaniu,
że ta sieć poprawnie sortuje bitoniczne ciągi o dowolnych wartościach.

Sieć pó/czyszcząca

Na sieć sortującą ciągi bitoniczne składa się wiele połączonych szeregowo sieci
pólczyszczącycb. Każda sieć półczyszcząca ma głębokość 1; i-te wejście jest
połączone za pomocą komparatora z wejściem i+ n/2 dla i= l, 2, ... , n/2
(zakładamy, i.e n jest parzyste). Na rysunku 28.7 widać sieć pólczyszczącą
HALF-CLEANER[8] o 8 wejściach i 8 wyjściach.
Jeśli bitoniczny ciąg zer i jedynek jest podawany na wejście sieci półczysz­
czącej, to na jej wyjściu w górnej połowie znajdują się mniejsze wartości, w dol-
nej większe, a obie połowy są bitoniczne. W istocie jedna z nich jest wtedy
oczyszczona - czyli składa się z samych tylko zer lub samych jedynek - stąd
nazwa sieć półczyszcząca. (Pamiętajmy, że ciągi oczyszczone są bitoniczne).
Powyższe własności sieci pólczyszczących zostały sformułowane w następują­
cym lemacie.
______ ________________________
,,,_, _
721
ROZDZIAŁ 28. SIECI SORTUJĄCE

~
o
o
o
o
o Jl o-
o
o ig
I o Jl ;;, I I
i
I
!
o iil 8 [ I o
I
I I
I ~ I I ~s ~

I~
~
I
o o ~ iil I I
o I
·a
o I I ~ ;;,
o I ·"
"' o I
iil 8
Rys. 28.7. Sieć porównująca HALF-C.EANER{S]. Są tu pokazane dwa różne ciągi wejściowe i wyjś­
ciowe. Zakładamy, że na wejściu sieci jest ciąg bitonicmy. Wtedy na wyjściu sieci półczyszczącej
każdy element w górnej połowie jest nie większy ni:!:każdy element w dolnej połowie. Co więcej,
obie polowy są bi toniczne i co najmniej jedna z nich jest oczyszczona

LEMAT28.3.
Jeśli na wejście sieci półczyszczącej jest podany bitoniczny ciąg zer i jedynek, to
ciąg wyjściowy ma następujące własności: obie połowy - górna i dolna - są
bitoniczne, każdy element w górnej połowie jest nie większy niż dowolny ele-
ment w dolnej połowie oraz co najmniej jedna połowa jest oczyszczona.

DOWÓD
W sieci porównującej HALF-CLEANER[n] są porównywane wartości na wej-
ściach o numerach i oraz i+ n/2 dla i = 1, 2, ... , n/2. Bez straty ogólności
możemy założyć, że ciąg wejściowy jest postaci 00 ... 011 ... 100 ... O. (Sytuacja,
w której ciąg wejściowy jest postaci 11 ... 100 ... 011 ... 1 jest symetryczna).
Możliwe są trzy przypadki, w zależności od tego, w który ciąg zer lub jedynek
„trafia" punkt n/2, a jeden z nich (ten, w którym punkt środkowy przypada
w bloku jedynek) rozbija się na dwa kolejne osobne przypadki. Wszystkie
cztery sytuacje są pokazane na rys. 28.8. W każdej z nich są spełnione tezy
lematu.

Bitoniczna sieć sortująca
Składając sieci półczyszczące rekurencyjnie, tak jak na rys. 28.9, otrzymujemy
sieć sortującą ciągi bitoniczne. Najpierw w skład sieci BITONIC-SORTER{n]
wchodzi sieć HALF-CLEANER [n], na której wyjściu, zgodnie z lematem 28.2,
pojawiają się dwa ciągi bitoniczne o dwukrotnie mniejszej długości, takie że
każdy element w górnej połowie sieci jest nie większy niż dowolny element w jej
dolnej połowie (patrz rys. 28.9). Wystarczy więc użyć dwóch kopii sieci BITO-
NIC-SORTER [n/2], aby rekurencyjnie posortować obie połowy ciągu wejścio­
wego. Na rysunku 28.9a rekurencja została ukazana w sposób jawny, a na

722
28.3. BITONICZNA SIEĆ SORTUJĄCA

Podział Porównanie Złożenie


'I \
ro Góra
,---,
Góra

1
-,, -
fil? o r
\ Bitoniczny
oczysx.czony
Bitoniczny ~ ., "m".. o """'""'li•• I o I o ...........11,,- '
o
'~ lJ Dół
Dół
\ l.~~j {a)

r io Góra Góra o t{ Bitonicmy


..,,.
'
I oI
~

' ·1

~
,,
,. ' ..........
.,1,,,. )
Bitonicmy ' .. ..,••""•li"'
..v•~•· I ,,......,..,11,,-
;
"
1
o
I ;1 ( Bitoniczny
Dół Dół oczyszcmny
\ L()! (b) '

r-i Góra
·-11
0
: ;, Bitonicmy
I j
o
Bitonicmy .) ....
1
II
......,...11,,
..
o Li~ ol
LoJ ~I
,,,,
.....,...... '
I
mmmmjl•••
__ J'
1011
I oczy&zczony

[i] > Bitonicmy


i, o Dół

(::-)
Dół
Lo.J)
--, \

(i ~j Góra I I;, s· .
1tomczny
I
' '
,--~ ,--1
I P.'a °
,_,
·1 1 oczyu.czony
W
' '

Bitoniczny \ ·· ""'"'.. .,......,.!I"" ' m '"' "' ul!1>• o' "'"'"'"''li••· ' )
o 1
' o LoJ 1 ! Bitonicmy
Dół Dól
\ __J .."1)
(d)

Rys. 28.8. Możliwe porównania w sieci HALF-CLEANER[n].O ciągu wejściowym zakładamy, że jest
bitonicznym ciągiem zer i jedynek. Bez straty ogólności możemy założyć, że jest on postaci 00 ...
011 ... 100 ... O.Podciągi zer są białe, a podciągi składające się z jedynek szare. Wejścia są pcxlzielo-
ne na polowy, tak że dla i= I, 2, ... , n/2 wejścia o numerze i oraz i+ n/2 zostają porównane.
(a)-{b) Przypadki, w których połowa przypada w ciągu jedynek. (c)-(tl) Przypadki, w których
połowa przypada w ciągu zer. We wszystkich przypadkach każdy element w górnej połowie jest nie
większy niż każdy element w dolnej połowie, obie polowy są bitonicme oraz co najmniej jedna
połowa jest oczyszczona

723
ROZDZIAŁ 28. SIECI SORTUJĄCE

rys. 28.9b - została „rozwinięta" i widać, że bitonicma sieć sortująca składa


się z szeregu coraz mniejszych sieci p6łczyszczącycb. Głębokość D(n) sieci BI·
TONIC-SORTER[n] wyraża się za pomocą następującej zależności rekurencyjnej:

dla n=l
D(n) - {~(n/2) +l dla n=21; oraz k~ 1

której rozwiązaniem jest funkcja D(n) = lgn.

- o o o o
-
-
' " '
-· .
' S0,,'${"'2]
·~
~ ~

au
o
I
o
o
o
o
o
o ~

~
ffALp.
' ' ,; '

·-o I
o o o •
o
-
'
ĆJJWa{A]
'

''
'
' '
' ,,.,
'

' ..'
d

-- o
·.. 1
I
o
o
I
"..
~
o

·~~
- '
'' ·'"
' ,,<~,·,,, I
- ' ' " ' I -
0/.IJ o .t ... ' I
- ..,, ,' ' f ,, '
' '
o "'' I
-
' I
(,) (b)

Rys. 28.9. Sieć porównująca BITONIC-SORTER.{111zilustrowana tutaj dla 11 = 8. (1.) Konstrukcja


rekurencyjna: sieć HALF-CiEANER [11]połączona z dwoma równoległymi kopiami sieci BITONIC-
-SORTER [11/2].(b) Sieć po rozwinięciu rekurencji. Każda składowa HALF-Cl.HANERzostała
zacieniowana

Wynika stąd, że bitoniczny ciąg zero-jedynkowy można posortować za


pomocą sieci BITONIC-SORTER o głębokości lg n. Z faktu analogicmego do
zasady zero-jedynkowej (patrz zad. 28.3-6) wynika, że za pomocą tej siecimoż­
na posortować dowolny ciąg bitoniczny.
ZADANIA
28.3-1. Ile jest bitonicznych ciągów zero-jedynkowych?
28.3-2. Wykaż, że jeśli n jest dokładną potęgą 2, to sieć BITONIC-SORTER[n
zawiera 0(nlgn) komparatorów.
28.3-3. Opisz, jak skonstruować sieć o głębokości O(lgn) sortującą ciągi bito-
niczne, jeśli liczba wejść n nie jest dok.ładną potęgą 2.
28.3-4. Wykaż, że jeśli na wejściu sieci półczyszczącej jest dowolny ciąg bito-
niczny, to ciąg wyjściowy ma następujące własności: obie połowy - górna
i dolna - są bitoniczne oraz każdy element w górnej połowie jest nie więk­
szy niż dowolny element w dolnej połowie.
28.3-S. Niech dane będą dwa ciągi zer i jedynek. Udowodnij, że jeśli kaidy
element jednego z ciągów jest nie mniejszy niż dowolny element drugiego,
to jeden z ciągów jest oczyszczony.

724
28.4. SIEĆ SCALAJĄCA

28.3-6. Udowodnij następujący odpowiednik zasady zero-jedynkowej dla bito-


nicznych sieci sortujących: jeśli sieć sortuje dowolny bitoniczny ciąg zero-
-jedynkowy, to poprawnie sortuje dowolny ciąg bitoniczny.

28.4. Sieć scalająca

Nasza sieć sortująca będzie się składać z siecisclllających, które służą do scalania
dwóch posortowanych ciągów w jeden posortowany ciąg wyjściowy. Sieć MER"
GER [n] uzyskamy jak.o modyfikację sieci BITONIC-SORTER[n]. Podobnie jak
w przypadku bi tonicznej sieci sortującej, udowodnimy poprawność sieci scalają­
cej tylko dla ciągów zero-jedynkowych. W zadaniu 28.4-1 należy pokazać, jak
można rozszerzyć ten dowód na przypadek ciągów dowolnych wartości.
Konstrukcja sieci scalającej jest oparta na następującym intuicyjnym rozu-
mowaniu. Jeśli dla danych dwóch posortowanych ciągów odwrócimy porządek
w drugim ciągu, a następnie połączymy oba ciągi, to w wyniku otrzymamy ciąg
bitoniczny. Na przykład dla danych posortowanych ciągów zero-jedynkowych
X= 00000111 oraz Y = 00001111, po odwróceniu Y (YR = 11I 10000) łączymy
X z yx, otrzymując ciąg bitoniczny 0000011111110000. Aby scalić ciągi wej-
ściowe X i Y, wystarczy teraz wykonać sortowanie bitoniczne na połączonych
ciągach X i yR.
SiećMERGER[n] można skonstruować, modyfikując pierwszą sieć półczy­
szczącą w sieci BITONIC-SORTER[nlPomysł polega na niejawnym odwróceniu
drugiej polowy ciągu wejściowego. Dla danych posortowanych ciągów (a 1 , a2 ,
..., a„12) oraz (a„12+ 1 , a„12 + 2 , .•• , a,.), które chcemy scalić, wystarczy nam
wynik bitonicznego posortowania ciągu (a 1 , a2 , .•• , a„12, a,., a,,_ 1 , ••• , a„12 + 1 ).

a, o
o
o
o
,,
,,
>, a, o -
_j)
o b,
o ,, ·a~ >,

I
I
o
o
,,
b,
I iil
>,

.~
a,
a,
a,...l
I o
o
,,
b, -"'
o
••
,,
a,
o
o
I
I
'• I -g a, ...l
iil a, o o
I
'•
,,
,, -
>,
ij
••o
o o b, a, o I o
o
I I ·"
'• "' a, o I ,, iil
(,) (b)

Rys. 28.10. Porównanie pierwszego poziomu sieci MERGER[n]oraz sieci HALl'-CLEANERfnJ. (a) Na
pierwszym poziomie w sieci MERGER[n]z dwóch monotonicznych ciągów (a 1 , a2 , ... , a. 12 ) oraz
(a. 12+ 1, a012 + 2 , •.. , a.) powstają dwa ciągi bitoniczne (bi, h 2 , •••, h. 12) oraz (h. 12 + 1, h.12 + 2, ••. , h~>·
(b) Równoważna operacja w sieci HALf-Cl.EANER[n]. Z ciągu bitonicznego (a 1, a,, ..., a011 , a,,,
a._ 1, •.• , a. 12 + 1) powstają dwa ciągi bitoniczne (b 1, b 2 , •••, b012 ) oraz (b., h._ 1, ••• , h. 12+ 1)

725
ROZDZIAŁ 28. SIECI SORTUJĄCE

Pierwsza sieć półczyszcząca w sieci BITONIC-SORTER[n] porównuje wejścia


i z n/2 + i dla i= I, 2, ... , n/2, wobec tego w sieci scalającej odpowiedni frag-
ment sieci porównuje wejścia o numerach i oraz n - i+ 1 (patrz rys. 28.10).
W tym nowym rozwiązaniu kryje się pewna subtelność: dolna połowa ciągu
wychodzącego z pierwszej fazy sieci scalającej jest odwrócona w stosunku do
wyjścia ze zwykłej sieci pólczyszczącej. Wystarczy jednak zauważyć, że w wy-
niku odwrócenia ciągu bitonicznego otrzymamy znowu ciąg bitoniczny, obie
połowy można więc następnie posortować bitonicznie, bo spełniają one włas­
ności z lematu 28.3.

~ o o o
·~ •o
t:
o o
I
o
-#121
.. ~ I > "'
o
>
>
h'" ••
> > '"·
> > > . '
o
o. I o
~ I
',',!{,;;' ,, ,.•,• >
~ o
. ; ·;

> > >

>
' '' I
·Bm\)Nr(;.i.
'. I
.,
'
·~
o
t:o I I
I I
> •o I
>
I I
I
o.
1,1 (b)

Rys. 28.11. Sieć scalająca dwa posortowane ciągi wejściowe w jeden posortowany ciąg wyjściowy.
Sieć MEROEll[n]różni się od sieci BITONIC-SoRTBR[n] tylko tym, że zamiast pierwszego fragmentu
HALF·CLEAN'ER[n] porównuje wejścia i z n - i+ I dla i= I, 2, ... , n/2. Tutaj n= 8. (a) Sieć roz.
łożona na pierwszy poziomporównań, po którejnastępują dwie równoległe kopie sieci BrroNic-
[n/2]. (b) Ta samasieć z rozwiniętą
-SoRTER rekurencją.Kolejnepoziomy zostały za.cieniowane
Przy połączeniach znapują się przykładowe wartości liczbowe

W wylliku otrzymujemy sieć scalającą jak na rys. 28.I 1. Sieć MERGER{n]


różni się od sieci BITONIC-SORTER[n]tylko pierwszym poziomem. Stąd głębo­
kość sieci MERGER(n]jest równa lgn.

ZADANIA
28.4-1. Udowodnij odpowiednik zasady zero~jedynkowej dla sieci scalających.
Wykaż w szczególności, że jeśli sieć porównująca poprawnie scala dowolne
dwa niemalejące ciągi zero-jedynkowe, to działa poprawnie dla ciągów
niemalejących o dowolnych wartościach.
28.4-2. Ile różnych wejściowych ciągów zero-jedynkowych trzeba użyć, aby
sprawdzić, czy sieć porównująca jest siecią scalającą.
28.4-3. Wykaż, że każda sieć scalająca jeden element z ciągiem n - 1 elemen~
to wym musi mieć głębokość co najmniej lg n.
* 28.4-4. Rozważ sieć scalającą z wejściami a 1 , a2 , ••• , am gdzie n jest dokładną
potęgą 2, w której dwa ciągi rosnące przeznaczone do scalenia to (a 1 , a 3 ,

726
28.5. SIEĆ SORTUJĄCA

... , a"_ 1 ) i (a 2 , a 4 , ... , an>· Udowodnij, że liczba komparatorów w tego


typu sieci jest .Q(nlgn). Dlaczego to dolne ograniczenie jest interesujące?
(Wskaz6wka: Podziel komparatory na trzy zbiory).
* 28.4-5. Udowodnij, że każda sieć scalająca, niezależnie od kolejności wejść,
zawiera .Q(nlgn) komparatorów.

28.5. Sieć sortująca

Zebraliśmy już wszystkie elementy wystarczające do skonstruowania sieci sor-


tującej dowolny ciąg wartości. W skład sieci SORTER[n]wchodzi sieć scalająca,
będąca w istocie równoległym odpowiednikiem algorytmu sortowania przez
scalanie z podrozdz. 1.3.1. Konstrukcja i działanie tej sieci są przedstawione
na rys. 28.12.
Na rysunku 28.12a widać rekurencyjną strukturę sieci SORTER[n]. Ciąg
n wartości na wejściu zostaje podzielony na połowy, które zostają posortowane
rekurencyjnie (i równolegle) za pomocą dwóch kopii sieci SORTER[n/2]. Owa
posortowane ciągi są następnie scalone przez sieć MERGER[n]. Przypadkiem

..
• MBR0BR[2J
- ~ -- ~
SORTBR{n/2] MERGER(4J
. .. ~

. ..
-jMERoP.R[2Jl.
- ~
MBlOBR{11] MERGf!R[8]
. .
_,,,.,]
~ ~
Ml!RQER.{21
- ~ . ~
MERGER(41
- ~ ~

I a,
""""""' (hl

o [I
o
Io
)

o I o o
I I
o
I I
o o
I
o ,__p
.. [I

o I - o
[I
o _o I
o I I I
o --. . . . I .• .. I
Głębokość I 2 2 3 4444556
(<}

Rys. 28.12, Sieć SoRTER[n] złożona rekurencyjnie z sieci scalających. (a) Konstrukcja rekurencyjna.
(b) Rozwinięcie rekurencji. (c) Sytuacja po zastąpieDlu pudelek scalających odpowiednimi sieciami
scalającymi. Zamaczana jest głębokość każdego komparatora oraz przykładowe wartości

727
ROZDZIAŁ 28. SIECI SORTUJĄCE

granicznym dla rekursji jest sytuacja, w której n = I, czyli trzeba posortować


ciąg o długości I. Ciąg taki jest oczywiście już posortowany. Na rysunku
28.12b widać wynik rozwinięcia rekursji, a na rys. 28.12c - całą sieć powstałą
przez zastąpienie „pudelek" przez właściwe sieci scalające.
Dane przepływają przez lg n po.ziomów sieci S0RTER(n], Na każdym
z wejść sieci jest już posortowany ciąg o długości 1. Pierwszy po.ziom sieci
S0RTER[n] składa się z n/2 kopii sieci MERGER[2], które równolegle scalają
1-elementowe ciągi, wyznaczając posortowane ciągi o długości 2. N a drugim
poziomie, składającym się z n/4 kopii sieci MERGER[4], są równolegle scalane
2-elementowe ciągi i wyznaczane posortowane ciągi o długości 4. Ogólnie, dla
k = 1, 2, ... , lgn, po.ziom k składa się z n/2" kopii sieci MERGER[2ł], które
równolegle scalają 2"- 1 -elementowe ciągi, wymaczając posortowane ciągi
o długości 2t. Na ostatnim poziomie powstaje jeden posortowany ciąg, składa­
jący się z wartości wejściowych. Można przez indukcję wykazać, 7.eta sieć
poprawnie sortuje ciągi zero-jedynkowe, więc przez odwołanie się do zasady
zero-jedynkowej (twierdzenie 28,2) wiemy, że sortuje ciągi dowolnych wartości.
Głębokość powyższej sieci sortującej można wyrazić rekurencyjnie. Niech
D(n) oznacza głębokość sieci SORTER[n].Jest ona równa sumie D(n/2) (są dwie
kopie sieci SORTER[n/2], lecz działają one równolegle) oraz głębokości sieci
MERGER[n] równej lgn. Głębokość sieci SORTBR[n/2]wyraża się więc za po-
mocą następującej zależności rekurencyjnej:

o dla n= 1
D(n)-
{ D(n/2) + lgn dla n=2" oraz k;;,:1

której rozwiązaniem jest D(n) = E>(lg2n). W ten sposób pokazaliśmy, jak sor-
tować n liczb równolegle w czasie O(lg 2 n).

ZADANIA
28.5-1. Ile jest komparatorów w sieci SORTER[n]?
28.S-2. Wykaż, że głębokość sieci SORTER[n] jest równa dokładnie (lgn)
Ogn + I)/2.
28.S-3. Załóżmy, że mamy do dyspozycji zmodyfikowany komparator, na któ-
rego wejście są podawane dwa posortowane ciągi o długości k. Zostają one
scalone, po czym większe k elementów zostaje skierowane do wyjścia
,,max", a pozostałe do wyjścia „min" zmodyfikowanego komparatora.
Wykaż, że każda sieć sortująca o n wejściach, w której zastąpiono zwykłe
komparatory powyższymi 2JDodyfikowanymi komparatorami, poprawnie
sortuje ciągi nk liczb, jeśli składają się one z posortowanych podciągów
o długości k.
28.5-4. Chcemy podzielić 2n elementów (a 1 , a2 , a 2 ,,) na dwie równe części
.•• ,
tak, aby największe z nich znalazły się w jednej, a pozostałe w drugiej.
7~2
8 ______________________
7
_
PROBLEMY

Wykaż, że po wcześniejszym posortowaniu ciągów (a 1 , a2 , ••• , a,,) i (a,,+ 1 ,


a,,+2 , ... , a 2 ,,) można wykonać ten podział za pomocą sieci o stałej głę­
bokości.
* 28.S-5. Niech S(k) będzie głębokością sieci sortującej o k wejściach, a M(k)
głębokością sieci scalającej o 2k wejściach. Przypuśćmy, że mamy ciąg
n liczb do posortowania oraz wiemy, że każda liczba jest oddalona co
najwyżej o k od swojej pozycji w ciągu posortowanym. Wykaż, że można
posortować tych n liczb za pomocą sieci o głębokości S(k) + 2M(k).
* 28.5-6. Elementy macierzy m x m można posortować, powtarzając k razy na-
stępującą procedurę:

1. Posortuj każdy nieparzysty wiersz niemalejąco.


2. Posortuj każdy parzysty wiersz nierosnąco.
3. Posortuj każdą kolumnę niemalejąco.

Ile powtórzeń k potrzeba do posortowania tablicy oraz jak należy


odczytywać posortowany ciąg?

Problemy
28-1. Sieci sortujące przez transpozycje
Sieć porównująca jest siecią transpozycyjną, jeśli każdy komparator łączy są­
siednie linie, tak jak na rys. 28.3.
(a) Wykaż, że każda sortująca sieć transpozycyjna o n wejściach ma O(n 2 )
komparatorów.
(b) Udowodnij, że sieć transpozycyjna o n wejściach jest siecią sortującą wtedy
i tylko wtedy, gdy poprawnie sortuje ciąg (n, n - 1, ... , 1). (Wskazówka:
Użyj indukcji, podobnie jak w dowodzie lematu 28.l).

Sieć sortująca typu odd-even o n wejściach (a 1 , a2 ,


a,,) składa się z n po-
.•. ,
ziomów komparatorów. Na rysunku 28.13 znajduje się sieć transpozycyjna
typu odd-even o 8 wejściach. Jak widać na rysunku, dla i= 2, 3, ... , n - 1 oraz
d= I, 2, ... , n linia i jest połączona za pomocą komparatora o głębokości
dz linią}= i+ ( -1) 1 +",jeśli tylko 1 ~}~ n.

(c) Udowodnij, że rodzina sieci typu odd-even składa się rzeczywiście z sieci
sortujących.

28-2. Sieć scalająca Batchera


W podrozdziale 28.4 opisaliśmy sieć scalającą opartą na sortowaniu bitonicz-
nym. Zajmiemy się teraz konstrukcją sieci scalającej typu odd-eveo. Przyjmijmy,
-------- ..-----------------------=
729
ROZDZIAŁ 28. SIECI SORTUJĄCE

b,
b,

- --
~ ~

b,

-
-- ---
-- - - b,
b,
- b,
b,
b,

Rys. 28.13. Sieć lypu odd-even o 8 wejściach

że n jest dokładną potęgą 2 oraz że chcemy scalić posortowane elementy w li-


niach (a 1, a 2 , ... , a,.) z posortowanym ciągiem w liniach (a,.+ 1 , a,.+2 , •.. , a 2,.).
Skonstruujemy rekurencyjnie dwie sieci scalające typu odd-even, które równo-
legle scalają posortowane podciągi. Pierwsza z nich scala ciąg wejściowy (a 1 ,
a3 , •.• , a,._1 ) z ciągiem wejściowym (a,.+ 1 , a,.+3 , ..• , a 2,,_ 1 ) (numery nieparzy-
te). Druga scala ciąg (a 2 , a 4 , ••• , a,.) z ciągiem (a,.+ 2 , a,.+4 , ••• , a 2 ,.) (numery
parzyste). Aby odpowiednio połączyć dwa posortowane podciągi, wstawiamy
komparator między linie 2i i 2i + 1 dla i = 1, 2, ..., n - 1.

(a) Narysuj sieć scalającą o 2n wejściach dla n = 4.


(b) Użyj zasady zero-jedynkowej, aby wykazać, że sieć scalająca typu odd-
-even o 2n wejściach jest rzeczywiście siecią scalającą.
(c) Jaka jest głębokość sieci scalającej typu odd-even o 2n wejściach?

28-3. Sieci permutacyjne


Sieć permutacyjnao n wejściach i n wyjściach składa się z przełączników, umożli­
wiających połączenie jej wejścia z wyjściami, zgodnie z każdą z n! permutacji. Na
rysunku 28.14a widać sieć permutacyjną P 2 o 2 wejściach i 2 wyjściach, składają­
cą się z pojedynczego przełącznika, który albo przesyła wartości na wejściu
bezpośrednio do odpowiadających wyjść, albo zamienia wcześniej ich kolejność.

(a) Wykaż, że jeśli zastąpimy każdy komparator w sieci sortującej przełącz-


nikiem z rys. 28.14a, to uzyskamy sieć permutacyjną. Odpowiednio usta-
wiając przełączniki w takiej sieci, można więc dla dowolnej permutacji n:,
uzyskać połączenie i-tego wejścia z wyjściem o numerze n:(r).

Na rysunku 28.14b jest pokazana rekurencyjna konstrukcja sieci permuta-


cyjnej P 8 o 8 wejściach i 8 wyjściach, złożonej z dwóch kopii sieci P 4 oraz
8 przełączników, Przełączniki zostały tak ustawione, że sieć realizuje permuta-
cję n:= (4, 7, 3, 5, 1, 6, 8, 2), co wymusza (rekurencyjnie), aby górna kopia P 4
realizowała permutację (4, 2, 3, I), a dolna permutację (2, 3, 1, 4).

730
PROBLEMY

P,
7r(l)=4 r, I
7r(2);7 2

n(3)"'3 3

7r(4)"'5 4
r,
n(5)= I s
7r(6)=6 6

7r(7)=8 7

7r(8)=2 8

(,) (b)

Rys. 28.14. Sieci permutacyjne. (a) Sieć permutacyjna P2 składająca się z jednego przełącznika, który
może znajdować się w jednym z pokazanych stanów. (b) Rekurencyjna konstrukcja Pa z 8 prze-
łącZDlków oraz dwóch kopii P4 • Pokazane przełączniki oraz sieci P„ są. w ustawieniu wyznaczają­
cym permutację n= (4, 7, 3, 5, 1, 6, 8, 2)

(b) Pokaż, jak zrealizować permutację (5, 3, 4, 6, 1, 8, 2, 7) na sieci P8 ,


zaznaczając odpowiednie ustawienia przełączników, oraz permutacje wy·
znaczane przez 2 kopie sieci P 4 •

Niech n będzie dokładną potęgą 2. Można rekurencyjnie zdefmiować sieć


Pnjako odpowiednie połączenie dwóch kopii sieci Pn/Z•w sposób podobny do
powyższej konstrukcji P 8 •

(c) Zaprojektuj algorytm (na zwykłą maszynę RAM) działający w czasie O(n),
który ustawia n przełączników podłączonych do wejść i wyjść sieci Pn oraz
wyznacza permutacje, które muszą realizować obie kopie sieci P"12, aby
całość realizowała zadaną permutację n elementów. lJdowodnij popraw·
ność swojego algorytmu.
(d) Jaka jest głębokość i rozmiar sieci P"? Ile czasu zajmuje obliczenie na
maszynie RAM ustawień wszystkich przełączników wraz z przełącznikami
znajdującymi się wewnątrz obu egzemplarzy sieci Pn/Z?
(e) Wykaż, że dla n> 2 każda sieć permutacyjna o n wejściach - nie tylko
P, - realizuje pewną permutację za pomocą dwóch różnych ustawień prze·
łączników.

731
ROZDZIAŁ 28. SIECI SORTUJĄCE

Uwagido rozdziału

W książce Knutha [123] można znaleźć szczegółowe omówienie sieci sortują­


cych oraz ich historię. Po raz pierwszy badali je P.N. Armstrong, R.J. Nelson
i D.J. O'Connor w 1965 r. We wczesnych latach sześćdziesiątych K.E. Batcher
odkrył sieć scalającą dwa ciągi uporządkowane długości n w czasie O(lgn). Jest
to sieć scalająca metodą „odd-even". Batcher pokazał również, jak za pomocą
tej metody posortować n liczb w czasie 00g 2 n}. Wkrótce potem Batcher od-
krył sieć sortującą ciągi bitoniczne, podobną do sieci opisanej w podrodz. 28.3.
K.nuth przypisuje zasadę zero-jedynkową W.G. Bouriciusowi (1954), który
udowodnił jej odpowiednik dla modelu drzew decyzyjnych.
Przez długi czas pozostawało otwartym pytanie, czy istnieje sieć sortująca
o głębokości O(lgn). W 1983 r. Ajtai, Komlós i Szemerćdi [8) wykazali istnienie
takiej sieci sortującej, składającej się z O(nlgn) komparatorów. Wynik ten ma
jednak tylko znaczenie teoretyczne, ponieważ stałe ukryte w notacji O przy
oszacowaniu. ro:zmiaru są ogromne (rzędu wielu tysięcy).
Rozdział 29

Układy arytmetyczne

W modelu obliczeń odpowiadającym zwykłemu komputerowi opieramy się na


założeniu, że podstawowe działania arytmetyczne, takie jak dodawanie, odej-
mowanie, mnożenie czy dzielenie, zajmują jednostkę czasu. Takie założenie jest
dość rozsądne, ponieważ większość elementarnych operacji na maszynie ze
swobodnym dostępem do pamięci ma podobne koszty. Gdy jednak przychodzi
do zaprojektowania układów, które realizują te operacje, przekonujemy się, że
szybkość ich działania istotnie zależy od wielkości liczb, na których operujemy.
Wszyscy nauczyliśmy się jeszcze w szkole podstawowej, jak dodawać dwie
n-cyfrowe liczby dziesiętne w E>(n) krokach (choć nauczyciel z pewnością nie
przywiązywał większej wagi do szacowania wymaganej liczby kroków).
W tym rozdziale przedstawimy układy, które służą do wykonywania ob-
liczeń arytmetycmych. Najlepszy czas, jakiego możemy się spodziewać od sek-
wencyjnego algorytmu dodawania dwóch liczb n-cyfrowych, wynosi E>(n). Za
pomocą układów działających równolegle można to zrobić szybciej. Zaprojek-
tujemy tutaj układy, które szybko wykonują dodawanie i mnożenie. (Odej-
mowanie jest w rzeczywistości tym samym co dodawanie, a dzielenie jest
przedmiotem problemu 29-1). Będziemy zakładać, że na wejście naszych ukła­
dów będą podawane n-bitowe liczby naturalne zapisane binarnie.
W podrozdziale 29.1 wprowadzimy pojęcie układu kombinacyjnego.
Pokażemy, w jaki sposób głębokość układu odpowiada jego „czasowi działa­
nia". Jako pierwszy przykład układu zaprezentujemy sumator pełny, który
będzie składnikiem większości pozostałych układów omawianych w tym roz-
dziale. W podrozdziale 29.2 przedstawimy dwa układy służące do dodawania
liczb: sumator szeregowy, działający w czasie 9(n), oraz sumator równoległy,
którego czas działania wynosi zaledwie O(lgn). Wyjaśnimy tak.że, jak działa
sumator z zapamiętywaniem przeniesień, który umożliwia zredukowanie prob-
lemu zsumowania trzech liczb do problemu dodania 2 liczb w czasie E>(l).

733
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

W podrozdziale 29.3 omówimy dwa układy mnożące: tablicowy, działający


w czasie @(n), oraz drzewiasty Wallace'a, mnożący w czasie 9(lg n). Wreszcie
w podrozdziale 29.4 przedstawimy układy z taktowaną pamięcią (rejestrami)
oraz pokażemy, jak oszczędzić na liczbie układów, używając ich do wielu ce-
lów jednocześnie.

29.1. Układy kombinacyjne


Podobnie jak sieci porównujące z rozdz. 28, układy kombinacyjne działają
równolegle: w jednym kroku wiele „procesorów" może jednocześnie wykony-
wać obliczenia. W tym podrozdziale zdefiniujemy układy kombinacyjne oraz
pokażemy, jak z elementarnych układów (bramek) budować większe układy.

Elementarne układy kombinacyjne (bramki logiczne)


Układy arytmetyczne w prawdziwych komputerach są budowane z elementów
połączonych przewodami. Elementarny układ kombinacyjny jest elementem
układu o stałej liczbie wejść i stałej liczbie wyjść, obliczającym dobrze określo­
ną funkcję. Niektóre elementy rozważane w tym rozdziale będą bramkami lo-
gicznymi, których wartości wejściowe i wyjściowe należą do zbioru {O, 1}, gdzie
O oznacza wartość FAł.SZ (FALSE), a 1 wartość PRAWDA (TRUE).
Na rysunku 29.1 są pokazane cztery podstawowe bramki logiczne, z któ-
rych będziemy w tym rozdziale składać większe układy: bramka NOT (negac-
ja), bramka AND (logiczne „i"), bramka OR (logiczne „lub") oraz bramka
XOR (,,wykluczające lub"). (Znajdują się tam także dwie inne bramki logiczne:
bramka NAND i bramka NOR, które pojawią się w niektórych zadaniach). Na
wyjściu bramki NOT pojawia się wartość z przeciwna do wartości x, podanej
na wejście. Pozostałe trzy bramki mają dwa wejścia x i y oraz jedno wyjście z.
Funkcję oblicz.aną przez każdą bramkę można przedstawić za pomocą
tablicy wartości, jak na rys. 29.1. W tablicy są podane wartości pojawiające się
na wyjściu bramki dla dowolnych wartości na wejściach. Na przykład z tablicy
dla bramki XOR można odczytać, że jeśli na jej wejściu znajdują się wartości
x = O i y = 1, to na wyjściu będzie wartość z = 1. Będziemy używać symbo-
li: -, na oznaczenie funkcji NOT, A - funkcji AND, v - funkcji OR,
a EB- funkcji XOR. Na przykład: OEB1 = 1.
Bramki w prawdziwych układach nie reagują natychmiast. Dopiero gdy
wartości na wejściach bramki się ustalą (tzn. są stałe przez pewien czas), możemy
mieć gwarancję, że po pewnym określonym czasie wartości na wyjściu bramki
będą stałe i zgodne z obliczoną przez nią funkcją. Ten czas potrzebny na ustalenie
wartości na wyjściu bramki nazywa się jej czasem propagacji. Będziemy zakładać,
że wszystkie bramki rozpatrywane w tym rozdziale mają stały czas propagacji.

734
29.1. UKŁADY KOMBINACYJNE

X ~x X y X< X y xvy
o I o o o o o o
I o o I o o I I
I o o I o I
I I I I I I

(•) (b) (c)

X X

y ' y

X y x<lly X y -,(X AJ) X y -,(X V y)


o o o o o 1 o o I
o I I o I 1 o I o
I o I 1 o I I o o
I I o 1 1 o I I o
(d) (o) en
Rys. 29.1, Sześć podstawowych bramek logicznych. Pod każdą z bramek znajduje się tabelka opisują­
ca działanie bramki. (a) Bramka NOT. (b) Bramka AND. (c) Bramka OR. (d) Bramka XOR.
(e) Bramka NAND (NOT-AND). (f) Bramka NOR (NOT-OR)

Układy kombinacyjne
Układ składa się z jednej lub wielu bramek połączonych acyklicznie. Wyjścia
jednej bramki są połączone przewodami z wejściami innej bramki w taki spo-
sób, że wartość wyjściowa pierwszej bramki jest wartością wejściową drugiej.
Wyjście jednej bramki może zostać połączone z wieloma wejściami innych bra-
mek. Liczbę wejść, z którymi jest połączone dane wyjście, nazywamy jego
stopniem rozgałęzienia. Układy kombinacyjne nie zawierają żadnych cykli oraz
nie mają pamięci (takiej jak rejestry opisane w podrozdz. 29.4).

Sumator pe/ny
Naszym pierwszym przykładem układu kombinacyjnego jest sumator pełny,
przedstawiony na rys. 29.2. Sumator pełny ma 3 wejścia x, y i z oraz
2 wyjścia c i s. Działanie tego układu można opisać za pomocą następującej
tabelki.

735
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

xyz xyz
JOi - JOi

(J
'
Głębokosć J
00 00

' y ' " y '


I O I I O I
I-' I I-'

o
o
d, I
''"""" C

Głębokość I 2 Głębokość I 2 3

(c) (d)

Rys. 29.2. Sumator pełny. (a) W chwili O wartości początkowe pojawiaJą się na wejściach.
(b) W chwili l pojawiają się wartości na wyjściach bramek A-0, czyli tych które mają głębokość l.
(e) W chwili 2 pojawiają się wartości na wyjściach bramek Ei F, czyli tych, które mają głębo­
kość 2. (d) W chwili 3 pojawia się wartość na wyjściu bramki O

y
X

o o
'o 'o 'o
o o I o I
o I o o I
o I I I o
I o o o I
I o I I o
I I o I o
I I I I I

736
29.1. UKŁADY KOMBINACYJNE

Wartość pojawiająca się na wyjściu s odpowiada parzystości (ang. parity) sumy


bitów wejściowych, tj.

s = parity(x, y, z) = x EBy EBz (29.1)

a wartość na wyjściu c określa, czy większość (ang. majority) bitów wejścio­


wych jest równa O czy 1:

c = majority(x, y, z)= (x A y) v (y A z) v (x Az) (29.2)

(Ogólnie funkcje parity i majority można określić dla dowolnej liczby bitów
wejściowych. Wartość funkcji parity wynosi 1 wtedy i tylko wtedy, gdy na
nieparzystej liczbie wejść znajduje się 1. Funkcja majority przyjmuje wartość
1 wtedy i tylko wtedy, gdy na ponad połowie wejść znajduje się 1). Zauważmy,
że zestawiając bity cis, otrzymujemy sumę bitów wejściowych w zapisie binar-
nym. Na przykład, jeśli x = l, y = O i z = 1, to (c, s) = (10) 1>, co stanowi
dwójkowy zapis liczby 2, tj. sumy x, y i z.
Każde z wejść x, y i z sumatora ma stopień wejściowy 3. Jeżeli operacja
realizowana przez bramkę jest przemienna i łączna (jak np. AND, OR lub
XOR), to liczbę jej wejść nazywamy stopniem wejściowym. Na rysunku 29.2
stopień wejściowy każdej bramki wynosi 2, lecz można na przykład zastąpić
bramki XOR oznaczone A i E za pomocą jednej bramki XOR o 3 wejściach,
a bramki OR oznaczone F i G za pomocą jednej bramki OR o 3 wejściach.
Przeanalizujemy teraz działanie sumatora pełnego. Przyjmijmy, że każda
bramka ma jednostkowy czas propagacji. Na rysunku 29.2a widzimy wartości
wejściowe pojawiające się na wejściach w chwili O. Wszystkie wejścia bramek
A-D (i żadnych innych) mają w tej chwili ustalone wartości, więc w chwili I
pojawiają się na ich wyjściach wartości przedstawione na rys. 29.2b. Zauważmy,
że bramki A-D działają równolegle. Wejścia na bramkach Ei F (lecz jeszcze nie
na G) mają ustalone wartości w chwili 1, a w chwili 2 na ich wyjściach pojawia-
ją się wartości przedstawione na rys. 29.2c. Wartość s (na wyjściu bramki E)
można odczytać w chwili 2. Jednak wartość c nie jest jeszcze wtedy ustalona.
Wartości na wejściach bramki G ustalają się w chwili 2, więc w chwili 3 na jej
wyjściu pojawia się wreszcie poprawna wartość c przedstawiona na rys. 29.2d.

Głębokość układu

Podobnie jak w przypadku sieci porównujących omawianych w rozdz. 28,


czas propagacji całego układu kombinacyjnego określamy jako największą
liczbę bramek, jaka może wystąpić na pewnej ścieżce biegnącej od jednego

1
i Aby poprawić czytelność, pomijamy tut.aj przecinki między eJementami ciagu bitowego.

737
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

z wejść do jednego z wyjść układu. Aby określić głębokość układu (odpowiada-


jącą czasowi działania układu w najgorszym przypadku). definiujemy najpierw
indukcyjnie głębokość występujących w układzie połączeń między bramkami.
Każde wejście układu ma głębokość O. Jeżeli bramka ma wejścia x 1, x 2, ... , xn
o głębokościach odpowiednio d 1, d,., ..., dn, to jej wyjścia mają głębokość
max(d 1, di, ..., dJ + 1. Głębokość bramki definiujemy jako głębokość jej wyjść.
Głębokość układu kombinacyjnego definiujemy jako największą głębokość
bramki występującej w tym układzie. Dzięki temu, że założyliśmy niewystępo­
wanie cykli w układach kombinacyjnych, powyższe pojęcia głębokości są dob-
rze zdefmiowane.
Jeśli czas propagacji wszystkich bramek jest stały, to czas propagacji
całego układu w najgorszym przypadku jest proporcjonalny do jego głębo­
kości. Na rysunku 29.2 są pokazane głębokości wszystkich bramek w su-
matorze. Głębokość układu wynosi 3, ponieważ bramką o największej głę­
bokości jest G.
Układ logiczny może czasem obliczać poprawne wartości znacznie szybciej
niż wynika to z jego głębokości. Przypuśćmy na przykład, że jedno z wejść
bramki AND jest połączone z wyjściem pewnego dużego podukładu, a na
drugie wejście jest wprost podana wartość O. Wartość na wyjściu będzie więc
z pewnością równa O, niezależnie od wartości obliczonej przez duży podukład.
W ogólności nie możemy jednak z góry przewidzieć, jakie wartości pojawią się
na wejściach układu. Dlatego określanie czasu dz.iałania układu za pomocą
jego głębokości jest uzasadnione.

Rozmiarukładu
Projektując układy logiczne, staramy się zwykle minimalizować nie tylko ich
głębokość, ale także rozmiar, czyli liczbę użytych bramek. Rozmiar układu
odpowiada w pewnym sensie złożoności pamięciowej algorytmu. Na przykład
sumator na rys. 29.2 ma rozmiar 7, ponieważ składa się z 7 bramek.
Ta definicja rozmiaru nie jest szczególnie przydatna w przypadku małych
układów o stałym rozmiarze. Nasz sumator ma na przykład stałą liczbę wejść
i wyjść i realizuje pewną ustaloną funkcję, spełnia więc warunki, jakich wyma-
galiśmy od bramki logicznej. Zgodnie z powyższą defmicją ma on zatem roz-
miar I, ponieważ przyjmujemy, że każda bramka ma rozmiar 1.
Pojęcie rozmiaru uldadu stosuje się głównie w odniesieniu do rodzin ukła­
dów obliczających podobne funkcje. Opiszemy dalej dla przykładu sumator,
na którego wejście są podawane dwie n-bitowe liczby. Chodzi tutaj oczywiście
nie o jeden układ, lecz raczej o całą rodzinę układów - po jednym dla każdej
długości danych wejściowych. Definicja ronniaru układu, jaką przyjęliśmy po-
wyżej, pozwala w tym kontekście na pewną swobodę w doborze wygodnego
zestawu bramek, który może zmienić rozmiar realizacji układu co najwyżej

7'.łR
29.2. UKŁADY SUMUJĄCE

o stały czynnik. Oczywiście w praktyce określenie rozmiaru układu jest bar-


dziej złożone, ponieważ liczy się nie tylko dobór zestawu bramek, ale także
powierzchnia potrzebna na rozmieszczenie ich w układzie scalonym.

ZADANIA
29.1-1. Na układzie
z rys. 29.2 zamień wartość na wejściu y na I. Określ, jakie
wartości pojawią się na wyjściach poszczególnych bramek.
29.1-2. Zaprojektuj układ o n wejściach obliczający funkcję parity, składający
się z n - 1 bramek XOR i mający głębokość r1gnl.
29.1-3. Wykaż, że dowolną bramkę logiczną można skonstruować ze stałej
liczby bramek AND, OR oraz NOT. (Wskazówka: Wyznacz tablicę warto-
ści funkcji obliczanej przez tę bramkę).
29.1-4. Wykaż, że każdą funkcję logiczną można zrealizować za pomocą sa-
mych tylko bramek NAND.
29.1-5. Skonstruuj układ realizujący funkcję obliczaną przez bramkę XOR,
wykorzystujący tylko cztery 2-wejściowe bramki NAND.
29.1-6. Niech C będzie układem logicznym o n wejściach, n wyjściach i głębo­
kości d. Połączmy dwie kopie układu C w ten sposób, że wyjścia pierwszej
kopii są połączone bezpośrednio z wejściami drugiej. Ile wynosi największa
możliwa głębokość powstałego w ten sposób układu, a ile najmniejsza
możliwa głębokość?

29.2. Układy sumujące

Zajmiemy się teraz problemem dodawania liczb w postaci binarnej. Przedsta-


wimy trzy układy wykonujące to działanie. Najpierw przyjrzymy się sumatoro-
wi szeregowemu, który ma rozmiar E>(n)i dodaje dwie liczby n-bitowe w czasie
E>(n).Można poprawić ten czas do O(lgn), używając sumatora równoległego,
który ma również rozmiar E>(n).Na koniec przedstawimy swnator z zapamię­
tywaniem przeniesień, który w czasie 0(1) sprowadza problem obliczenia su-
my trzech n-bitowych liczb do obliczenia sumy liczby n-bitowej i liczby
(n+ 1)-bitowej. Także ten układ ma rozmiar E>(n).

29.2.1. Sumatorszeregowy
Rozpoczniemy od zwyczajnej metody dodawania liczb binarnych. Załóżmy, że
binarną reprezentacją nieujemnej liczby całkowitej a jest ciąg n hitów (an_ 1 ,
an-2• ... , ao), gdzie n~ r1g(a + l)l oraz

·-' 1
a- L a,2
J=O

739
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

Dla danych n-bitowych liczb a= (a 11_ 1, a,._1, •.• , au> oraz b = (b 11_ 1, b,._1, •.. ,
b0 ) chcemy uzyskać (n+ 1)-bitową liczbę s =a+ b = (s,,, s,,_1, ••• , s0). Na
rysunku 29.3 widać przykład dodawania dwóch liczb 8-bitowych. Dodajemy
liczby w kolumnach od prawej do lewej, propagując ewentualne przeniesienie
z kolumny i do kolumny i+ I, dla i= O, 1, ..., n - I. Na i-tej pozycji danymi
wejściowymi są bity a;, b; oraz bit przeniesienia c1; wyznaczamy bit sumy s1 oraz
nowy bit przeniesienia c;+ 1• Bit przeniesięnia c1+ 1 jest przeniesieniem z kolum-
ny i-tej do kolumny (i+ 1)-szej. Nie ma żadnego przeniesienia do kolumny O,
przyjmujemy więc, że c0 = O. Bit przeniesienia c„jest bitem sumy s,,.

8 7 6 5 4 3 2 I o ;
I I
o
o
I
I
o
I
I
I
I
o
I
o
I
o
o
-- '
a
I I o I o I o I ~ b
I o o I I o o I I
'
Rys. 29.3. Dodawanie dwóch liczb 8-bitowych o = (100110011) i h = (11010101 ); ich suma wynosi
s = (100110011). Bity Ci są bitami przeniesienia. W każdej kolumnie znajdują się (od góry do
dołu) ci, "" h, oraz Ji dla pewnego i. Bit c0 jest zawsze równy O.

Zauważmy, że kai.dy bit sumy s1 jest równy wartości funkcji parity (,,pa-
rzystość") bitów a1, b1 oraz c1 (por. równanie (29.1)). Co więcej, bit przeniesie-
nia c1+ 1 jest z kolei wartością funkcji majority (,,większość") bitów a1, b1 oraz c1
(por. równanie (29.2)). Dzięki temu kai.dy krok dodawania może zostać za-
implementowany za pomocą jednego sumatora pełnego.
Sumator szeregowy n-bitowy (ang. ripple-carry adder) składa się z n połą­
czonych szeregowo sumatorów pełnych FA0 , FA 1, ••• , FA,._1, tak że wyjście c1+ 1
sumatora FA1 jest połączone bezpośrednio z wejściem sumatora FA 1+ 1• Na
rysunku 29.4 jest pokazany 8-bitowy sumator szeregowy. Bity przeniesienia
,,przepływają" z prawej do lewej strony. Wejściowy bit przeniesienia c0 suma·
tora FA I został na stałe przyłączony do O, niezależnie od wartości wejściowych
całego układu. Na wyjściu układu jest (n+ l)·bitowa liczba s = (sn, sn-i, ... ,
s0 ), gdzie s„jest równe c~, wyjściowemu bitowi przeniesienia z sumatora FA,..

,, '• ,, ,,
I o o I I o o I I

I
,,
o I I I O O I I I O I I I o o I

Rys. 29.4. Sumator si.eregowy 8-bitowy wykonujący dodawanie 1 rys. 29.3. Bit c0 ma stale wartość O,
co zostało oznaczone przez romb, a bity przeniesienia przepływają przez układ od prawej do lewej

740
29.2. UKŁADY SUMUJĄCE

Bity przeniesienia przepływają kolejno przez wszystkie n sumatorów


pełnych, czas działania n-bitowego sumatora szeregowego wynosi więc @(n).
Mówiąc dokładniej, sumator dwubitowy FA; znajduje się w układzie na głębo­
kości i+ 1. Najgłębszym sumatorem w obwodzie jest FAn-i• głębokość n-bito-
wego sumatora szeregowego jest więc równa n. Rozmiar układu jest równy
@(n), bo sumator szeregowy składa się z n bramek (sumatorów pełnych).

29.2.2. Sumatorrównoległy
Sumator szeregowy wymaga czasu @(n), ponieważ bity przeniesień muszą
przepływać przez cały układ. W sumatorze równoległym propagacja przenie-
sień jest szybsza dzięki specjalnej drzewiastej strukturze układu. Dzięki temu
dodawanie dwóch liczb n-bitowych odbywa się w czasie O(lgn).
Zasadniczy pomysł opiera się na spostrzeżeniu, że w sumatorze szerego-
wym każdy sumator pełny FA 1 „zna" wartości a, oraz b1 znacznie wcześniej
niż c,. W układzie sumatora równoległego ta częściowa informacja jest wy-
korzystana.
Załóżmy na przykład, że a 1_ 1 = b,_ 1• Wartość przeniesienia c, jest warto-
ścią funkcji majority (,,większość"), mamy więc c; = a1_ 1 = b1_ 1 niezależnie od
wartości c;_ 1• Jeśli a 1_ 1 = b 1_ 1 = O,to możemy anulować przeniesienie c1, wymu-
szając dla niego wartość O, nie czekając na wyznaczenie wartości c1_ 1• Podob-
nie, jeżeli a1_ 1 = b1_ 1 = 1, to możemy wygenerować przeniesienie c1 = I nieza-
leżnie od wartości c1_ 1 •
Jeżeli jednak a1_ 1 i,: b1_1> to wartość c, zależy od wartości c1_ 1• Wiadomo
w szczególności, że c1 = c1_ 1, bo c1_ 1 ma decydujący „głos" w wyborze większo­
ściowej wartości, która wyznacza c;. W tej sytuacji propagujemyprzeniesienie,
bo przeniesienia wejściowe i wyjściowe są sobie równe.
Tabelka na rys. 29.5 zawiera klasyfikację możliwych przypadków w zależ­
ności od stanu przeniesienia, gdzie k oznacza „anulowanie przeniesienia",
g - ,,generowanie przeniesienia", a p - ,,propagowanie przeniesienia".
Rozważmy dwa kolejne sumatory pełne FA 1_ 1 oraz FA 1 jako jedną
całość. Przeniesieniem wejściowym tego układu jest c1_ 1, a wyjściowym C;+i·
Podobnie jak w przypadku pojedynczego sumatora, powyższy układ dwóch
kolejnych sumatorów może anulować, generować lub propagować przeniesienia.

a,_i bi-!
,, stan przenies.ienia
o o o k
o I c,_1 p
I o c,_1 p
I I I g

Rys. 29.S. Bit c, oraz bit stanu przenies.ienia sumatora pełnego FA,_1, odpowiarlające wejściom a,_ 1,
b,_ 1 oraz c,_,w sumatorze szeregowym

741
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

Połączone sumatory anulują przeniesienie, jeśli FA1 anuluje przeniesienie albo


FA 1_ 1 anuluje przeniesienie, a FA 1je propaguje. Podobnie, układ dwóch suma-
torów generuje przeniesienie, jeśli F A 1 generuje przeniesienie albo FA;_ 1 generuje
przeniesienie, a FA, je propaguje. Wreszcie, para sumatorów propaguje prze-
niesienie, ustalając c1 + 1 = c;_ 1, jeśli oba jej składniki propagują przeniesienia.
Tabela na rys. 29.6 zawiera zestawienie stanów przeniesienia dla szeregowego
połączenia dwóch sumatorów pełnych. Możemy traktować tę tabelę jako defi-
nicję operatora stanu przeniesienia ® na zbiorze {k, p, g}. Operator ten ma
ważną z naszego punktu widzenia własność łączności (patrz zad. 29.2-2).

FA,
® k p g
k k k g
p k p g
k g g
'
Rys. 29.6. Stan przeniesienia dla szeregowego połączenia dwóch sumatorów pełnych FA 1_ 1 i FAJ
wyrażony za pomocą ich stanów przeniesienia, jako operator statnu przeniesienia ® określony na
zbiorze {k, p., g}

Za pomocą stanu przeniesienia można wyrazić każdy bit prze-


operatora
niesienia c1 za pomocą wartości wejściowych. Zaczniemy od zdefmiowania
x 0 = k, oraz

k, jeśli a;-1 = b1-1 = O


X1= P, jeśli QI-\ =f:.bł-I (29.3)
g, jeśli a 1_ 1 = b 1_ 1 = 1

dla i = 1, 2, ... , n. Stąd dla i = 1, 2, ... , n wartość x 1 jest stanem przeniesienia


określonym tak jak na rys. 29.6.
Przeniesienie c, z sumatora pełnego FA 1_ 1 może zależeć od stanu prze-
niesienia wszystkich sumatorów FA1 dla j = O, 1, ... , i - 1. Zdefiniujmy
Yo= X0 = k oraz

Y1=Y1-1®X1 (29.4)
=x 0 ®x 1 @ ... ®x;

dla i= 1, 2, ... , n. O y 1 można myśleć jako o „prefiksie" wyrażenia


x 0 ® x 1 ® ... ® x,,; obliczanie wartości y 0, y 1, ••• , y~ nazywamy obliczaniem prefi-
ksów. (Y,/ rozdziale 30 zajmiemy się równoległym obliczaniem prefiksowym
w bardziej ogólnym kontekście). Na rysunku 29.7 znajdują się wartości x 1 oraz
Y; odpowiadające dodawaniu binarnemu z rys. 29.3. Następujący lemat uwyw
datnia znaczenie wartości y 1 dla dodawania równoległego.

742
29.2. UKŁADY SUMUJĄCE

8 7 6 5 4 3 2 I o
'
a o I o I I I I o
'
h. I I o I o I o I
'
X
'
Y,
p
g

g
k 9 p
k g g

g
p p
k k
k

I I o I I I o o o
''
Rys. 29.7. Wartości x, i y, dla i= O, I, ..., 8, które odpowiadają wartościom a„ b, oraz c1 z rys. 29.3.
Każda wartość x, została zacieniowana razem z wartościami a,_ 1 i b1_ 1 od których jest zależna

LEMAT29.1.
Niech x 0 , x 1, ••• , xn oraz Yo,y 1, ••• , Yn będą zdefiniowane za pomocą równań
(29.3) i (29.4). Dla i= O, 1, ... , n zachodzą następujące warunki:
{l) jeśli y 1 = k, to c1 = O,
(2) jeśli y, = g, to c1 = I, oraz
(3) Y; = p nie występuje.

DOWÓD
Dowód przebiega przez indukcję względem i. Krok podstawowy indukcji:
i= O, wynika z definicji y 0 = x 0 = k oraz c0 = O. Załóżmy teraz, aby wykonać
krok indukcyjny, że teza lematu zachodzi dla i - l. W zależności od wartości
Y; są możliwe trzy przypadki.
1. y 1 = k, to z yj = Y;-i ® x 1 oraz definicji operatora stanu przeniesienia
Jeśli
® z rys. 29.6 wynika, że x 1 = k albo Xi = p i Y;-i = k. Jeżeli x 1 = k, to
z równania (29.3) mamy, że a;_ 1 = h;_ 1 = O, więc c1 = majority(a 1_ 1, b1_ 1,
c;_1) = O, Jeśli z kolei x 1 =pi y1_ 1 = k, to a;_ 1 "Fh1_ 1 oraz, przez indukcję,
c;_1 = O. Stąd majority(a;_ 1, h1_ 1, c,_ 1) = O, więc c1 = O.
2. Jeśli y 1 = g, to albo x 1 = g, albo x 1 = p i y 1_ 1 = g. Jeśli x 1 = g, to
a;_ 1 = b 1_ 1 = I, skąd wynika, że C; = I. Jeśli x 1 = p oraz Yi-i = g, to
a;_ 1 "Fb1.• i, więc z założenia indukcyjnego c;_1 = 1, z czego wynika c1 = 1.
3. Jeśli y 1 = p, to z rys. 29.6 wynika, że y 1_ 1 = p, co jest sprzeczne z założeniem
indukcyjnym.

Z lematu 29.l wynika, że każdy bit c1 można wyznaczyć na podstawie
stanu przeniesienia y 1• Gdy już będziemy mieli wartości wszyskich bitów prze-
niesienia, całą sumę możemy obliczyć w czasie 9(1), obliczając równolegle bity
s1 = parity(a;, b1, c;) dla i= O, I, ... , n (przyjmując, że an= hn = O). Problem

743
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

szybkiego dodawania dwóch liczb sprowadza się więc do obliczania prefik-


sowego stanów przeniesienia Yo, y 1, ••• , Y~·

Obliczanie stanów przeniesień za pomocą układu obliczającego


prefiksyrównolegle
Za pomocą układu obliczającego prefiksy równolegle, w przeciwieństwie do
sumatora szeregowego, który wyznacza wartości sekwencyjnie, możemy szyb-
ciej obliczyć n + 1 stanów przeniesienia y 0 , y 1, ••• , Yn· Okazuje się, że da się
zaprojektować odpowiedni układ o głębokości O(lg n) oraz rozmiarze E>(n).
Zanim skonstruujemy układ równolegle obliczający prefiksy, wprowadzi-
my najpierw notację, która ułatwi nam zrozumienie jego działania. Dla i oraz
j spełniających nierówności O ,s;;i~ j ~ n zdefiniujmy

[/,kJ [O,i-1]

x, x.,_'' x.' X. ,
J-,
X.
j

Rya. 29.8. Element konstrukcyjny układu równolegle obliczającego prefiksy. Pokauny węzeł jest
korz.eniem poddrzewa, którego wartości na liściach są z przedriału od x, do x 1 • Lewe poddrzewo
obejmuje wejścia od x, do x1_ 1, a prawe wejścia od x1 do x 1• W skład węzła wchodzą dwie bramki
®, driałające w różnych chwilach obliczenia przebiegającego w całym układzie. Jedna z bramek
oblicza [i, kJ .... [i, j - IJ ® U,kJ,a druga oblicm [O,j - I] -[O, i - l] ® [i, j - I]. Obliczane war~
tości są podane przy połączeniach

744
29.2. UKŁADY SUMUJĄCE

Z tej definicji wynika, że dla i= O, 1, ... , n mamy [i, 11= x„ Oprócz tego dla i,
j oraz k takich, że O ::::;;i < j ,e;;k ::;;;;
n, spełniona jest tożsamość

[i, kJ- [i, j - IJ® [j, kJ (29.5)

ponieważ operator stanu przeniesienia jest łączny. Przy zastosowaniu tej no-
tacji obliczanie prefiksów polega na wyznaczeniu wartości Y; = [O,i] dla i= O,
1, ..., n.
Jedyną bramką, której będziemy używać w układzie równolegle obliczają­
cym prefiksy, będzie bramka operatora ®· Rysunek 29.8 jest ilustracją meto-
dy łączenia par bramek tego typu tak, aby stanowiły wewnętrzne węzły drzewa
binarnego, a na rys. 29.9 widać układ równolegle obliczający prefiksy dla
n= 8. Zauważmy, że chOCpołączenia w tym układzie tworzą strukturę drzewa
binarnego, jednak układ ten nie jest drzewem. Wejścia układu Xi, x 1 , ... , xn
znajdują się w liściach, a wejście x 0 w korzeniu. Podobnie wyjścia y0 , y 1, ... , Yn-i

f0,8]
,,
[0,0] [0,4]

[1,4] [5.8]
[0.2] [0,4] (0.6]
[1,2] (3,4] [5,6] (7,8J
[0,1] [0.2] (0,3] [0,4] [0,6] [0,11
[1,1] [2.21 [3,3] 14,4] [5,5] (7 ,71 (8,8]
Yo XI .X2 yI Y2 X3 x, Y1 Y4 X5 x6 Ys y6 x, Xg y1
(•)

'•

(b)

Rys. 29.9. Układ równolegle obliczający prefiksy dla n = 8. (a) Ogólna struktura układu oraz wartoś­
ci przenoszone każdym połączeniem. (b) Ten sam obwód z zaznaczonymi wartościami odpowiada-
jącymi rys. 29.3 i rys. '29.7

745
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

znajdują się w liściach, a wyjście y„ w korzeniu. (Aby ułatwić zrozlllllienie


sposobu działania tego układu, indeksy zmiennych na rys. 29.8 i 29.9 rosną od
strony lewej do prawej, a nie jak zwykle od prawej do lewej).
Dwie bramki ® w jednym węźle drzewa są aktywne zwykle w różnych
chwilach, bo mają różne głębokości w układzie. Jak widać na rys. 29.8, jeśli
poddrzewo o korzeniu w danym węźle obejmuje przedział x 1, X;+ i, ••• , X1cwejść,
w tym lewe poddrzewo obejmuje przOOział X;, X;+ 1, ... , xi_ 1, a prawe przedział
xi' xi+L• ... , x*" to węzeł ten oblicza dla swego ojca wartość [i, k] na podstawie
wszystkich wejść obejmowanych przez swoje poddrzewo. Możemy przyjmować
indukcyjnie, że lewy i prawy syn obliczają wartości [i, j - I] oraz [j, k], więc
w węźle wystarczy użyć tych wartości do obliczenia [i, k] +- [i, j - I]® [j, k].
Po pewnym czasie od tej oddolnej fazy obliczeń każdy wierzchołek otrzy-
muje od swego rodzica wartość [O, i - l], gdzie x 1 jest najbardziej na lewo
wysuniętym wejściem obejmowanym przez ten węzeł. Zadanie każdego węzła
polega teraz na obliczaniu odpowiednich wartości dla swoich synów. Najbar-
dziej wysuniętym na lewo wejściem lewego syna węzła jest również X;, więc do
lewego syna wystarczy przekazać niezmienioną wartość [O,i - 1]. Najbardziej
na lewo wysuniętym wejściem obejmowanym przez prawego syna jest x1, trzeba
więc policzyć dla niego wartość [O,j - 1]. Ale każdy węzeł otrzymuje wartość
[O,i - 1] od swego ojca oraz wartość [i,j - 1] od swego lewego syna; wystarczy
więc obliczyć [O,j - 1] +- [O,i - I]® [i, k] i przesłać ją do prawego syna.
Na rysunku 29.9 widać cały układ z wyszczególnionym przypadkiem brze-
gowym w korzeniu drzewa. W korzeniu wartością wejściową układu jest x 0 =
= [O,O],a jedna dodatkowa bramka ® oblicza wartość [O,n]= [O,O]® [I, n].
Jeśli n jest dokładną potęgą 2, to układ równolegle obliczający prefiksy
składa się z 2n - 1 bramek ®. Obliczenie n + 1 prefiksów zajmuje tylko
O(lgn) czasu, ponieważ obliczenia przebiegają w górę drzewa, a następnie
z powrotem w dół. Dokładne obliczenie głębokości układu jest przedmiotem
zad. 29.2-5.

Sumator równoległy

Mając już do dyspozycji układ obliczający prefiksy, możemy dokończyć


konstrukcję sumatora równoległego. Konstrukcja ta jest pokazana na
rys. 29.10. Swnator IHJitowy równoległy składa się z n + 1 układów KPG
o rozmiarze 0(1) każdy oraz układu równolegle obliczającego prefiksy
o wejściach x 0, Xi, •.. , x,, (x 0 ma stale wartość k) i wyjściach y 0 , y 1, ... , y,,.
Układ KPG 1 na podstawie zewnętrznych wejść do układu a1 oraz h; oblicza
bit s;. (Wejścia a„ i h„mają stale wartość O). Dla danych a1_ 1 oraz b1_ 1 układ
K.PG1_ 1 oblicza wartość x 1e {k, p, g} zgodnie z równaniem (29.3) i zwraca ją
jako zewnętrzne dane wyjściowe układu obliczającego prefiksy. (Wartość x,,+1
zostaje zignorowana). Obliczenie x 1 zajmuje czas 0(1). Po upływie czasu

746
29.2. UKŁADY SUMUJĄCE

KPG0
9 p

KPG,
9 9

XPG0
'
' XPG,
~· 9

<PG,
g p

xro,
9 g

XPG,
' p

XPG,
' p

xro,
o '

h,
I
loa.,oh1", h,
I I

al I\
li
JI ~4I h,
I

~
I li
h,
I
il;: 1,,'
I

al hl
11
,,,,
:o I

,, 11
,, ,, I11 li I I
,,
', '' ', '' ''
Rys. 29,10. Konstrukcja n-biiowego sumatora równoległego dla n= 8. Sumator składa się z n+ I
układów KPGh dla i= O, l, ..., n. Kazdy układ KPG, oblicza stan przeniesienia x,+i na podstawie
wartości wejściowych a1 oraz b~ (Wejścia a. i h. mają stale wartość O, co zostało ukazane na
rysunku za pomocą rombu). Te wartości są następnie przekazywane do układu obliczającego
prefiksy, których wartości są oznaczone na rysunku jako y,. Na koniec każdy układ KPG 1 bierze
wartość y,, interpretuje ją jako bit przeniesienia c 1 i wyznacza bit s 1 = parity(a 1, b~ c1). Na rysunku
są też pokazane przykładowe wartości, odpowiadające tym z rys. 29.3 i 29.9

O(lgn) układ obliczający prefiksy wyznacza wartości y0 , y 1, ••• , Y~- Zgodnie


z lematem 29.1 wartość y 1 jest równa albo k, albo g; nie może być równa p.
Każdą z wartości Y; należy interpretować jako przeniesienie do sumatora dwu-
bitowego FA; w układzie sumatora szeregowego: Y; = k odpowiada c1 = D,
a y 1 = g odpowiada ci = 1. Dlatego wartość y 1 zostaje skierowana do KPG,
jako odpowiednik przeniesienia Ci, po czym bit .v1 = parity(a;, bi, c;) zostaje
obliczony w czasie stałym. Dzięki temu sumator równoległy działa w czasie
O(lgn) oraz ma rozmiar @(n).

29.2.3. Sumatorz zapamiętywaniem przeniesień


Sumator równoległy dodaje dwie n-bitowe liczby w czasie O(lgn). Nieco za-
skakujący jest fakt, że trzy n-bitowe liczby można dodać w czasie większym
zaledwie o stałą. Trik polega na sprowadzeniu dodawania trzech liczb do pro-
blemu dodawania tylko dwóch liczb.
Dla danych n-bitowych liczb X= <xn-l• xn-2' ... , Xo), Y = <Yn-!• Yn-2•
... , Yo) oraz z= (zn-J• zn_2, ... , z0 ) n-bitowy sumator z zapamiętywaniem prze-
niesień wyznacza n-bitową liczbę u= (u,._ 1, u,._2 , ... , Uo) oraz (n+ 1)-bitową
liczbę v = (v,., v,._1, ... , v0 ) takie, że

u+v=x+y+z
Jak widać na rys. 29.Ila, polega to na obliczeniu

747
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

u1 = parity(x,., y 1, zJ
v1+ 1 = majority(x 1, y,.,zJ
dla i= O, 1, ..., n - 1. Bit v0 jest zawsze równy O.

•' •' ' ' ' l o )

o o o l l l o l •
l o o o l
l o l •
'
l o o l o l l o • ' '
o l o o I I l o • "
I o o I o I o I o • '
,.,
'•
l o o l o l o l o

,., ,., ,•. ,.,


o o o
,.,
l I I l

FA,

!!0010000101 001 Jl! !00011

(b)

Rys. 19.11, Sumator z zapamiętywaniem przeniesiet\. (a) Dodawanie z zapamiętywaniem przeniesień.


Dla danych trzech n-bitowych liczb x, y i z, wyznaczamy 11-bitową liczbę u oraz (11+ 1)-bitową
liczbę v, takie że x + y + z = u + v. Kolejna i-ta para zacieniowanych bitówjest funkcją x„ y 1 i z1•
(b) 8-bitowy sumator z zapamiętywaniem przeniesień. Każdy sumator pełny FA.1 ma na wejś­
ciu wartości x„ y, oraz z„ w wyniku daje bit sumy ui, oraz bit przeniesienia V 4+ i, Bit v0 jest stale
równy O

Sumator z zapamiętywaniem przeniesień przedstawiony na rys. 29.llb


składa się z n sumatorów pełnych FA 0 , FA 1, ... , FA,,_1• Dla i= O, 1, ..., n - 1
sumator dwubitowy FA 1ma na wejściu wartości x 1, y 1 oraz z 1• Wyjście majority
sumatora FA; traktujemy jako u1, a jego wyjście parity, jako v1+ 1• Bit v0 ma
stale wartość O.
Obliczanie wszystkich 2n + 1 bitów wyjściowych jest niezależne, można
więc je wykonywać równolegle. Dzięki temu sumator z zapamiętywaniem
przeniesień działa w czasie 0(1), a jego rozmiar wynosi 0(n). Stąd, aby do-
dać trzy liczby, wystarczy najpierw wykonać obliczenie na sumatorze z zapa-
miętywaniem przeniesień w czasie 0(1), a następnie użyć sumatora równo-
ległego, który działa w czasie O(lg n). Chociaż ta metoda nie jest asympto-
tycznie lepsza niż użycie dwóch sumatorów równoległych, jednak w prak-
tyce jest znacznie szybsza. Co więcej, w podrozdz. 29.3 przekonamy się,

748
29.2. UKŁADY SUMUJĄCE

zeużycie sumatora z zapamiętywaniem przeniesień jest istotne dla szybkich


algorytmów mnożenia.

ZADANIA
29.2--1.Przyjmijmy a- (01111111), b - (00000001) oraz n- 8. Wyznacz bi-
ty sumy oraz przeniesienia dla tych ciągów, obliczane przez sumatory pełne
w sumatorze szeregowym. Wyznacz stany przeniesień x 0, x 1, ••• , x 3 odpo-
wiadające a i b; opisz każde połączenie w układzie obliczającym prefiksy
z rys. 29.9 wartością przez nie przenoszoną, jeśli na wejściu znajdują się
powyższe wartości X;; wyznacz końcowe wartości wyjściowe y0, Yi, ..., y 8•
29.2-2. Wykaż, że operator stanu przeniesienia ®, określony w tabeli
z rys. 29.5 jest łączny.
29.2-3. Pokaż na przykładzie, jak zbudować układ równolegle obliczający pre-
fiksy w czasie O(lgn), jeśli n nie jest dokładną potęgą 2; narysuj taki układ
dla n = 11. Scharakteryzuj czas działania i rozmiar układów o strukturze
dowolnego drzewa binarnego równolegle obliczających prefiksy.
29.24. Zaprojektuj układ pełniący funkcję układu KPG;. Przyjmij założenie,
że na wyjściu x 1 pojawia się: (00), jeśli x 1 = k; (11), jeśli x 1 = g; oraz
(10), jeśli X;= p. Podobnie wartość O na wejściu y„ jest interpretowana
jako y 1 = k, a wartość I jako y 1 = g.
29.2-5. Zaznacz przy każdym połączeniu w układzie równolegle obliczającym
prefiksy na rys. 29.9a jego głębokość. Scieżka krytyczna w układzie to
ścieżka prowadząca od wejścia do wyjścia układu, na której jest maksy-
malna liczba bramek. Wy1-nacz ścieżkę krytyczną na rys. 29.9a oraz wy-
każ, że jej długość wynosi O(lg n}. Wskaż węzeł, którego bramki ® działa­
ją w odstępie czasu 0(1gn}. Czy jest taki węzeł, którego obie bramki
® działają jednocześnie?
29.2-6. Przedstaw rekurencyjny „schemat blokowy" układu z rys. 29.12, dla
dowolnego n będącego dokładną potęgą 2. Na podstawie tego schematu
udowodnij, że układ ten oblicza prefiksy. Wykaż, że ma on głębokość
0(1gn} i rozmiar 0(nlgn}.
29.2-7. Jaki jest maksymalny stopień rozgałęzienia dowolnego wyjścia w su-
matorze równoległym? Wykaż, że dodawanie daje się wykonywać w cza-
sie O(lgn} za pomocą układu o rozmiarze 0(n}, nawet jeśli ograniczy-
my się do bramek o ograniczonym przez Stałą wyjściowym stopniu roz-
gałęzienia.
29.2-8. Układkontrolny ma n wejść oraz m = flg(n + l}l wyjść. Jeśli inter-
pretować wyjścia jako liczbę binarną, to układ kontrolny wyznacza liczbę
jedynek na wejściach. Na przykład dla ciągu (10011110) na wejściu na
wyjściu pojawia się ciąg (101), co oznacza, zew ciągu wejściowym jest
pięć jedynek. Zaprojektuj układ kontrolny o rozmiarze @(n) i głębokości
O(lgn).

749
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

* 29.2-9. Wykaż, że dodawanie n-bitowych liczb można wykonywać za pomocą


układu o głębokości 4 oraz ro2miaru wielomianowego względem n, jeśli
bramki AND i OR mogą mieć dowolny stopień wejściowy. (Można także
uzyskać głębokość 3).

,, ,, ,, ,,

x, x, x,
Rys. 29.12. Układ równolegle obliczający prefiksy z radania 29.2-6

* 29,2-10. Wykonajmy na sumatorze szeregowym dodawanie dwóch liczb n-bi-


towych, w których każdy bit został wylosowany niezależnie z jednakowym
prawdopodobieństwem zera i jedynki. Wykaż, że z prawdopodobieństwem
co najmniej l - 1/n żaden bit przeniesienia nie propaguje się dalej niż
o O(lg n) pozycji. Innymi słowy, mimo że głębokość sumatora szeregowego
wynosi 0(n), dla losowo wybranych liczb wyjścia stabilizują się już po
czasie O(lgn).

29.3. Układy mnożące

Za pomocą „szkolnego" algorytmu mnożenia pisemnego, zilustrowanego na


rys. 29.13, możemy obliczyć 2n-bitowy iloczyn p = (p 2,., P'ln-l• ..., p 0 ) dwóch
liczb n-bitowych a= (a,., a,._1, ... , aci>i b = (b,., b,._1, ••• , 60). Rozpatrujemy
kolejno bity liczby b, od b0 do b,._1• Dla każdego bitu b1 o wartości 1 dodajemy
do iloczynu a przesunięte w lewo o i pozycji. Dla każdego bitu b1 o wartości
O dodajemy O. Przy oznaczeniu m(I) = a·b 1 ·2i obliczamy więc

750
29.3. UKŁADY MNOZĄCE

,-1
p=a·b= 1:m''
J=O

Każdy składnik m<0 nazywamy iloczynem częściowym. Jest w sumie n iloczy-


nów częściowych do zsumowania, z bitami na pozycjach od Odo 2n - 2. Prze-
niesienie z najbardziej znaczącej pozycji daje wartość bitu na pozycji 2n - 1.

I I I o =
__ ,,,....
I I o I = "
b
-· - '

I I I o = nf"
o o o o = nf')
I I I o = m<2)
I I I o -----· -- = nf"
I o I I o I I o = p

Rys. 29.13. ,,Szkolny" algorytm mnożenia pisemnego, na przykładzie mnożenia a = (1110) przez
,- '
h=(l!Ol), co daje w wyniku p=(IOI10IIO). Dodajemy Lmm, gdzie mC1>=a·bj·i. Tutaj
,-,
n= 4. Każdy wyraz powstaje przez przesunięcie a (jeili h, = I), albo O (jeśli b, = O) o i po-
m(I)
zycji w lewo. Bity, które nie zostały pokazane na rysunku są zawsze równe O, niezależnie od
wartości a i h

W tym podrozdziale przedstawimy dwa układy służące do mnożenia


dwóch liczb n-bitowych. Tablicowy układ mnożący działa w czasie 0(n) i ma
rozmiar 9(n 2). Drzewiasty układ mnożący Wallace'a ma również rozmiar
E>(n2 ), lecz działa w czasie @(lgn). Oba układy są oparte na szkolnym algoryt-
mie mnożenia pisemnego.

29.3.1. Tablicowy układ mnożący


Tablicowy układ mnożący składa się z trzech bloków. Pierwszy blok wyzna-
cza iloczyny częściowe, drugi - sumuje iloczyny częściowe, używając w tym
celu sumatora z zapamiętywaniem przeniesień, a trzeci - dodaje 2 liczby
powstałe po fazie drugiej, wykorzystując sumator szeregowy lub sumator
równoległy.
Na rysunku 29.14 jest przedstawiony tablicowy układ mnożący dla dwóch
liczb wejściowych a= an-1>an_2, ••• , 'lo i b = bn-l• bn-ż• ..., b0 • Wartości aj
„przepływają" pionowo, a wartości b, - poziomo. Każdy bit wejściowy jest
podawany na wejścia n bramek AND, tworząc iloczyny częściowe. Za pomocą
sumatorów pełnych, w konfiguracji odpowiadającej sumatorom z zapamięty­
waniem przeniesień, są sumowane iloczyny częściowe. Mniej znaczące bity
całego iloczynu pojawiają się na wyjściach po prawej stronie, a bardziej zna-
czące bity powstają przez dodanie dwóch liczb, generowanych przez ostatni
sumator z zapamiętywaniem przeniesień.

751
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

,, '1,
I I I o

I
d:'1
1
o•>
o
(O) j
m,

b o
' o
IO

FA(ll FA(ł> FA(l) Po


l
b, I ' '
rf;'
P,
FA(2) FAfl} FA<»
., 1 ' ' '
P,

Pa

I I
P; P,

Rys. 29.14. Tablicowy układ mnożący, który oblicza iloczyn p = (.p.,,.,h.-i• ..., pr) dwóch liczb
n-bitowych a= (a._u a._ 2, ... , !lo) l b = (b._ 1, b._v ..., ho),pokazany tutaj dla n= 4. Ku.da
bramka AND G}11 oblicza bit iloczynu częściowego mY,.Każdy rząd sumatorów pełnych składa.
się na jeden sumator z zapamiętywaniem przeniesień. Dolne n bitów iloczynu to m~ oraz bity
u wymaczane przez wyjścia Wajnie prawej kolumny sumatorów pełnych. Górne n bitów iloczynu
powstaje przez dodanie bitów u oraz bitów II generowanych przez najniższy rząd sumatorów
pełnych. Na rysunku są. pokazane wartości bitów dla liczb a= (1110) oraz b = (1101) na wejś­
ciu, co daje iloczyn p = (10110110), podobnie jak. na rys. 29.13 i rys. 29.15

752
29.3. UKŁADY MNOŻĄCE

Omówimy teraz dokładniej sposób działania tablicowego układu mnożą~


cego. Dla danych liczb wejściowych a= an-t• an_2, ••• , a 0 i b = bn-t• bn_2 , ••• , b0
bardzo łatwo jest obliczyć bity iloczynów częściowych. W szczególności, dla
i,j= O, 1, ... , n-1 mamy

mYt;= ai·bi
Iloczyn jednobitowych wartości można obliczyć bezpośrednio, używając bram-
ki AND, zatem wszystkie bity iloczynów częściowych (oprócz tych, o których
i tak wiadomo, że są równe O, więc nie trzeba ich w zasadzie obliczać) można
wyznaczyć w jednym kroku, używając n 2 bramek AND.

o o
I I
o
I
o
o
-- o m(O)

o o o o - m'"
-- J"J"
- --·· ·····- -- -
o I I I o
o o o
I I I o - m(ll

--
-------- -- -·---·-
I I o I I o ufll

o I o vCll

I I I o - J" m!3l

I o I o I I o --
-
I
-
I
o
I
I
o
I o I I o - •"
·-·- ·- ..

Rys. 29.15. Obliczanie sumy iloczynów częściowych przez wielokrotne dodawanie 2 zapamięty­
waniem przeniesień. W tym przykładzie a= (I 110) a b = (1101 ). Biły nie pokazane na rysun-
ku są zawsze równe O, niezależnie od wartości a i b. Najpierw obliczamy ,n!0l + m!ll +O=
= u(ll + 0ui, potem ull) + tfll + ,n(l) = ,1,2J + tfll, następnie u(l) + 0 (2\ + ml31= u!ll + 0 c,1 i osta-
tecznie p = m( 0l + m(l) + m!l) + mUl = u 0 > + u!3l. Zwróćmy uwagę, że Po = m~ 0l oraz p 1 = uJQdla
i=l,2, ... ,n-1

Na rysunku 29.15 widać, w jaki sposób tablicowy układ mnożący sumuje


iloczyny częściowe z rys. 29.13, używając dodawania z zapamiętywaniem prze-
niesień. Rozpoczyna od dodania (z zapamiętaniem przeniesień) liczb m( 0 ), m( 1 >
oraz O, w wyniku czego powstaje (n+ 1)-bitowa liczba ii 1>oraz (n+ 1)-bitowa
liczba v<1l. (Liczba v<1 > ma tylko n+ 1 bitów, a nie n+ 2, ponieważ (n+ 1)-szy
bit zarówno liczby O, jak i ml0 > jest równy O). Stąd mt0 > + m( 1 > = u<1 l + v( 1l.
Następnie są sumowane z zapamiętywaniem przeniesień liczby ut1 >,v(ll oraz
m<2l, w wyniku czego powstaje (n+ 2)-bitowa liczba u( 2 > oraz (n+ 2)-bitowa
2 ,jak i vl) 2 są
1
liczba v(2 >.(Ponownie v< 2
J ma tylko n+ 2 bity, bo zarówno ui-¼1
równe O). Stąd wynika równość mt 0 > + m( 1 > + m<2 > = ii 2 l + v<2 l. Podobnie dla
i= 2, 3, ... , n - 1 są dodawane z zapamiętywaniem przeniesień liczby u<i-ll,
W wyniku zostają wygenerowane (2n - 1)-bitowe liczby u<n-ll
v<1 - 1 > oraz mU>_
oraz v<n-l), gdzie

753
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

u<n-1) + v<n-1) = ·-'


L m(I)
I"'· O
-p
W rzeczywistości dodawanie z zapamiętywaniem przeniesień na rys. 29.15
jest wykonywane na większej liczbie bitów, niż to jest w istocie konieczne.
Zauważmy, że dla i= 1, 2, ... , n - 1 oraz}= O, 1, ... , i - 1 mamy my>=O ze
względu na przesunięcie iloczynu częściowego. Oprócz tego v~i) = O dla i= 1,
2, ... , n-1 oraz}= O, 1, .,., i, i+n, i+n+ 1, ... , 2n- l (patrz zad. 29.3-1).
Dzięki tym spostrzeżeniom możemy ograniczyć dodawanie z zapamiętywa­
niem przeniesień do zaledwie n - I bitów.
Zastanówmy się, w jaki sposób tablicowy układ mnożący realizuje wyżej
opisany ciąg dodawań z zapamiętywaniem przeniesień. Każda bramka AND
jest oznaczona przez G)il dla pewnego i oraz j z przedziałów O ~ i~ n - l
i O~}~ 2n - 2. Bramka GYl wyznacza m)i), czylij-ty bit i-tego iloczynu częś­
ciowego. Dla i= O, 1, ... , n - 1 i-ty rząd bramek AND oblicza n znaczących
. ' częsciowego
b1tow ' . 1'!oczynu m(O, czy1·
1 ( m (I} U)
11+ 1- 1 , m 11+i-2., ... , m,
li>) .
Z wyjątkiem sumatorów w górnym rzędzie (tj. dla i= 2, 3, ... , n - 1) na
wejście każdego sumatora pełnego FAY>są podawane trzy bity - my>,uy-i)
i vy- 1 i - a na wyjściu pojawiają się dwa bity - u)'> i v)i_t 1 , (Zauważmy, że
w skrajnie lewej kolumnie sumatorów pełnych zachodzi równość
u\~-11':ł 1 = m\ 1l.n-1). Na wejście każdego sumatora pełnego FA )1> są podawane
wartości m) 0 >,m) 1> i O, a na wyjściu pojawiają się dwa bity - u) 1l i v)\>1 .
Zwróćmy teraz uwagę na wyjścia tablicowego układu mnożącego. Jak już
wcześniej zaobserwowaliśmy, v~n-tl = Odla j = O, 1, ..., n - 1. Stąd p = u)"- 1 >
dla}= O, 1, ... , n - I. Co więcej, dzięki temu, że mlfl = O, zachodzi u~>=mg>>
a ponieważ mniej znaczących i bitów każdego m<fJoraz vli·- 1 >jest równe O,więc
u1(O --u 1(•-,,dl az-,· - 2 3, ... ,n - I orazJ-,. - O I , ... ,z. - 1. Stąd p 0 -m - (O).
0 1przez
indukcję mamy, żep 1 = u\il dla i= 1, 2, ... , n - 1. Wyższa polowa bitów iloczy-
nu, tj. (p 2n-J• P2n-i• ..., Pn>, jest generowana przez n-bitowy sumator, który
sumuje wartości z wyjść najniższego rzędu sumatorów pełnych:

Pi,,-2, ···•Pn)=
<P211-I•
_
-
(Uzn-2.,
,.-,, Uzn-
<•-•j, .. ,, Un,.-,,) + ( Vzn-t,
,.-,, <•-•J <•-11)
V211- , ... , Vn

Analiza
Dane „przepływają" przez tablicowy układ mnożący od strony lewej do prawej
oraz z góry w dól. Dolne bity iloczynu <Pn-i•Pn-i• ... , p 0) zostają wyznaczone
w czasie @(n);tyle samo czasu potrzeba na przygotowanie danych wejściowych
dla sumatora. Jeśli użyjemy sumatora szeregowego, to zanim pojawią się wyż­
sze bity iloczynu (p 2n_ 1, P2n-i, ..., Pn), upływa kolejnych 0(n) jednostek czasu.

754
29.3. UKŁADY MNOŻĄCE

Jeżeli natomiast zostanie użyty sumator równoległy, to potrzeba dodat-


kowo tylko E>(lgn) czasu, lecz całkowity czas działania układu pozostaje
równy E>(n).
W skład tablicowego układu mnożącego wchodzi n2 bramek AND oraz
n2 - n sumatorów pełnych. Sumator potrzebny do uzyskania górnej połowy
bitów iloczynu powiększa liczbę bramek o kolejne 0(n). Całkowity rozmiar
tablicowego układu mnożącego wynosi więc 0(n 2 ).

29.3.2. Drzewa Wallace'a


Dnewo Wallace'& to układ, w którym problem dodania n liczb n-bitowych jest
sprowadzany do problemu zsumowania 2 liczb 0(n)-bitowych. Wykorzystując
równolegle Ln/3J sumatorów z zapamiętywaniem przeniesień, można sprowa-
dzić sumę n liczb do sumy f2n/Jl liczb. Dalej wystarczy już rekurencyjnie za-
stosować drzewo Wallace'a do pozostałych f2n/Jl liczb. W ten właśnie sposób
zbiór liczb do zsumowania jest sukcesywnie pomniejszany, aż pozostaną tylko
2 liczby. Dzięki równoległemu sumowaniu z zapamiętywaniem przeniesień
drzewa Wallace'a umożliwiają pomnożenie dwóch liczb n-bitowych w czasie
0(lgn) przy użyciu układu o rozmiarze 0(n 2).
Na rysunku 29.16 widać drzewo Wallace'a 1l sumujące 8 iloczynów częś­
ciowych m(0 >,m<1 l, ... , m(7 >.Iloczyn częściowy mU>składa się z n+ i bitów.
Każda linia repre7,entuje całą liczbę, a nie pojedynczy bit; obok każdej linii
znajduje się liczba bitów, które ta linia reprezentuje (patrz zad. 29.3-3). Suma-
tor z podglądem przeniesień na dole dodaje (2n - 1)-bitową liczbę do liczby
2n-bitowej, co daje w wyniku 2n-bitowy iloczyn.

Analiza
Czas działania drzewa Wallace'a o n wejściach zależy od głębokości sumato-
rów z zapamiętywaniem przeniesień. Na kai,dym po7iomie drzewa kolejne trój-
ki liczb zostają przetworzone w pary liczb, oprócz co najwyżej 2 liczb (takich
7
jak np. m<6 l i m<"> w pierwszej fazie). Wynika stąd, że maksymalną głębokość
D(n) górnej części drzewa Wallace'a o n wejściach można wyrazić w postaci
następującej równania rekurencyjnego:

o dla n~ 2
D(n) - I dlan=3
D(12n/3l) + I dla n~4

Jak widać na tym rysunku, drzewo Wallace'a nie jest faktycznie drzewem, lecz acyklicznym
ii
grafem skierowanym. Nazwa została zachowana ze względów historycznych.

-------------------------------~=
755
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

m ", m ",
14 15

j1•
p

Rys. 29.16. Drzewo Wallace'a które sumuje 11= 8 iloczynów częściowych m1°l,m0 l, ..., mP). Każda
linia oznacza w istocie liczbę; obok każdej linii znajduje się liczba bitów, które ta linia reprezen-
tuje. Lewe wyjście kaWego sumatora z zapamiętywaniem przeniesień omacza bit sumy, a prawe
bit przeniesienia

którego rozwiąz.aniem jest D(n) = @(lgn) (por. przypadek 2 tw. 4.1 o rekuren-
cji uniwersalnej). Każdy sumator z zapamiętywaniem przeniesień działa w cz.a-
sie @(l). Wszystkie n częściowych iloczynów można wyznaczyć równolegle
w czasie @(1). (Najniższe i - 1 bitów mt0 , dla i= 1, 2, ... , n - 1, można na
stałe połączyć z O). Sumator równoległy działa w czasie 0(1g n). Stąd całkowity
czas mnożenia dwóch n-bitowych liczb jest równy 8(Jgn).
Układ mnożący n-bitowe liczby, oparty na drzewach Wallace'a, ma roz-
miar 0(n 2 ). Można się o tym przekonać, przeprowadzając następujące rozu-
mowanie. Oszacujemy najpierw rozmiar górnej części drzewa Wallace'a. Sto-
sunkowo łatwo jest otrzymać dolne ograniczenie O(n 2), ponieważ na pierw-
szym poziomie znajduje się L2n/3J sumatorów z zapamiętywaniem przeniesień,
z których każdy zawiera co najmniej n sumatorów pełnych. Aby uzyskać górne
ograniczenie O(n 2 ) zauważmy, że każdy sumator z zapamiętywaniem. przenie-
sień w drzewie Wallace'a zawiera co najwyżej 2n sumatorów pełnych, ponie-
waż ostateczny iloczyn ma 2n bitów. Wystarczy zatem wykazać, że w drzewie
Wallace'a jest w sumie tylko O(n) sumatorów z zapamiętywaniem przeniesień.
Niech C(n) będzie całkowitą liczbą sumatorów z zapamiętywaniem przeniesień
29.J. UKŁADY MNOŻĄCE

w drzewie Wallace'a z n liczbami na wejściu. Prawdziwa jest następująca zależ­


ność rekurencyjna:

jeśli n=3
C(n) <:{ ~(f2n/Jl) + Ln/3J, jeśli n~4

której rozwiązaniem jest C(n) = @(n) z punktu 3 twierdzenia o rekurencji


uniwersalnej. Uzyskaliśmy więc asymptotycznie dokładne oszacowanie @(n 2)
na ro2JIIiar górnej części drzewa Wallace'a. Iloczyny częściowe można wy-
generować za pomocą układu o rozmiarze 0(n 2 ), a sumator równoległy
w ostatniej fazie ma ro2JIIiar @(n). Stąd całkowity ro2JIIiar układu mnożącego
wynosi 0(n 2 ).
Układ mnożący oparty na drzewie Wallace'a jest asymptotycznie szybszy
niż tablicowy układ mnożący, mając ten sam asymptotycznie ro2JIIiar, lecz jego
struktura nie jest tak regularna jak układu tablicowego (co jest istotne, gdy
dążymy do fizycznej realizacji). Sprawia to, że nie jest on dość „gęsty'' (między
bramkami w układzie pozostaje dużo nie wykorzystanego miejsca). W prakty-
ce stosuje się zwykle rozwiązania kompromisowe. Używa się na przykład
dwóch równoległych tablic, z których każda sumuje połowę iloczynów częścio­
wych. Czas propagacji jest wtedy dwa razy mniejszy niż w przypadku jednej
tablicy, w której dodaje się wszystkie n iloczynów częściowych. Dwa dodatko-
we sumatory z zapamiętywaniem przeniesień redukują cztery liczby wygenero-
wane przez dwie tablice do dwóch liczb, które następnie zostają dodane za
pomocą sumatora równoległego. Całkowity czas propagacji jest nieco większy
niż połowa odpowiedniego czasu dla pojedynczego układu tablicowego plus
dodatkowy czas O(lgn).

ZADANIA
vY=
29.3-1. Udowodnij, że w tablicowym układzie mnożącym 1 O dla i= 1, 2,
..., n - 1 orazj = O, 1, ..., i, i+ n, i+ n+ 1, ..., 2n - 1.
29.3-2. Wykaż, że w tablicowym układzie mnożącym z rys. 29.14 wszystkie
(oprócz jednego) sumatory pełne w najwyższym rzędzie są zbędne. W wy-
niku ich usunięcia niektóre połączenia będą inaczej poprowadzone.
29.3-3. Zaló:imy, że sumator z zapamiętywaniem przeniesień ma wejścia x,
y i z oraz wyjścia si co długościach odpowiednio n"',ny, nz, n, i nc bitów.
Przyjmijmy również, bez straty ogólności, że nx ~ ny ~ n,. Wykaż, że
ns = nz oraz ze

n, dla
n -
0
{ n,+ 1 dla

29.3-4. Wykaż, że można wykonywać mnożenie w czasie O(lgn) za pomocą


układu o rozmiarze O(n 2), nawet jeśli ograniczymy się do bramek o ogra-
niczonym przez stalą wyjściowym stopniu rozgałęzienia.
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

29.3-S. Opisz efektywny algorytm obliczania ilorazu liczby binarnej x przez 3.


(Wskazówka: Wykorzystaj fakt, że zapisując liczby binamie, otrzymujemy
tożsamość: .010101... - .Ol x I.Ol x 1.0001 x ... ).
29.~. Załóżmy, że dana jest liczba x = (xn_ 1, xn_2 , ••. , x 0 ) oraz s = (s,,,_ 1,
sm_2, ••. , s0 ), gdziem= r-Ignl. Przesunięcie cykliczne liczby x os bitów jest
liczbą y = <Yn-l•Yn-l• ... , y 0) taką, że Y 1 = X 1+,modn dla i= O, 1, ... , n -1.
Zaprojektuj układ efektywnie obliczający przesunięcie cykliczne. Jak wy-
razić funkcję „przesunięcie cykliczne" za pomocą mnożenia modulo?

29.4. Układy z taktowaną pamięcią

W układachkombinacyjnych każda bramka jest używana tylko raz w trakcie


obliczeń. Elementy układów można wykorzystywać wielokrotnie, jeśli wpro-
wadzi się do nich taktowane jednostki pamięci (rejestry). Dzięki wielokrot-
nemu użyciu elementów układy z taktowaną pamięcią mogą być znacznie
mniejsze niż analogiczne układy bez rejestrów.
W tym podrozdziale omówimy układy z taktowaną pamięcią, za pomocą
których można dodawać i mnożyć liczby. Rozpoczniemy od przedstawienia
układu o rozmiarze 0(1), zwanego bitowym sumatorem szeregowym, dodają­
cego dwie n-bitowe liczby w czasie 0(n). Następnie zajmiemy się układami
mnożącymi o strukturze wektora. Przedstawimy wektorowy układ mnożący
o rozmiarze 0(n), mnożący dwie liczby n-bitowe w czasie 0(n).

29.4.1. Bitowy sumator szeregowy


Wprowadzimy pojęcie u.kładu z taktowaną pamięcią na przykładzie problemu
dodawania dwóch liczb n-bitowych. Na rysunku 29.17 widać sposób użycia
jednego sumatora pełnego w celu uzyskania (n+ 1)-bitowej sumy s = (sn, sn-i•
... , s0) dwóch liczb n-bitowych a= (an-I• an_2, ••• , a 0) i b = (bn--ł• bn_2 , .•. , b0).
Na wejście sumatora bity są podawane parami: najpierw a0 i b0 , potem a 1 i b 1
itd. Chcemy, aby wyjściowy bit przeniesienia z jednej pozycji był jednocześnie
wejściowym bitem przeniesienia na następnej pozycji, lecz nie możemy połą­
czyć wyjścia sumatora pełnego bezpośrednio z jego wejściem. Pojawia się
bowiem problem z synchronizacją: bit przeniesienia p 1 musi pojawiać się jed-
nocześnie z wartościami na wejściach a; i b1• Jeśli bit przeniesienia nie pojawi się
w tej samej chwili co odpowiadające mu wartości wejściowe, to wynik może
być niepoprawny.
Jak widać na rys. 29.17, rozwiązanie problemu synchronizacji stanowią
układy z taktowaną pamięcią, składające się z układu wzbogaconego o jeden
lub więcej rejestrów. Dane wejściowe układu są wówczas podawane z zewnątrz
albo z wyjść rejestrów. Podobnie, wartości wyjściowe układu można kierować

758
29.4. UKŁADY Z TAKTOWANĄ PAMIĘCIĄ

,, ,, ''
,,
o ' I o ti
I I I o FA I u o- FA I
FA ,- :c FA ,, ,-
''
'' '' '' 'o ' ' li
I o 10 I Il

", h, ' '½ h, a, ", h,


. .,..... ..,., ...•.. ;;™: "
.....
.... 111'1"
"

-..
"" '
'
;,gąem: r:;~f,!ifii
.-
1)

..
'"'""'
;'\ęjifh" 'I«-J
'W"."'111'tł ....,,.,;
......... ~

- - )"""•·•'' "'• t::d", '"'""


....
·····"···
su

(a) (bi (c) (d) Je)

Rys. 29.17. Działanie bitowego sumatora szeregowego. Podczas i-tego okresu sygnału zegarowego
dJa i = O, 1, ..., n sumator pełny FA pobiera na wejścia bity a 1 i b, ze świata zewnętrznego, oraz bit
p, z rejestru. Sumator pełny umieszcza bit .f,na wyjściu z obwodu, a bit przeniesienia P1+i posyła do
rejestru, do wykorzystania w następnym okresie zegarowym. Rejestr jest inicjowany wartością
p 0 = O.{a)-{e) Stan układu w każdym z pięciu okresów zegarowych, podc:r.as obliczania sumy liczb
a= (1011) i b = (1001), tj. s = (10100)

albo poza układ, albo do wejść rejestrów. Tak samo jak w przypadku układów
kombinacyjnych, na fragmenty układów kombinacyjnych w układach z tak~
towaną pamięcią nakładamy ograniczenie, że nie mogą one zawierać cykli.
Każdy rejestr w układzie z taktowaną pamięcią jest sterowany sygnałem
okresowym, zwanym inaczej sygnałem zegarowym. Za każdym razem, gdy syg-
nał zegarowy ma wartość 1, rejestr zapamiętuje wartość znajdującą się wów-
czas na jego wejściu. Czas między kolejnymi impulsami zegara nazywamy jego
okresem. W globalnie taktowanym układzie wszystkie rejestry są sterowane za
pomocą tego samego zegara.
Przyjrzyjmy się dokładniej działaniu rejestru. Każdy impuls zegarowy jest
traktowany jako punkt w czasie. W chwili jego wygenerowania przez zegar
rejestr odczytuje wartość znajdującą się na wejściu w tej chwili i ją zapamiętuje.
Ta zapamiętana wartość pojawia się następnie na wyjściu rejestru, gdzie może
posłużyć do obliczenia wartości, które zostaną umieszczone w rejestrach przy
następnym impulsie z zegara. Innymi słowy, wartość znajdująca się na wejściu
rejestru w pewnym czasie między kolejnymi impulsami zegara pojawia się na
jego wyjściu w następnym okresie między impulsami.
Zajmiemy się teraz szczegółowym omówieniem układu z rys. 29.17, zwa-
nego bitowym sumatorem szeregowym. Aby zapewnić poprawność wyników
sumatora pełnego, będziemy zakładać, że okres sygnału zegarowego jest nie
mniejszy niż czas propagacji sumatora, co gwarantuje, że wartości w układzie
mają czas na ustabilizowanie się między kolejnymi impulsami. Kiedy wartość
sygnału zegarowego (rys. 29.17a) wynosi O, na wejścia sumatora pełnego są
podawane wartości bitów a0 i b0 • Zakładamy, że rejestr zostaje zainicjowany
--------- ---- ....
,.---------~=
759
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

tak, że początkowo zawiera wartość O;początkowy bit przeniesienia, które jest


odczytywane z wyjścia rejestru, jest więc równy c0 = O. Nieco później, lecz
jesz.cze wtedy, gdy wartość sygnału zegarowego wynosi O, ustalają się wartości
na wyjściu s0 sumatora pełnego oraz wyjściu bitu przeniesienia c1• Bit sumy
zostaje skierowany na wyjście układu, gdzie zostanie zapewne zapamiętany
jako część całej sumy s. Wartość przeniesienia jest podawana na wejścia rejest-
ru, więc c1 zostaje wczytane do rejestru przy następnym takcie zegara. Stąd od
początku pierwszego okresu zegarowego rejestr zawiera wartość c 1• W tym
pierwszym okresie zegarowym, poka:,,anym na rys. 29.17b, na wejścia sumato-
ra pełnego są podawane wartości a 1 i b 1• Sumator, odczytując z rejestru war-
tość c1, generuje wartości s 1 oraz c2• Bit sumy s 1 zostaje skierowany na wyjście,
a bit c2 zostaje przesłany do rejestru. Ten cykl powtarza się n razy, jak widać na
rys. 29.l?e, na którym rejestr zawiera wartość c,,. Na wejścia są wówczas poda-
wane wartości a,,= b,.= O, dzięki czemu otrzymujemy s,, = c,,.

Analiza
Aby ustalić całkowity czas t obliczenia wykonywanego przez globalnie tak-
towany układ, trzeba znać liczbę p niezbędnych okresów zegarowych oraz dłu­
gość każdego okresu d; wtedy t = pd. Długość okresu zegarowego musi wy-
starczać na ustabilizowanie się wszystkich wartości w układzie między kolej-
nymi taktami zegara. Mimo źe dla niektórych danych wejściowych układ może
się stabilizować wcześniej, jednak aby można było mieć gwarancję, że działa
poprawnie dla wszystkich danych, d musi być co najmniej proporcjonalne do
głębokości układu.
Oszacujmy czas potrzebny na dodanie dwóch liczb n-bitowych za pomocą
bitowego sumatora szeregowego. Każdy okres zegarowy ma długość 0(1), po-
nieważ głębokość sumatora dwubitowego wynosi 0(1). Wygenerowanie wszys-
tkich danych wyjściowych wymaga n + l taktów zegara, czas działania bitowe-
go sumatora szeregowego jest więc równy (n+ 1)0(1) = 0(n).
Rozmiar bitowego sumatora szeregowego (liczba bramek oraz rejestrów)
wynosi 0(1 ).

Porównanie dodawania szeregowegoz bitowym dodawaniem


szeregowym
Zwróćmy uwagę, że sumator szeregowy odpowiada zwielokrotnionemu bito-
wemu sumatorowi szeregowemu, w którym rejestry zastąpiono przez bezpo-
średnie połączenia między bramkami. Inaczej mówiąc, sumator szeregowy od-
powiada przestrzennemu „rozwinięciu" obliczenia bitowego sumatora szerego-
wego, w którym i-ty sumator pełny zastępuje i-ty okres zegarowy bitowego
sumatora szeregowego.

760
29.4. UKŁADY Z TAKTOWANĄ PAMIĘCIĄ

Ogólnie, zawsze możemy zastąpić układ z taktowaną pamięcią przez rów-


noważny układ kombinacyjny, jeśli z góry wiemy, ile potrzeba okresów zegaro-
wych na przeprowadzenie obliczeń. Mamy tu oczywiście do czynienia z pew-
nym kompromisem pomiędzy zasobami. Z jednej strony układy taktowane
potrzebują znacznie mniej bramek (np. w bitowym sumatorze szeregowym jest
@(n) razy mniej bramek niż w sumatorze szeregowym), lecz z drugiej strony
układy kombinacyjne mają prostsze elementy sterujące - nie jest potrzebny
zewnętrzny zegar ani synchronizowany układ zewnętrzny, który dostarcza da-
ne wejściowe do układu i zapamiętuje wyniki. Co więcej, mimo że układy mają
taki sam asymptotyczny czas działania, układy kombinacyjne działają zwykle
nieco szybciej. Dodatkowe przyspieszenie jest możliwe dzięki temu, że zwyczaj-
ny układ nie musi czekać na ustalenie się wszystkich wartości podczas każdego
okresu zegarowego. Jeśli wartości na wszystkich wejściach od razu się ustalą,
to zmiana stanów w układzie zachodzi z maksymalną możliwą szybkością, bez
czekania na impuls zegara.

29.4.2. Wektoroweukłady mnożące

Układy mnożące dwie liczby n-bitowe z podrozdz. 29.3 mają rozmiar 0(n 2
).
Przestawimy teraz dwa układy mnożące o strukturze wektora (a nie jak po-
przednio tablicy dwuwymiarowej). Szybszy z nich działa w czasie @(n).
Wektorowe układy mnożące są implementacją algorytmu rosyjskich wieś­
niaków (nazwa bierze się stąd, że ludzie z Zachodu odwiedzający Rosję w XIX
w. odkryli, że jest on tam powszechnie stosowany), którego działanie jest przed-
stawione na rys. 29.18a. Dla danych dwóch liczb a i b tworzymy dwie kolumny
liczb, z liczbami a i b na ich początku. W każdym wierszu wartość w kolum-
nie a jest połową poprzedniej wartości w kolumnie a z „obciętą" ewentualną

b b
",,.·-Ó;;'·;;:'ff'f'
"ftl '
"
Ji>OJ'f' r11.01
~.;·;Jt ''36'·" '1001' 111010
4 116 j(}(J l l 10100
2 232 l (J l '' 10100()
'

I( I ;'·~ I 111010000
_____
_,
'

551 !0001001 I !
(a) (b)

Rys. 29.18. Mnożenie 19 przez 29 za pomocą


algorytmu rosyjskich wieśniaków. W każdym wiersm
wartość w kolumnie a jest polową poprzedniej wartości w kolumnie a z „obciętą" ewentualną
częścią ułamkową.. W kolumnie b majduje się dwukrotność poprzedniej wartości. Dodajemy do
siebie wszystkie liczby z kolumy h, dla których odpowiednie wartości z kolumny a są nieparzyste.
Te rzędy zostały na rysunku zacieniowane. Ich suma jest szukanym iloczynem. (a) Liczby zapisane
driesiętnie. (b) Te same liczby w ukladrie dwójkowym

761
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

Numer komórki Numer komórki


9 8 7 6 5 4 3 2 I O 9876543210
a(O)= 19
b(0)=29
U(O) =0
v(O) =0

(l{l) =9 a(
1)=9

b(l):58 b(l)=58
1
p(l)"' 29 ,} ) = 29
V(!): 0

(l(2)"" 4 a\Z) =4
2 2
b( )=116 b( )=116
p(Z) = 87 ,} 2l = 39
v(l) =48

(l(3) =2 a(
3l = 2
3
b( )=232 b(3)=232
p(3) = 87 u(
3) = 39
3
v( ) = 48

a(
4l,,, I a(
4) = 1
4 4
b( )=464 b( ) =464
p(4) = 87 ,/ 4)"' 39
4
v( ) = 48

(l(5)=0 a(S) =0
b(S)=928 b(S)=928
p(5): 551 u(SJ= 455
,} 51= 96

(•) (b)

Rys. 29.19. Wektorowa implementacja algorytmu rosyjskich wieśniaków, na przykładzie mnożenia


a= 19 = < 1001 I) przez b = 29 = <I I !Ol), czyli dla n = 5. Pokazana jest sytuacja przed każdym
j-lym krokiem; pozostają.ce znaczące bity aW oraz bw zostały zacieniowane. {a) Wolniejsza im-
plementacja działają.ca w czasie 0(n 2). 7..achodzip( 5l = a· b, ponieważ af~l = O. W każdym z n kro-
ków algorytmu odbywa się sumowanie potokowe. Długość pojedynczego okresu zegarowego
jest proporcjonalna do długości tablicy, tj. 0(n), co daje w sumie czas 0(n 2 ). (b) Szybsza im-
plementacja, działająca w czasie0(n), dzięki użyciu w każdym kroku sumowania z zapamiętywa­
niem przeniesień, które działa w czasie za.ledwie 0(1). W sumie wykonuje się 2n ~ 1 = 9 kroków;
po ostatnim przedstawionym kroku, kolejne dodawania z zapamiętywaniem przeniesień dają
w końcu u!9 l = a·b

762
29.4. UKŁADY Z TAKTOWANĄ PAMIĘCIĄ

częścią ułamkową. W kolumnie b znajduje się dwukrotność poprzedniej warto-


ści. W ostatnim wierszu wartość w kolumnie a jest równa 1. Następnie bierze-
my pod uwagę wszystkie wartości z kolumny b, dla których odpowiednia war-
tość w kolumnie a jest nieparzysta. Ich suma jest równa iloczynowi a· b.
Chociaż algorytm rosyjskich wieśniaków wydaje się dość zaawansowany,
na rys. 29.18b widać, że w rzeczywistości jest to implementacja szkolnego algo-
rytmu mnożenia pisemnego w układzie dwójkowym, z liczbami zapisywanymi
dziesiętnie, a nie binamie. Wiersze, w których wartość z kolumny a jest niepa-
rzysta, wnoszą do iloczynu wyraz b, pomnożony przez odpowiednią potęgę 2.

Wolna implementacja wektorowa


Na rysunku 29.19a jest przedstawiony jeden ze sposobów implementacji al-
gorytmu rosyjskich wieśniak.ów dla liczb n-bitowych. Układ taktowany zega-
rem składa się z wektora o 2n komórkach. Każda komórka zawiera trzy rejest-
ry. Jeden z nich zawiera bit z wejścia a, drugi bit z wejścia b, a trzeci bit
iloczynu p. Wartość bitu a; przedj-tym krokiem algorytmu będziemy oznaczać
przez a,(Jl., aU) z defi 1ruuJemy
. . .
następująco.. aUl -- ( 02<n- , a2U>.., , .•• , ao
Ul) .
11 1 11 2
Algorytm wykonuje n kroków, numerowanych O, I, ... , n - l; każdy krok
trwa jeden okres zegarowy. W trakcie działania algorytmu jest zachowywany
niezmiennik, że przed )-tym krokiem zachodzi

(29.6)

(por. zad. 29.4-2). Początkowo a<0 > = a, b10l = b oraz pt 0J = O. W )-tym kroku
są wykonywane następujące obliczenia:

1. Jeśli aU!jest nieparzyste (tj. aW> = 1), to dodaj b do p: pu+ 1>-bf.J1 + pw.
(Dodawanie odbywa się za pomocą sumatora szeregowego rozpiętego przez
długość całego wektora; bity przeniesienia przepływają od prawej do lewej).
Jeśli aUl jest parzyste, top pozostaje niezmienione: pU+tJ - pUJ.
2. Przesuń a w prawo o jedną pozycję:

a,
u+iJ
-
{aPJdla
1 i:::;-;;2n - 2
O::;-;;
O dlai=2n-1

3. Przesuń b w lewo o jedną pozycję

p+i>_ U>1 dla o::;-;;1::;-;;2n-1


b,_ .
6
{O dlai=O

Po wykonaniu n kroków zostaną przesunięte wszystkie bity a, więc a(~) = O.


Z niezmiennika 29.5 wynika, że wtedy p<11l = a· b.
--------
763
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

Dokonamy teraz analizy tego algorytmu. Zakładając, że sterowanie operu-


je jednocześnie na wszystkich komórkach, wykonujemy w sumie n kroków.
Każdy krok zajmuje w najgorszym przypadku 0(n) czasu, ponieważ głębokość
sumatora szeregowego wynosi 0(n); stąd długość każdego okresu zegarowego
musi być co najmniej 0(n). Każde przesunięcie zajmuje tylko 0(1) czasu.
W sumie czas działania algorytmu wynosi 0(n 2). Rozmiar tablicowego układu
mnożącego wynosi 0(n), ponieważ każda komórka ma rozmiar ograniczony
przez stałą.

Szybka implementacja wektorowa


Używając sumatora z zapamiętywaniem przeniesień zamiast sumatora szerego-
wego, możemy zredukować czas potrz.ebny na wykonanie każdego kroku do
0(1), poprawiając czas działania całego układu do E>(n). Jak widać na rys.
29.19b, ponownie każda komórka zawiera jeden bit z a oraz jeden bit z b.
W każdej komórce są pamiętane dodatkowo dwa bity, po jednym z u oraz z v,
pochodzące z wyjścia sumatora z zapamiętywaniem przeniesień. W czasie obli-
czania iloczynu za pomocą układu zawierającego sumator z zapamiętywaniem
przeniesień zachowywany jest niezmiennik, że przed j-tym· krok.iem zachodzi

(29.7)

(por. zad. 29.4-2). W każdym kroku a i b są przesuwane, tak jak w wolniejszej


implementacji, więc w sumie równania (29.6) i (29.7) implikują uU>+ vU>= cU>.
Stąd bity u oraz v zawierają tę samą informację co bity c w wolniejszej im-
plementacji.
W j-tym kroku szybszej implementacji jest wykonywane dodawanie
u i v z zapamiętywaniem przeniesień, przy czym dodawane wartości zależą od
tego, czy ajest parzyste czy nieparz.yste. Jeśli aW
1 = 1, to obliczamy

uP+t) +- parity(bP 1, uP),vP,) dla i= O, 1, ... , 2n - 1


oraz
. . (b'"
vp+i>+- ;aJortty (,)1 , vr-
r- 1, u,- li)
1) dlal~i~2n-l
{ dlai=O
Jeżeli natomiast a~ = 1, to obliczamy
up+tJ +- parity(O, uP,, v}il) dla i= O, I, ..., 2n - I
oraz
(J+ll {majority(O, uY.?-
1 , vP2
1) dlal~i~2n-1
v, ,+- o dlai=O

764
PROBLEMY

Po zaktualizowaniu wartości u i v w każdym kroku a zostaje przesunięte w pra-


wo, a b w lewo, podobnie jak w wolniejszej implementacji.
Szybsza implementacja wykonuje w sumie 2n-1 kroków. Dlaj~ n za-
chodzi aUl = O, więc z niezmiennika (29.7) wynika, że ulf> + vUl = a·b. Gdy już
ustali się aUl = O, pozostałe kroki są tylko po to, aby zsumować u i v za pomo-
cą dodawania z zapamiętywaniem przeniesień. Wykazanie, że v<2"- 1> = O (skąd
wynika już, że u( 2 ,,·- 1J = a· b) jest przedmiotem zadania 29.4-3.
Całkowity czas działania w pesymistycznym przypadku wynosi 0(n), po-
nieważ każdy z 2n - 1 kroków trwa 0(1) jednostek czasu. Całkowity rozmiar
układu jest równy 0(n), ponieważ każda z komórek ma rozmiar 0(1).

ZADANIA
29.4-1. Mając dane a= (101101 ), b = (Ol 1110) oraz n = 6, przedstaw dzia-
łanie algorytmu rosyjskich wieśniaków na liczbach a i b, zarówno w no-
tacji dziesiętnej, jak i dwójkowej.
29.4-2. Wykaż, że niezmienniki (29.6) i (29.7) są zachowywane przez wektoro-
we układy mnożące.
29.4-3. Wykaż, że w szybszej wersji wektorowego układu mnożącego zachodzi
vt2,,-1J = O. ·
29.4-4. Przeanalizuj i opisz, w jaki sposób można potraktować tablicowy
układ mnożący z podrozdz. 29.3.1, jako rozwinięcie szybszego wektorowe-
go układu mnożącego.
29.4-5. Niech (x 1, x 2, ••• ) będzie ciągiem wartości emitowanych po jednej na
każdy impuls zegara. Dla ustalonej liczby n, układ ma obliczać wartość

y1 = max x1
r--,,+1..;i,;;1

dla t = n, n + 1, ... Inaczej mówiąc, y 1 jest największą spośród n ostatnio


odebranych przez układ wartości. Zaprojektuj układ o rozmiarze O(n),
który w każdym okresie zegarowym odbiera wartość x 1 i wyznacza wartość
y 1 w czasie 0(1), W skład układu mogą wchodzić rejestry oraz bramki
obliczające maksimum z dwóch liczb.
* 29.4-6. Rozwiąż zadanie 29.4-5, używając tylko O(lgn) bramek „maksimum".

Problemy
29-1. Układy dzielące
Układ dzielący można zbudować z układów odejmujących i mnożących, wyko-
rzystując metodę zwaną iteracją Newtona. My zajmiemy się zbliżonym prob-
lemem - obliczania odwrotności, ponieważ dodanie do układu obliczającego
odwrotności jednego układu mnożącego, daje w efekcie układ dzielący.

765
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

Pomysł polega na obliczaniu ciągu y0 , y 1, .. , przybliżeń odwrotności liczby


• •
x przy uzyc1u wzoru

Załóżmy, że liczba x jest dana jako n-bitowy ułamek z przedziału 1/2 ~ x ~ 1.


Odwrotność może być ułamkiem z nieskończonym rozwinięciem cyklicznym,
ograniczymy się więc do obliczenia n-bitowego przybliżenia z dokładnością do
najmniej znaczącego bitu.
(a) Przyjmij, że IY;- 1/zl::;;:
e dla pewnej stałej e > O. Udowodnij, że
lY;+i - 1/z)::;;:e2 •
(b) Wskaż początkowe przybliżenie y 0 takie, że Yk spełnia zależność
lvk - 1/zl ::;;:2 - 2.t dla każdego k ~ O. Jakie duże musi być k, aby Yk było
równe odwrotności x z dokładnością do najmniej znaczącego bitu?
(c) Zaprojektuj układ, który dla danej n-bitowej liczby x oblicza n-bitowe
przybliżenie liczby 1/z w czasie O(lg 2 n). Jaki jest rozmiar Twojego układu?
(Wskazówka: Przy odrobinie pomysłowości można poprawić ograniczenie
E>(n2 lgn) na rozmiar układu).

29-2. Formuły logiczne dla symetrycznych funkcji logicznych


Funkcja n-argumentowa /(x 1, Xi, ... , xn) jest symetryczna, jeśli /(x 1, Xi,
..., xJ =/(x,,_(iJ,x,,_c
2i, ... , x,.(n))dla dowolnej permutacji 1t zbioru {l, 2, ... , n}.
Naszym celem będzie wykazanie, że dla każdej funkcji symetrycznej f
istnieje formuła logiczna reprezentująca f o rozmiarze wielomianowym wzglę­
dem n. (Dla naszych celów formula logiczna będzie słowem złożonym ze
zmiennych x 1, x 2, ... , xn, nawiasów oraz spójników logicznych v, A oraz •).
Dokonamy tego, zamieniając układ o logarytmicznej głębokości na rów-
noważną formułę o rozmiarze wielomianowym. Będziemy zakładać, że
wszystkie układy są zbudowane z 2-wejściowych bramek AND i OR oraz
bramek NOT.

(a) Rozpoczniemy od bardzo prostej funkcji symetrycznej. Uogólniona n-ar-


gumentowa funkcja majority (,,większość'') jest zdefiniowana następująco:

. . (Xi, x 1 + x 2 + ...+ Xn > n/2


jeśli
maJor1tyn Xi, ... , xJ = { O,
I, .
w przeciwnym razie
.

Zaprojektuj układ obliczający funkcję


majority" o głębokości O(lgn).
(Wskazówka: Zbuduj drzewo sumatorów).
(b) Niech/ będzie dowolną funkcją logiczną n zmiennych binarnych x 1, x 2, ... ,
xn. Załóżmy też, że istnieje układ C o głębokości d, obliczający funkcję f

766
UWAG! DO ROZDZIAŁU

Pokaż, jak na podstawie C skonstruować formułę logiczną reprezentującą


f o długości 0(2d). Wyciągnij stąd wniosek, że istnieje formuła o wielo-
mianowej długości reprezentująca funkcję majority n.
(c) Wykaż, że każda symetryczna funkcja logiczna J(x 1, x 2, ... , xn) moi.e być
"
przedstawiona jako funkcja Lx;.
;~ 1
(d) Wykaż, że każda n-argumentowa symetryczna funkcja logiczna może zo-
stać obliczona za pomocą układu o głębokości O(lgn).
(e) Wykaż, i.e każdą n-argumentową symetryczną funkcję logiczną można
reprezentować za pomocą formuły logicznej o długości wielomianowej
względem n.

Uwagido rozdziału
Większość ksiąi.ek o arytmetyce komputerowej skupia się bardziej na prak-
tycznych aspektach konstrukcji układów niż związanej z tym teorii algoryt-
mów. Savage [173] jest jednym z niewielu autorów, którzy zajmowali się właś­
ciwościami algorytmicznymi. Spośród opracowań, w których omówiono aryt-
metykę komputerową z uwzględnieniem zagadnień dotyczących sprzętu, pole-
camy szczególnie książki Cavanagha [39] i Hwanga [108}. Do dobrych prac na
temat projektowania układów można zaliczyć książkę 1Iilla i Patersona [96]
oraz (uwzględniająe'4 teorię języków formalnych) ksiąźkę Kohaviego [126].
Aiken i Hopper [71sięgają do początków historii algorytmów arytmetycz-
nych. Sumowanie szeregowe jest co najmniej tak stare jak liczydło, które ist-
nieje od około 5000 lat. Pierwsze automatyczne urządzenie wykonujące sumo-
wanie szeregowe zostało skonstruowane przez B. Pascala w 1642 r. Maszyna
licząca wykonująca ciąg dodawań potrzebnych do wyznaczenia iloczynu liczb
została zaprojektowana przez S. Morlanda w 1666 r. oraz niezależnie przez
G.W. Leibniza w 1671 r. Algorytm rosyjskich wieśniaków powstał z pewnością
wcześniej nii. w XIX wieku. Według Knutha [122] był używany przez matema-
tyków egipskich już około 1800 r.p.n.e.
Stany (anuluj, generuj i propaguj) ciągu przeniesień zostały wykorzystane
w maszynie liczącej zbudowanej w Harvardzie w połowie lat czterdziestych
[I 80]. Jedna z pierwszych implementacji sumowania równoległego została opi-
sana przez Weinbergera i Smitha [199], lecz ich metoda wymagała użycia du-
i.ych bramek. Ofman [152) wykazał, i.e można dodawać dwie liczby n-bitowe
w czasie O(lg n) za pomocą dodawania równoległego przy użyciu bramek
o stałym rozmiarze.
Pomysł przyspieszenia mnożenia za pomocą dodawania z zapamiętywaniem
przeniesień pochodzi od Estrina, Gilchrista i Pomerene'a [64]. Atrubin [13]
opisał nieskończony wektorowy układ mnożący, za pomocą którego moi.na

767
ROZDZIAŁ 29. UKŁADY ARYTMETYCZNE

mnożyć liczby binarne o dowolnej długości. Układ ten generuje n-ty bit iloczynu
zaraz po otrzymaniu n~tych bitów z wejścia. Układ mnożą.cy oparty na drzewach
Wallace'a jest przypisywany Wallace'owi [197], lecz na ten sam pomysł wpadł
niezależnie Ofman [152].
Algorytmy dzielenia sięgają czasów I. Newtona, który około 1665 r. wyna~
lazł metodę, nazywaną dziś iteracją Newtona. W problemie 29-1 używamy
iteracji Newtona do zbudowania układu dzielącego o głębokości O(lg n). Tę
2

metodę poprawili Beame, Cook i Hoover [19], którzy wykazali, że dzielenie


liczb n~bitowych można wykonywać w czasie 0(1gn).
Rozdział 30

Algorytmy równoległe

Wraz z rozwojem komputerów umożliwiających przetwarzanie równoległe


wzrosło zainteresowanie algorytmamirównoległymi: algorytmami, które po-
zwalają na wykonywanie w danej chwili więcej niż jednej operacji. Badania
nad algorytmami równoległymi rozwinęły się już na tyle, że możemy mówić
o powstaniu nowej dziedziny badawczej rządzącej się własnymi prawami. Fa-
ktycznie, w ostatnich latach odkryto algorytmy równoległe dla wielu prob-
lemów, które w tej książce rozwiązaliśmy za pomocą zwykłych algorytmów
sekwencyjnych. W tym rozdziale opiszemy kilka prostych algorytmów rów-
noległych, które zilustrują podstawowe pojęcia i metody stosowane w tej dzie-
dzinie informatyki,
żeby móc badać algorytmy równoległe, musimy ustalić wpierw odpowied-
ni model obliczeń równoległych. Maszyna o dostępie swobodnym (RAM), któ-
ra była stosowana w większości rozdziałów tej książki, jest modelem obliczeń
sekwencyjnych. Omawiane przez nas modele równoległe - sieci sortujące
(rozdz. 28) i układy kombinacyjne (rozdz. 29) - są zbyt ograniczone, żeby
można było badać na przykład algorytmy wykorzystujące struktury danych.
Modelem obliczeń równoległych, używanym w tym rozdziale, będzie rów-
noległa maszyna o dostępie swobodnym, oznacz.ana jako PRAM (skrót od
ang. Para/lei Random Access Machine). Wiele algorytmów równoległych dla
tablic, list, drzew i grafów daje się łatwo wyrazić w modelu PRAM. Chociaż
w modelu PRAM pomija się wiele ważnych aspektów rzeczywistych maszyn
równoległych, zasadnicze własności algorytmów są zachowywane. Jeśli w mo-
delu PRAM jeden z algorytmów zachowuje się lepiej niż drugi, to jest mało
prawdopodobne, że ich 'WZględne zachowanie zmieni się istotnie, gdy oba al-
gorytmy zaimplementujemy na rzeczywistym komputerze równoległym.

769
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

Model PRAM
Na rysunku 30. l widać podstawową architekturę maszyny równoległej o do-
stępie swobodnym (PRAM). PRAM składa się z p zwykłych (sekwencyjnych)
procesorów P0 , P 1 , ... , P11_ 1, które mają dostęp do wspólnej, globalnej pamię­
ci. Wszystkie procesory mogą „równolegle" (jednocześnie) odczytywać z pa-
mięci globalnej lub do niej zapisywać. Procesory mogą także wykonywać rów-
nolegle różnorodne operacje arytmetyczne i logiczne.

: '"· ;;;,o,a,;:: :, ;.:.,· ..


"' '" ;;,:;;,,::: ·: ,;·;.:;:
•• '+--~ :·•:,;::,::·::,·::,:·
'•'·.·.'r
...... ....................
...
."'""" , """'"' ....
..............
..................... ,., ..
, .....,.
"
..... ,., .....
........
, "'" , .
, .., ...""".
···•"" """'
.: :::
...
.....
/°'"ro----1
...,r;,..
..
: ·""'";);;;:,
., .......
,............ ,., ......
............
,:,::;
;;y;;;:;;;;; , ......
·::::, ..
.,,,:;;·;;>·.;.,:·,,,
.,..........
, ..
...
..
. ' ... ,. ......
................. """"'"
, ..................
.,".
........................ ',
.... . '" ..............
.....
. ... ~
........ ....... ....... .
'"' "
' • ... : ' ',i ·,Y,j.;i;'
: .. ;'. ·!t'l;
• . ..
;:•,:
~' "'f/ , .. .,
......
;;z;; .. ·,,::::
.......
' ..: ' "'" ,. ""'"'""
.,,.,,.,,s,,,M,.,.M
..........
•. ,·;";
................. • .
.......................
:::::·:::
. ·:;::;: ::r::
.................. .
..
.. ,, ..................
....
:::-.:::::;;;;,;,:;;/g;
, ... .....
.,, "'''"'"'".
" ....... .
.. .........
"
,,
·"""'"'"" .......... .... ..
...
. ...
...........
, ....
... .. .....
,'< .. ,, .....
, .... "..
,., ..

·,·1---- ............. /""'


,.,.,,.,. ....
: · ,;;;;;;;:.11:;r;;;;;;
' .......
' . ...
""""""""'·'"' ,, ....
li. ..,.. . ................
;:;;;;;;;:;;p;,,:;;;,) ,,. .....
,,, ..
'"' "'"
. ..
.._,
...............
,"' ..........
,., """"""'""
, ,.........
..,'"'""'""'·"'"· ,n
.,
Rys. 30.1. Podstawowa architektura maszyny PRAM. Maszyna składa się z p procesorów P 0 , P1 ,
..., Pp- i przyłączonych do wspólnej pamięci. Kaidy procesor może w jednej jednostce czasu od-
wołać się do (zapisać do lub odczytał z) dowolnego słowa wspólnej pamięci

Podstawowym założeniem - jakie przyjmujemy, badając wydajność algo-


rytmów w modelu PRAM - jest, że czas działania może być mierzony liczbą
równoległych dostępów do pamięci, wykonywanych podczas działania algoryt-
mu. To założenie jest prostym uogólnieniem założenia dla zwykłej, sekwencyj-
nej maszyny o dostępie swobodnym, w której czas działania mierzony liczbą
dostępów do pamięci jest asymptotycznie taki sam jak czas działania mierzony
jakąkolwiek inną miarą. To proste założenie będzie nam dobrze służyło w na-
szym przeglądzie algorytmów równoległych, chociaż w rzeczywistych kompu-
terach równoległych dostęp do pamięci globalnej nie jest realizowany w jednej
jednostce czasu: czas dostępu do pamięci rośnie wraz z liczbą procesorów kom-
putera równoległego.
Niemniej jednak przyjęte tu założenie o jednostkowym czasie dostępu do
pamięci ma swoje wytłumaczenie. Rzeczywiste komputery równoległe są za-
zwyczaj wyposażone w sieć komunikacyjną wnożliwiającą realizację abstrak-
cyjnej pamięci globalnej. Odczytywanie lub zapisywanie danych za pomocą
takiej sieci jest relatywnie wolniejsze w porównaniu z operacjami arytmetycz-

770
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

nymi, logicznymi itp. Tak więc zliczanie liczby równoległych dostępów do pa-
mięci w algorytmach równoległych daje w rzeczywistości zupełnie dobrą ocenę
ich względnych wydajności. Słabą stroną założenia o jednostkowym czasie do-
stępu do pamięci w modelu PRAM jest to, że w rzeczywistych maszynach
równoległych pewne realizacje dostępu do pamięci są szybsze od innych. Jed-
nakże, jako pierwsze przybliżenie, założenie o jednostkowym czasie dostępu do
pamięci w modelu PRAM jest całkowicie uzasadnione.
Czas działania algorytmu równoległego zależy od liczby procesorów, na
których ten algorytm jest wykonywany oraz od rozmiaru danych wejściowych.
Dlatego, analizując algorytmy równoległe, musimy zwracać uwagę zarówno na
ich czas działania, jak i na liczbę używanych procesorów. To kontrastuje
z przypadkiem algorytmów sekwencyjnych, w analizie których skupialiśmy się
głównie na czasie działania. Co jest charakterystyczne, to zależność (ang. tra-
de-off) między czasem działania algorytmu równoległego a liczbą używanych
procesorów. Podrozdział 30.3 poświęcimy omówieniu takich zależności.

Dostępy do pamięci: jednoczesneczy wyłączne


Mówimy, że algorytm dla maszyny PRAM jest algorytmem z jednoczesnym
odczytem (lub typu CR; od ang. concurrent-read),jeśli podczas jego wykonywa-
nia wiele procesorów może jednocześnie czytać z tej samej komórki wspólnej
pamięci. Algorytmem z wyłącznym odczytem (lub typu ER; od ang. exclusive-
-read) nazywamy algorytm dla maszyny PRAM, w którym nigdy dwa proceso-
ry nie mogą jednocześnie czytać z tej samej komórki pamięci. Podobne rozróż­
nienie można wprowadzić w wypadku jednoczesnego zapisywania do wspólnej
pamięci, dzieląc algorytmy dla maszyny PRAM na te z jednoczesnym zapisem
(lub typu CW; od ang. concurrent-write) i te z wyłącznym zapisem (lub typu
EW; od ang. exclusive-write). Do oznaczenia różnych typów algorytmów bę­
dziemy używali następujących skrótów:
• EREW - algorytmy z wyłącznym odczytem i wyłącznym zapisem;
• CREW - algorytmy z jednoczesnym odczytem i wyłącznym zapisem;
• ERCW - algorytmy z wyłącznym odczytem i jednoczesnym zapisem;
• CRCW - algorytmy z jednoczesnym odczytem i jednoczesnym zapisem.
Najpopularniejszymi typami algorytmów są dwa skrajne - BREW i CRCW.
Maszyna PRAM, która umożliwia wykonywanie tylko algorytmów typu
BREW, jest nazywana maszyną EREW PRAM, a maszynę umożliwiającą wy-
konywanie algorytmów typu CRCW nazywa się maszyną CRCW PRAM. Na
maszynie CRCW PRAM można oczywiście wykonywać algorytmy typu
EREW, ale maszyna BREW PRAM nie umożliwia bezpośrednio wykonywa-
nia algorytmów typu CRCW. Ponieważ maszyna BREW PRAM nie musi
zapewniać obsługi konfliktów w dostępach do pamięci, architektura takiej

771
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

maszyny jest stosunkowo prosta, a działanie maszyny jest dlatego szybkie. Jeśli
założenie o jednostkowym czasie dostępu do pamięci ma dostarczyć sensownie
dokładnej miary wydajności algorytmów, to CRCW PRAM wymaga bardziej
skomplikowanych rozwiązań sprzętowych. Jednakże pisanie programów na
maszynę CRCW jest bezspornie prostsze niż pisanie programów na maszynę
EREW PRAM.
Z pozostałych dwóch typów algorytrnów-CREW i ERCW - więcej uwagi
w literaturze przedmiotu poświęcono algorytmom typu CREW. Z praktycz-
nego punktu widzenia umożliwienie jednoczesnych zapisów nie jest trudniejsze
niż umożliwienie jednoczesnych odczytów. W tym rozdziale każdy algorytm
dopuszczający jednoczesny odczyt lub jednoczesny zapis będziemy traktowali
jako algorytm typu CRCW, nie rozróżniając typów CREW i CRCW. Pewne
subtelne różnice między tymi typami omówimy w podrozdz. 30.2.
Jeśli nie poczyni się żadnych dodatkowych założeń, to nie jest jasno okreś­
lone, co zostanie zapisane w komórce pamięci w wyniku jednoczesnego zapisy-
wania do niej przez wiele procesorów w algorytmie typu CRCW. W tym roz-
dziale przyjmiemy, że kiedy wiele procesorów jednocześnie zapisuje do tej sa-
mej komórki pamięci, wtedy muszą zapisywać jednolitą (tę sarną) wartość.
Model, w którym przyjmuje się, że konflikty zapisu są rozstrzygane w ten
właśnie sposób, nazywamy jednolitym-CRCW (ang. common-CRCW). W lite-
raturze można spotkać wiele typów maszyny PRAM, które różnią się sposo-
bami rozwiązywania konfliktów zapisu. Można wśród nich wyróżnić sposób
• dowolny (ang. arbitrary) - zapamiętywana jest dowolna wartość z wartości
zapisywanych do tej samej komórki pamięci;
• priorytetowy (ang. priority) - zapamiętywana jest wartość zapisywana przez
. ..
procesor o naJmrueJszym numerze;
• mieszany (ang. combining) - zapamiętywana wartość jest pewną, jednak ściś­
le określoną kombinacją zapisywanych wartości.
W tym ostatnim przypadku ściśle określona kombinacja jest zazwyczaj
ł.ączną i przemienną operacją, jak na przykład dodawanie (zapamiętywana jest
suma zapisywanych wartości) lub branie maksimum (zapamiętywana jest tylko
wartość największa).

Synchronizacja i sterowanie
Algorytmy dla maszyny PRAM działają poprawnie pod warunkiem, że są one
w pełni zsynchronizowane. W jaki sposób taka synchronizacja jest zapewnia-
na? Procesory w algorytmach dla maszyny PRAM muszą często sprawdzać
warunki zakończenia wykonywania pętli, które zależą od stanów wszystkich
procesorów. W jaki sposób implementuje się funkcje, które sterują wykonywa-
niem algorytmów?

772
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

Nie będziemy omawiać szeroko tych zagadnień. W wielu rzeczywistych


komputerach wykorzystuje się sieci sterujące łączące procesory, które pomaga-
ją w synchronizacji i sprawdzaniu warunków końca pętli. Jest charakterystycz-
ne, że za pomocą sieci sterujących funkcje kontrolne można implementować
tak szybko, jak za pomocą sieci wspomagających wymianę informacji (ang.
routing networks) można implementować odwołania do pamięci globalnej.
Dla naszych celów wystarczy przyjąć, że procesory są ściśle zsynchronizo-
wane, bez zagłębiania się, jak to jest rzeczywiście zrobione. Wszystkie proceso-
ry wykonują te same instrukcje w tym samym czasie. Żaden procesor nie roz-
poczyna wykonywania kolejnej instrukcji, dopóki wszystkie nie zakończą wy-
konywania instrukcji bieżącej. Podczas omawiania pierwszego algorytmu rów-
noległego pokażemy, w których miejscach musimy założyć, że procsory są
zsynchronizowane.
Będziemy zakładali, że testowanie warunków zakończenia wykonywania
pętli, które zależą do stanów wszystkich procesorów, można zrealizować za
pomocą sieci sterującej w czasie stałym. Dla pewnych modeli BREW PRAM
spotykanych w literaturze nie robi się tego założenia i do łącznego czasu
działania algorytmu wlicza się czas (logarytmiczny) potrzebny na testowanie
warunków zakończenia wykonywania pętli (patrz zad. 30.1-8). Jak wyjaś­
nimy w podrozdz. 30.2, CRCW PRAM nie potrzebuje sieci sterującej do
testowania warunków zakończenia wykonywania pętli: taki test można prze-
prowadzić w czasie stałym, robiąc użytek z możliwości jednoczesnego zapisu
do pamięci.

Zawartość rozdziału

W podrozdziale 30.1 wprowadzimy metodę przeskakiwania, która pozwala na


szybkie, równolegle manipulowanie listami. Pokażemy, w jak.i sposób zastoso-
wać tę metodę do obliczeń prefiksowych na listach i jak można zaadaptować
szybkie algorytmy dla list do obliczeń na drzewach. W podrozdziale 30.2 omó-
wimy związek między efektywnością algorytmów typów CRCW i BREW oraz
pokażemy, że możliwość jednoczesnego dostępu do pamięci zwiększa moc ob-
liczeniową maszyny PRAM.
W podrozdziale 30.3 zaprezentujemy twierdzenie Brenta, z którego wy~
nika, w jaki sposób można na maszynie PRAM efektywnie symulować układy
kombinacyjne. W tym podrozdziale omówimy także ważny temat dotyczący
efektywności pracy wykonywanej podczas działania algorytmu równoległego
oraz podamy warunki, które muszą być spełnione, żeby można było efektyw-
nie przetłumaczyć algorytm dla p-procesorowej maszyny PRAM na algorytm
dla p'-procesorowej maszyny PRAM, dla każdego p' < p. W podrozdziale 30.4
rozważymy jeszcze raz problem obliczeń prefiksowych na liście i przedstawimy
algorytm probabilistyczny dla tego problemu, który wykonuje małą pracę. Na

773
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

koniec, w podrozdz. 30.5, pokażemy, w jaki sposób można równolegle, deter-


ministycznie złamać symetrię w czasie dużo mniejszym od czasu logaryt-

mtcznego.
Algorytmy prezentowane w tym rozdziale są w większości algorytmami
grafowymi. Stanowią one tylko ubogi wybór z istniejących obecnie algoryt-
mów równoległych. Jednakże metody pokazane w tym rozdziale są w pełni
reprezentatywne dla tych używanych w algorytmach równoległych w innych
działach infonnatyki.

30.1. Przeskakiwanie
Do szczególnie interesujących algorytmów dla maszyny PRAM zalicza się te,
które operują na wskaźnikach. W tym podrozdziale zbadamy bardzo silną
metodę - metodę przesk.akiwaniat - która pozwala na tworzenie szybkich
algorytmów równoległych dla list. W szczególności przedstawimy algorytm,
który w czasie O(lgn) oblicza dla każdego obiektu na liście n-obiektowej jego
odległość od końca listy. Następnie :zmodyfikujemy ten algorytm w taki spo-
sób, żeby można było wykonywać równoległe obliczenia prefiksowe na liście
n-obiektowej, także w czasie O(lgn). Na koniec zaprezentujemy metodę umoż­
liwiającą przekształcanie wielu problemów dla drzew na problemy dla list,
które to można następnie rozwiązać za pomocą przeskakiwania. Wszystkie
algorytmy omawiane w tym podrozdziale są algorytmami typu BREW: jedno-
czesne dostępy do tej samej komórki pamięci nie są wymagane.

30.1.1 . Ustalanie porządku obiektów na liście


Nasz pierwszy algorytm operuje na listach. Listy na maszynie PRAM można
pamiętać tak samo,jak pamięta się listy na zwykłej maszynie RAM. Jednakże,
żeby równolegle operować na obiektach listy, wygodnie jest związać z każdym
obiektem „odpowiedzialny" za ten obiekt procesor, Założymy, że jest danych
tyle procesorów, ile jest obiektów na liście, oraz że i-ty procesor jest odpowie-
dzialny za i-ty obiekt. Na rysunku 30.2a widać przykładową listę (3, 4, 6, 1, O,
5). Procesory odpowiedzialne za swoje obiekty Geden procesor odpowiada za
jeden obiekt listy) mogą operować na nich w czasie stałym.
Przypuśćmy, że jest dana n-obiektowa lista Li chcemy dla każdego obiek-
tu listy L obliczyć jego odległość od końca tej listy. Bardziej fonnalnie, jeśli
next jest wskaźnikiem do następnego obiektu na liście, to chcemy dla każdego
obiektu i policzyć wartość d[i] taką, że

t Cz.asami ta metoda nazywa się metodą podwajania (przyp. tłum.)

=~--""'"""'-··------------------------
774
30. 1. PRZESKAKIWANIE

d[;J = {o,
d[nexr[;JJ + I,
jeśli
jeśli
next[i] = NIL
next [i] # NIL

Problem obliczania wartości d nazywamy problememmtalania porządku obiek-


tów na liście (ang. list-ranking).
Jedno z rozwiązań tego problemu polega po prostu na przekazywaniu
odległości w tył, poczynając od końca listy. Ta metoda zabiera czas @(n),
ponieważ k-ty obiekt od końca musi czekać, aż zostaną policzone odległości
dla wszystkich k ~ 1 obiektów występujących za nim na liście. To rozwiązanie
jest w istocie sekwencyjne.
Procedura LIST-RANK ustala porządek na liście w czasie O(lgn).

LIST-RANK(L)
1 for każdy procesor i in parallel {równolegle wykonaj}
2 doifnext[iJ=NIL
3 then d[i] +- O
4 else d(;J- I
5 while istnieje obiekt i taki, że next [i] # NIL
6 do for każdy procesor i in parallel
7 do if next [i] =f.NIL
8 then d[;J- d(;J + d[nexr[;JJ
9 next[i] +- next[next[i]]

Na rysunku 30.2 jest pokazane, w jaki sposób algorytm LIST-RANK obli-


cza odległości. Każda część rysunku obrazuje stan listy przed wykonaniem

(,) 1'r:3---1a4I:3
· 1 • Etl\'.+·
l'.11 ...W-»tfiiil.3.
6 1 o
1--->•t0:.1IJ
31->-lol/'J
5

4 6 I 5
(b)
-
/'
-- -
JiIZl
3 4 6 I 5
fi]•;;] ~ m.l
. ml
(cl
-
.

- -- 1·oa,1,,.
I

3 6 1 o
(d) llft"'1
l!WLlJ l,'ffiJ 11„d &\111
Rys. 30.Z. Obliczanie odległości obiektów listy od jej końca w czasie O(lg n), gdzie n Jest liczbą obiek-
tów na liście, z wykorzystaniem metody przeskakiwania. (1) Lista z z.ainicjowanymi wartościami d.
Po wykonaniu aJgorytmu d[i] jest równe odległości obiektu i od końca listy. Numer procesora
odpowiedziaJnego za dany obiekt listy jest zapisany nad tym obiektem. (b}-(d) Wskaźniki i wartoś­
ci d po wykonaniu każdej iteracji pętli while w algorylm.ie LIST·RANK
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

jednej iteracji pętli while z wierszy 5-9. W części (a) widać listę zaraz po etapie
inicjowania. W pierwszej iteracji wskaźniki next pierwszych pięciu obiektów
listy są różne od NIL, tak że procesory odpowiedzialne za te elementy wykonu-
ją działania opisane w wierszach 8-9. Wynik obliczeń jest widoczny w części
(b). W drugiej iteratji tylko wskaźniki pierwszych czterech obiektów są różne
od NIL. Wynik wykonania tej operatji jest pokazany w części (c). W trzeciej
iteracji operacje są wykonywane tylko na pierwszych dwóch obiektach. Osta-
teczny wynik wykonania algorytmu LIST-RANK widać w części (d).
Operatję z wiersza 9, polegającą na wykonaniu przypisania next[i] +-
+- next[next[i]], nazywamy pneskokiem. Zauważmy, że wartości pól next
zmieniają się w trakcie wykonywania algorytmu, co powoduje zniszczenie
wejściowej listy. Jeśli lista powinna zostać zachowana, to można zrobić kopie
wskaźników next i używać kopii do obliczania odległości.

Poprawność

W algorytmie LIST-RANKjest zachowywany następujący niezmiennik: dla każ­


dego obiektu i na początku każdej iteracji pętli while z wierszy 5-9 suma war-
tości d w padliście o początku w i jest równa odległości obiektu i od końca
wyjściowej listy L. Dla przykładu na rys. 30.2b pod.listą o początku w obiekcie
3 jest ciąg (3, 6, O). Wartościami d dla obiektów tego ciągu są 2, 2 i I. Suma
wartości d wynosi 5, co jest równe odległości obiektu 3 od końca pierwotnej
listy L. W trak.cie wykonywania algorytmu niezmiennik jest zachowywany,
ponieważ ilekroć jest przerywane połączenie obiektu z jego następnikiem, war-
tość d następnika jest dodawana do wartości d tego obiektu.
Zauważmy, że dla poprawności działania tego algorytmu konieczne jest,
żeby równoległe dostępy do pamięci były zsynchronizowane. Przy każdym wy-
konaniu wiersza 9 mogą być zmienione wartości kilku wskaźników next. Musi-
my być pewni, że wszystkie odczyty z pamięci po prawej stronie instrukcji
przypisania (odczytywanie next[next[i]]) występują przed wszystkimi zapisami
do pamięci (zapisywanie next[i]) z lewej strony instrukcji przypisania.
Zobaczmy teraz, dlaczego algorytm LIST-RANK jest algorytmem typu
BREW. Ponieważ każdy procesor jest odpowiedzialny za co najwyżej jeden
obiekt, każdy odczyt i zapis w wierszach 2-7 jest wyłączny. Również wyłączne
są zapisy w wierszach 8-9. Zauważmy, że w metodzie przeskakiwania jest za-
chowywany następujący nie,111iennik: dla każdych dw6ch różnych obiektów
ki i albo next[k] '=/:-next[l], albo next[k] = next[l] =NIL.Ten niezmiennik jest
oczywiście prawdziwy dla początkowej listy i jest zachowywany w wierszu 9.
Ponieważ wszystkie wartości next nie równe NIL są różne, wszystkie odczyty
w wierszu 9 są wyłączne.
Musimy założyć, że wykonanie wiersza 8 jest zsynchronizowane, jeśli
wszystkie odczyty mają być wyłączne. W szczególności żądamy, żeby wszystkie

776
30.1. PRZESKAKIWANIE

procesory i odczytały najpierw d[i], a potem d[next[i]]. Przy takiej synchroni~


zacji, jeśli dla obiektu i wartość next[i] -=I-NIL i istnieje obiekt j wskazujący na
i (tzn. next [j] = 1), to w pierwszym odczycie jest pobierana wartość d[i] dla
procesora i, a w drugim odczycie jest pobierana wartość d[i] dla procesora j.
Tak więc algorytm LIST-RANK.jest typu BREW.
Od tej chwili będziemy pomijać szczegóły dotyczące synchronizacji i zało­
żymy, że maszyna PRAM i wykonywane na niej programy działają zgodnie
i synchronicznie w taki sposób, że wszystkie procesory wykonują odczyty i za-
pisy w tym samym czasie.

Analiza
Pokażemy teraz, że dla n-obiektowej listy algorytm L!ST-RANK działa w czasie
O(lgn). Ponieważ inicjowanie przebiega w czasie stałym i każda iteracja pętli
wbile zabiera stały czas, wystarczy pokazać, że liczba wykonywanych iteracji
wynosi dokładnie fig nl. Istotną obserwacją jest, że w każdej iteracji przeskoki
wskaźników powodują przekształcenie każdej listy na dwie: jedną składającą
się z obiektów na pozycjach parzystych i drugą składającą się z obiektów na
pozycjach nieparzystych. A zatem każdy krok, w którym wskaźniki przeskaku-
ją, podwaja liczbę list i :anniejsza o połowę ich długości. Dlatego po wykonaniu
wszystkich flgnl iteracji wszystkie listy zawierają tylko po jednym obiekcie.
Zakładamy, że test zakończenia pętli w wierszu 5 jest wykonywany w cza-
sie stałym (przyjmujemy, że maszyna BREW PRAM ma do tego celu specjalną
sieć sterującą). Celem zadania 30.1-8 jest opisanie implementacji algorytmu
LIST-RANK na maszynie BREW PRAM, która działa w czasie O(lgn), a test
sprawdzający koniec wykonywania pętli jest wykonywany w sposób jawny.
Oprócz równoległego czasu działania istnieje jeszcze jedna miara wydajno-
ści algorytmów równoległych. Pracę wykonywaną przez algorytm równoległy
defmiuje się jako iloczyn jego czasu działania i liczby użytych procesorów.
Intuicyjnie, praca jest określona liczbą obliczeń, jakie wykonuje sekwencyjna
maszyna RAM, symulując działanie algorytmu równoległego.
Procedura LIST-RANK wykonuje pracę 0(nlgn), ponieważ jej czas działa­
nia wynosi 0(lgn), a liczba zastosowanych procesorów wynosi 0(n). Prosty
algorytm sekwencyjny dla problemu ustalania porządku na liście działa w cza-
sie ®(n), co oznacza, że procedura LIST-RANK wykonuje większą pracę, niż
jest to absolutnie konieczne, ale tylko o czynnik logarytmiczny.
Mówimy, że algorytm A dla maszyny PRAM jest sekwencyjnie-efektywny
w odniesieniu do algorytmu B (sekwencyjnego lub równoległego) dla tego sa-
mego problemu, jeśli praca wykonywana przez A różni się od pracy wyko-
nywanej przez B co najwyżej o stały czynnik. Można też powiedzieć prościej,
że algorytm A dla maszyny PRAM jest sekwencyjnie-efektywny, jeżeli jest on
sekwencyjnie-efektywny w odniesieniu do najlepszego moiJiwego algorytmu

777
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

sekwencyjnego (dla maszyny RAM) dla tego samego problemu. Ponieważ naj-
lepszy możliwy algorytm dla problemu ustalania kolejności na liście działa
w czasie @(n), algorytm LIST-RANK nie jest sekwencyjnie-efektywny. W pod-
rozdziale 30.4 przedstawimy sekwencyjnie-efektywny algorytm równoległy dla
problemu ustalania porządku na liście.

30.1.2. Równolegle obliczenia prefiksowe na liście


Metoda przeskakiwania ma znacznie szersze zastosowanie niż tylko obliczanie
odległości na liście. W podrozdziale 29.2.2, przy okazji omawiania układów
arytmetycznych, pokazaliśmy, jak obliczenia prefiksowe mogą być użyte do
szybkiego wykonywania dodawania binarnego. Teraz prześledzimy, w jaki
sposób zastosować metodę przeskakiwania do wykonywania obliczeń prefik-
sowych. Przedstawimy algorytm typu BREW wykonujący obliczenia prefik-
sowe w czasie O(lgn) na liście złożonej z n obiektów.
Obliczenieprefiksowedefiniuje się za pomocą binarnego, łącznego opera-
tora ®· Obliczenie jest wykonywane dla ciągu wejściowego (x 1 , x 2 , ••• , x,.),
a jego wynikiem jest ciąg (y 1 , y 2 , ••• , y,.) taki, że y 1 = X 1 i

Yk=Yk-i®xk

=X1@X2@ ... @Xk

dla k = 2, 3, ... ,n.Innymi słowy, każdy ykjest otrzymywany przez „wymnoże­


nie" przez siebie pierwszych k elementów ciągu xk - stąd bierze się określenie
,,preflks". (y,I definicji z rozdz. 29 elementy ciągu są indeksowane od O, pod-
czas gdy tutaj są indeksowane od 1 - nieistotna różnica).
Przykładem obliczenia prefiksowego może być obliczenie na n-obiektowej
liście, której każdy element ma wartość 1, a operator® oznacza zwykłe doda-
wanie. Ponieważ k-ty element listy ma wartość xk = I, dla k = l, 2, ..., n, wy-
nikiem obliczenia prefiksowego jest Yk = k - indeks k-tego elementu. Tak więc
innym sposobem ustalenia porządku na liście jest odwrócenie listy (co można
zrobić w czasie stałym), wykonanie zdefiniowanego powyżej obliczenia prefik-
sowego i odjęcie 1 od każdej obliczonej wartości.
Zaprezentujemy teraz algorytm typu BREW, który równolegle oblicza
prefJ.k.sy na n-obiektowej liście w czasie O(lgn). Dla wygody przyjmujemy na-
stępujące oznaczenie:

[i,j] = X 1@Xi+l@ ... @XJ

dla liczb całkowitych i oraz) z przedziału 1 ~i~ j :s;;n. Wtedy [k, k] = x"'dla
k=l,2, ...,ni
[i, kJ - [i,jJ® [j + 1, kJ

778
30.1. PRZESKAKIWANIE

dla O~ i ~j < k ~ n. W przyjętej notacji celem obliczenia prefiksowego jest


obliczenie Yk = [1, k], dla k = 1, 2, ... , n.
Kiedy obliczenie prefiksowe jest wykonywane dla listy, chcemy, żeby po-
rządek elementów w ciągu wejściowym x 1, x 2 , ••• , x" był określony przez ko-
lejność występowania tych elementów na liście, a nie przez pozycje obiektów
w tablicy, w której są przechowywane. (Celem zadania 30.1-2 jest podanie
algorytmu prefiksowego dla tablic). W algorytmie LIST-PREFIXobliczenia roz-
poczynają się z wartościami x[i], w każdym obiekcie i na liście L. Jeśli obiekt
i jest k-tym obiektem od początku listy, to x[i] = x1r:jest k-tym elementem
ciągu wejściowego. Tak więc wynikiem obliczenia prefiksowego jest y[i] =
- Y, - [I, k].

LIST-PREFIX(L)
1 for każdy procesor i in parallel
2 do y[i]- x[i]
3 while istnieje obiekt i taki, że next[i] # NIL
4 do for każdy procesor i in parallel
5 do if next[i] i=, NIL
6 then y[next[i]J - y [i]® y [next [i]]
7 next[i] +- next[next[i]]

Powyższy pseudokod i rys. 30.3 wskazują na podobieństwo między algo-


rytmami LIST-PREFIX j LIST·RANK. Jedynymi różnicami są: inicjowanie i ak-
tualizowanie wartości di y. W procedurze LIST-RANK procesor i aktualizuje

(b)

(<)

Rys. 30.3. Algorytm L!ST-PREFIXobliczania prefiksów na !iście. (a) Począlkową wartością y dla
k-tego obiektu na liście jest [k, kJ. Wskaźnik nexl dla k-tego obiektu wskazuje na obiekt (k + 1)-szy
lub NIL,jeśli k jest ostatnim obiektem na liście. (łHi) Wartości y i nexl przed wykonaniem testu
w wierszu 3. Wynik działania algorytmu jest pokazany w części (d). Dla każdego obiektu k war-
tością y jest [I, k]

779
ROZDZIAŁ 30. ALGORYTMY ROWNOLEGŁE

wartość d[i] - własną wartość d - podczas gdy w procedurze LisT-PREFIX


procesor i aktualizuje y[next[i]]-wartość y przynależną innemu procesorowi.
Zauważmy, że algorytm LIST-PREFIXjest typu EREW (z tego samego powodu
co algorytm LIST-RANK:jest zachowywany niezmiennik, że dla różnych obiek-
tów i orazj albo next[i] # next[jJ, albo next[iJ = next[j] = NIL).
Na rysunku 30.3 widać stany listy przed każdą iteracją pętli while.W pro-
cedurze LIST-PREFIX jest zachowywany następujący niezmiennik: po zakoń­
czeniu t-tej iteracji pętli whilek-ty procesor pamięta [max(l, k - 21 + 1), k] dla
k = l, 2, ... , n. W pierwszej iteracji k-ty obiekt listy wskazuje początkowo na
obiekt (k + 1)-szy, z wyjątkiem ostatniego obiektu, którego wskaźnik ma war-
tość NIL. W wierszu 6 k-ty obiekt, dla k = 1, 2, ... , n - 1, pobiera wartość
[k + I, k + 1] od swojego następnik.a. Potem wykonuje się operacja
[k, k] ® [k + 1, k + 1], dając w wyniku wartość [k, k + 1], którą zapisuje się
z powrotem do następnik.a k-tego obiektu. Z kolei wskaźniki next przeskakują
tak samo jak w algorytmie LIST-RANK. Wynik wykonania pierwszej iteracji
jest pokazany na rys. 30.3b. Podobnie wygląda druga iteracja. Dla k = 1, 2, ...,
n - 2 k-ty obiekt pobiera wartość [k + 1, k + 2J od swojego następnika (który
jest określony przez nową wartość pola next), a następnie zapamiętuje
[k - 1, k] ® [k + 1, k + 2] - [k - 1, k + 2] w swoim następniku. Wynik ob-
liczeń ilustruje rys. 30.3c. W trzeciej i ostatniej iteracji tylko pierwsze dwa
obiekty na liście mają wskaźniki różne od NIL i pobierają wartości od swoich
następników z odpowiednich list. Końcowy wynik obliczeń jest pokazany na
rys. 30.3d. Poprawność algorytmu wynika z obserwacji, że w każdym kroku,
jeśli wykonamy obliczenia prefiksowe na każdej z istniejących list, każdy
obiekt otrzyma swoją poprawną wartość.
Ponieważ w obu algorytmach jest zastosowana ta sama metoda przeskaki-
wania, analiza algorytmu LIST-PREFIX jest taka sama jak algorytmu LIST-
-RANK: algorytm jest typu EREW, jego czas działania wynosi O(lgn), a wyko-
nana praca wynosi 0(nlgn).

30.1.3. Metoda cyklu Eulera


W tym podrozdziale wprowadzamy metodę cyklu Eulera i pokazujemy, w jaki
sposób można ją zastosować do obliczania głębokości każdego węzła w drze-
wie binarnym o n węzłach. Zasadniczym krokiem w tym algorytmie jest równo~
legie obliczenie prefJ.k:sowe.Algorytm działa w czasie O(lgn) i jest typu BREW.
Drzewa binarne na maszynie PRAM będziemy przechowywali w sposób
podobny do opisanego w pod.rozdz. 11.4. Każdy węzeł i ma pola parent[i],
left[i] oraz right[i], które wskazują, odpowiednio, na ojca, lewego syna i pra-
wego syna tego węzła. Załóżmy, że każdy węzeł jest identyfikowany przez
nieujemną liczbę całkowitą. Z powodów, które wkrótce staną się jasne, z każ­
dym węzłem zwiążemy nie jeden, a trzy procesory; nazwiemy je procesorami A,

780
30.1. PRZESKAKIWANIE

Bi C. Powinniśmy łatwo odwzorowywać węzły na odpowiadające im proceso-


ry; na przykład z węzłem i możemy związać procesory 3i, 3i + 1 oraz 3i + 2.
Obliczanie głębokości każdego węzła w drzewie binarnym o n węzłach
zabiera na maszynie sekwencyjnej czas E>(n). Działanie prostego algorytmu
równoległego obliczania głębokości można porównać do zjawiska rozchodze-
nia się „fali" od korzenia w dól drzewa. Fala osiąga wszystkie węzły na tej
samej głębokości w tym samym czasie. Jeśli razem z falą jest przenoszony
licznik, którego wartość jest powiększana o I na każdym poziomie drzewa, to
w ten sposób można obliczyć głębokość każdego węzła. Ten algorytm zacho-
wuje się dobrze dla pełnych drzew binarnych, ponieważ jego czas działania jest
proporcjonalny do wysokości drzewa. Jednakże wysokość drzewa może być
równa n - 1, w którym to wypadku algorytm działa w czasie E>(n)- nie lep-
szym niż czas działania algorytmu sekwencyjnego. Stosując metodę cyklu Eule-
ra, możemy jednak obliczyć głębokości węzłów na maszynie EREW PRAM
w czasie O(lgn), niezależnie od wysokości drzewa.
Cyklem Eulera w grafie nazywamy cykl, który przechodzi przez każdą
krawędź dokładnie raz (chociaż może wielokrotnie odwiedzać ten sam wierz-
chołek). Z problemu 23-3 wiemy, że spójny graf skierowany ma cykl Eulera
wtedy i tylko wtedy, gdy stopień wejściowy każdego wierzchołka v jest równy
jego stopniowi wyjściowemu. Ponieważ w skierowanej wersji grafu nieskiero-
wanego kazdej nieskierowanej krawędzi (u, v) odpowiadają dwie skierowane
krawędzie (u, v) i (v, u), wersja skierowana dowolnego spójnego grafu nieskie-
rowanego -i dlatego też dowolnego drzewa nieskierowanego - ma cykl Eulera.
żeby policzyć głębokości węzłów w drzewie binarnym T, budujemy naj-
pierw cykl Eulera w skierowanej wersji T (potraktowanego jako graf nieskie-
rowany). Cykl odpowiada obchodzeniu drzewa i jest reprezentowany na
rys. 30.4a jako lista przechodząca przez węzły drzewa. Struk.tura tej listy jest
następująca:

• Procesor A z danego węzła wskazuje na procesor A z jego lewego syna,


jeśli lewy syn istnieje, a na procesor B z tego samego węzła, w przeciwnym
wypadku.
• Procesor B z danego węzła wskazuje na procesor A należący do jego prawe-
go syna, jeśli prawy syn istnieje, a na procesor C z tego samego węzła,
w przeciwnym wypadku.
• Procesor C z danego węzła wskazuje na procesor B należący do jego ojca,
jeśli węzeł jest lewym synem swojego ojca, a na procesor C należący do jego
ojca, jeśli węzeł jest prawym synem swojego ojca. Procesor C w korzeniu
wskazuje na NIL.
Tak więc początkiem listy utworzonej z cyklu Eulera jest procesor A z ko~
rzenia, a końcem procesor C, także z korzenia. Mając dane wskaźniki tworzące
źródłowe drzewo, cykl Eulera można skonstruować w czasie stałym. Po skon-

781
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

struowaniu listy, reprezentującej cykl Eulera w drzewie T, umieszczamy


1 w każdym procesorze A, O w każdym procesorze Bi -1 w każdym proceso-
rze C (patrz rys. 30.4a). Następnie wykonujemy równoległe obliczenia prefik-
sowe, używając dodawania jako łącznej operacji, tak jak robiliśmy to w pod-
rozdz, 30.1.2. Rysunek 30.4b ilustruje wynik obliczeń prefiksowych,
Twierdzimy, że po wykonaniu równoległych obliczeń prefiksowych głębo­
kość każdego węzła jest policzona w należącym do niego procesorze C. Dla-
czego? Liczby 1, O, -1 zostały umieszczone w procesorach A, Bi C w taki
sposób, że liczby z każdego poddrzewa sumują się do O. W każdym węźle
i procesor A wnosi 1 do każdej sumy obliczanej w lewym poddrzewie tego
węzła, odzwierciedlając fakt, że głębokość lewego syna węzła i jest o jeden
większa od głębokości węzła i. Procesor B wnosi O,ponieważ głębokość lewego
syna węzła i jest taka sama jak głębokość prawego syna węzła i. Procesor
C wnosi -1, tak że z punktu widzenia ojca węzła i całkowite obejście pod-
drzewa o korzeniu w i nie ma wpływu na wartość sumy obliczanej u ojca i.
Listę reprezentującą cykl Eulera można obliczyć w czasie stałym, Składa
się ona z 3n obiektów i stąd równoległe obliczenia prefiksowe zabierają czas
O(lgn). Łączny czas obliczania głębokości wszystkich węzłów wynosi zatem
O(lg n). Ponieważ jednoczesne dostępy do wspólnej pamięci nie były konieczne,
omawiany algorytm jest typu BREW.

ZADANIA
30.1-1. Podaj algorytm typu EREW, który w czasie O(lgn) sprawdza dla każ­
dego obiektu na n-obiektowej liście, czy jest on obiektem środkowym
(ln/2J-girn).
30.1-2. Podaj algorytm typu EREW, który w czasie O(lgn) wykona obliczenia
prefiksowe na tablicy x[l „ n]. Nie używaj wskaźników, lecz wykonuj bez-
pośrednio obliczenia na indeksach.
30.1-3. Załóżmy, że każdy obiekt na n-obiektowej liście L został pokolorowa-
ny albo na czerwono, albo na niebiesko. Podaj efektywny algorytm typu
EREW tworzenia dwóch list złożonych z obiektów L: jednej składającej się
z obiektów niebieskich i jednej złożonej z obiektów czerwonych.
30.1-4. Na maszynie EREW PRAM rozproszono n obiektów między kilka
rozłącznych list cyklicznych. Podaj efektywny algorytm, który wybiera do-
wolnego reprezentanta z każdej listy i przekazuje identyflk:ator wybranego
obiektu do każdego innego obiektu na tej liście. Przyjmij, że kaidy proce-
sor zna własny, jednoznaczny indeks.
30.1-5. Podaj algorytm typu EREW, który w czasie O(lgn) oblicza ro7miary
poddrzew o korzeniach we wszystkich n węzłach drzewa binarnego.
(Wskazówka:Weź różnicę z dwóch sum obliczanych wzdłuż cyklu Eulera).
30.1-6. Podaj efektywny algorytm typu EREW obliczania numeracji preorder,
inorder i postorder w dowolnym drzewie binarnym.

782
30.1. PRZESKAKIWANIE

' . ( ,,

(b)

Rys. 30.4. Zastosowanie metody cyklu Eulera do obliczania głębokości każdego węzła w drzewie
binarnym. (a) Cykl Eulera jest listą odpowiadają.cą obchodzeniu drzewa. Ktirly procesor zawiera
liczbę używaną. w równoległych obliczeniach prefiksowych do wyliczania głębokości węzłów.
(b) Wynik równoległych obliczeń prefiksowych na liście z {a). Procesor C w ktirlym węźle {poko-
lorowany na czarno) zawiera obliczoną głębokość tego węzła. (Możesz sprawdzić wynik obliczeń
{prefiksowych, wykonując je sekwencyjnie.)

783
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

30.1-7. Rozszerz metodę cyklu Eulera na drzewa uporządkowane o dowol-


nych stopniach węzłów. W szczególności opisz taką reprezentację drzew
uporządkowanych, która pozwala na zastosowanie metody cyklu Eulera.
Podaj algorytm typu BREW, który w czasie O(lgn) policzy głębokości
węzłów w drzewie uporządkowanym o n węzłach.
30.1-8. Opisz implementację na maszynie BREW algorytmu LisT-RANK., dzia-
łającą w czasie O(lgn), w której jawnie jest sprawdzany warunek zakończe­
nia pętli. (Wskazówka: Przeplataj sprawdz.anie warunku z akcją wykonywa-
ną wewnątrz pętli).

30.2. Algorytmytypu CRCWa algorytmytypu EREW


Spór o to, czy architektura komputera równoległego powinna, czy nie powin-
na, umożliwiać wykonywanie jednoczesnych dostępów do pamięci, pozostaje
bez odpowiedzi. Jedni uważają, że rozwiązania sp17.ętowe pozwalające na wy-
konywanie algorytmów typu CRCW są drogie i wykorzystywane zbyt rzadko,
by uzasadnione było zajmowanie się modelem CRCW PRAM. Inni narzekają,
że maszyna EREW PRAM narzuca zbyt duże ograniczenia programistyczne.
Odpowiedź prawdopodobnie leży gdzieś pośrodku i dlatego zostało zapropo-
nowanych wiele kompromisowych modeli. Niemniej jednak będzie pouczające
Zbadanie, jaka jest korzyść z możliwości wykonywania jednoczesnych dostę­
pów do pamięci.
W tym podrozdziale pokazujemy, że istnieją problemy dla których algory-
tmy typu CRCW zachowują się zdecydowanie lepiej niż najlepsze algorytmy
typu EREW. Problemem, dla którego jednoczesny odczyt z pamięci umożliwia
skonstruowanie szybszego algorytmu, jest problem znajdowania identyfikato-
rów korzeni drzew w lesie. Problemem, dla którego jednoczesny zapis do pa-
mięci umożliwia skonstruowanie szybszego algorytmu, jest problem znajdowa-
nia najmniejszego elementu w tablicy.

Problem, w rozwiązaniu którego pomaga jednoczesny odczyt


Załóżmy, że jest dany las drzew binarnych, w którym każdy węzeł ima wskaź­
nik parent [il do swojego ojca, i chcemy znaleźć dla każdego węzła identyfika-
tor korzenia drzewa, do którego ten węzeł należy. Z każdym węzłem i w lesie
F wiążemy procesor i. Algorytm FIND-ROOT, opisany poniżej, wykorzystuje
metodę przeskakiwania do znajdowania korzenia drzewa zawierającego węzeł i
i zapamiętuje ten korzeń w zmiennej root [i].

FIND-ROOTs(F}
1 for każ.dy procesor i in paralleł

784
30.2. ALGORYTMY TYPU CRCW A ALGORYTMY TYPU EREW

2 do if parent [i] = NIL


3 tben root[i] ..,_i
4 wbile istnieje węzeł i taki, że
parent[i] 'F NIL
5 do for każdy procesor i in parallel
6 do if parent [i] 'F NIL
7 theo root[i] ..,_root [parent[i]]
8 parent [i]..,_parent [parent[i]]

Rysunek 30.5 ilustruje działanie algorytmu FIND-ROOTS. Po etapie inicjo-


wania (wiersze 1-3), pokazanym na rys. 30.5a, jedynymi węzłami, które znają
identyfikatory swoich korzeni są same korzenie. W pętli wbile (wiersze 4-8) są
wykonywane skoki wskaźników i wypełniane pola root. Rysunki 30.5b-d obra-
zują stany lasu po pierwszej, drugiej i trzeciej iteracji pętli wbile.
Jak można zauważyć, w algorytmie jest zachowywany niezmiennik mówią­
cy, że jeśli parent[i) = NIL, to root[i] jest identyfikatorem korzenia drzewa
zawierającego i.
'Algorytm FIND-ROOTS jest typu CREW i działa w czasie O(lg d), gdzie
d jest największą głębokością drzewa w lesie. Jedyne zapisy do pamięci wy-
stępują w wierszach 3, 7 i 8 i wszystkie one są wyłączne, ponieważ w każdym
z nich procesor i zapisuje tylko w węźle i. Jednakże odczyty w wierszach 7-8 są
jednoczesne, gdyż kilka procesorów może wskazywać na ten sam węzeł. Na
rysunku 30.5b widzimy na przykład, że podczas drugiej iteracji pętli wbile
root [4] i parent [4] są czytane przez procesory 18, 2 i 7.
Zasadniczo z tych samych powodów co w wypadku LIST-RANK czas dzia-
łania algorytmu FIND-ROOTS wynosi O(lg d'): w każdej iteracji długość każdej
ścieżki maleje o połowę. Widać to wyraźnie na rys. 30.5.
Jak szybko dla n węzłów w lesie można ustalić korzenie drzew, które je
zawierają, używając tylko wyłącznych odczytów? Prosty dowód pokazuje, że
potrzeba do tego czasu Q(lgn). Zasadniczą obserwacją jest, że gdy odczyty są
wyłączne, wtedy w każdym kroku maszyny PRAM można skopiować daną
informację do co najwyżej jednej, innej komórki pamięci; tak więc liczba ko-
mórek pamięci, które mogą zawierać kopie tej samej informacji, może się
w każdym kroku co najwyżej podwoić. Jeśli spojrzymy na pojedyncze drzewo,
to po etapie inicjowania tylko co najwyżej 1 komórka pamięci zawiera identy-
fikator korzenia. Po kroku 1 co najwyżej 2 komórki mogą zawierać identyfika-
tor korzenia; po k krokach co najwyżej 2ł. komórek może zawierać identyfi-
kator korzenia. Jeśli rozmiar drzewa wynosi 0(n), to w chwili zakończenia
działania algorytmu identyfikator korzenia musi znaleźć się w 0(n) różnych
miejscach w pamięci. żeby tak się stało, potrzeba .Q(lgn) kroków.
Gdy głębokość d drzewa o największej głębokości w lesie wynosi 2°UK l,
11

algorytm FIND-ROOTS, który jest typu CREW, działa asymptotycznie szybciej


niż jakikolwiek algorytm typu EREW. W szczególności, dla każdego lasu

785
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

<•) 8

,,

(!)''
,,
·"''

(c) 8
@i • "@
"@ Iii;'' @' "'@ ''@
17<i, @]3
tp" ''@ ~ ?i)
''@ ~ © "@ @'' ''®I
",'
'
(d)
@' (j) ,,
"@
l.~

@"
~· "il
@'
''@ ®
,,
2(@
®' '@
19@
@ "
"@ @ © 23® ®16 IO@
l@ ©
Rys. 30.5. Znajdowanie korz.eni w lesie drzew binarnych na maszynie CREW PRAM. Obok węzłów
majdują się ich numery, a wartości pól root są podane wewnątrz węzłów. Dowiązania repn=ntują
Wllkaźniki do ojców. (•Kd) Stan drzew w lesie przed kaidorazowym wykonaniem wierS7.ll.4 w al-
gorytmie FIND-ROOTs. Zauważmy, że długości ścieżek są połowione w każdej iteracji

o n węzłach,w którym drzewo o największej głębokości jest drzewem zrów-


noważonym o E>(n) węzłach, głębokość d = OOgn). W takim wypadku FIND-
-ROOTS działa w czasie O(lglgn). Każdy algorytm typu EREW musi działać
w czasie .Q(lgn), który jest asymptotyC'Z.nie dłuższy. Zadanie 30.2-1 dostarcza
prostszego przykładu obrazującego, że jednoczesny odczyt czasami pomaga
zaprojektować efektywniejszy algorytm.

786
30.2. ALGORYTMY TYPU CRCW A ALGORYTMY TYPU EREW

Problem, w rozwiązaniu którego pomaga jednoczesny zapis

W celu zademonstrowania przewagi zapisu jednoczesnego nad zapisem wyłącz­


nym rozważmy problem obliczania elementu maksymalnego w tablicy liczb
rzeczywistych. Zobaczymy, że każdy algorytm. typu EREW dla tego problemu
wymaga czasu !l(lgn) i że to samo odnosi się do algorytmów typu CREW. Ten
problem można rozwiązać w czasie 0(1) na maszynie CRCW z jednolitym
zapisem. W tego typu maszynie, gdy wiele procesorów zapisuje do tej samej
komórki pamięci, wszystkie muszą zapisywać tę samą wartość.
Opiszemy teraz algorytm FAST-MAX typu CRCW, który majduje maksi-
mum z n liczb danych w tablicy A [O.. n - l]. Jest tu wykorzystywanych n2
procesorów. Każdy procesor porównuje A [i] z A [j] dla pewnych i, j z prze-
działu O .:::;;
i, j ~ n - l. W wyniku w algorytmie jest wykonywana ,,macierz"
porównań i dlatego na każdy z n 2 procesorówmozemy patrzeć jak na procesor
mający dwuwymiarowy indeks (i,J), a nie tylko jednowymiarowy indeks z ma-
szyny PRAM.

FAST-MAX(A)
1 n+- length [A]
2 for i +- O to n - l in parallel
3 do m[i] +- TRUE
4 fori+-Oton-lij+-Oton-linparallel
5 doifA[i]<A[j]
6 then m [i]+- FALSE
7 for i +- O to n - 1 in parallel
8 do if m[i) = TRUE
9 then max+- A [i]
10 return max

W wierszu 1 jest ustalana długość tablicy A; wiersz ten może realizować


jeden procesor, powiedzmy procesor O. W algorytmie jest wykorzystywana
tablica m[O .. n-1]. Procesor i odpowiada za m[i]. Chcemy, żeby po zakoń­
czeniu działania algorytmu wartością m[i] było TRUE wtedy i tylko wtedy, gdy
A [i] jest elementem maksymalnym w tablicy A. Na początku przyjmujemy,
że każdy element może być maksymalny (wiersze 2-3) i liczymy, że operacje
porównania z wiersza 5 pozwolą wykluczyć te elementy, które nie mogą być
maksymalne.
Rysunek 30.6 ilustruje pozostałą część algorytmu. W pętli opisanej w wie-
rszach 4-6 jest sprawdzana każda uporządkowana para elementów z A. Dla
każdej pary A [i] i A [j] w wierszu 5 testuje się, czy A [i] < A [j]. Jeśli po-
równanie daje w wyniku TRUE, to wiemy, że A[i] nie może być elementem
maksymalnym. Ten fakt jest zapamiętywany w wierszu 6 w wyniku wykonania

787
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

przypisania m [i] - FALSE.Wiele par (i, j) (a raczej procesorów odpowiadają­


cych za te pary) może zapisywać do m[i] jednocześnie, ale wszystkie one zapi-
sują tę samą wartość: FALSE.

A [j]
m
F' 6
T
9
T
. __,

F
2
'"""

T
9
·-·--·-
"""""

A [i]
'
6
9
F
F
F
F
T
F
F
F
T
F
F
T
2 T T T F T F
9 F F F F F T
------ .. -------
mu9

Rys. 30.6. Znajdowanie maksimum z n warlości w czasie O(I) na maszynie CRCW przez algorytm
FAST-MAX. Dla każdej uporządkowanej pary elementów z tablicy A= (S, 6, 9, 2, 9) wynik
porównania A [i]< A Ul jest pokez.any jako element macierzy. Lltera T jest skrótem od TRUE,
a litera F - od FA.I.Sil.Dla każdego wiersza zawierającego wartość TRUE(literę T) odpowiadający
mu element m, pokazany z prawej strony, ma wartość FALSB(litera F). Elementy z m, zawierające
wartości TRUE, odpowiadają maksymalnym elementom z A. W tym wypadku w zmiennej max
zostaje zapisane 9

Dlatego po wykonaniu wiersza 6 wartość m[i] = TRUE tylko dla tych in-
deksów i, dla których A [i] jest maksymalnym elementem w A. W wierszach
7-9 wartość maksymalna jest zapisywana w zmiennej max, która jest następnie
zwracana jako wynik działania algorytmu. Kilka procesorów może jednocześ­
nie zapisywać w zmiennej max, ale jeśli tak jest, to wszystkie one zapisują tę
samą wartość. Jest to zgodne z modelem CRCW z jednolitym zapisem.
Ponieważ wszystkie trzy „pętle" w naszym algorytmie są wykonywane
równolegle, FAST-MAX działa w czasie 0(1). Oczywiście algorytm ten nie jest
sekwencyjnie efektywny - jest w nim używanych n2 procesorów, a problem
znajdowania maksimum w tablicy można sekwencyjnie rozwiązać w czasie
0(n). Można jednak uzyskać algorytm o lepsz.ej sekwencyjnej efektywności, co
pozostawiamy jako zad. 30.2-6.
W pewnym sensie istotne dla algorytmu FAST-MAXjest to, że maszyna
CRCW PRAM jest zdolna obliczyć iloczyn logiczny (AND) n zmiennych
w czasie stałym, używając n procesorów. (Ponieważ taki iloczyn można ob-
liczyć na CRCW z jednolitym zapisem, można go również obliczyć na każdym
innym typie maszyny CRCW). W rzeczywistości w algorytmie FAST-MAX
jest obliczanych kilka iloczynów logicznych jednocześnie - dla każdego i = O,
1, ...,n-1
·-'
m[i]- /\ (A[iJ;.A[i])
}""O

co wynika z praw De Morgana (5.2).

788
30.2. ALGORYTMY TYPU CRCW A ALGORYTMY TYPU EREW

Tę silną własność obliczania ANO można zastosować w inny sposób. Wy-


korzystując na przykład zdolność maszyny CRCW do obliczania AND w cza-
sie 0(1), możemy zrezygnować ze specjalnej sieci sterującej używanej do testo-
wania, czy wszystkie procesory zakończyły wykonywanie pętli. (Istnienie takiej
sieci zakładaliśmy w modelu EREW). Żeby stwierdzić, czy wszystkie procesory
zakończyły wykonywanie pętli, wystarczy po prostu policzyć AND z wartości,
które wskazują na stan obliczeń poszczególnych procesorów (TRUE- skończył;
FALSE- nie skończył).
Model EREW nie ma tak.ich udogodnień. Każdy algorytm typu EREW
potrzebuje !l(lg n) kroków na obliczenie maksimum z n elementów. Dowód jest
koncepcyjnie podobny do dowodu dotyczącego dolnego ograniczenia na czas
znajdowania korzenia drzewa binarnego. W tamtym dowodzie badaliśmy, ile
węzłów może „znać" identyfikator korzenia, i pokazaliśmy, że liczba ta może
się w każdym kroku co najwyżej podwoić. W problemie obliczania maksimum
z n elementów badamy, ile elementów można traktować jako potencjalne mak -
simum. Intuicyjnie, z każdym krokiem liczba ta może zmaleć co najwyżej o po-
łowę, co prowadzi do dolnego ograniczenia f!(lgn).
Warte podkreślenia je':l,tto, że dolne ograniczenie O(lg n) na czas obliczania
maksimum jest także prawdziwe dla modelu z jednoczesnym odczytem, tzn.
dla algorytm.ów typu CREW. Cook, Dworki Reischuk [SO]pokazali, że każdy
algorytm typu CRBW obliczający maksimum z n elementów wymaga czasu
!l(lg n), nawet jeśli pozwolimy na użycie nieograniczenie wielu procesorów
. . . . . .
1 n1eogran1czoneJ pam.1ęc1.

Symulacja algorytmów typu CRCW za pomocą algorytmów


typu EREW
Wiemy już, że algorytmy typu CRCW mogą rozwiązywać pewne problemy
szybciej niż algorytmy typu BREW. Ponadto każdy algorytm typu BREW
może być wykonywany na maszynie CRCW PRAM. Dlatego model CRCW
jest istotnie silniejszy od modelu BREW. Ale na ile jest silniejszy? W podroz-
dziale 30.3 pokażemy, że p-procesorowa maszyna EREW PRAM może posor-
tować p liczb w czasie O(lgp). Wykorzystamy teraz ten wynik do pokazania
teoretycznego, górnego ograniczenia na silę maszyny CRCW PRAM w stosun-
ku do maszyny EREW PRAM.

TwIERDZENIE30.1.
Każdy p-procesorowy algorytm typu CRCW może być co najwyżej O(lgp)
razy szybszy od najszybszego p-procesorowego algorytmu typu BREW dla
tego samego problemu.

789
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

DOWÓD
Pokażemy, jak symulować w czasie O(lgp) na maszynie EREW PRAM jeden
krok z algorytmu typu CRCW. Ponieważ procesory w obu maszynach mają
taką samą moc, wystarczy skoncentrować się na dostępach do pamięci. Nasz
dowód ograniczymy tutaj tylko do jednoczesnych zapisów. Implementację jed-
noczesnych odczytów zostawiamy jak.o zad. 30.2-8
W symulacji jednoczesnego zapisu p procesorów maszyny EREW wyko-
rzystuje pomocniczą tablicę A o długości p. Idea symulacji jest zilustrowana
na rys. 30.7. Kiedy procesor P 1 z maszyny CRCW, dla i= O, 1, ... , p- 1, ma
zapisać wartość x 1 do komórki I;, odpowiadający mu procesor z maszyny
EREW zapisuje uporządkowaną parę (/ 1, x 1) w A [i). Ponieważ każdy procesor
(na maszynie EREW) zapisuje w innym miejscu pamięci, zapisy te są wyłączne.
Następnie pary zapisane w tablicy A są sortowane w czasie OQgp) względem
pierwszych elementów w parach. Po wykonaniu sortowania wszystkie wartości
(drugie elementy par), które na maszynie CRCW miały być zapisane w tym
samym miejscu, występują kolejno w A.
Każdy procesor P 1 z maszyny EREW, dla i= 1, 2, ... , p - 1, ogląda teraz
A[i] = (/1, x 1) i A[i- 1] = (/,, x,), gdzie j i k są wartościami z przedziału
O~J. k~p- l. Jeśli 11 -::f:.ft. lub i= O, to procesor P1, dla i= O, 1, ... , p-1,
zapisuje wartość x 1 na pozycji 11 w pamięci globalnej. W przeciwnym razie
procesor nie podejmuje żadnej akcji. Ponieważ tablica A została posortowana
względem pierwszych elementów w parach, tylko jeden procesor z.a.pisuje do tej
samej komórki pamięci i dlatego taki zapis jest wyłączny. Tak więc każdy krok
jednoczesnego zapisu z maszyny CRCW z jednolitym zapisem można zaimple-
mentować na maszynie EREW PRAM w czasie OQgn).

Można także symulować inne modele z jednoczesnym zapisem. (Patrz



zad. 30.2-9).
Powstaje z.a.tern pytanie, który z modeli jest bardziej wskazany - CRCW
czy EREW - a jeśli CRCW, to który z jego pod.modeli. Zwolennicy modeli
CRCW wskazują, że są one łatwiejsze do programowania, a algorytmy na nich
wykonywane są szybsze. Krytycy twierdzą. że rozwiązania sprzętowe imple-
mentujące jednoczesne dostępy do pamięci są wolniejsze od rozwiązań sprzęto­
wych implementujących wyłączne dostępy do pamięci i dlatego szybszy czas
działania algorytmów typu CRCW jest fikcją. Powiadają oni, że w rzeczywis-
tości nie jest możliwe znalezienie maksimum z n wartości w czasie stałym.
Jeszcze inni mówią, że model PRAM - zarówno BREW, jak i CRCW
- jest całkowicie chybiony. Procesory muszą być połączone siecią komunika-
cyjną i taka sieć powinna być częścią modelu. Procesory powinny mieć moż­
liwość bezpośredniej komunikacji tylko z sąsiadami w sieci.
Jest całkiem jasne, że zagadnienie „właściwego" modelu obliczeń równo-
ległych nie zostanie łatwo rozwiązane przez wskazanie na którykolwiek z mo-

790
30.2. ALGORYTMY TYPU CRCW A ALGORYTMY TYPU EREW

Pamięc' globalna
maszynyc:14:·w
.....
.....
., ····'""""
.........
,,.,,,. ,
"""

12 '
~,.~·=~! ' '
,
•;
....
,.,.,,.,,,,,
'"'"
., '
'
"

43 I ,,
.~..~,.~
,,,.,,,,.......~.'
~~

..... ....
""""'"'"'
·'""""'"""
·"• ,,.,.
;,;;•:;;-,•,;;;;
,, .. ,. .,
....,,, ......
26 92
.·;·:;·:-';;:;
'.., ".
"., ..
-·---"--
"'

I, I

A
• (8.12) - I u
-~------·,
(8,12) --~ 1
(29,43) · 2

• 29,43)
-~-, ! :O

(b)

Rys. 30.7. Symulacja jednoczesnego zapisu na maszynie BREW PRAM. (a) Krok, w .którym 6 proce-
sorów maszyny CRCW z jednolitym ttpisem. pisze jednocześnie do wspólnej pamięci. (b) Symula-
tja kroku z (a) na maszynie EREW PRAM. Najpierw uporządkowane pary składające się z adresu
w pamięci i wartości, która tam ma zostać zapisana, są zapisywane w tablicy .4. Następnie tablica
.4 jest sortowana. Porównując sąsiednie elementy w tablicy, zapewniamy, że tylko pierwszy zapis,
z grupy identycmych zapisów do pamięci globalnej, zostaje wykonany. W tym wypad.ku zapisują
procesory P 0 , P, i P ~

deli. Jednak trzeba zdawać sobie sprawę z jednej wainej rzeczy: te modele są
tylko modelami. W świecie rzeczywistym różne modele stosuje się w różnych
granicach. Stopień, w jakim model odpowiada istniejącym rozwiązaniom tech-
nicznym, jest stopniem, w jakim analiza algorytmów w tym modelu pozwala
przewidywać zjawiska występujące w świecie rzeczywistym. Dlatego jest ważne

791
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

badanie różnorodnych modeli obliczeń równoległych i algorytmów dla nich,


żeby wraz z rozwojem dziedziny obliczeń równoległych można było świadom.ie
uzgodnić, które z paradygmatów obliczeń równoległych najlepiej odpowiadają
zastosowaniom praktycznym.

ZADANIA
30.2-1. Przypuśćmy, że wiemy o tym, iż las drzew binarnych składa się z tylko
jednego drzewa o n węzłach. Pokaż, że przy tym założeniu problem znaj-
dowania korzeni można rozwiązać na maszynie CREW PRAM w czasie
0(1). Uzasadnij, że kamy algorytm BREW dla tego problemu wymaga
czasu 0:(lg n).
30.2-2. Podaj algorytm typu BREW dla problemu znajdowania korzeni w lesie
o n węzłach działający w czasie O{lgn).
30.2-3. Podaj n-procesorowy algorytm typu CRCW, który oblicza sumę lo-
giczną (OR) n mliennych w czasie 0(1).
30.2-4. Opisz efektywny algorytm typu CRCW mnożenia dwóch macierzy lo-
gicznych wymiaru n x n przy użyciu n 3 procesorów.
30.2-5. Opisz algorytm typu BREW, który używając n 3 procesorów, oblicza
w czasie O(lg n) iloczyn dwóch macierzy wymiaru n x n zawierających licz-
by rzeczywiste. Czy istnieje szybszy algorytm na maszynie CRCW z jedno-
litym zapisem? Czy istnieje szybszy algorytm na jednym z silniejszych mo-
deli CRCW?
* 30.2-6. Udowodnij, że dla każdej stałej e > O istnieje algorytm typu CRCW,
który w czasie 0(1) przy uZyciu O(n 1 +,) procesorów znajduje maksymalny
element w n-elementowej tablicy.
* 30.2-7. Pokaż, jak scalić w czasie 0(1) na priorytetowej maszynie CRCW
PRAM dwie posortowane tablice, każda o długości n. Opisz, jak wykorzy-
stać ten algorytm do sortowania w czasie O(lgn). Czy Twój algorytm jest
sekwencyjnie efektywny?
30.2-8. Uzupełnij dowód twierdzenia 30.1, opisując implementację, w czasie
O(lgp) nap-procesorowej maszynie BREW PRAM, jednoczesnego cx:lczy-
tu z p-procesorowej maszyny CRCW PRAM.
30.2-9. Pokaż, jak na p-procesorowej maszynie BREW PRAM symulować
p-procesorową, z mieszanym zapisem maszynę CRCW PRAM, ze spowol-
nieniem tylko O(lgp). (Wskazówka:Zastosuj obliczenia prefiksowe).

30.3. TwierdzenieBrentai sekwencyjnaefektywność


Z twierdzenia Brenta wynika, jak można symulować efektywnie na maszynach
PRAM układy kombinacyjne. Wykorzystując to twierdzenie, możemy zaadap~
tować dla modelu PRAM wiele wyników z rozdz. 28 dla sieci sortujących

792
30.3. TWIERDZENIE BRENTA I SEKWENCYJNA EFEKTYWNOSC

i wiele wyników z rozdz. 29 dla układów arytmetycznych. Czytelnika nie znają­


cego tematyki dotyczącej układów kombinacyjnych zachęcamy do przejrzenia
rozdz. 29.
Układ kombinacyjny jest siecią acykliczną składającą się z elementów kom-
binacyjnych. Każdy element kombinacyjny ma jedno lub więcej wejść. W tym
podrozdziale zakładamy, że każdy element kombinacyjny ma tylko jedno wyj-
ście. (Elementy o k > 1 wyjściach można traktować jak k oddzielnych elemen-
tów). Liczbę wejść nazywamy stopniem wejściowym elementu, a liczbę elemen-
tów, do których wartość obliczana w danym elemencie jest kierowana, nazy-
wamy stopniem wyjściowym tego elementu. W tym podrozdziale zakładamy, że
każdy element kombinacyjny ma ograniczony przez stałą stopień wejściowy,
a stopień wyjściowy może być dowolny.
Rozmiarem układu kombinacyjnego jest liczba z.awartycb w nich elemen-
tów kombinacyjnych. Liczbę elementów kombinacyjnych na najdłuższej ścież­
ce od wejścia układu do wyjścia danego elementu nazywamy głębokością tego
elemetu. Głębokością układu nazywamy maksymalną głębokość z głębokości
jego elementów.

TwIERDZENIE 30.2. (fwierdzenie Brenta)


Każdy układ kombinacyjny o rozmiarze n, głębokości di ograniczonym przez
stałą
stopniu wejściowym można symulować na p-procesorowej maszynie
CREW PRAM w czasie O(n/p + d).

DOWÓD
Dane wejściowe dla symulowanego układu przechowujemy w pamięci globalnej
maszyny PRAM. W pamięci globalnej rezerwujemy też miejsce na dane pojawia-
jące się na wyjściu każdego elementu układu. Działanie jednego elementu można
wówczas symulować na jednym procesorze maszyny PRAM w czasie 0(1)
następująco. Procesor symulujący element po prostu odczytuje dane wejściowe
dla tego elementu z odpowiednich miejsc w pamięci, w których są przechowywa-
ne dane wejściowe dla całego układu lub dane wyjściowe tych elementów, które
produkują dane wejściowe dla elementu symulowanego. W ten sposób jest
symulowane przesyłanie danych między elementami w układzie. Następnie pro-
cesor oblicz.a wartość funkcji zadanej przez symulowany element i z.apisuje wynik
w odpowiednim miejscu globalnej pamięci. Ponieważ stopień wejściowy każdego
elementu jest ograniczony, każda funkcja może być obliczona w czasie 0(1).
Pozostaje pokazać, w jakiej kolejności przydzielać p procesorów maszyny
PRAM elementom układu, żeby łączny czas symulacji wynosił O(n/p + d).
Głównym ograniczeniem, jakie napotykamy, jest to, że element nie może być
symulowany, zanim nie zostaną obliczone wszystkie jego dane wejściowe. Mo-
żliwość jednoczesnego odczytu ma zastosowanie zawsze wtedy, kiedy kilka
symulowanych elementów wykorzystuje tę samą wartość.
---------------------·-- ..~·----=~
793
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

Ponieważ wejścia wszystkich elementów o głębokości 1 są jednocześnie


wejściami całego układu, elementy te są jedynymi, które początkowo można
symulować. Po zakończeniu symulacji elementów na głębokości 1 można symu-
lować elementy na głębokości 2 itd., aż do zakończenia symulacji elementów
o głębokości d. Istotna jest tu następująca obserwacja: jeśli została zakończona
symulacja wszystkich elementów o głębokościach od 1 do i, to moźemy rozpo-
cząć równoległą symulację dowolnego podzbioru elementów o głębokości i + l,
a jest to możliwe, gdyż obliczenia wykonywane przez te elementy są niezależne.
Dlatego nasza strategia przydzielania procesorów do elementów jest cał­
kiem prosta. Wszystkie elementy na głębokości i są symulowane przed elemen-
tami na głębokości i + 1. Na danej głębokości i jednocześnie symulujemy p ele-
mentów. Rysunek 30.8 ilustruje tę strategię dla p = 2.
Przeanalizujmy naszą strategię symulacji. Dla i = 1, 2, ... , n niech n1 będzie
liczbą elementów układu o głębokości i. Zatem

Rozważmy n1 elementów na głębokości i. Grupujemy je w fn1/pl grup, z któ-


rych pierwszych Ln 1/pj grup zawiera pop elementów, a pozostałe elementy,
jeśli są takie, należą do ostatniej grupy. Wówczas obliczenia wykonywane
przez elementy na głębokości i można symulować na maszynie PRAM w czasie
0(1n;/Pl ). Łączny czas symulacji jest zatem rzędu

n
--+d
p

Jeśli stopień wyjściowy każdego elementu w układzie wynosi 0(1 ), to
twierdzenie Brenta można rozszerzyć na symulację w modelu BREW.

WNIOSEK
30.3.
Każdy n-elementowy układ o głębokości di ograniczonych stopniach wejścio­
wym i wyjściowym można symulować na p-procesorowej maszynie BREW
PRAM w czasie O(n/p + d).

DOWÓD
Wykonujemy symulację podobną do tej z dowodu twierdzenia Brenta. Jedyną
różnicą jest symulacja przewodów, które w symulacji z twierdzenia 30.2 wyma-

794
30.3. TWIERDZENIE BRENTA I SEKWENCYJNA EFEKTYWNO$ć

11 Głębokość i

3 I

5 2

2 3

2 4

3 5

lys. 30.8. Twierdzerue Brenta. Symulacja układu o rozmiarze 15 i głębokości 5 przez 2-procesorową
maszynę CREW PRAM w 9 .:s;;15{1 + 5 krokach. Sieć jest symulowana od góry do dołu. Elemen-
ty, które są symulowane w tym samym czasie, są połączone w grupy oznaczone na rysunku
ciemnoszarym kolorem. Kaida grupa jest etykietowana liczbą równą numerowi kroku, w którym
są symulowane elementy z tej grupy

gały jednoczesnych odczytów. W symulacji na maszynie EREW wartość ob-


liczana przez element kombinacyjny nie jest bezpośrednio odczytywana przez
procesor, który tej wartości potrzebuje. Zamiast tego procesor symulujący ele-
ment obliczający tę wartość robi stalą liczbę jej kopii, po jednej dla każdego
procesora, który jej potrzebuje. Następnie procesory, dla których obliczona
wartość jest daną wejściową, mogą ją odczytać, nie kolidując ze sobą.


Opisana metoda symulacji na maszynie EREW nie działa dla elementów
o dowolnym stopniu wyjściowym, ponieważ w każdym kroku kopiowanie mo-
że zabierać więcej niż stały czas. Tak więc do symulacji układów o dowolnym
stopniu wyjściowym potrzebujemy jednoczesnego odczytu. (Z przypadkiem
dowolnego stopnia wejściowego można sobie czasami poradzić - jeśli elementy

795
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

układu są wystarczająco proste - wykonując symulację na maszynie CRCW.


Patn zad. 30.3-1).
Z wniosku 30.3 otrzymujemy szybki algorytm sortowania na maszynie
EREW PRAM. Jak podaliśmy w uwagach do rozdz. 28, sieć sortująca AK.S
dla n liczb ma głębokość O(lgn) i używa O(nlgn) komparatorów. Ponieważ
stopień wejściowy komparatorów jest ograniczony, istnieje algorytm typu
EREW sortujący n liczb w czasie O(lgn) przy użyciu n procesorów. (Wykorzy-
staliśmy ten wynik w twierdzeniu 30.l do pokamnia, że maszyna EREW
PRAM może symulować CRCW PRAM z co najwyżej logarytmicznym spo-
wolnieniem). Niestety, stałe ukryte w notacji O są tak duże, że ten algorytm
sortowania ma wyłącznie teoretyczne znaczenie. Istnieją jednakże praktyczniej-
sze algorytmy sortowania typu BREW. Zalicza się do nich zwłaszcza równo-
legły algorytm sortowania przez scalanie zaproponowany przez Cole'a [46].
Przypuśćmy teraz, że mamy algorytm dla maszyny PRAM, który używa
p procesorów, ale w naszej dyspozycji jest maszyna mająca tylko p' < p proce-
sorów. Chcielibyśmy jednak wykonać algorytm p-procesorowy na mniejszej
p'-procesorowej maszynie w sposób sekwencyjnie efektywny. Wykorzystując
pomysł z dowodu twierdzenia Brenta, możemy podać pewien warunek okreś­
lający, kiedy jest to możliwe.

TwIERDZENIE 30.4.
Jeśli algorytm A. działa
nap-procesorowej maszynie PRAM w czasie t, to dla
każdego p' < p istnieje
algorytm A' dla tego samego problemu działający na
p'-procesorowej maszynie PRAM w czasie O(pt/p').

DOWÓD
Ponumerujmy kolejne krok.i wykonywane w algorytmie A liczbami 1, 2, ..., t.
Algorytm A' symuluje każdy krok algorytmu A w czasie O(fp/p'l). Jest t ta-
kich kroków, tak więc całkowity czas symulacji wyoosi 0(1p/p'l t) - O(pt/p),
ponieważ p' < p. +
Algorytm A wykonuje pracę pt, a praca wykonywana przez A.' wynosi
(pt/p')p' = pt; symulacja jest zatem sekwencyjnie efektywna. W konsekwencji,
jeśli algorytm A jest sam sekwencyjnie efektywny, to także algorytm A' jest
sekwencyjnie efektywny.
Kiedy poszukujemy algorytmów sekwencyjnie efektywnych dla danego
problemu, nie jest konieczne konstruowanie różnych algorytmów dla różnych
liczb procesorów. Przypuśćmy na przykład, że potraftmy pokazać dokładne
dolne ograniczenia t na czas działania każdego algorytmu równoległego (bez
względu na liczbę używanych procesorów) rozwiązującego dany problem, i za-
łó:źmy, że najlepszy algorytm sekwencyjny dla tego problemu działa w cza-
sie w. Wówcz».S,żeby dla tego problemu otrzymać algorytmy efektywnie sek-
wencyjne dla wszystkich liczb procesorów p, dla których jest to możliwe, wy-

796
30.4. SEKWENCYJNIEEFEKTYWNERÓWNOLEGŁE OBLICZENIA PREFIKSOWE

starczy tylko skonstruować algorytm sekwencyjnie efektywny, który używa


p = 0(w/t) procesorów. Twierdzenie 30.4 gwarantuje istnienie takiego algoryt-
mu dla p' = o(p). Dla p' = ro(p) żaden tak.i algorytm nie istnieje, ponieważ
t jest dolnym ograniczeniem na czas działania każdego algorytmu równoleg-
łego i p't = w(pt) = w(w).

ZADANIA
30.3-1. Udowodnij twierdzenie analogiczne do twierdzenia Brenta dla symula-
cji układów logicznych z bramkami AND i OR o dowolnym stopniu wej-
ściowym. (Wskazówka: Niech „rozmiarem" będzie łączna liczba wejść do
bramek w całym układzie).
30.3-2. Pokaż, że obliczenia prefiksowe dla n wartości przechowywanych w ta-
blicy można na maszynie BREW PRAM zaimplementować w czasie
O(lgn}, używając O(n/lgn) procesorów. Dlaczego tego wyniku nie można
rozszerzyć bezpośrednio na przypadek listy?
30.3-3. Podaj sekwencyjnie efektywny algorytm typu BREW, który w czasie
O(lgn) mnoży macierz A wymiaru n x n przez wektor b wymiaru n.
(Wskazówka: Skonstruuj dla tego problemu układ kombinacyjny).
30.3-4. Podaj algorytm typu CRCW mnożenia dwóch macierzy wymiaru
n x n przy użyciu n 2 procesorów. Twój algorytm powinien być sekwencyj-
nie efektywny względem zwykłego, sekwencyjnego algorytmu mnożenia
macierzy, działającego w czasie 0(n 3 ). Czy potrafisz przerobić swój algo-
rytm na algorytm typu EREW?
30.3-5. W pewnych modelach obliczeń równoległych pozwala się na to, żeby
w trak.cie obliczeń procesory stawały się nieaktywne. Tak więc liczba pro-
cesorów wykonujących obliczenia może się zmieniać w każdym kroku.
W takim modelu zdefiniujmy pracę jako łączną liczbę kroków wykonywa-
nych w trak.cie działania algorytmu przez aktywne procesory. Pokaż, że
każdy algorytm typu CRCW, który wykonuje pracę w i działa w czasie t,
można wykonać na p-procesorowej maszynie BREW PRAM w czasie
O((w/p + t) lgp). (Wskazówka: Trudną częścią zadania jest ustalanie kolej-
ności symulowania aktywnych procesorów w trakcie przebiegu obliczeń).

* 30.4. Sekwencyjnieefektywnerównolegleobliczenia
prefiksowe
W podrozdziale 30.1.2 zapoznaliśmy się z algorytmem LIST-R.ANK wyznaczania
porządku elementów na liście, którego można użyć do obliczania sum prefikso-
wych na n-obiektowych listach. Algorytm ten używa n procesorów i wykonuje
pracę 0(n lg n). Ponieważ możemy łatwo policzyć sumy preftk.sowesekwencyjnie
w czasie 0(n), algorytm LIST-RANKnie jest sekwencyjnie efektywny.

797
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

W tym podrozdziale zaprezentujemy probabilistyczny, równoległy algo-


rytm typu EREW obliCUlnia sum prefiksowych, który jest sekwencyjnie efek-
tywny. Algorytm ten używa 0(n/lgn) procesorów i działa w czasie O(lgn)
z dużym prawdopodobieństwem. Jest on zatem sekwencyjnie efektywny z du-
żym prawdopodobieństwem. Ponadto z twierdzenia 30.4 wynika, że z tego
algorytmu otrzymuje się natychmiast algorytm sekwencyjnie efektywny dla ka-
żdej liczby procesorów p = O(njlgn).

Rekurencyjne, równolegle obliczenia prefiksowe


Probabilistyczny, równoległy algorytm preflk:sowy RANDOMIZED-LIST-
-PREFIXoperuje na n-obiektowej liście, wykorzystując p = 0(n/lgn) proceso-
rów. W czasie wykonywania algorytmu każdy procesor odpowiada za
n/p = 0(lgn) obiektów z listy wejściowej. Na początku rekursji obiekty są
przypisane do procesorów w dowolny sposób (nie muszą być koniecznie kolej-
nymi na liście), a potem „właściciel" obiektu już się nie zmienia. Dla wygody

{a)

••
.a

{c)

{d)

Rys. 30.9. Ilustracja działania sekwencyjnie efektywnego, probabilistycznego, rekurencyjnego, rów-


noległego algorytmu RANDOMIZED-LIST-Plt.EFIX dla listy składającej się z n obiektów. (a}{b) Do
usunięcia z listy są wybierane nie sąsiadujące obiekty (pokolorowane na czarno). WartoŚ1:: każdego
czarnego obiektu jest używana do obliczenia nowej wartości następnego obiektu na liście, po czym
obiekt jest usuwany z listy. Następnie są rekurencyjnie obliczane sumy prefiksowe na skróconej
liście. (c)-(d) Obliczone wartości obiektów na skróconej liście są ich właściwymi sumami prefik-
sowymi na liście pierwotnej. Obiekty usunięte są włączane z powrotem na listę i każdy z nich
korzyflta z wartości poprzednika, żeby obliczyć swoją końcową wartoŚ1::

798
30.4. SEKWENCYJNIEEFEKTYWNERÓWNOLEGŁE OBLICZENIA PREFIKSOWE

I[l,t]l4:;I Mr;! p.a,J:.Uj•,lls,sJJ<:;1(~ ,fAl!lill


611',j+i'
Usuwanie
z lis

••

1111
I Usuwanie
ł z listy

Poziom l Poziom Poziom Poziom Poziom S


Lista
ajwyższy) pusta
2 3
' (najniższy)

I Włączenie z powrotem
ł na lisl~

1111

:ys. 30.10, Kolejne poziomy rekursji po wywołaniu RANDOMIZED--LIST·PREFIX dla lisly 9-obiektowej.
Na każdym poziomie rekunji obiekty pokolorowane na czarno są usuwane z listy. Rekursjarozwija s.ię
aż do osiągnięcia listy puslej, a następnie usunięte obiekty są włączane z powrotem na listę

przyjmujemy, że
lista jest dwukierunkowa. (Listę jednokierunkową można
przekształcić w listę dwukierunkową w czasie O(l)"t).
Idea algorytmu RANDOMIZED-LIST-PREFIXpolega na wykonaniu nastę­
pujących kroków: najpierw usuwamy część obiektów z listy, następnie rekuren-
cyjnie wykonujemy obliczenia prefiksowe dla skróconej w ten sposób listy, po
czym wstawiamy na powrót usunięte początkowo elementy, otrzymując wynik.i
obliczenia preftlcsowego dla całej listy wejściowej. Rysunek 30.9 ilustruje pro-
ces rozwijania rekursji, a rys. 30.10 obrazuje, jak rekursja jest zwijana. Pokaże­
my trochę później, że na każdym poziomie rekursji są zachowywane następują­
ce dwie własności:

1 Jeśli mamy do dyspozycji n procesorów. Przy nJlgn procesorach zabiera to czas OQgn)
(przyp. tłum.).
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

(1) co najwyżej jeden obiekt z obiektów przypisanych do danego procesora


zostaje wybrany do usunięcia z listy;
(2) żadne dwa sąsiednie elementy na liście nie są wybrane do usunięcia.

Zanim pokażemy, jak wybierać obiekty, żeby miały te własności, prze-


śledźmy w szczegółach sposób wykonywania obliczeń prefiksowych. Załóżmy,
że na pierwszym poziomie rekursji k-ty obiekt na liście został wybrany do
usunięcia. Z tym obiektem jest związana wartość [k, k], która jest pobierana
przez obiekt (k + 1)-szy na liście. (Z przypadkami brzegowymi, np. gdy k jest na
końcu listy, można sobie łatwo poradzić i ich opis pomijamy). Obiekt (k + 1)-
-szy, z którym jest związana wartość [k + I, k + 1], oblicza i zapamiętuje
[k, k + I] - [k, k] ® [k + I, k + I]. Następnie k-ty obiekt jest usuwany z listy.
Na tak skróconej liście obliczenia prefiksowe są następnie wykonywane
rekurencyjnie - procedura RANDOMIZED-LIST-PREFIX wywołuje samą siebie.
(Po osiągnięciu listy pustej rozpoczyna się zwijanie rekursji). Zauwaimy, że po
powrocie z wywołania rekurencyjnego każdy obiekt na skróconej liście ma
policzoną wartość, która jest równa wartości sumy prefiksowej dla tego obiek-
tu na liście pierwotnej. Pozostaje tylko włączyć z powrotem na listę uprzednio
usunięte obiekty, takie jak obiekt k-ty, i policzyć ich sumy prefiksowe.
Po włączeniu k-tego obiektu na listę jego końcowa wartość (suma prefi-
ksowa) może zostać obliczona za pomocą wartości z obiektu (k - 1)-szego. Po
powrocie z rekursji (k- 1)-szy obiekt zawiera [1, k - 1] i dlatego obiekt k-ty
-którego wartość ciągle jest równa {k, k] - potrzebuje tylko sięgnąć po wartość
[I, k - I] i obliczyć [I, k] - [I, k- I] 18>[k, k].
Z własności (1) wynika, że z każdym wybranym obiektem jest zwiążany
inny procesor, który najpierw usuwa obiekt z listy, a następnie włącza go
z powrotem na listę. Własność (2) zapewnia, że procesory nie przeszkadzają
sobie nawzajem podczas usuwania różnych obiektów z listy, a następnie pod-
czas włączania ich z powrotem na listę (patrz zad. 30.4-1). Obie własności
razem gwarantują, że obliczenia na każdym poziomie rekursji można wykonać
w czasie stałym bez konfliktów odczytu i zapisu.

Wybieranie obiektów do usunięcia


w jaki sposób w procedurze RANDOMIZED-LIST-PREFIX są wybierane obiekty
do usunięcia? Wybrane obiekty muszą mieć obie wymienione wcześniej włas­
ności, a dodatkowo chcemy, żeby czas potrzebny do dokonania wyboru był
krótki (najlepiej stały). Ponadto chcielibyśmy, aby jak najwięcej obiektów zo-
stało wybranych.
Następująca metoda losowego wyboru spełnia nasze wymagania. Wybór
obiektów do usunięcia następuje w wyniku wykonania przez każdy procesor
poniższych trzech kroków:

800
30.4. SEKWENCYJNIE EFEKTYWNE RÓWNOLEGŁE OBLICZENIA PREFIKSOWE

1. Procesor pobiera jeden obiekt i, jeszcze nie usunięty z listy, spośród obiek-
tów, za które odpowiada.
2. Procesor „rzuca monetą symetryczną", otrzymując z równym prawdopodo-
bieństwem albo ORLA, albo RESZKĘ,
3. Jeśli wypadł ORZEŁ i obiekt next[i1 nie został pobrany przez związany z nim
procesor lub został pobrany, ale odpowiadający za niego procesor wyrzucił
RESZKĘ, to procesor zaznacza i jako wybrany do usunięcia.

W tej metodzie wyboru obiektów do usunięcia dokonuje się w czasie sta-


łym, a sama metoda nie wymaga jednoczesnych dostępów do pamięci.
Musimy pokazać, że opisana metoda zachowuje podane wcześniej dwie
własności. Własność (I) jest oczywiście spełniona, ponieważ każdy procesor
pobiera tylko jeden obiekt, który zostaje kandydatem do usunięcia. Aby poka-
zać, że jest spełniona własność (2), załóżmy przeciwnie, że i oraz next[i] są
dwoma kolejnymi obiektami, które zostały wybrane do usunięcia. Jest to moż­
liwe tylko wtedy, kiedy oba obiekty zostały pobrane przez swoje procesory
w kroku 1 i oba procesory w kroku 2 „wyrzuciły" ORLA.Ale obiekt i nie jest
zaznaczany do usunięcia, jeśli procesor odpowiedzialny za next [i] ,,wyrzucił"
ORLA - sprzeczność .

.naliza
Ponieważ w każdym rekurencyjnym kroku czas działania procedury RANDO-
MIZED-LIST-PREFIXjest stały, do analizy czasu działania algorytmu wystarczy
określić, ile kroków potrzeba, żeby usunąć wszystkie obiekty z pierwotnej listy.
W każdym kroku każdy procesor z prawdopodobieństwem co najmniej 1/4
usuwa z listy pobrany przez siebie obiekt i. Dlaczego? ORZEŁ jest wyrzucany
z prawdopodobieństwem 1/2, a prawdopodobieństwo, że next[1] nie zostanie
pobrany przez odpowiadający za niego procesor lub zostanie pobrany i ten
procesor wyrzuci RESZKĘ, wynosi co najmniej 1/2. Ponieważ dwa rzuty monetą
są zdarzeniami niezależnymi, możemy pomnożyć ich prawdopodobieństwa
przez siebie, otrzymując prawdopodobieństwo co najmniej 1/4 na to, że obiekt
pobrany przez dany procesor zostanie usunięty. Ponieważ każdy procesor od-
powiada za @(lgn) obiektów, oczekiwany czas usunięcia wszystkich obiektów
związanych z jednym procesorem wynosi S(lgn).
Niestety, z tej prostej analizy nie wynika, że oczekiwany czas działania
procedury RANDOMIZED-LIST-PREF1X wynosi 8(lgn). Jeśli na przykład więk­
szość procesorów usuwa szybko wszystkie swoje obiekty, a kilku procesorom
zabiera to dużo więcej czasu, średni czas potrzebny do usunięcia obiektów
przez jeden procesor może nadal wynosić @(lgn), ale czas działania całego
algorytmu jest długi.

801
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

Oczekiwany czas działania procedury RANDOMIZED-LIST-PREFIXjest rze-


czywiście 0(lg n), chociaż nie widać tego tak łatwo. Pokażemy, że z prawdopo-
dobieństwem co najmniej 1 - 1/n wszystkie obiekty zostaną usunięte z listy po
co najwyżej clgn rekurencyjnych krokach dla pewnej stałej c. W zadaniach
30.4-4 i 30.4-5 należy podać uogólnienie tego dowodu i pokazać, że oczekiwa-
ny czas działania algorytmu wynosi @(lgn).
W dowodzie wykorzystuje się spostrzeżenie, że doświadczenie losowe po-
legające na wybieraniu przez dany procesor obiektów do usunięcia można tra-
ktować jak ciąg prób Bemoulliego (patrz rozdz. 6). Próba kończy się suk-
cesem, gdy obiekt zostaje wybrany. W przeciwnym razie próba kończy się
porażką. Ponieważ naszym celem będzie pokazanie, że z małym prawdopodo-
bieństwem któryś z procesorów nie usunie swoich obiektów z listy, możemy
założyć, że prawdopodobieństwo sukcesu wynosi dokładnie 1/4 (a nie co naj-
mniej 1/4). (Patrz zad. 6.4-8 i 6.4-9, w których jest formalne uzasadnienie dla
podobnych założeń).
ż.eby uprościć dalszą analizę, zakładamy, że mamy dokładnie n/lg n proce-
sorów, z których każdy odpowiada za lgn obiektów. Wykonujemy clg n prób
Bemoulliego (c określimy później) i interesuje nas Marzenie, że mniej niż lgn
z nich zakończyło się sukcesem. Niech X będzie zmienną losową określającą
łączną liczbę sukcesów. Z wniosku 6.3 otrzymujemy, że prawdopodobieństwo
zdarzenia, iż procesor usunie z listy mniej niż lgn obiektów w clgn próbach
• • • •
wynosi co naJwyzeJ

Pr{X < lgn),:; ( cl")(3)''••-••


l:n 4

-(,c(!)'-')""
"(:)''"
= 1/n2
jeśliprzyjmiemy c ~ 20. (Wiersz drugi wynika z nierówności (6.9)). Tak więc
prawdopodobieństwo, że nie wszystkie obiekty przynależne do danego proce-
sora zostaną usunięte z listy w clg n krokach, wynosi co najwyżej 1/n2 •
Chcemy teraz oszacować prawdopodobieństwo, że pewne obiekty spośród
wszystkich obiektów na liście nie zostaną z niej usunięte w c lgn krokach.

802
30.4. SEKWENCYJNIEEFEKTYWNERÓWNOLEGŁE OBLICZENIA PREFIKSOWE

Z nierówności Boole'a (6.22) otrzymujemy, że to prawdopodobieństwo jest


równe co najwyżej sumie prawdopodobieństw, iż któryś z procesorów nie usu-
nie wszystkich swoich obiektów. Ponieważ jest n/lgn procesorów i każdy
z nich nie usuwa wszystkich swoich obiektów z prawdopodobieństwem co naj-
wyżej 1/n2 , prawdopodobieństwo tego, że istnieje jakikolwiek procesor, który
nie usunie wszystkich swoich obiektów, wynosi co najwyżej

n I I
~- . -·---- ~ -
lgn n2 ....., n

W ten sposób udowodniliśmy, że z prawdopodobieństwem co najmniej I - 1/n


każdy obiekt zostaje usunięty z listy po OOgn) krokach. Ponieważ obliczenia
w każdym kroku są wykonywane w czasie stałym, czas wykonania RANDOMI-
ZED-LIST-PREFIXz dużym prawdopodobieństwem wynosi O(lgn).
Stala c ~ 20 w oszacowaniu clg n na czas działania algorytmu może wyda-
wać się zbyt duża z praktycznego punktu widzenia. W rzeczywistości została
ona dobrana na potrzeby analizy i nie odzwierciedla rzeczywistego zachowania
się algorytmu. W praktyce ten algorytm jest bardzo szybki. Stale współczyn­
niki pojawiające się w analizie są tak duże, gdyż zdarzenie polegające na usu-
nięciu przez jeden procesor wszystkich jego obiektów z listy jest zależne od
zdarzenia, że inny procesor usunie wszystkie swoje obiekty z listy. Z powodu
tych zależności została użyta nierówność Boole'a, w której nie wymaga się
niezależności. W wyniku otrzymuje się jednak gorszą stalą niż ta, jakiej ogólnie
można by się spodziewać w praktyce.

ZADANIA
30.4-1. Zilustruj na rysunku, co może zdarzyć się złego w algorytmie RAN-
DOMIZED-LIST-PREFIX, jeśli dwa sąsiednie obiekty na liście zostaną jedno-
cześnie wybrane do usunięcia.
r 30.4-2. Zaproponuj prostą zmianę w algorytmie RANDOMIZED-LIST-PREFIX,
żeby jej czas działania w najgorszym przypadku wynosił O(n) dla listy
złożonej z n obiektów. Wykorzystaj definicję wartości oczekiwanej do udo-
wodnienia, że z tą modyfikacją oczekiwany czas działania algorytmu wy-
nosi 00gn).
r 30.4-3. Pokaż, w jak.i sposób zaimplementować algorytm RANDOMIZED-
-LIST-PREFIX,żeby w najgorszym przypadku każdy procesor używał pa-
mięci rozmiaru O(n/p), niezależnie od głębokości rekursji.
r 30.4-4. Wykaż, że dla każdej stałej k ~ 1 algorytm RANDOMIZED-LIST-PRE-
FIX działa w czasie 00gn) z prawdopodobieństwem co najmniej 1- l/n1.
Pokaż, jak k ~a na stałą w oszacowaniu na czas działania algorytmu.
r 30.4-5. Korzystając z wyniku zad. 30.4-4, pokaż, że oczekiwany czas działania
algorytmu RANDOMIZED-LIST-PREFIX wynosi O(lgn).

803
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

łamanie symetrii
30.5. Deterministyczne
Rozwaimy sytuację, w której dwa róZD.eprocesory żądają wyłącznego dostępu
do obiektu, W jaki sposób procesory mogą zdecydować, który z nich zdobywa
prawo dostępu jako pierwszy? Chcielibyśmy uniknąć zarówno takich sytuacji,
w których oba nabywają prawa dostępu, jak i takich, w których żaden nie
nabywa takiego prawa. Problem wyboru jednego z procesorów jest przykła­
dem problemu łamania symetrii. Wszyscy wielokrotnie spotykaliśmy się z za-
mieszaniem, jakie powstaje, gdy dwoje uprzejmych ludzi chce jednocześnie
przejść przez te same drzwi. Podobne problemy łamania symetrii spotykamy
często przy układaniu algorytmów równoległych. Efektywne rozwiązania tych
problemów są wysoce użyteczne.
Jedna z metod łamania symetrii polega na rzucaniu monetą. Rzut monetą
można zaimplementować na komputerze za pomocą generatora liczb loso-
wych. W wypadku łamania symetrii dla dwóch procesorów rzut monetą wy-
konują oba procesory. Jeśli jeden wyrzuci ORLA, a drugi wyrzuci RESZKĘ,
to ten, który wyrzucił ORLA, wygrywa. Jeśli oba wyrzucą to samo, próbują
jeszcze raz. Przy tej strategii symetria jest łamana w oczekiwanym stałym czasie
(patrz zad. 30.5-1).
O skuteczności metody losowego wyboru przekonaliśmy się w podrozdz.
30.4. W algorytmie RANDOMJZED-LIST-PREFIX sąsiednie obiekty na liście nie
mogą być jednocześnie wybrane do usunięcia, ale liczba wybranych obiektów
powinna być jak największa. Wśród pobranych obiektów żaden się jednak nie
wyróżnia. Jak się przekonaliśmy, losowość dostarcza prostej i skutecznej meto-
dy łamania symetrii między sąsiednimi elementami na liście, która gwarantuje
jednocześnie wybór wielu obiektów z dużym prawdopodobieństwem.
W tym podrozdziale zapoznamy się z deterministyC"Zną metodą łamania
symetrii. W tej metodzie zamiast wykonywania rzutów monetą działa się na
indeksach procesorów lub adresach w pamięci. Przykładowo, dla dwóch proce-
sorów możemy złamać symetrię, wybierając procesor z mniejszym indeksem
jako pierwszy - w oczywisty sposób można to zrobić w czasie stałym.
Ten sam pomysł, tylko wykorzystany dużo sprytniej, zastosujemy w algo-
rytmie łamania symetrii na n-obiektowej liście. Naszym celem jest wybór stałe­
go procenta obiektów z listy, unikając przy tym wyboru obiektów sąsiednich.
Algorytm będzie można wykonać na n-procesorowej maszynie EREW w czasie
O(tg• n). Ponieważ lg• n :E;5 dla wszystkich n :E;2 65536 , we wszystkich praktycz-
nych zastosowaniach O(lg • n) można traktować jako małą stałą (patrz s. 59).
Nasz algorytm składa się z dwóch częsci. W części pierwszej koloruje się
listę 6 kolorami w czasie O(lg• n). W części drugiej 6-pokolorowanie przekształ­
ca się w czasie stałym w „maksymalny zbiór niezależny" obiektów z listy.
Maksymalny zbiór niezależny będzie zawierał stały procent wszystkich obiek-
tów i żadne dwa jego obiekty nie będą sąsiednie.

804
30.5. DETERMINISTYCZNE ŁAMANIE SYMETRII

Kolorowania i maksymalne zbiory niezależne

Kolorowaniem grafu nieskierowanego G = (V, E) nazywamy każdą funkcję


C: V-+ N taką, że jeśli C(u) = C(v), to (u, v)ff.E, dla wszystkich u, v EV. Inny-
mi słowy, żadne sąsiednie wierzchołki nie mają tego samego koloru. W 6-kolo-
rowaniu listy kolory należą do zbioru {O, 1, 2, 3, 4, 5} i żadne dwa kolejne
wierzchołki nie mają tego samego koloru. Tak naprawdę każdą listę można
pokolorować 2 kolorami, kolorując wierzchołki o parzystej odległości od koń­
ca kolorem O, a pozostałe kolorem 1. Takie kolorowanie można obliczyć w cza-
sie O(lg n) za pomocą równoległych obliczeń prefiksowych, jednak w wielu
zastosowaniach wystarczy tylko obliczyć 0(1)-kolorowanie. Pokażemy, że
6-kolorowanie można obliczyć w czasie O(lg n) bez korzystania z losowości.
0

Niezależnym zbiorem wierzchołków grafu G = (V, E) nazywamy każdy


podzbiór wierzchołków V' c V taki, że każda krawędź z E jest incydentna z co
najwyżej jednym wierzchołkiem z V'. Maksymalny zbiór niezależny (lub MIS;
skrót od ang. maxima/ independent set) jest niezależnym zbioretn wierzchołków
V' takim, że dla wszystkich wierzchołków ve V - V' zbiór V' u {v} nie jest
niezależny - każdy wierzchołek spoza V' sąsiaduje z pewnym wierzchołkiem
z V'. Nie należy mylić problemu obliczania maksymalnego zbioru niezależnego
- problem łatwy - z problemem obliczania zbioru niezależnego o największej
liczności - problem trudny. Problem obliczania zbioru niezależnego o najwięk­
szej liczności w dowolnym grafie jest NP-zupełny. (Rozdział 36 zawiera omó-
wienie NP-zupełności. Problem 36-1 dotyczy zbiorów niezależnych o najwięk­
szej liczności). Najliczniejszy zbiór niezależny (a stąd także maksymalny) na
n-obiektowej liście można znaleźć w czasie O(lgn). W tym celu można wyko-
rzystać równoległe obliczenia prefiksowe, podobnie jak we wspomnianym
wcześniej 2-kolorowaniu, do wyznaczenia obiektów o parzystych odległoś­
ciach od końca listy. W tej metodzie do zbioru niezależnego jest wybiera-
nych ln/21 obiektów. Zauważmy jednak, że każdy maksymalny niezależny
zbiór obiektów na n-obiektowej liście zawiera co najmniej n/3 obiektów, ponie-
waż z każdych trzech kolejnych obiektów co najmniej 1 musi być w tym zbio-
rze. Pokażemy, że mając dane kolorowanie listy stałą liczbą kolorów, można
w czasie stałym obliczyć maksymalny zbiór niezależny obiektów z tej listy,

<olorowanie listy 6 kolorami


Do pokolorowania listy 6 kolorami użyjemy algorytmu Six-COLOR. Nie poda-
my formalnego zapisu tego algorytmu, ale opiszemy pewne jego szczegóły.
Zakładamy, że początkowo z każdym obiektem x z listy jest związany jeden
procesor P(x)e{O, 1, ... , n -1}. -
W algorytmie SIX-COLORdla każdego obiektu x na liście jest obliczany
ciąg kolorów C 0 [x], C 1 [x], ... , C..,[x]. Początkowe kolorowanie C0 jest

------------------
805
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

n-kolorowaniem, W każdej iteracji na podstawie kolorowania C1 jest obliczane


nowe kolorowanie C1 + 1 , dla k = O, 1, ... , m. Ostatnie kolorowanie Cm jest
6-kolorowaniem i udowodnimy, że m = O(lg•n).
Początkowe kolorowanie jest banalnym n-kolorowaniem, w którym
C0 (x] = P(x). Ponieważ żadne dwa obiekty na liście nie mają tego samego
koloru, żadne dwa sąsiednie obiekty liście nie mają tego samego koloru i dlate-
go to kolorowanie jest poprawne. Zauważmy, że każdy kolor w początkowym
kolorowaniu można zapisać za pomocą flgnl bitów, co oznacza, że można go
pamiętać w jednym słowie komputera.
Kolejne kolorowania otrzymujemy w następujący sposób, Iteracja k-ta,
dla k = O, 1, 2, ... , m - 1, rozpoczyna się od kolorowania Cl i kończy koloro-
waniem Cl+t• w którym liczba bitów potrzebna do zapamiętania koloru
jest mniejsza (patrz pierwsza część rys. 30.11). Przypuśćmy, że na początku
iteracji każdy kolor w kolorowaniu Cl jest zapisany za pomocą r bitów.
Nowy kolor obiektu x zostanie określony na podstawie obecnego koloru
x i koloru obiektu next[x].
Aby być bardziej precyzyjnym, załóżmy, że dla każdego obiektu x mamy
Cl[x] = a i C1[next[x]] = b, gdzie a= (a,_ 1 , a,_ 2 , ... , a 0 ) i b = (b,_ 1 , b,_ 2 ,
... ,b 0 ) są kolorami r-bitowymi. Ponieważ Cl[x] "F Cl[next[x]], istnieje taki bit,
na którym te kolory się różnią. Niech i będzie numerem najmniej znaczącego
bitu, na którym te kolory się różnią (a 1 "F b1). Ponieważ O ~ i ~ r - 1, więc
i można zapisać m pomocą tylko flg rl bitów: i= (ifli,1 _ 1, iri,,1_ 2, ••• , i0 ).
Nowym kolorem x jest kolor powstały z i przez dopisanie a1 jako najmniej
znaczącego bitu. Tak więc

Cl+ 1[x] = (i, ai)

Nowym kolorem ostatniego elementu na liście jest (O, a 0 ), Stąd liczba bitów
potrzebnych do zapisania każdego koloru wynosi co najwyżej flgrl + l, Mu-
simy pokazać, że jeżeli na początku ka Mej iteracji kolorowanie jest poprawne,
to po jej wykonaniu nowe kolorowanie jest także poprawne. W tym celu wy-
każemy, że nierówność Cl[x] 'F C1[next[x]] pociąga za sobą nierówność
Cl+ 1{x] 'F Cl+ 1[next[x]], Załóżmy, że CJx] = a i Cl[next[x]] = b oraz że
Cl+ 1 [x] = (i, a1) i C1+ 1[next[x]] = <J,b1), Należy rozpatrzyć dwa przypadki.
Jeśli i "Fj, to (i, a1) 'F (J, b1) i dlatego oba nowe kolory są różne. Jeśli i= j,
to a1 "Fb1 = b1, co wynika z naszej metody nadawania nowego koloru, i po-
nownie oba nowe kolory są różne, (Podobnie można rozważyć sytuację na
końcu listy).
Metoda przekolorowywania używana w algorytmie Six-COLOR zamienia
kolor r-bitowy na kolor (flgrl + 1)-bitowy, co oznacza, że liczba bitów ściśle
maleje, jeśli tylko r ~ 4. Dla r = 3 dwa kolory mogą się różnić na jednej

806
o o o
o o o o
il
o
t ~ ~§ o·;~~8 o o o o~~
·a:: ~§ ·1~
o

li -;6
·•

.t::
·-
·•
"'o .-:::
oi!
o o o
12,; ft:
~]
!5 " • o
~] -~]- -~]- " fi]
Q.. ił: )3 p,. i !5
o o 0
o
" • o
~]
" 8. ,:i.. ~

" " " " " "

·001 001 00 I 001 001

·t100 010 010

0010 100 100 100 100

0110 · Oli Oli

lłltlO 0000 010 010 ] 010

0010 100

0110

01111

óoo10 Oli

011
J_
101

0001 001

0000 ooo ooo 1100


-

00001

01010
0001

0000
001

~" [ "'"U ()()() ~ ~ _ooo_J


•~
Rys. 30.l 1. Działanie algorytmów Srx-CoLORi LIST-MISłamiących symetrię na liście. Zastosowanie obu
algorytmów po kolei pozwala mależi: duży zbiór nie sąsiadujących ze sobą obiektów na liście w czasie
O(lg·n) przy użyciu n procesorów. Początkowa lista n= 20 obiektów znajduje się po lewej stronie
rysunku (umieszczona pionowo). Wszystkie obiekty mają początkowo pa.ra.nriróżne kolory, będą.ce
5-bitowymi liczbami. Algorytm S1x-Co1.0Rpotrze buje zaledwie dwóch iteracji, by pokolorować tę listę
kolorami ze zbioru {O, 1, 2, 3, 4, 5}. W trakcie działania algorytmu LIST-MIS białe obiekty zostają
dodane do zbioru MIS, a czarne zostają wykluczone, tj. ich bit aliue zostaje ustawiony na FALSE
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

z trzech pozycji O, 1 lub 2. Każdy nowy kolor powstaje z dopisania Olub 1 do


(00), (01) lub (10), co w konsekwencji daje ponownie liczbę 3-bitową. Jed-
nakże tylko 6 z 8 liczb 3-bitowych można otrzymać w ten sposób, a stąd
wynika, że po zakończeniu działania procedury S1x-COLOR lista jest rzeczywi-
ście poprawnie kolorowana 6 kolorami.
Przy założeniu, że każdy procesor może w stałym czasie wyznaczyć naj-
mniejszy indeks i oraz wykonać operację przesunięcia w lewo (ang. left-shift)
na słowie maszyny ~ talcie operacje są dostępne na wielu rzeczywistych maszy-
nach - każda iteracja jest wykonywana w stałym c:zasie. Algorytm SIX-COLOR
jest algorytmem typu BREW: dla każdego obiektu jego procesor potrzebuje
tylko dostępu tylko do x i next[x].
Na koniec zobaczmy, dlaczego tylko O(lg•n) iteracji wystarcza do przejś­
cia od początkowego n-kolorowania do 6-kolorowania. Przypomnijmy, że lg• n
oznacza liczbę, która określa, ile razy trzeba złożyć funkcję lg, żeby wartość
tak. otrzymanej funkcji dla n była nie większa niż 1. Inaczej, jeśli przez lgll)n
oznaczymy i-krotne złożenie funkcji lg, to

tg·n = min{i ~ O:Ig1°n~ l}

Niech r 1 będzie liczbą bitów potrzebnych do zapisania kolorów w kolorowaniu


C1• Udowodnimy przez indukcję, że jeśli flgl1>nl~ 2, to r 1 ~ flg(1lnl + 2. Na
początku r1 ~ flg nl . Po wykonaniu i-tej iteracji potrzebna liczba bitów maleje
do r 1+ 1 = flgrJ + 1. Przyjmując, że założenie indukcyjne zachodzi dla r 1_ 1 ,
otrzymujemy

r1 = ~gr,-,1 +1

,;; ~g(~g<1-''•l + 2l] + l


,;; ~g(]g"- ''n+ 3)1 + 1

,;; ~g(21g"-''n)l +l
= ~g(!g(I-''n) + ll + l
= ~g'"nl + 2
Wiersz czwarty wynika z założenia, że flgUlnl ~ 2, co oznacza, że f1g<1- 1lnl ~
~ 3. Dlatego po m =lg• n krokach liczba bitów w kolorowaniu wynosi
r,,, ~ flg<"'lnl + 2 = 3, ponieważ z defmicji lg" wynika, że IgC"'ln~ 1. Tak więc
jedna więcej iteracja wystarcza do otrzymania 6-kolorowania. Łączny czas
działania procedury SIX-COLORS wynosi zatem O(tg•n).

808
30.5. DETERMINISTYCZNE ŁAMANIE SYMETRII

Obliczanie z 6-kolorowania maksymalnego zbioru


niezależnego

Kolorowanie jest trudniejszą częścia łamania symetrii. Przedstawimy teraz


n-procesorowy algorytm LIST-MIS typu EREW, który w czasie O(c) oblicza
maksymalny zbiór niezależny dla n-obiektowej listy, mając dane jej c-koloro-
wanie. Po obliczeniu 6-kolorowania listy możemy więc w stałym czasie wy-
znaczyć na niej maksymalny zbiór niezależny.
Druga część rys. 30.11 ilustruje ideę działania algorytmu LIST-MIS. Załóż­
my, że mamy dane c-kolorowanie C. Z każdym obiektem wiążemy jeden bit
alive [x], który informuje, czy x jest ciągle kandydatem do włączenia do zbioru
niezależnego. Początkowo alive[x] = TRUE dla wszystkich obiektów x.
Algorytm wykonuje te same obliczenia, kolejno dla każdego z c kolorów.
W obliczeniach dla koloru i procesor odpowiedzialny za obiekt x sprawdza,
czy C[x] =ii alive[x] = TRUE. Jeśli oba warunki są spełnione, to procesor
zaznacza, że x należy do konstruowanego zbioru MIS. Dla wszystkich obiek-
tów sąsiadujących z tymi zakwalifikowanymi do zbioru niezależnego - wystę­
pujących na liście bezpośrednio przed lub za nimi - bit alive[x] jest ustawiany
na FALSE. Te obiekty nie mogą należeć do MIS, gdyż sąsiadują z obiektami
z MIS. Po c iteracjach każdy obiekt albo należy do zbioru MIS, albo jego bit
alive jest ustawiony na FALSE.
Musimy pokazać, że otrz~any zbiór jest maksymalny i niezależny.
Dla dowodu niezależności przypuśćmy, że dwa sąsiednie obiekty x i next[x]
zostały umieszczone w tym zbiorze. Ponieważ są one sąsiednie i C jest koloro-
waniem, C[x] #- C[next[x]]. Bez straty ogólności możemy założyć, że
C[x] < C[next{x]]. Tak więc x jest umieszczany w zbiorze MIS przed next [x].
Ale wówczas a/ive[next[x]] przyjmuje wartość FALSE, zanim obiekty o kolo-
rze C[next[x]] są rozważane, i dlatego next[x] nie mógł być umieszczony
w zbiorze MIS.
Aby się przekonać, że MIS jest maksymalny, przypuśćmy, że żaden
z trzech kolejnych obiektów x, y i z nie został umieszczony w MIS. Jedynym
sposobem na to, żeby y nie był dołączony do zbioru MIS, jest dołączenie do
MIS któregoś z obiektów x i z, co spowodowałoby ustawienie bitu alive[y] na
FALSE.Ponieważ przy naszych założeniach ani x, ani z nie zostały umieszczone
w zbiorze MIS, więc w kroku obliczeń dla koloru C[v] bit alive [v] = TRUE
i y musiał zostać dołączony do zbioru MIS.
Każda iteracja w algorytmie LIST-MIS zabiera na maszynie PRAM czas
0(1). Algorytm jest typu EREW, gdyż procesor związany z każdym obiektem
wymaga dostępu tylko do tego obiektu oraz jego poprzednik.a i następnika na
liście. Łącząc algorytmy 6-kolorowania (SIX-COLORS)i obliczania maksymal-
nego zbioru niezależnego (L1sT-MIS), możemy deterministycznie złamać sy-
metrię na liście w czasie O(lg• n).

809
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

ZADANIA

30.5-1. Pokaż, że
metoda łamania symetrii z przykładu z początku tego pod-
rozdziału działa w oczekiwanym czasie stałym.
30.5-2. Pokaż,jak.mając dane 6-kolorowanie, można kolorować listę 3 kolora-
mi w czasie 0(1), używając n procesorów maszyny EREW PRAM.
30.>3. Załóżmy, że każdy węzeł różny od korzenia w n-węzłowym drzewie
T ma wskaźnik do ojca. Podaj algorytm typu CREW, który w czasie
00g' n) pokoloruje T stalą liczbą kolorów.
* 30.5-4. Podaj efektywny algorytm dla maszyny PRAM kolorujący stałą liczbą
kolorów grafy o stopniu 3. Przeanalizuj swój algorytm.
30.>S. Zbiorem k-władającym na liście nazywamy zbiór obiektów (władców)
z listy taki, że żadni dwaj władcy nie są sąsiedni i co najwyżej k obiektów
nie będących władcami (poddanych) oddziela dwóch kolejnych władców.
Tak więc maksymalny zbiór niezależny jest 2-władający. Pokaż, jak można
dla n-obiektowej listy obliczyć w czasie 0(1) i przy użyciu n procesorów
zbiór O(lgn)-władający. Pokaż, jak przy tych samych założeniach można
obliczyć w czasie 0(1) zbiór O(lglgn)-władający.
* 30.5-6. Pokaż, jak wyznaczyć 6-kolorowanie n-obiektowej listy w czasie
O(lg(lg•n)). Załóż, że każdy procesor może zapamiętać obliczoną wcześ­
niej tablicę ro2JDiaru O(lgn). (Wskazówka: Od ilu wartości zależy końcowy
kolor jednego obiektu w algorytmie 6-kolorowania SIX-COLOR?)

Problemy
30-1. Odcinkowe obliczenia prefiksowe
Podobnie jak zwykłe obliczenia prefiksowe, odcinkowe obliczenia prefiksowe
definiuje się za pomocą pewnego, łącznego operatora ®· Na wejściu jest dany
ciąg x = (x 1 , x 2 , ... , x,,), którego elementy nalei.ą do pewnej dziedziny S, i ciąg
odcinkowy b = (b 1 , 6 2 , ... , 6,,), którego elementy należą. do zbioru {O,I}, przy
czym b 1 = 1. Wynikiem odcinkowych obliczeń prefiksowych jest ciąg
y = (),1 , y 2 , •.• , y,,) elementów z dziedziny S. Bity z ciągu b wyznaczają po-
działy x i y na odcinki; nowy odcinek rozpoczyna się wszędzie tam, gdzie
b1 = 1, i ciągnie się aż do kolejnego bitu równego 1 (wyłącznie) lub wyczerpa-
nia się całego ciągu. Odcinkowe obliczenia prefiksowe polegają na wykonaniu
obliczeń prefiksowych niezależnie dla każdego odcinka z x i otrzymaniu w wy-
niku odpowiedniego odcinka wy. Rysunek 30.12 ilustruje odcinkowe oblicze-
nia prefiksowe z użyciem zwykłego dodawania.

(a) Zdefmiujmy operację ® na uporządkowanych parach (a, z), (a', z')e


e{O, l} x S jak następuje:

810
PROBLEMY

_ {(a, z®z'), jeśli a' =O


(a, z)® (a', z') - (I, z'),
jeśli a' = 1

Udowodnij, że operacja ® jest łączna. -


(b) Pokaż, jak na maszynie EREW PRAM zaimplementować dowolne odcin-
kowe obliczenia prefiksowe na n-elementowej liście w czasie O(lgn).

b = Il o ol,1 o,Gl 1 o o o o ·0-1


0··1I{ .....
x = I 2 3 4 5 6 7 8 9 IO Il 12 13 14
y = I 3 6 4 9 6 7 15 24 34 45 57 13 27

Rys. 30.12. Odcinkowe obliczenia prefiksowe dla ciągu odcinkowego bi ciągu wejściowego x. Ciąg y
jest ciągiem wynikowym. Gąg b wyznacza S odcinków

(c) Opisz algorytm typu EREW, który w czasie O(klgn) posortuje listę n liczb
k-bitowych.

30-2. Szybki, n-procesorowy algorytm obliczania maksimum


Naszym celem jest wyznaczenie maksimum z n liczb na maszynie CRCW
PRAM przy użyciu p = n procesorów.

(a) Pokaż, że problem wyznaczania maksimum z m ::;:;;p/2 liczb można na


p-procesorowej maszynie CRCW PRAM sprowadzić w czasie 0(1) do pro-
blemu wyznaczania maksimum z co najwyżej m 2 /p liczb.
(b) Ile liczb pozostanie po powtórzeniu k razy algorytmu z części (a), jeśli
rozpoczniemy odm= LP/2J liczb?
(c) Pokaż, że problem wyznaczenia maksimum z n liczb można rozwiązać na
maszynie CRCW PRAM w czasie O(lglgn) przy użyciup = n procesorów.

30-3. Spójne składowe


Prześledzjmy teraz algorytm typu CRCW obliczania spójnych składowych grafu
nieskierowanego G = (V, E) przy użyciu IVI+ IEIprocesorów. Strukturą danych
wykorzystywaną w tym algorytmie jest las zbiorów rozłącznych (patrz pod-
rozdz. 22.3). Dla każdego wierzchołka ve V mamy wskaźnik p[v] do ojca. Począ­
tkowo p [v] = v: wierzchołek wskazuje na samego siebie. Po zakończeniu działa­
nia algorytmu, dla każ.dych dwóch wierzchołków u, ve V, p[u] = p[v] wtedy
i tylko wtedy, gdy u.....,,v w G. W trakcie wykonywania algorytmu wskaźniki
p tworzą las ukorzenionych drzew wskaźnikowych. Gwiazdą nazywamy drzewo
wskafuikowe, w którymp [u] = p[v] dla wszystkich wierzchołków u i v w drzewie.
W algorytmie obliczania spójnych składowych zakładamy, że każda kra-
wędź (u, v)eE występuje dwukrotnie: raz jako (u, v) i raz jako (v, u). PodM
stawowymi operacjami używanymi w algorytmie są zahaczanie (HOOK) i skok

811
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE


(JUMP). Wykorzystywany jest też podprogram STAR, w którym zm1enneJ •

star[v] jest przypisywana wartość TRUE, jeśli v należy do gwiazdy.


HOOK(G)
I STAR(G)
2 for każda krawędź (u, v)eE[G] in parallel
3 do if star[u] i p[u] > p[v]
4 theo pl),(u]] - p[v]
5 SrAR(G)
6 for każda krawędź (u. v)eE{G] in parallel
7 doif star[u] ip[u] "'p[v]
8 theo pl),[u]]-p[v]
JUMP(G)
1 for każdy vE V[G] in parallel
2 do p[v] - pl),[v]]
W opisywanym przez nas algorytmie obliczania spójnych składowych po
wykonaniu na początku obliczeń jednej operacji HOOK wykonuje się wielo-
krotnie na przemian operacje HOOK i JUMP do chwili, w której w wyniku
wykonania operacji JUMP nie zostanie zmieniony żaden wskaźnik. (Zwróć
uwagę, że dwie operacje HOOK są wykonywane przed wykonaniem pierwszej
operacji JUMP).

(a) Podaj pseudokod dla operacji STAR(G).


(b) Pokaż, że wskaźniki p rzeczywiście tworzą ukorzenione drzewa, w których
korzenie wskazują na siebie. Udowodnij, że jeśli u i v są w tym samym
drzewie wskaźnikowym, to u,....,.
v w G.
(c) Udowodnij, że opisany algorytm jest poprawny: wykonywanie algorytmu
kończy się i po zakończeniu obliczeń p[u] = p[v] wtedy i tylko wtedy,
gdy u,....,.vwG.

Żeby przeanalizować czas działania zaprezentowanego algorytmu obliczania


spójnych składowych, rozważmy jedną spójną składową C, o której zakłada­
my, że ma co najmniej dwa wierzchołki. Załóżmy, że w pewnym punkcie ob-
liczeń wierzchołki ze składowej C nalci.ą do drzew wskaźnikowych ze zbioru
{T 1}. Zdefiniujmy potencjał składowej C jako

<D(C)- I;height(T,)
T,

gdzie beigbt(TJ jest wysokością drzewa T1• Celem naszej analizy jest pokaza-
nie, że każdorazowe wykonanie pary operacji HOOK i JUMP zmniejsza cli(C)
o stały czynnik.

812
PROBLEMY

(d) Udowodnij, że po wykonaniu pierwszej operacji HOOK wysokość każdego


drzewa wskażnikowego jest większa niż O i <ti(C) ~ 1V].
(e) Uzasadnij, że oprócz pierwszej operacji HOOK kolejne operacje HOOK ni-
gdy nie zwiększają Cl>(C).
(f) Pokaż, że po operacji HOOK, z wyjątkiem pierwszej, żadne drzewo wskaź­
nik.owe nie jest gwiazdą, chyba że takie drzewo zawiera wszystkie wierz-
chołki z C.
(g) Uzasadnij, że jeśli składowa C nie skurczyła się do pojedynczej gwiazdy, to
po wykonaniu operacji JUMP wartość potencjału Cl>{C)jest równa co naj-
wyżej 2/3 jego poprzedniej wartości. Zilustruj pesymistyczny przypadek.
(h) Wywnioskuj, że analizowany algorytm wyznaczy wszystkie spójne składo­
we grafu G w czasie O(lg V).

30-4. Transponowanie obrazu rastrowego


W grafice rastrowej na obrazu ramki można spojrzeć jak na macierz bitową
M wymiaru p x p. Na ekranie użytkownika jest widoczna górna lewa pod-
macierz M wymiaru n x n (Wynika to z rozwiązań sprzętowych stosowanych
do wyświetlania obrazów rastrowych). Do przemieszczania prostokątów bitów
z jednego miejsca na drugie wewnątrz macierzy M służy operacja BITBLT
(skrót od ang. BLock Transfer of Bits). W szczególności, w wyniku wywołania
BITBLT(r 1 , c 1 , r2 , c2 , nr, nc, •) otrzymujemy

M[r 2 + i, c2 + j]+-M[r 2 + i, c2 + J]•M[r 1 + i, c1 + j]


dla i=O, 1, ... , nr-1 ij = O, 1, ... , nc-1, gdzie* oznacza dowolną z 16
dwuargumentowych funkcji boolowskich.
Naszym celem jest wykonanie transpozycji obrazu (M[i, j] +- M[j, i])
w widocznej na ekranie części bufora obrazu. Zakładamy, że koszt kopiowania
bitów jest mniejszy niż koszt wywołania procedury BITBLT. Dlatego jesteśmy
zainteresowani dokonaniem transpozycji przy użyciu jak najmniejszej liczby
operacji BITBLT.
Pokaż, że transpozycję obrazu widocznego na ekranie można wykonać za
pomocą O(lgn) operacji BITBLT. Załóżmy, żep jest wystarczająco większe od
n tak, że niewidoczna część bufora obrazu zawiera wystarczającą ilość pa.mięci
roboczej. Jak wiele potrzeba dodatkowej pamięci? (Wskazówka: Zastosuj rów-
noległą metodę typu „dziel i zwyciężaj", wykonując pewne operacje BITBLT
z iloczynem logicznym AND).

813
ROZDZIAŁ 30. ALGORYTMY RÓWNOLEGŁE

Uwagido rozdziału

Prace Akta [9], Karpa i Ramachandran [118] oraz Leightona [135] zawierają
przegląd algorytmów równoległych dla problemów kombinatorycznych. Róż­
norodne architektury maszyn równoległych są opisane przez Hwanga i Briggsa
[109] oraz Hwanga i DeGroota [110].
Teoria obliczeń równoległych ma swój początek w latach czterdziestych
naszego stulecia, kiedy to J. Von Neumann [38] wprowadził ograniczony mo-
del obliczeń równoległych nazywany automatem komórkowym. Automat ko-
mórkowy jest w istocie dwuwymiarową tablicą procesorów o skończonej licz-
bie stanów, połączonych w prostokątną siatkę. Model PRAM zdefm.iowali
formalnie Fortune i Wyllie [73] w 1978 r., aczkolwiek wielu innych autorów
omawiało wcześniej zasadniczo podobne modele.
Metoda przeskakiwania została wprowadzona przez Wylliego [204]. Rów-
noległe obliczenia prefiksowe pojawiły się po raz pierwszy w pracy Ofmana
[152] w kontekście dodawania równoległego. Metoda cyklu Eulera pochodzi
od Tarjana i Vishkina [191].
Związek między czasem działania a liczbą procesorów w obliczeniach ma-
ksimwn ze zbioru n liczb zbadał Valiant [193), który także pokazał, że nie
istnieje sekwencyjnie efektywny algorytm dla tego problemu działający w cza-
sie 0(1). Cook, Dworki Reishuk [50] udowodnili, że wyznaczenie maksimum
na maszynie CREW PRAM wymaga czasu O(lgn). Metodę symulacji algo-
rytmów typu CRCW za pomocą algorytmów typu EREW :zaproponował Vi-
shkin [195].
Twierdzenie 30.2 podał Brent [34]. Anderson i Miller [11] opracowali pro-
babilistyczny, sekwencyjnie efektywny algorytm ustalania porządku na liście.
Dla tego samego problemu podali oni także algorytm detenninistycmy, który
jest tak.że sekwencyjnie-efektywny. Goldberg i Plotkin [84] zaproponowali de-
terministyczny algorytm łamania symetrii, omówiony w tym rozdziale. Jest on
oparty na podobnym algorytmie pochodzącym od Cole'a i Vishkina [47] i dzia-
łającym w takim samym czasie.
Rozdział 31

Operacjena macierzach

Operacje macierzowe należą do istoty obliczeń naukowych. Wydajne algoryt-


my działające na macierzach mają więc duże znaczenie praktyczne. Rozdział
ten zawiera krótki wstęp do teorii macierzy i operacji macierzowych, u szcze-
gólnym uwzględnieniem problemów mnożenia macierzy i rozwiązywania ulda-
dów równań liniowych.
W podrozdziale 31.1 wprowadzimy podstawowe pojęcia i oznaczenia.
Następnie, w podro7.dziale 31.2, przedstawimy algorytm Strassena mnożenia
) = O(n • ). W podrozdziale 31.3 zde-
1 2 81
dwóch macierzy n x n w cza.sic E>(n1g
finiujemy quasi-pierścienie, pierścienie i ciała, wyjaśniając założenia potrzebne,
by można było stosować algorytm Strassena. Podrozdział ten zawiera również
asymptotycznie szybki algorytm mnożenia macierzy boolowskich. W pod-
rozdziale 31.4 pokażemy, jak: rozwiązywać układy równań liniowych, wy-
korzystując rozkład LUP, a w podrozdziale 31.5 opiszemy związki między
zagadnieniem mnożenia macierzy a problemem ich odwracania. W podroz-
dziale 31.6 zajmiemy się ważną klasą symetrycznych macierzy dodatnio okre-
ślonych wskazując, jak można je wykorzystać przy wyszukiwaniu najlepszego
(w sensie najmniejszych kwadratów) rozwiązania nadokreślonego układu ró-
wnań liniowych.

31.1. Własności macierzy


W tym podrozdziale dokonamy przeglądu pewnych podstawowych własności
macierzy i zasadniczych pojęć dotyczących ich teorii, zwracając szczególną
uwagę na te z nich, które będą nam potrzebne w następnych podrozdziałach.

815
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

Macierzei wektory
Macierz jest prostokątną tablicą zawierającą liczby, Na przykład

a,,
a,, "'')
a,,
= (1
4
25 3)
6
(31.1)

jest macierzą A = (a11) wymiaru 2 x 3, gdzie dla i= 1, 2 i j = 1, 2, 3 element


macierzy w wierszu i i kolumnie j jest równy a11• Używamy wielkich liter do
oznaczenia macierzy i odpowiadających im indeksowanych małych liter do
oznacVłnia ich elementów. Zbiór wszystkich macierzy wymiaru m x n zawiera-
jących liczby rzeczywiste oznaczamy Rm"n. W ogólnym przypadku zbiór ma-
cierzy m x n o wartościach w zbiorze Szapisujemy jako S"'"n.
Macierz transponowaną macierzy A oznaczamy AT i otrzymujemy ją, za-
mieniając wiersze z kolumnami w macierzy A. Na przykład dla macierzy A jak
w równaniu (31.1) macierz transponowana AT wygląda tak:

1 4
AT= 2 5
3 6
Wektor jest jednowymiarową tablicą liczb. Na przykład

2
X= 3 (31.2)
5 •

jest wektorem o rozmiarze 3. Do oznaczenia wektorów używamy małych liter,


i-ty element wektora o rozmiarze n oznaczamy przez x 1 dla i= I, 2, ... , n.
Ustalamy też standardową postać wektora jak.o wektor kohnnnowy równoważ­
ny z macierzą n x 1; odpowiadający mu wektor wierszowy otrzymujemy, wy-
konując operację transpozycji:

XT=(2J5)

Wektor jednostkowy e1 to taki wektor, którego i-ty element jest równy 1,


a wszystkie pozostałe ~ O. Zazwyczaj wymiar wektora jednostkowego jedno-
znacznie wynika z kontekstu.
Macien zerowa to macierz, której każdy element jest równy O. Do jej
oznacŻenia używamy symbolu O. Nie prowadzi to do niejednoznaczności, gdyż

816
31.1. WŁASNO$CI MACIERZV

zwykle z kontekstu jasno wynika, czy chodzi o macierz zerową, cz;yo liczbę O.
Jeśli mamy na myśli macierz, to znany jest też z reguły jej wymiar.
Szczególnie często rozważa się macierze kwadratowen x n. Na specjalną
uwagę zasługują następujące ich rodzaje:

1. Macierz diagonalna spełnia warunek: a11= O, jeśli tylko i 'F ). Ponieważ


wszystkie elementy leżące poza przekątną są równe zero, macierz tego typu
jest więc jednoznacznie wyznaczona przez elementy leżące na przekątnej:

•11 o '" o
diag(a 11 , a22 , ... , ann) =
o a,, ' " o
' ' '
'
' '

o o
2. Macierz jednostkowa n x n oznaczana przez In jest macierzą diagonalną
z jedynkami na przekątnej

I. - diag(l, I, ... , I)

I o '" o
o I , __
o
' ' ' '
'
' •

o o 1

Kiedy I pojawia się bez indeksu, wymiar macierzy musi wynikać z konteks-
tu; i-ta kolumna macierzy jednostkowej jest wektorem jednostkowym e1•
3. Macierz trójdiagonalnaT to taka, dla której t 0 = O, jeśli tylko li - Jl > l.
Niezerowe elementy występują tylko na głównej przekątnej, bezpośrednio
nad nią (t 1•1+ 1 dla i= 1, 2, ... , n -1) lub bezpośrednio pod nią (11+ 1 ,1 dla
i= 1, 2, ... , n - 1):

111 112 o o '" o o o


1,1 ,,, ,,, o ' " o o o
o ,,, ,,, 134 ." o o o
• •
T- •
'
' ' ' '
' '
'

o o o o " . ln-2,n-2 1n-l,n-1 o


o o o o ." ln-1,n-l 1n-1,n-1 1n-1,n

o o o o ." o 1n,n -1 IM

817
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

4. Macierz trójkątna górna U to taka, dla której u1i = O, jeśli i> j. Wszystkie
elementy poniżej przekątnej są więc równe O:

"11 "1, ...


U=
o u,, ...
• • •

• •

o o ...
Macierz trójkątną górną nazywamy jednostkową macierzą trójkątną górną,
jeśli ma same jedynki na przekątnej.
5. Macierz trójkątna dolna L to taka, dla której ulJ = O, jeśli i< j. Wszystkie
elementy powyżej przekątnej są więc równe O:

111 o ... o
l,1 1,, ... o
L= •

l,1 I,, ... I,,

Macierz trójkątną dolną nazywamy jednostkową macierzą trójkątną dolną,


jeśli ma same jedynki na przekątnej.
6. Macierz permutacyjna P ma dokładnie jedną jedynkę w każdym wierszu
i w każdej kolumnie oraz same zera na wszystkich pozostałych pozycjach.
Przykładem macierzy permutacyjnej jest

O I O O O
O O O I O
P= I O O O O
O O O O I
O O I O O

Nazwa bierze się stąd, że pomnożenie wektora x przez taką macierz daje
w wyniku permutację elementów x.
7. Macierz symetryczna A spełnia warunek A= Ar. Na przykład

1 2 3
2 6 4
3 4 5
jest macierzą symetryczną.

818
31.1. WŁASNOŚCI MACIERlY

Operacje na macierzach

Elementami macierzy i wektorów są liczby z ustalonej struktury algebraic:mej,


takiej jak liczby rzeczywiste, zespolone lub całkowite modulo pewna liczba
pierwsza. W strukturze takiej muszą być określone operacje dodawania i mno-
żenia. Uogólnimy teraz te pojęcia na macierze.
Dodawanie macierzy definiujemy następująco: jeśli A = (a;1) i B = (b11) są
macierzami m x n, to ich suma C = (cu) =A+ B jest macierzą m x n zdefi-
niowaną w taki oto sposób:

dla i= 1, 2, ... , m i j = I, 2, ... ,n.Dodawanie macierzy jest więc zdefiniowane


po współrzędnych. Macierz zerowa jest elementem neutralnym operacji doda-
. .
warna macierzy:

A +O-A

-O+A

Jeśli ,l jest liczbą, a A = (aii) - macierzą, to AA = (,laii) jest skalarną wielo-


krotnościąmacierzy A uzyskaną przez pomno7..enie każdego jej elementu przez
).. Jako szczególny przypadek definiujemy macierz przeciwną do macierzy
A= (aij) jako - 1 ·A= -A, czyli element macierzy -A o współrzędnych i,j
jest równy - a;j· Zachodzi więc:

A+(-A)-0
-(-A)+A

Po wprowadzeniu tej definicji możemy zdefiniować odejmowanie macierzy jako


dodanie macierzy przeciwnej: A - B = A + (-B).
Mnożenie macierzy definiujemy w następujący sposób. Bierzemy dwie ma-
cierze A i B pasujące do siebie w znaczeniu tak.im, że liczba kolumn macierzy
A jest równa liczbie wierszy macierzy B. (W ogólności, jeśli w wyrażeniu wystę­
puje iloczyn macierzy AB, to zawsze domyślnie zakładamy, że macierze A i Bpa-
sują do siebie). Jeśli A= (au) jest macierzą m x n, a B = (bft) jest macierzą
n x p, to ich iloczyn C = AB jest macierzą C = (clk) wymiaru m x p, gdzie

cit= L' a,ibik


j= 1
(31.3)

dla i= 1, 2, ... , m i k = 1, 2, ... , p. Procedura MATRIX-MULTIPLY z pod-


rozdz. 26.l wykonuje mnożenie macierzy w sposób bezpośrednio oparty na

819
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

równości (31.3), ograniczając się przy tym wyłącznie do macierzy kwadrato-


wych: m = n = p. Aby pomnożyć dwie macierze n x n, program MATRIX-
-MULTIPLYwykonuje n 3 operacji mnożenia i n 2(n - I) operacji dodawania
w czasie E>(n3 ).
Macierze mają wiele (choć nie wszystkie) algebraicznych własności typo-
wych dla liczb. Macierze jednostkowe są elementami neutralnymi operacji
mnożenia macierzy

dla dowolnej macierzy A wymiaru m x n. Pomnożenie przez macierz zerową


daje macierz zerową

Mnożenie macierzy jest łączne:

A(BC) = (AB)C (31.4)

dla pasujących do siebie macierzy A, B i C. Jest też ro'M2.ielne względem


dodawania:

A(B + C) = AB+ AC
(B+ C)D=BD+ CD
Mnożenie macierzy n X n nie jest jednak przemienne, chyba że n= 1. Na przy-

kład, jeśli A = (~ ~) i B = (~ ~), to

AB=(~~)
zaś

BA=(~~)

Iloczyn macierzy przez wektor i wektora przez wektor są zdefiniowane


przez utożsamienie wektora z macierzą n x 1 Oub macierzą I x n w przypadku
wektora wierszowego). Jeśli więc A jest macierzą m x n, a x jest wektorem
o rozmiarze n, to Ax jest wektorem o rozmiarze m. Jeśli x i y są wektorami
o rozmiarze n, to

'
xTy= LxJ1;
l "' 1

820
31.1. WŁASNOSCI MACIER2Y

jest liczbą (formalnie: macierzą 1 x 1) nazywaną iloczynem skalarnym x i y.


Macierz xyT jest macierzą Z wymiaru n x n (nazywaną iloczynem zewnętrznym
x i y) taką, że zu = XJ!J· Norma (euklidesowa) l!xllwektora x o rozmiarze n jest
zdefiniowana następująco:

llxll= (xi + xf + ... + x;)112

Jest to więc długość wektora x w n-wymiarowej przestrzeni euklidesowej.

Macierze odwrotne, rzędy i wyznaczniki


Macierz odwrotną do macierzy A wymiaru n x n oznaczamy przez A- 1 (jeśli
istnieje) i definiujemy jak.o macierz n x n taką, że AA- 1 =In= A- 1 A. Na
przykład

(
1
1O
-(o
1)-1 1
1) -1

Dla wielu niezerowych macierzy kwadratowych nie ma macierzy odwrotnych.


Macierz, do której nie istnieje macierz odwrotna, nazywamy macierzą nieod-
wracalną lub osobliwą. Przykładem niezerowej macierzy osobliwej jest

Jeśli dla danej macierzy istnieje macierz odwrotna, to macierz tę nazywamy


odwracalną lub nieosobliwą. Macierze odwrotne, jeśli istnieją, są określone jed-
noznacznie (patrz zad. 31.1-4). Jeśli A i B są macierzami nieosobliwymi kwad-
ratowymi, to

(31.6)

Operacja odwracania macierzy jest przemienna z operacją transpozycji:

Wektory x 1 , x 2 , ••• , xn są liniowo zależne, jeśli istnieją współczynniki c 1 , c2 ,


... , en, nie wszystkie równe zero, tak.ie że c 1 x 1 + c 2x 2 + ...+ C,rXn=O.Na przy-
kład wektory x 1 = (l 2 3)r, x 2 = (2 6 4)r oraz x 3 = (4 11 9)T są liniowo zależ­
ne, ponieważ 2x 1 + 3x 2 - 2x 3 = O. Jeśli wektory nie są liniowo zależne, to

821
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

mówimy, że są liniowo niezależne, Na przykład kolumny macierzy jednostko-


wej są liniowo niezależne.
Rząd kolumnowy niezerowej macierzy A wymiaru m x n definiujemy jako
moc największego zbioru liniowo niezależnych kolumn macierzy A. Podobnie,
rząd wierszowy macierzy A określamy jak.o moc największego zbioru liniowo
niezależnych wierszy macierzy A. Podstawową własnością każdej macierzy
A jest to, że rząd wierszowy jest zawsze równy rzędowi kolumnowemu, tak
więc możemy po prostu mówić o rzędzie macierzy A; oznaczamy go przez
rank(A). Rząd macierzy m x n jest liczbą całkowitą z przedziału od O do
min(m, n) włącznie. (Rząd macierzy zerowej wynosi O, a rząd macierzy jedno-
stkowej n X n jest równy n). Według innej, równoważnej definicji rząd macie-
rzy A wymiaru m x n jest najmniejszą liczbą r taką, że istnieją macierze
Bi C wymiaru odpowiednio: m x r i r x n takie, że

Macierz kwadratowa n x n ma pełny rząd, jeśli


jej rząd jest równy n. Pod-
stawową własność rzędów macierzy charakteryzuje poniższe twierdzenie.

TwIERDZENIE31.1.
Macierz kwadratowa ma pełny rząd wtedy i tylko wtedy, gdy nie jest osobliwa .

Macierz m x n ma pełny r..iąd kolumnowy, jeśli jej rząd wynosi n.



Wektor zerujący macierzy A to taki wektor niezerowy x, że Ax = O. Poniż­
sze twierdzenie, którego dowód pozostawiamy jako zadanie 31.1-8, oraz wnio-
sek płynący z niego odnoszą pojęcia rzędu kolumnowego oraz odwracalności
do wektorów zerujących.

TWIERDZENIE31.2.
Macierz A ma pełny rząd kolumnowy wtedy i tylko wtedy, gdy nie ma wek-
torów zerujących.


WNIOSEK 31.3.
Macierz kwadratowa A jest osobliwa wtedy i tylko wtedy, gdy ma wektor

zeruJący.


Minort:.10(jmacierzy A wymiaru n x n, dla n> 1, nazywamy macierz Ar;11
wymiaru (n - 1) x (n- I) otrzymaną przez usunięcie i-tego wiersza ij-tej ko-
lumny z macierzy A. Wyznacznik macierzy A wymiaru n x n definujemy reku-
. . . ,
rencyJnte za pomocą m1norow

822
31.1. WŁASNO$CI MACIERZV

jeśli n =1
det(A) = a 11 det(A 1111) - a 12 det(Ar 121 ) (31.7)
+ ...+ ( - I)"+ 1 a 111det(A! 1 „1), jeśli n> 1

Składnik ( - I ) 1+i det(A! 1il) jest nazywany podwyznacznikiemwzględnym ele-


mentu au.
Następujące
twierdzenia, których dowody tu pomijamy, charakteryzują
podstawowe własności wyznacznika.

TwIERDZENlE 31.4. (Własności wyznacznika)


Wyznacznik macierzy kwadratowej A ma następujące własności.

• Jeśli którykolwiek wiersz lub którakolwiek kolumna macierzy A jest zero-


wa, to det(A) - O.
• Wyznacznik macierzy A mnoży się przez A.,jeśli elementy jednego wiersza
(lub jednej kolumny) macierzy A zostały pomnożone przez .:l.
• Wyznacznik macierzy A pozostaje nie zmieniony, gdy elementy w jednym
wierszu (kolumnie) zostają dodane do innego wiersza (kolumny).
• Wyznacznik macierzy A jest równy wyznacznikowi macierzy AT.
• Wyznacznik macierzy A zmienia wartość na przeciwną, jeżeli którekolwiek
dwa wiersze (kolumny) zostały zamienione miejscami.
Ponadto dla dowolnych macierzy kwadratowych A i B zachodzi det(AB) =
- det(A)det(B).


TWIERDZENIE 31.5.
Macierz A wymiaru n x n jest osobliwa wtedy i tylko wtedy, gdy det(A) = O.


Macierze dodatnio określone

Macierze dodatnio określone odgrywają istotną rolę w wielu zastosowaniach.


Macierz A wymiaru n x n nazywamy dodatnio określoną, jeśli xT Ax > O dla
każdego wektora x rozmiaru n, takiego że x =pO. Na przykład jednostkowa
macierz jest dodatnio określona, ponieważ dla dowolnego niezerowego wek-
tora x = (x 1 x 2...x,,)T zachodzi

823
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

"
L xl
I= 1

>0

Jak zobaczymy, macierze pojawiające się w zastosowaniach są często do-


datnio określone, co zawdzięczamy poniższemu twierdzeniu:

Tw!ERDZENIE31.6.
Dla dowolnej macierzy A z pełnym rzędem kolumnowym macierz Ar A jest
dodatnio określona.

DOWÓD
Musimy pokazać, że xT(ATA)x > O dla każdego niezerowego wektora x. Weź­
my więc dowolny wektor x

x'(A' A)x - (Ax)'(Ax) (patrz zad. 31.1-3)

- l!Axll'

;. o (31.8)

ZauwaZDly teraz, że !1Ax112


to po prostu suma kwadratów elementów wektora
Ax. Czyli jeśli 11AxH
2
= O, to każdy element Ax jest równy O, tj. Ax = O. Ponie-
waż A ma pełny rząd kolumnowy, Ax = O implikuje x = O, zgodnie z twier-
dzeniem 31.2. Tak więc Ar A jest dodatnio określona.


Inne własności macierzy dodatnio określonych opiszemy w podrozdz. 31.6.
ZADANIA
31.1-1. Udowodnij, że iloczyn dwóch macierzy trójkątnych dolnych jest ma-
cierzą trójkątną dolną. Udowodnij, że wyznacznik macierzy trójkątnej
(dolnej lub górnej) jest równy iloczynowi elementów leżących na jej prze-
kątnej. Udowodnij, że macierz odwrotna do macierzy trójkątnej dolnej,
jeśli istnieje, też jest trójkątna dolna.
31.1-2. Udowodnij, że jeśli P jest macierzą permutacyjną n x n, zaś A jest
macierzą n x n, to PA można otrzymać z macierzy A przez permutację jej
wierszy, a AP - przez permutację kolumn. Udowodnij, że iloczyn dwóch
macierzy permutacyjnych jest macierzą permutacyjną. Udowodnij, że jeśli
P jest macierzą _permutacyjną, to jest ona odwracalna, macierzą odwrotną
do niej jest pT, a pT także jest macierzą permutacyjną.

824
31.1. WŁASN05CI MACIERZV

31.1-3. Udowodnij, że (AB)T = BTAT oraz że ATA jest zawsze macierzą sy.
metryczną.

31.1-4. Udowodnij, że jeśli Bi C są macieuami odwrotnymi do A, to B = C,


31.1-5. Niech A i B będą macierzami kwadratowymi takimi, że AB= I. Udo·
wodnij, że jeśli macierz A' powstała z A przez dodanie wierszaj do wiersza
i, to macierz B' odwrotną do A' można otrzymać przez odjęcie kolumny
i od kolumny jw macierzy B.
31.1-6. Niech A będzie nieosobliwą macierzą kwadratową, której elementy
należą do ciała liczb zespolonych. Pokaż, że każdy element macierzy A- 1
jest rzeczywisty wtedy i tylko wtedy, gdy każdy element macierzy A jest
rzeczywisty.
31.1-7. Pokaż, że jeśli A jest nieosobliwą macierzą symetryczną, to macierz
A- jest symetryczna. Pokaż, że jeśli B jest dowolną (pasującą) macierzą,
1

to BABT jest macierzą symetryczną.


31.1-8. Pokaż, że macierz A ma pełny rząd kolumnowy wtedy i tylko wtedy
gdy Ax = O implikuje x = O. (Wskazówka: Wyrai, liniową zależność jednej
kolumny od innych jako równanie macierzowo•wektorowe).
31.1-9. Udowodnij, że dla dowolnych dwóch pasujących do siebie macierzy
A i B zachodzi

rank(AB),; min(rank(A), rank(B))

przy czym równość zachodzi wtedy, gdy przynajmniej jedna z macierzy


A lub B jest nieosobliwą macierzą kwadratową. (Wskazówka: Użyj drugiej
defmicji rzędu macierzy).
31.1-10. Niech będą dane x 0 , x 1 , ... , x 11_ 1. Udowodnij, że wyznacznik macierzy
Vandermonde'a

I x, x5 ••• xi-1
V(x 0 , X 1 , .•• , X 11_ 1 ) =
I x, xl •• • xi.-1
• •
• •
.,:-,
I x11-1
'
X11- l •••
,- '

wynosi

det(V(x,, x,, ..., x,_,))- n


O<,.J<k ...11- l
(x, - X;)

(Wskazówka: Pomnóż kolumnę i przez -x 0 , wynik dodaj do kolumny


i + 1 dla i = n - 1, n - 2, ... , 1, a następnie użyj indukcji).

825
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

31.2. AlgorytmStrassenamnożenia macierzy


W podrozdziale tym przedstawiamy godny uwagi rekurencyjny algorytm
Strassena, służący do mnożenia macierzy n x n, który działa w czasie
0(n1K7) = O(n 2,8). Dla dostatecznie dużych n jest więc on szybszy niż narzucają­
cy się algorytm MATRIX-MULTIPLY mnożenia macierzy w czasie 0(nl) z pod-
rozdz. 26.1.

Zarys algorytmu
Algorytm Strassena może być rozpatrywany jako zastosowanie znanej metody:
,,dziel i zwyciężaj". Załóżmy, że chcemy obliczyć iloczyn C = AB, gdzie A,
B i C są macierzami n x n. Jeśli założymy ponadto, że n jest dokładną potę­
gą 2, to możemy podzielić każdą z macierzy A, B i C na cztery macierze
n/2 x n/2 i przepisać równość C = AB w następujący sposób:

(31.9)

(W zadaniu 31.2-2 zajmujemy się przypadkiem, gdy n nie jest dokładną potęgą
2). Dla wygody podmacierze macierzy A są etykietowane alfabetycznie od le-
wej do prawej, podczas gdy podmacierze B są etykietowane z góry do dołu,
czyli zgodnie ze sposobem mnożenia macierzy. Równanie (31.9) odpowiada
czterem równaniom

r=ae+bf (31.10)

s=ag+bh (31.11)

t=ce+df (31.12)

U=cg+dh (31.13)

Każda z nich przedstawia dwie operacje mnożenia macierzy n/2 x n/2 i opera-
cję dodawania otrzymanych iloczynów. Posługując się tymi równaniami przy
tworzeniu naturalnego algorytmu typu „dziel i zwyciężaj", otrzymujemy na-
stępujące równanie rekurencyjne określające czas T(n) potrzebny do pomnoże­
nia dwóch macierzy n x n:

T(n) - ST(n/2) + ®(n 2) (31.14)

Niestety, równanie (31.14) ma rozwiązanie T(n) = 9(nl); metoda ta nie jest


więc szybsza od standardowej.

826
31.2. ALGORYTM STRASSENA MNOŻENIA MACIER2Y

V. Strassen odkrył inne rekurencyjne podejście do tego problemu, które


wymaga jedynie 7 rekurencyjnych operacji mnożenia macierzy n/2 x n/2 oraz
0(n 2 ) operacji dodawania lub odejmowania wartości skalarnej, co prowadzi
do równania rekurencyjnego

T(n) - 7T(n/2) + ®(n')

(31.15)

Metoda Strassena składa się z czterech kroków:


I. Podziel dane macierze A i B na podmacierze n/2 x n/2, tak jak w równaniu
(31.9).
2. Używając 0(n 2 ) operacji dodawania i odejmowania skalarów, oblicz 14
macierzy n/2 x n/2: A 1 , B 1 , A 2 , B 2 , .•. , A 1 , B1 •
3. Rekurencyjnie oblicz 7 iloczynów P 1 = A;B; dla i= 1, 2, ... , 7.
4. Oblicz podmacierze r, s, t, u macierzy wynikowej C, dodając i/lub odej-
mując ro2lllaite kombinacje macierzy P;, używając jedynie 0(n 2 ) operacji
dodawania lub odejmowania skalarów.
Taka procedura spełnia równanie rekurencyjne (31.15). Pozostaje teraz tylko
uzupełnić brak.ujące szczegóły.

Określanie iloczynów podmacierzy

Nie jest rzeczą do końca jasną, jak Strassen odkrył iloczyny podmacierzy, na
których opiera się jego algorytm. Odtworzymy teraz jedną z możliwych dróg
prowadzących do tego odkrycia.
Przyjmijmy, że każdy iloczyn P1 może być zapisany w postaci

P; = AiBI

= (1Xi1a+ IXizb+ IX13C


+ IX;4d)·(/J,1e+ {JiJ"+/J;]K + /J14h) (31.16)

gdzie współczynniki cxii,/J;j należą do zbioru {-1, O, l}. Zakładamy więc, że


każdy iloczyn może być obliczony przez dodanie lub odjęcie pewnych pod-
macierzy macierzy A, dodanie lub odjęcie pewnych podmacierzy macierzy B,
a następnie pomnożenie uzyskanych wyników. Bardziej ogólne strategie są
możliwe, ale ta okazuje się wystarczająca.
Jeśli przedstawimy wszystkie nasze iloczyny w ten sposób, to możemy
używać tej metody rekurencyjnie, bez zakładania przemienności mnożenia, po-
nieważ w każdym iloczynie wszystkie podmacierze macierzy A występują po

827
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

lewej stronie, a podmacierze macierzy B - po prawej. Ta własność jest ważna


dla rekurencyjnych zastosowań tej metody, ponieważ operacja mnożenia ma~
cierzy nie jest przemienna.
Dla wygody będziemy używać macierzy 4 x 4 w celu reprezentowania
kombinacji liniowych iloczynów podmacierzy o tej własności, że każdy iloczyn
łączy jedną pod.macierz macierzy A z jedną podmacierzą macierzy B, tak jak
w równaniu (31.16). Na przykład równanie (31.10) możemy zapisać jako

r=ae+bf

+l o o o e
o +l o o f
=(ab Cd)
o o o o g
o o o o h

e f g h
a + •

b • + • •

d • •

W ostatnim wyrażeniu użyliśmy skróconego zapisu, w którym ,, +" oznacza


+I,,.·" oznacza O, a,,-" oznacza -1. (Od tej chwili będziemy też pomijać
etykiety wierszy i kolumn). Posługując się tą notacją, uzyskujemy następujące
równania dla pozostałych podmacierzy macierzy C:

s=ag+bh
• +
• • +
• •

• •

t=ce+df

• •

+
• +
828
31,2. ALGORYTM STRASSENA MNOŻENIA MACIERZV

U=cg+dh

• •

=
+ •

+
Nasze poszukiwania szybszego algorytmu mnożenia macierzy rozpoczy-
namy od obserwacji, że podmacierz s może być przedstawiona jako
s = P 1 + P 2 , gdzie każda z macierzy P 1 i P 2 jest obliczona przy użyciu jednej
.. . .
operacJ1 mnozerua:

P1 = A1B1
=a·(g-h)
=ag-ah

+ -

• •

Pz = AzBz
=(a+b)·h
=ah+bh

• +
+

Macierz t może być obliczona w podobny sposób, jako t = P 3 + P 4 , gdzie

=(c+d)·e

829
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

=ce+ de

"

"

+
+
oraz

-d·(f-e)

-df-de

+
Wyrazem istotnym będziemy nazywać każdy z ośmiu wyra.z.ów występują­
cych po prawej stronie równań (31.10)-(31.13). Użyliśmy już 4 iloczynów do
obliczenia podmacierzy s i t, których wyrazami istotnymi są ag, bh, ce i df
Zauważmy, że z P 1 oblicza się wyra.z.istotny ag, z P 2 -wyraz istotny bh, z P 3
- wyraz istotny ce, a z P 4 -wyra.z. istotny 4f.Musimy więc teraz tylko obliczyć
podmacierze r i u, których wyrazami istotnymi są ae, bf, cg i dh, nie używając
przy tym więcej niż 3 razy operacji mnożenia macierzy. Macierz P 5 jest okreś­
lona w specjalny sposób, tak by obliczyć dwa wyrazy istotne naraz:

- (a + d) · (e + h)

=ae+ah+de+dh

+ +

+ +
830
31.2. ALGORYTM STRASSENA MNOŻENIA MAC!ERZV

Oprócz wyrazów istotnych ae i dh macierz P 5 zawiera też wyrazy nieistotne,


takie jak ah i de, które należy usunąć. Do tego celu możemy użyć macierzy P 4
i P 2 ale wówczas pojawiają się dwa inne nieistotne wyrazy:

P5 + P4 - P 2 = ae +dh+ df - bh

• + +
Dodając ws1.akże jeszcze jeden iloczyn

- (b - d) · if + h)
-bf+bh-df-dh

+ +
• •

otrzymujemy

= ae + bf

+
• +

Wartość u może być obliczona z macierzy P 5 w podobny sposób przez


użycie macierzy P 1 i P 3 do zamiany nieistotnych wyrazów w macierzy P 5

na inne:

831
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

+ • +
- •

- •

+
Odejmując dodatkowy iloczyn

- (a - c) · (e + g)

=ae+ag-ce-cg

+ +

- • -
• •

dostajemy

=cg+dh

• •

+
• • +

Do obliczenia C = AB wystarcza więc 7 iloczynów P 1 , P2 , ... , P 7 , co koń­


czy opis metody Strassena.

Uwagi
Duża stała ukryta w złożoności czasowej algorytmu Strassena czyni go nie-
praktycznym poza przypadkami, w których macierze są duże (n przynajmniej

832
31.2. ALGORYTM STRASSENA MNOŻENIA MACIERZY

45) i gęste (mało elementów zerowych). Dla małych macierzy zwykły algorytm
jest bardziej polecany, a dla dużych, ale rzadkich macierzy, istnieją specjalne
algorytmy w praktyce bardziej efektywne niż algorytm Strassena. Metoda
Strassena jest więc interesująca głównie z teoretycznego punk.tu widzenia.
Używając zaawansowanych metod, nie wchodzących w zakres tej książki,
można w rzeczywistości mnożyć macierze n x n w czasie lepszym niż 0(nlł:7).
Obecnie znane najlepsze ograniczenie górne wynosi w przybliżeniu w O(n2·376).
Najlepszym ograniczeniem dolnym jest oczywiste !l(n 2) (oczywiste dlatego, że
musimy wypełnić n 2 pozycji w macierzy wynikowej). Tak więc obecnie nie
wiemy, jak trudnym zadaniem jest w rzeczywistości mnożenie macierzy.
Konstruując algorytm. Strassena, nie zakładaliśmy, że elementy macierzy
są liczbami rzeczywistymi. Jedynym istotnym założeniem jest to, że są one
elementami pewnego pierścienia. Jednak czasami, jeśli to założenie nie jest
spełnione, możemy radzić sobie innymi metodami, które umożliwiają stosowa-
nie tego algorytmu. Mówimy o tym szerzej w następnym podrozdziale.
ZADANIA
31.2-1. Użyj algorytmu Strassena do obliczenia iloczynu

31.2-2. Jak zmodyfikowałbyś algorytm. Strassena, aby mnożył macierze n x n,


w których n nie jest dokładną potęgą 2? Pokaż, że otrzymany algorytm
działa w czasie 0(n 1B7).
31.2-3. Jak.ie jest największe k, dla którego, jeśli można pomnożyć macierze
3 x 3, używając k operacji mnożenia (nie zakładając przemienności mno-
żenia), to można pomnożyć macierze n x n w czasie O(ltg 7)? Jaki będzie
czas działania tego algorytmu?
31.2-4. V. Pan odkrył sposób mnożenia macierzy 68 x 68 przy użyciu 132 464
operacji mnożenia, macierzy 70 x 70 przy użyciu 143 640 operacji mnoże­
nia i macierzy 72 ><72 przy użyciu 155 424 operacji mnożenia, Za pomocą
której z tych metod osiągniemy najlepszy asymptotycznie czas, jeśli za-
stosujemy ją w algorytmie mnożenia macierzy wykorzystującym metodę
,,dziel i zwyciężaj"? Porównaj czas działania tego algorytmu z czasem dzia-
łania algorytmu Strassena.
31.2-5. Jak szybko można obliczyć iloczyn macierzy kn ><n i macierzy n x kn,
używając algorytmu Strassena jako podprogramu? Odpowiedz na to samo
pytanie, zamieniając kolejność danych macierzy.
31.2-6. Pok.aż, jak pomnożyć liczby zespolone a + bi i c + di, używając jedynie
3 operacji mnożenia liczb rzeczywistych. Algorytm powinien dla danych a,
b, c i d obliczać ac - bd (część rzeczywistą) oraz ad+ be (część urojoną).

833
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

*31.3. Różne strukturyalgebraicznei mnożenie


macierzyboolowskich

Własności operacji mnożenia i dodawania macierzy zależą od własności struk-


tur algebraicznych, do których należą elementy tych macierzy. W tym podroz-
dziale rozpatrujemy 3 rodzaje tego typu struktur: quasi-pierścienie, pierścienie
i ciała. Możemy zdefiniować mnożenie macierzy określonych nad quasi-pierś­
cieniami. Okazuje się jednak, że do poprawności algorytmu Strassena wymaga-
na jest struktura pierścienia. Przedstawimy również prostą sztuczkę sprowa-
dzenia problemu mnożenia macierzy boolowskich ( określonych nad quasi-
-pierścieniem, który nie jest pierścieniem) do mnożenia macierzy określonych
nad pierścieniem. Na koniec wyjaśnimy, dlaC"Legonie da się w naturalny spo-
sób wykorzystać własności ciała do konstrukcji lepszych algorytmów mnoże-
' '
ma macierzy.

Quasi-pierścienie

Niech (S, EB, 0, O, T) oznacza strukturę algebraiczną, w której Sjest zbiorem


elementów, EB i 0 są dwuargumentowymi operacjami na zbiorze S (odpo-
wiednio: operacjami dodawania i mnożenia), a O oraz l są różnymi wy-
różnionymi elementami S. Taką strukturę nazywamy quasi-pierścieniem, jeśli
ma następujące własności:
1. {S, EB, Ó)jest monoidem:
• Sjest zamknięty ze względu na EB,czyli a EBb ES dla dowolnych a, be S.
• EB jest operacją łączną, czyli a EB(b EBc) = (a EBb) EBc dla dowolnych
a,b,ceS.
• O jest elementem neutralnym operacji EB; czyli, a EBd = Offi a = a dla
dowolnych aeS.
Podobnie (S, O, T) jest monoidem.
2. Ojest anihilatorem, czyli a O O = O0 a = O dla dowolnych a e S.
3. Operacja EBjest przemienna, czyli a EBb = b EBa dla dowolnych a, b eS.
4. Operacja 0 jest rozdzielnawzględem E!l,czyli a O (b Ellc) - (a 0 b) Ell(a 0 c)
i (b Ellc) 0 a - (b 0 a) Ell(c 0 a) dla dowolnych a, b, ceS.

Przykładami quasi-pierścieni mogą być quasi-pierścień boolowski ({O, 1},


v , /\, O, 1), gd7ie v oznacza alternatywę, a /\ ~ koniunkcję, czy struktura
liczb naturalnych (N, +, ·, O, I), gdzie+ i · oznaczają zwykle operacje doda-
wania i mnożenia. Dowolny półpierścień domknięty (patrz podrozdz. 26.4) jest
też quasi-pierścieniem; półpierścienie domknięte mają dodatkowo własności

834
* 31.3. RÓŻNE STRUKTURY ALGEBRAICZNE I MNOŻENIE MACIERZY BOOLOWSKICH

idempotentności i sumy nieskończonej. Możemy rozszerzyć operacje EBi 0 na


macierze, tak jak to uczyniliśmy z+ i· w podrozdz. 31.1. Oznaczając macierz
jednostkową n x n składającą się z Oi 1 przez I n, łatwo zauważyć, że mnożenie
macierzy jest dobrze zdefiniowane i zbiór macierzy sam tworzy quasi-pierścień,
zgodnie z następującym twierdzeniem.

TwIERDZENIE 31.7. (Macierze utworzone nad quasi-pierścieniem tworzą quasi-


-pierścień)
Jeśli (S, EB,0, O, l) jest quasi-pierścieniem i n~ 1, to (S""n, EB,0, O,I,J też
jest quasi-pierścieniem.

DOWÓD
Przeprowadzenie dowodu pozostawiamy czytelnikowi jako zad. 31.3-1.


Pierścienie

W quasi-pierścieniach nie można wykonywać odejmowania. Inaczej jest


w przypadku pierścieni, czyli quasi-pierścieni (S, EB,0, O, I), które spełniają
dodatkową własność:

5. Każdy element należący do S ma element odwrotny względem dodawania,


czyli dla dowolnych a ES istnieje element be S taki, że a EBb = b EBa = ·o.
Takie b jest też często nazywane elementem przeciwnym do a i jest oznacza-
ne przez (-a).

Jeśli wiemy, że
istnieje element przeciwny do każdego elementu, to możemy
zdefiniować odejmowanie jako a - b =a+ (-b).
Istnieje wiele przykładów pierścieni. Liczby całkowite (Z, +, ·, O, I) ze
zwykłymi operacjami dodawania i mnożenia tworzą pierścień. Liczby całkowi­
te modulo n dla dowolnego całkowitego n> 1 - czyli (Zft, +, ·, O, 1),
gdzie + jest dodawaniem module n, a · jest mnożeniem modulo n - tworzą
pierścień. Innym przykładem jest zbiór R[x] wielomianów skończonego stop-
nia zmiennej x z rzeczywistymi współczynnikami, wraz ze zwykłymi operac-
jami (czyli (R[x], +,·,O, 1), gdzie+ jest operacją dodawania wielomianów,
a · operacją ich mnożenia).
Z następującego wniosku wynika, że twierdzenie 31.7 można uogólnić
w sposób naturalny na pierścienie.

WNIOSEK31.8. (Macierze utworzone nad pierścieniem tworzą pierścień)


Jeśli (S, EB, 0, O, I) jest pierścieniem i n~ 1, to (S"~n, EB, O, O, I ,J też jest
. ' . .
p1ersc1eruem.

835
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

DOWÓD
Przeprowadzenie dowodu pozostawiamy czytelnikowi jak.o zad. 31.3-3.

Korzystając z tego wniosku, możemy udowodnić następujące



twierdzenie.

TwlERDZENIE 31.9.
Algorytm Strassena mnożenia macierzy działa prawidłowo dla macierzy utwo-
rzonych nad dowolnym pierścieniem.

DOWÓD
Algorytm Strassena zależy od poprawności algorytmu dla macierzy 2 x 2, któ-
ry wymaga tylko, by elementy macierzy należały do pierścienia. Ponieważ jest
tak z założenia, z wniosku 31.8 wynika, że macierze same tworzą pierścień.
Zatem zgodnie z zasadą indukcji algorytm Strassena działa poprawnie na każ­
dym poziomie rekursji.

Algorytm Strassena mnożenia macierzy istotnie zależy od istnienia dla



dodawania elementów przeciwnych. Z siedmiu iloczynów P 1 , P 2 , ... , P 1 cztery
wymagają odejmowania macierzy. W ogólności więc algorytmu Strassena nie
można stosować dla struktur będących quasi-pierścieniami.

Mnożenie macierzy boolowskich


Algorytm Strassena nie może być użyty bezpośrednio do mnożenia macierzy
boolowskich, ponieważ boolowski quasi-pierścień ({O, 1}, v, A, O, 1) nie jest
pierścieniem. Zdarzają sie przypadki, gdy quasi-pierścień jest zawarty w większej
strukturze, która jest pierścieniem. Na przykład liczby naturalne (quasi-pierś­
cień) są podzbiorem zbioru liczb całkowitych (pierścień), możemy więc użyć
algorytmu Strassena do pomnożenia macierzy liczb naturalnych, traktując takie
macierze jak macierze liczb całkowitych. Niestety boolowsk.i quasi-pierścień nie
może być rozszerzony w podobny sposób do pierścienia (patrz zad. 31.3-4).
Z następującego twierdzenia wynika prosta sztuczka, za pomocą której
problem mnożenia macierzy boolowskich można zredukować do problemu
mnożenia macierzy zbudowanych nad pierścieniem.
Problem 31-1 dotyczy innego, bardziej efektywnego podejścia do tego za-
gadnienia.

TwIERDZENIE 31.10.
JeśliM(n) oznacza liczbę operacji arytmetycznych potrzebnych do pomnożenia
dwóch macierzy n x n zbudowanych z liczb całkowitych, to dwie macierze
boolowskie n x n mogą być pomnożone za pomocą O(M(n)) operacji aryt-
metycznych.

836
* 31.3. RÓŻNE STRUKTURY ALGEBRAICZNE I MNOŻENIE MACIERZY BOOLOWSKłCH

DOWÓD
Oznaczmy dwie dane macierze przez A i B. Niech C = AB w boolowskim
quasi-pierścieniu, czyli

"
c11= V a1k/\bki
k= 1

Zamiast przeprowadzać działania w boolowskim quasi-pierścieniu, obliczamy


w pierścieniu liczb całkowitych iloczyn C', używając danego algorytmu mnoże­
nia macierzy, który wykonuje M(n) operacji arytmetycznych. Mamy więc

c/i = L" aikbAJ


k" 1

Kai,de wyrażenie aikbAJnależące do tej sumy jest równe O wtedy i tylko wtedy,
gdy aik A bki = O, natomiast jest równe l, wtedy i tylko wtedy, gdy a 1k A bAJ= I.
Zatem suma c;1 wynosi O wtedy i tylko wtedy, gdy każde wyrażenie jest rów-
ne O, lub - co jest równoważne ~ wtedy i tylko wtedy, gdy alternatywa tych
wyrażeń (czyli c~) wynosi O. Macierz boolowska C może więc być odtworzona
za pomocą E>(n ) operacji arytmetycznych z całkowitoliczbowej macierzy C'
po prostu przez przyrównanie każdej sumy c/1 do O. Liczba operacji arytme-
tycznych dla całej procedury wynosi więc O(M(n)) + 9(n 2 ) = O(M(n)), ponie-
waż M(n) - i:ł(n').


Używając algorytmu Strassena, możemy zatem wykonać operację mnoże­
nia macierzy boolowskich w czasie O(rt'17).
W zwykłej metodzie mnożenia macierzy boolowskich wykorzystuje się je-
dynie zmienne boolowskie. Stosując podaną adaptację algorytmu Strassena,
możemy uzyskać wynikową macierz z elementami rozmiaru n, wymagającymi
raczej całego słowa maszynowego niż pojedynczych bitów. Bardziej niepokoją­
ce jest to, że wyniki pośrednie, które są liczbami całkowitymi, mogą urosnąć
do nawet większych rozmiarów. Jedną z metod zabezpieczania się przed zbyt
dużym wzrostem wyników pośrednich jest wykonywanie wszystkich obliczeń
modulo n+ 1. Zadanie 31.3-5 polega na wykazaniu, że liczenie modulo n+ l
nie ma wpływu na poprawność algorytmu.

Ciała

Pierścień (S, EB, 0, O,I) nazywamy ciałem, jeśli spełnia on dwie dodatkowe
własności.

837
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

6. Operacja 0 jest pnemienna, czyli a 0 b = b 0 a dla dowolnych a, beS.


7. Każdy niezerowy element należący do S ma element odw1otny względem
mnożenia, czyli dla dowolnego aeS- {O} istnieje element beS taki, że
a 0 b = b 0 a= l. Element b jest często nazywany odw1otnością a i ozna-
czany przez a~ 1 .

Przykładem ciała mogą być liczby rzeczywiste (R, +,·,O, 1), zespolone
(C, +,·,O, I) lub liczby całkowite modulo liczba pierwsza p (Zp, +,·,O, 1).
Ponieważ w ciałach istnieje element odwrotny, możliwe jest więc dzielenie.
Mamy też do dyspozycji przemienność. Zawężając uwagę z quasi-pierścieni do
pierścieni, Strassen był w stanie zmniejszyć czas potrzebny do pomnożenia
macierzy. Ponieważ elementy macierzy często należą do jakiegoś ciała - na
przykład liczb rzeczywistych - można by mieć nadzieję, że używając ciał za-
miast pierścieni w rekurencyjnym algorytmie typu Strassena, będzie można ten
• ••
czas Jeszcze poprawie.
To podejście nie wydaje się jednak zbyt owocne. W rekurencyjnym al-
gorytmie typu „dziel i zwyciężaj" macierze na każdym poziomie rekursji muszą
tworzyć ciało. Niestety naturalne uogólnienie na ciała twierdzenia 31.7 oraz
wniosku 31.8 nie jest prawdziwe. Dla n> 1 zbiór macierzy n x n nigdy nie jest
ciałem, nawet gdy są one zbudowane nad ciałem. Mnożenie macierzy n x n nie
jest bowiem przemienne, a dla wielu macierzy n x n nie istnieją macierze od-
wrotne. Lepsze algorytmy mnożenia macierzy są więc raczej oparte na teorii
pierścieni, a nie na teorii ciał.

ZADANIA
* 31.3-1. Czy algorytm Strassena działa nad strukturą algebraiczną (Z [x], +, ·,
O, 1), gdzie Z [x] jest zbiorem wszystkich wielomianów zmiennej x o współ­
czynnikach całkowitych, a + oraz· są zwykłymi operacjami dodawania
i mnożenia wielomianów?
* 31.3-2, Wytłumacz, dlaczego algorytm Strassena nie działa nad zamkniętymi
półpierścieniami (patrz podrozdz. 26.4) ani nad boolowskim quasi-pierś­
cieniem ({O,!}, v, A, O, 1).
* 31.3-3, Udowodnij twierdzenie 31.7 i wniosek 31.8.
*31.3-4. Pokaż, że boolowski quasi-pierścień ({O, l}, v, A, O, 1) nie da się
rozszerzyć do pierścienia. Innymi słowy, pokaż, że nie jest możliwe doda-
nie elementu ,, -1" do quasi-pierścienia w taki sposób, by uzyskana struk-
tura algebraiczna utworzyła pierścień.
31.3-5. Udowodnij, że jeśli wszystkie obliczenia w algorytmie z twierdzenia
31.10 są wykonywanemodulo n+ 1, to algorytm cały czas działa popraw-

nie.
31.3-6. Pokaż, jak efektywnie wykazać, czy dany graf nieskierowany zawiera
trójkąt (zbiór trzech parami sąsiednich wierzchołków).

838
31.4. ROZWIĄZVWANIE UKŁAD0W ROWNAN LINIOWYCH

* 31.3-7. Pokaż, że obliczanie iloczynu dwóch macierzy n x n nad boolowskim


quasi-pierścieniemjest sprowadzalne do problemu obliczenia domknięcia
przechodniego danego grafu o 3n wierzchołkach.
31.3-8. Pokaż, jak obliczyć domknięcie przechodnie danego grafu skierowa-
nego o n wierzchołkach w czasie O(n 187lgn). Porównaj ten wynik ze złożo­
nością procedury TRANSITIVE-CLOSURE w pod.rozdz. 26.2.

31.4. Rozwiązywanie układów równań liniowych


Rozwiązywanie układów równań liniowych jest podstawowym problemem, ja-
ki pojawia się w rozmaitych zastosowaniach. Układ tak.i może być wyrażony
jako równanie macierzowe, w którym każdy element macierzy lub wektora
należy do ustalonego ciała, zazwyczaj liczb rzeczywistych R. W niniejszym
podrozdziale rozważamy problem rozwiązywania układów równań za pomocą
metody nazywanej rozkładem LUP.
Rozważania rozpoczynamy, przyjmując zbiór równań liniowych z n nie-
wiadomymi x 1 , x 2 , •••, x,.:

U11X1 + U1zXz + ...+ a 1„x„ b,


Uz1X1 + UzzXz + ...+ a 2„X„ b,
• (31.17)

a„1X1 + a„zXz + ...+ a„,.x„ b.


Zbiór wartości zmiennych x 1 , x 2 , ••• , x,., które spełniają każde z równań
(31.17), nazywamy rozwiązaniem tego układu równań. W podrozdziale tym
zajmiemy się wyłącznie przypadkiem, w którym jest dokładnie n równań
z n niewiadomymi.
Równania (31.17) mogą zostać przepisane w wygodnej postaci równania
macierzowo-wektorowego

... a,. x, b,
... a, • x, b,
• •

a., a., ... x. b.


lub - co jest równowa:7.ne po podstawieniu A = (au), x = (xi) oraz b = (bJ
-jako

Ax=b (31.18)

839
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

Jeśli A nie jest macierzą osobliwą, to istnieje macierz A- 1 odwrotna do niej, a

(31.19)

jest szukanym wektorem. Możemy w następujący sposób dowieść, że wektor


x jest jedynym rozwiązaniem układu (31.18). Załóżmy, że istnieją dwa roz-
wiązania: x i x'. Wówczas Ax = Ax' =bi mamy

X= (A-'A)x
= A-'(Ax)
= A-'(Ax)
= (A · 0A)x'
= x'
W tym podrozdziale zajmiemy się głównie przypadkiem, w którym ma-
cierz A jest nieosobliwa lub - co jest równoważne (zgodnie z twierdzeniem
31.1) - rząd A jest równy liczbie niewiadomych n. Istnieją jednak inne moż­
liwości, które zasługują na krótkie omówienie. Jeśli liczba równań jest mniejsza
niż liczba niewiadomych n - lub mówiąc bardziej ogólnie, rząd A jest mniejszy
niż n - to układ nazywamy podokreślonym. Podokreślony układ równań ma
zazwyczaj nieskończenie wiele rozwiązań (patrz zad. 31.4-8), choć może nie
mieć w ogóle rozwiązań, gdy równania są sprzeczne. Jeśli liczba równań prze-
kracza liczbę niewiadomych n, to układ jest nadokreślony i może nie mieć
żadnych rozwiązań. Znajdowanie dobrych przybliżeń rozwiązań nadokreślo­
nych układów równań liniowych jest ważnym problemem., który rozważamy
w pod.rozdz. 31.6.
Wróćmy teraz do problemu rozwiązywania układu n równań z n niewiado-
mymi postaci Ax = b. Jednym z możliwych podejść jest obliczenie A- 1 , a na-
stępnie pomnożenie obydwu stron przez A- 1 , co da nam A- 1 Ax = A- 1 b, tj.
x = A- 1 b. To podejście prowadzi niestety do numerycznej niestabilności: błędy
w 2aokrągleniach kumulują się nadmiernie, kiedy używamy reprezentacji
zmiennoprzecinkowej zamiast idealnych liczb rzeczywistych. Na szczęście ist-
nieje inna metoda - rozkład LUP - która jest nwnerycznie stabilna i ma po-
nadto tę zaletę, że jest około 3 razy szybsza.

Szkic rozkładu LUP


Ideą rozkładu LUP jest malezi.enie trzech macierzy L, U i P wymiaru n x n
takich, że

(31.20)

840
31.4. ROZWJĄZVWANIE UKŁADÓW RÓWNAŃ LINIOWYCH

gdzie
• L jest jednostkową macierzą trójkątną dolną,
• U jest macierzą trójkątną górną,
• P jest macierzą permutacyjną.
Macierze L, U i P spełniające równanie (31.20) nazywamy rozkładem LUP
macierzy A. Pokażemy, że dla każdej nieosobliwej macierzy A istnieje taki
rozkład.
Zaletą obliczania rozkładu LUP dla macierzy A jest to, że układy równań
liniowych można rozwiązywać o wiele łatwiej, gdy macierze są trójkątne, tak
jak w przypadku macierzy L i U. Po znalezieniu rozkładu LUP macierzy
A możemy rozwiązać równanie (31.18) Ax = b, rozwiązując wyłącznie układy
równań liniowych, w następujący sposób. Mnożąc obydwie strony Ax = b
przez P, otrzymujemy równoważne równanie PAx = Pb, które zgodnie z wy~
nikiem zad. 31.1~2 sprowadza się do permutacji równań (31.17). Korzystając
z naszego rozkładu (31.20), dostajemy

LUx-Pb

Możemy teraz rozwiązać to równanie, rozwiązując dwa „trójkątne" ukła~


dy równań. Zdefiniujmy y = Ux, gdzie x jest szukanym wektorem. Najpierw
rozwiązujemy układ trójkątny dolny

Ly-Pb (31.21)

w którym y jest niewiadomą. Używamy do tego metody „podstawiania do


przodu".
Po znalezieniu y rozwiązujemy układ trójkątny górny

Ux=y (31.22)

w którym x jest niewiadomą. Robimy to za pomocą „podstawiania do tyłu".


Wektor x jest rozwiązaniem Ax = b, ponieważ macierz permutacji P jest
odwracalna (zad. 31.1-2):

Ax = p- 1 LUx
= p-1Ly
= p-lpb
-b
Naszym następnym krokiem jest pokazanie, jak działa podstawianie do
przodu i do tyłu, i rozwiązanie samego problemu rozkładu LUP.

841
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

Podstawianie do przodu i do tylu


Podstawianie do przodu służy do rozwiązywania trójkątnych dolnych układów
równań (31.21) w czasie S(n 2 ), dla danych L, P oraz b. Dla wygody permuta-
cję P będziemy przedstawiać w sposób zwięzły jako tablicę n:[l .. n]. Dla i= I,
2, ..., n, element n:[i] wskazuje, że P 1_,.[iJ=Ii P11= O dlaj i:- n:[i]. Zatem PA
ma aq;J,i w wierszu i i kolumnie j, a Pb ma blt[Jljako swój i-ty element. Ponie-
waż L jest jednostkową macierzą trójkątną dolną, równanie (31.21) możemy
zapisać jako

Y, = b!!:(l]
l21Y1+ Y2 = bJ<(l]
l31Y1+ /32)'2 + YJ = b,.[JJ

= b11:(n]
Jest rzeczą oczywistą, że rozwiązanie dla y 1 otrzymujemy wprost, gdyż
w pierwszym równaniu jest y 1 = bq 11. Po znalezieniu y 1 możemy podstawić
jego wartość do drugiego równania, otrzymując

Y2 = b„c21- l21Y1
Następnie możemy podstawić wartości y 1 i y 2 do trzeciego równania, co da
nam

YJ = h11:CJJ- (/31Y1+ l3iJ12)


W ogólności, podstawiamy wartości y 1, y 2, ... , y 1_ 1 „do przodu" do i-tego
równania, by znaleźć y;:
1-1

y 1 = b„r,i - L IJJyi
i"' 1
Podstawianie do tylu jest podobne do podstawiania do przodu. Dla da-
nych U i y rozwiązujemy n-te równanie i działamy wstecz, aż dojdziemy do
pierwszego równania. Tak jak podstawianie do przodu, proces ten wymaga
czasu 0(n 2 ). Ponieważ macierz U jest trójkątna górna, możemy zapisać układ
(31.22) jako

U11X1 +u12X2 + ... + U1,..-2xn-2+ U1,n-1X .. -1 + Y,


U22X2 + ...+ U2,n-2X11-l + U2,n-1Xn-l + Y2

Un-2,n-tXn-2 + Un-2,n-lXn-1 + Un-2,,.Xn Yn-2

Un-1,n-1Xn-1 + Un-1,,.Xn Yn-1

Un,,.X„ Yn
31.4. ROZWIĄZVWANIE UKŁADÓW RóWNAN LINIOWYCH

Możemy więc rozwiązać go ze względu na xn, x"_ 1 , ... , x 1 po kolei w na-


stępujący sposób:


lub ogólnie

x,- (Y,- .I u,;c,)/u„


1=1+ 1

Dla danych P, L, U oraz b procedura LUP-SOLVE znajduje x, używając


podstawiania do przodu i do tyłu. W następującym algorytmie przyjęliśmy
założenie, że wymiar n jest atrybutem rows [L] i że reprezentacja permutacji
P jest dana w tablicy n.

LUP-SOLVE(L,U, n, b)
1 n+-rows[L]
2 fori+-lton
i-1

3 doy 1 +--b„rll- Ll11Y1


j= 1
4 for i +- n downto 1

5 do x,-(Y,
- I u,,x,)/u„
)"'l+l
6 return x

Procedura LUP-SOLVE znajduje y, korzystając z podstawienia do przodu


w wierszach 2-3, a następnie znajduje x, używając podstawienia do tyłu w wier-
szach 4-5. Ponieważ sumy występujące w pętli for są ukrytymi pętlami, czas
działania wynosi więc 8 (n 2).
Jako przykład użycia tych metod rozważmy układ równań liniowych

1 2 O 0,1
3 5 4 X - 12,5
5 6 3 10,3

843
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

w którym
I 2 o
A- 3 5 4
5 6 3

0,1
b- 12,5
10,3
i szukamy niewiadomej x. Rozkład LUP jest następujący:

1 o o
L- 0,6 1 o
0,2 0,571 l

5 6 3
U= O 1,4 2,2
O O -1,856

oo l
P- O l O
l o o
(Można sprawdzić, żePA= LU). Używając podstawienia do przodu, rozwią­
zujemy Ly = Pb ze względu na y:

l o o Y, 10,3
0,6 I o Y, 12,5
0,2 0,571 1 Y, 0,1

otrzymując

10,3
6,32
-5,569

przez kolejne obliczenie y 1 , y 2 i y 3 . Używając podstawienia do tyłu, rozwiązu­


jemy Ux = y ze względu na x:

844
31.4. ROZWIĄZVWANIE UKŁADÓW RÓWNAŃ LINIOWYCH

5 6 3 x, 10,3
O 1,4 2,2 x, 6,32
O O -1,856 x, -5,569

otrzymując ostatecznie szukaną odpowiedź

0,5
-02
'
3,0

przez kolejne obliczenie x 3 , x 2 i x 1 •

Obliczanie rozkładu LU
Pokazaliśmy, źe jeślidokonamy rozkładu LUP danej nieosobliwej macierzy A,
to za pomocą podstawień do przodu i do tyłu możemy rozwiązać układ rów-
nań liniowych Ax = b. Pozostaje pokazać, jak w sposób efektywny otrzymać
rozkład LUP macierzy A. Zaczynamy od przypadku, w którym A jest nieosob-
liwą macierzą n x n, a macierz P jest niepotrzebna (czyli P = 111). W tym przy-
padku musimy znaleźć rozkład A= LU. Macierze Li U nazywamy rozkładem
LU macierzy A.
Metoda, jaką przeprowadzamy rozkład LU, jest nazywana eliminacją
Gaussa. Zaczynamy od odjęcia wielokrotności pierwszego równania od pozo-
stałych równań w ten sposób, że pierwsza zmienna zostanie z nich usunięta.
Z kolei odejmujemy wielokrotności drugiego równania od trzeciego i kolejnych
tak, by spowodować usunięcie z nich drugiej zmiennej. Postępujemy w ten
sposób tak długo, aż układ, który pozostanie, będzie miał postać trójkątną
górną- będzie to w rzeczywistości macierz U. Macierz L powstaje z czynników
mnożących wiersze, które powodują eliminację zmiennych.
Nasz algorytm implementujący tę strategię jest rekurencyjny. Chcemy
skonstruować rozkład LU dla macierzy A wymiaru n x n. Jeśli n= 1, to skoń­
czyliśmy pracę, gdyż możemy wybrać jako L = 11 i jako U= A. Dla n> 1
dzielimy A na cztery części:

a,, a,, •• • a,.


A-
a,, a,, ... a,.
• •

a., a., ... aM


845
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

-(allWT)
V A'
gdzie v jest wektorem kolumnowym wymiaru (n - 1), wT jest wektorem wier-
szowym wymiaru (n - 1), a A' jest macierzą (n - 1) x (n - 1). Następnie, ko-
rzystając z praw algebry macierzy (sprawdź te równości, wykonując odpowied-
nie mnożenia), możemy rozłożyć A na

A-("''wT)
A'
V

= ( v/a11 1 O ) ("''
ln-1 O

Zera w pierwszej i drugiej macieny w tym rozkładzie są odpowiednio wek-


torami wierszowymi i kolumnowymi wymiaru n - 1. Wyrażenie vwT/a 11,
utworzone przez obliczenie iloczynu zewnętrznego v i w, a następnie podziele-
nie każdego elementu wyniku przez a 11 , jest macierzą (n - 1) x (n - 1), co
pasuje do wymiaru macierzy A', od której jest odejmowana. Otrzymaną ma-
cierz (n - 1) x (n - 1)

(31.23)

nazywamy resztą
Scbura macierzy A ze względu na a 11 .
Następnie rekurencyjnie znajdujemy rozkład LU reszty Schura. Załóżmy, że

gdzie L' jest jednostkową macierzą trójkątną dolną, a U' jest macierzą trójkąt­
ną górną. Następnie, korzystając z praw algebry macierzy, otrzymujemy

A-(-
I
v/a11 o ) ("''O
In-1

WT)
O ) ("''O L'U'
- ( v/aI 11 ln-l

Q)
L'
(a WT)
11
O U'

8~4~6------------------------
31.4. ROZWIĄZVWANIE UKŁADÓW RÓWNAŃ LINIOWYCH

co prowadzi do naszego szukanego rozkładu LU. (Zauważmy, że ponieważ L'


jest jednostkową macierzą trójkątną dolną, więc L - też, a ponieważ U' jest
macierzą trójkątną górną, to analogicznie U - także).
Oczywiście, jeśli a 11 = O, to metoda ta nie zadziała, gdyż zajdzie potrzeba
dzielenia przez O. Nie zadziała też wtedy, gdy lewy górny element reszty Schura
A' - vwT/a 11 jest równy O,ponieważ dzielimy przez niego w następnym kroku
rekursji. Elementy, przez które dzielimy podczas rozkładu LU, nazywamy ele-
mentami osiowymi, bo znajdują się one na przekątnej macierzy U. Powodem,
dla którego wprowadzamy macierz permutacji P podczas rozkładu LUP, jest
właśnie to, że zwalnia ona nas z potrzeby dzielenia przez zero. Używanie per-
mutacji do omijania dzielenia przez O (lub przez małe liczby) jest nazywane
osiowaniem.
Ważną klasą macierzy, dla których rozkład LU zawsze jest poprawny, jest
klasa symetrycznych macierzy dodatnio określonych. Macierze te nie wymaga-
ją osiowania, a więc rekurencyjna strategia zarysowana powyżej może być
stosowana bez obawy konieczności dzielenia przez O. Ten fakt, podobnie jak
wiele innych, zostanie udowodniony w podrozdz. 31.6.
Nasz program rozkładający na LU macierz A postępuje zgodnie z reku-
rencyjną strategią, z wyjątkiem tego, że iteracja zastępuje rekursję. (fo prze-
kształcenie jest standardową optymalizacją procedur z „rekursją ogonową"
- czyli takich, których ostatnią operacją jest rekurencyjne wywołanie siebie
samej). Zakładamy, że wymiar macierzy A jest atrybutem rows[A]. Ponieważ
wiemy, że wynikowa macierz Urna zera poniżej przekątnej oraz że LU-SOLVE
nie sprawdza tych pozycji -program ich nie wypełnia. Analogicznie, ponieważ

wynikowa macierz L ma jedynki na przekątnej i zera poniżej przekątnej - po-
zycje te również nie zostają wypełnione. Zatem procedura oblicza wyłącznie
,,znaczące" pozycje macierzy L i U.

LU-DECOMPOSITION(A)
1 n+-rows[A]
2 fork+-1 ton
3 do Uu+-au
4 fori+-k+lton
5
6 U11 +- akl
7 fori+-k+lton
8 doforj+-k+l ton
9
10 return Li U

Zewnętrzna pętla for, zaczynająca się w wierszu 2, wykonuje się raz dla każ­
dego kroku rekursji. Wewnątrz tej pętli w wierszu 3 jest określany element
------------------ -----~=
847
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

osiowy jak.o «.1:.1:= au· W pętli for w wierszach 4-6 (do której nie wchodzimy,
gdy k = n) wektory v i wT są użyte do wypełnienia macierzy L i U. Elementy
wektora v są określone w wierszu 5 (v1 jest przechowywane w lik), a elementy
wektora wT są określone w wierszu 6 (wf jest przechowywane w u1a).Elementy
reszty Schura są liczone w wierszach 7-9 i przechowywane w macierzy A. Po-
nieważ wiersz 9 jest trzykrotnie zagnieżdżony, LU-DECOMPOSITION działa
w czasie 9(n 3 ) •

2 3 I 5
6 13 5 19
•3
3 l
4 7

5
4
2 J
,Je,·•· '
'

I
5

2
'

3
I
.l
4
4
I 5
2 4
2 19 10 23 I 16 9 18 I 4
4 10 l l 31 2 4 9 21 7
• 1 7 17 2 l
(•) (b) ( <.:) (d)

2 3 I 5 I o o o 2 3 l 5
6 13 5 19 3 l o o o 4 2 4

2 19 IO 23 l 4 l o o o I 2
4 IO Il 31 2 I 7 I o o o 3
A L u
(,)
Rys. 31.1. Ilustracja działania procedury LU-DECOMPOSTilON (a) Macierz A. (b) Element a 11 = 2
zaznaczony na cz.am.o jest osiowy, zaciemniona kolumna to v/a1i, a zaciemniony wiersz - wT.
Elementy U obliczone dotychczas są. powyżej linii poziomej, a elementy L - na lewo od linii
pionowej. Macierz reszty Schura A' - v.,,l"/a 11 zajmuje prawą dolną aęść. (c) Działamy teraz na
macierzy reszty Schura utworzonej w podpunkcie (b). Element a 22 = 4 zaznaczony na czarno jest
osiowy, a zacieniowane wiersze i kolumny to odpowiednio v/a22 i wT (pochodzące z podziału
reszty Schura). Linie dzielą macierz na dotychczas obliczone elementy U (powyżej), elementy
L (z lewej) i nową resztę Schura (część prawa dolna). (d) Nutępny krok kończy rozkład (element 3
w nowej reszcie Schura staje się częścią U, gdy proces się kończy). (e) Rozkład A = LU

Rysunek 31.1 ilustruje działanie procedury LU-DECOMPOSITION, ukazu-


jąc standardową optymalizację procedury, w której elementy macierzy L
i U są przechowywane „w miejscu" w macierzy A. Możemy więc ustalić
odpowiedniość między każdą pozycją a11 i /IJ (jeśli i> j) lub ulJ Geśli i,:;:;,;)
i modyfikować macierz A tak, że zawiera ona macierze Li U, kiedy procedura
dobiega końca. Program realizujący tę optymalizację może być otrzymany
z powyższego programu jedynie przez zastąpienie każdego odwołania do / lub
u odwołaniem do a; nietrudno sprawdzić, że ta transformacja zachowuje po~
prawność algorytmu.

848
31.4. ROZWIĄZVWANIE UKŁADÓW RÓWNAŃ LINIOWYCH

Obliczanie rozkładu LUP

Rozwiązując układ równań liniowych Ax = b, w ogólnym przypadku musimy


wyosiować elementy A leżące poza przekątną, by nie zaszła potrzeba dzielenia
przez O. Niepożądane jest nie tylko dzielenie przez O, ale również przez małą
liczbę, nawet jeśli A jest macierzą nieosobliwą, ponieważ numeryczne niesta-
bilności mogą mieć wpływ na wynik. Z tego powodu staramy się umieszczać na
osi duże liczby.
Aparat matematyczny wykorzystany przy rozkładzie LUP przypomina ten
stosowany przy rozkładzie LU. Przypominamy, że dla danej nieosobliwej ma-
cierzy A wymiaru n x n zadanie polega na znalezieniu macierzy permutacyjnej
P, jffinostk.owej macierzy trójkątnej dolnej L oraz macierzy trójkątnej górnej
U, takich że PA = LU. Przed podzieleniem macierzy A, tak jak to czyniliśmy
dla rozkładu LU, przenosimy niezerowy element znajdujący się w pierwszej
kolumnie, powiedzmy 0 11 , na pozycję (1, I) w macierzy. (Jeśli pierwsza kolum-
na zawiera wyłącznie zera, to macierz A jest osobliwa, ponieważ jej wyznacznik
jest równy O, zgodnie z twierdzeniami 31.4 i 31.5). Aby cała ta operacja była
poprawna, zamieniamy pierwszy wiersz z wierszem k-tym, co jest tym samym
co mnożenie macierzy A przez macierz permutacyjną Q z lewej strony (zad.
31.1-2). Możemy więc zapisać QA jako

QA -("••
V
w')
A'

gdzi e v = ( 0 21 , 0 31 , ••• , 0 111) T - z tą rozrucą,


,, •••
ze 0 11 zastępuje 0 11 ; w '( = 0 12 , o~3 ,
... , 011,)- A' jest macierzą (n - 1) x (n - 1). Ponieważ 0 11 :#:O, możemy wyko-
nać te same operacje tak jak w przypadku rozkładu LU z tym, że mamy teraz
pewność, że nie będziemy musieli dzielić przez O:

QA -("•• w')
V A'

( I
= v/0 O)("••
11 J"-_1 O

Reszta Schura A' - vwT/011 jest nieosobliwa, bo gdyby tak nie było, to wy-
znacznik: drugiej macierzy w ostatniej równości byłby równy O, zatem wyznacz-
nik A też byłby równy O, co znaczyłoby, że reszta jest osobliwa. Przeczy to
założeniu, że A jest nieosobliwa. Postępując tak konsekwentnie, możemy in-
dukcyjnie znaleźć rozkład LUP dla reszty Schura, jednostkową macierz trój-
kątną dolną L', macierz trójkątną górną U' i macierz permutacyjną P' takie, że

849
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

2.defmiujmy

która jest macierzą permutacyjną, ponieważ jest iloczynem dwóch macierzy


permutacyjnych (zad. 31.1-2). Otrzymujemy dalej

PA=(~
;,) QA

= (~ ;,) (.1:,1
= (P'v:a
0) (•11
P' O A'- vwT/a WT )
11 11

= (P'v:a
0
J,,_1
11
) (••1
o P'(A'
- vwr/a
WT
11 )
)

0 ) (••1WT)
= (P'v:a
JPl-1
11 0 L'U'

= (P'v:a
0)
(a,
11
WT)
L' O
1
U'

=LU

co prowadzi do rozkładu LUP. Ponieważ L' jest jednostkową macierzą trójkąt­


ną dolną, jest nią też L. Ponieważ U' jest macierzą trójkątną górną, jest nią i U.
Zauważmy, że inaczej niż w przypadku rozkładu LU, zarówno wektor
kolumnowy v/a11, jak i reszta Schura A' - vwT/a11muszą zostać pomnożone
przez macierz permutacyjną P'.
Tak jak w przypadku LU-DECOMPOSITION, algorytm realizujący rozkład
LUP zamienia rek.ursję na iterację. Jako usprawnienie bezpośredniej imple-
mentacji rekursji, dynamicznie utrzymujemy macierz permutacyjną P jako tab-
licę 1r, gdzie n.:[i]= j oznacza, że i-ty wiersz P zawiera jedynkę w kolumniej-tej.
Algorytm będzie też obliczał L i U „w miejscu" w macierzy A. Zatem, kiedy
procedura kończy działanie, mamy

850
31.4. ROZWIĄZYWANIE UKŁADÓW RÓWNAŃ LINIOWYCH

jeśli i> j
jeśli i~j

LUP-DECOMPOSITION(A)
1 n+-rows[A]
2 fori+-1 ton
3 dox[i]+-i
4 fork+-1 ton
5 dop+-0
6 łori+-kton
7 do if !a,.!> p
8 tbeo p +- laik!
9 k'+-i
10 ifp-0
11 tben error „macierz osobliwa"
12 zamień n[k] - 1t[k1
13 fori+-lton
14 do zamień a1c 1+-+a.t'i
15 fori+-k+lton
16 do all+- all/a"
17 forj+-k+lton
18 do a11+- aiJ - au:.a"i

Na rysunku 31.2 widać, jak procedura LUP-DECOMPOSITIONrozkłada


macierz. Tablica 1t jest inicjowana w wierszach 2-3, tak by przedstawiała per-
mutację identycznościową. Zewnętrzna pętla for zaczynająca się w wierszu
4 odpowiada rekursji. Przy każdym wykonaniu tej pętli, w wierszach 5-9, zo-
staje określony element a"'"
jako element o najmniesz.ej wartości bezwzględnej
spośród elementów pierwszej kolumny (kolumny k) macierzy (n - k + 1) x
x (n - k + 1), której rozkładu LU szukamy. Jeśli wszystkie elementy tej ko-
lumny równe są O, to w wierszach 10-11 zostaje zgłoszony błąd, że macierz jest
osobliwa. Aby wyosiować, zmieniamy x[k'] na x[k] w wierszu 12 i z.amieniamy
k-ty i k'-ty wiersz macierzy A w wierszach 13-14, czyniąc w ten sposób element
au- osiowym. (Całe wiersze są zamieniane, ponieważ w wyprowadzonej meto-
dzie nie tylko A' - vwT/a1c1 , ale również v/a1c
1 jest mnożone przez P'). Reszta
Schura jest w końcu obliczana w wierszach 15-18 w podobny sposób, jak jest
to robione w wierszach 4-9 LU-DECOMPOSITIONz tym, że w tym wypadku
algorytm działa „w miejscu."

851
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

2 o 2 0,6 ;;;j;i; ;:, :int:;,·:


3 3 4 -2
3 3 ""
.
.,, ll"'"
"""'
•-'"""
,,,,, '
,,,,s
"""" .

2 3 4 -2 2 o l ,6 -3,2

4
o
_, 5
-2
4
3,4 _,
2 l o 2 0,6 l 0,4 --0,2
4 -2 3,4 -I 4 4,2 --0,6
(a) (b) (c)

5 5 4 2 3 5 5 4 2 3 5 5 4 2
0,6 o l ,6 -3,2 I 0,4 l 0,4
0,4
--0,2 •-I
(d)
0,4
4,2
--0,2
--0,6
2
4
0,6
--0,2 4,2 --0,6
2
4 4 --0.5
(c) IO
-l 5 5 4 2 3 5 5 4 2 3 5 5 4 2
0,4 -2

o - ..
2 0,4 --0,2 l 0,4 -2 0,4 --0,2 l 0,4 -2 0,4 --0,2
3 0,6 o l ,6 -3,2 4 --0,2 0,5 4 --0,2 0,5
'"'
o '
4 --0,2 0,5
(g)
-5 2 0,6 o
(h)
2 0,6

(i)
o
•'
'
-3

oo[ o 2 o o o o
[ o o o
ooo[
3 3
2
3 -2
4 2
0,6

=
[
0,4 1 o o
o
''
o -2
o o
4 2
0,4 --0.2
4 --0,5
o1 oo ''
-l -2 3,4 -1
--0,2
0,6
0,5
o
1
0,4 1 o o o -3
p A L u

Rys. 31.2. Uustracja d'Zia.l:aniaprocedury LUP-DECOMPOSITION. (a) Dana macierz A z identyczno-


ściową pennutacją po lewej stronie. W pierwszym kroku algorytm stwierdza, że element 5 za-
znaczony na czarno w trzecim wierszujest elementem osiowym dla pierwszej kolumny. (b) Wiersze
pierwszy oraz trzeci są zamienione i pe1mutacja jest uaktualniona. Zacieniowany wiersz przed-
stawia v i wr. (c) Wektor v jest zamieniony przez v/5 i prawa dolna część macierzy zawiera resztę
Schura. Linie dzielą macierz na trzy części: lliementy U (powyżej), elementy L (po lewej stronie)
oraz elementy reszty Schura (prawa dolna część). (d}{f) Drugi krok. (g)-(i) Trzeci krok. Czwarty
(ostatni) krok nie powoduje już żadnych zmian. O) Rozkład LUP PA= LU

Z uwagi na trzykrotnie zagnieżdżoną pętlę czas działania procedury


LUP-DECOMPOSITION wynosi 0(n 3), tak samo jak czas działania LU-DE-
COMPOSITION. Wyosiowywanie kosztuje więc co najwyżej stały wynik w czasie
działania.

ZADANIA
31.4--1.Rozwiąż równanie

852
31.5. ODWRACANIE MACIERZV

} Q Q X1 3
4 I o X2 14
-6 5 I X3 -7

używając podstawiania do przodu,


31.4-2. Znajdź rozkład LU macierzy

4 -5 6
8 -6 7
12 - 7 12

31.4-3. Dlaczego pętla for w wierszu 4 procedury LUP-DECOMPOSITIONwy-


konuje się tylko n - l razy, podczas gdy odpowiadającą jej pętlę for
w wierszu 2 procedury LU-DECOMPOSITIONwykonuje się n ra:zy?
31.4-4. Rozwiąż równanie

J 5 4 X1 12
2 0 3 X2 9
5 8 2 x3 5

używając rozkładu LUP.


31.4-5. Jak wygląda rozkład LUP macierzy diagonalnej?
31.4-6. Jak wygląda rozkład LUP macierzy permutacji A? Udowodnij, że jest
on określony jednoznacznie,
31.4-7. Wykaż, że dla każdego n~ 1 istnieje osobliwa macierz n x n, która ma
rozkład LU.
* 31.4-8. Pokaż, jak można wydajnie rozwiązywać układy równań postaci
Ax = b nad boolowskim quasi-pierścieniem ({O, I}, v, A, O, I).
* 31.4-9. Załóżmy, że A jest macierzą m x n rzędu m, gdzie m < n. Jak. znaleźć
x 0 wektor wymiaru n oraz macierz B wymiaru m x (n - m) i rzędu n - m
takie, że każdy wektor postaci x 0 + By, dla yER"-m, jest rozwiązaniem
podokreślonego równania Ax = b.

31.5. Odwracaniemacierzy
Choć w zastosowaniach praktycznych do rozwiązywania układów równań li-
niowych nie używa się z reguły operacji odwracania macierzy, wybierając za-
miast nich techniki bardziej stabilne numerycznie, takie jak rozkład LUP,
czasami zachodzi jednak potrzeba odwrócenia macierzy. W podrozdziale tym

853
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

pokazujemy, jak. rozkład LUP może być wykorzystany do odwrócenia macie-


rzy. Rozważamy także problem interesujący z teoretycznego punktu widzenia,
mianowicie pytanie, czy algorytm odwracania macierzy może być przyspieszo-
ny za pomocą metod, takich jak. algorytm Strassena. W rzeczywistości bowiem
praca Strassena miała na celu znalezienie szybszego algorytmu rozwiązywania
układów równań liniowych.

Odwracaniemacierzyprzy użyciu rozkładu LUP


Załóżmy, że mamy rozkJad macierzy A. w postaci trzech macierzy L, U oraz
P takich, że PA.= LU. Używając procedury LU-SOLVE, możemy rozwiązać
równanie A.x = b w czasie 0(n 2). Ponieważ rozkład LUP zależy od A., ale nie
od b, możemy rozwiązać drugi układ postaci A.x = b' w dodatkowym czasie
0(n 2 ). W ogólnym przypadku, mając już raz obliczony rozkład LUP macierzy
A, możemy rozwiązać, w czasie 0(kn 2 ), k wersji układu Ax = b różniących się
tylko wektorem b.
Równanie
(31.24)
może być rozumiane jako zbiór n różnych równań postaci Ax = b. Równania
te definiują X jako macierz odwrotną do A. Mówiąc dokładniej, niech X 1
oznacza i-tą kolumnę macierzy X; przypomnijmy też, że wektor jednostkowy
e1 jest i-tą kolumną I,.. Równanie (31.24) może więc być rozwiązane ze względu
na X z.a pomocą rozkładu LUP zastosowanego do A po to, by rozwiązać
każde z równań

A.Xi= e,
oddzielnie ze względu na X 1• Każdy z n wektorów X 1 może być znaleziony
w czasie 0(n 2 ); obliczenie X z rozkJadu LUP macierzy A. zajmuje więc 0(n 3)
czasu. Ponieważ rozkład LUP macierzy A można wykonać w czasie 0(n 3 ),
macierz A- 1 odwrotna do A może więc zostać obliczona w czasie 0(n 3 ).

Mnożenie macierzya ich odwracanie


Pokażemy teraz, jak teoretyczne przyspieszenie operacji mnożenia macierzy
przekształcić na przyspieszenie operacji odwracania macierzy. W rzeczywisto-
ści udowodnimy nawet coś mocniejszego: odwracanie macierzy jest równoważ­
ne z ich mnożeniem, w następującym znaczeniu. Jeśli M(n) oznacza czas po-
trzebny do pomnożenia dwóch macierzy n x n, a J(n) oznacza C7.3S potrzebny
do odwrócenia macierzy n x n, to !(n)= 0(M(n)). Udowodnimy to w dwóch
krokach. Najpierw pokawny, że M(n) - O(J(n)), co jest względnie proste,
a następnie udowodnimy, że J(n) - O(M(n)).

854
31.5. ODWRACANIE MACIERZV

TwlERDZENIE 31.11. (Mnożenie macierzy nie jest trudniejsze niż icb odwracanie)
Jeśli możemy odwrócić macierz n x n w czasie /(n), gdzie J(n) = !l(n 2 ) i l(n)
spełnia warunek regularności /(3n) = O(I(n)), to możemy pomnożyć dwie maM
cierze n x n w czasie O(I(n)).

DOWÓD
Niech A i B oznaczają macierze n x n, których iloczyn C chcemy obliczyć.
Definiujemy macierz D wymiaru 3n x 3n w sposób następujący:

I" A O
D- O I. B
o o r.
Macierzą odwrotną do D jest

I. -A AB
1
D- = O I" -B
O O In
możemy więc obliczyć iloczyn AB, biorąc prawą górną pod.macierz macierzy
D- 1wymiaru n x n.
Macierz D możemy obliczyć w czasie 9(n 2
) = O(I(n)) i odwrócić ją w czaM
sie 0(/(3n)) = O(l(n)), zgodnie z warunkiem regularności nałożonym na ](n).
Mamy więc

M(n) - O(l(n))

Zauważmy, że I(n) spełnia warunek regularności, kiedy tylko wartości I(n)
nie „skaczą" za dużo. Na przykład, jeśli J(n) = S(n' lg' n) dla dowolnych staM
łych c > O, d ~ O, to I(n) spełnia warunek regularności.

Redukcja problemu odwracania macierzy do problemu


• • •
mnozen1amacierzy
Dowód faktu, że odwracanie macierzy nie jest trudniejsze niż ich mnożenie,
opiera się na pewnych własnościach macierzy dodatnio określonych, które bęM
dą udowodnione w pod.rozdz. 31.6.

TwlERDZENIE 31.12. (Odwracanie nie jest trudniejsze niż mnożenie)


Jeśli możemy pomnożyć dowolne dwie rzeczywiste macierze n x n w czasie
M(n), gdzie M(n) = .Q(n2 ) i M(n) spełnia następujące warunki regularności:

855
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

M(n) = O(M(n + k)) dla O.; k.; n i M(n/2).; cM(n) dla pewnej stałej c.; 1/2,
to możemy odwrócić dowolną rzeczywistą macierz nieosobliwą n x n w czasie
O(M(n)).

Dowoo
Można mlożyć, że n jest dokładną potęgą 2, gdyż mamy

A = (A-,
0)- o) 1

(Olt O ft

dla dowolnego k > O. Wybierając mtem k takie, że n+ k jest dokładną potęgą


2, możemy powiększyć macierz do wymiaru, który jest następną potęgą 2,
i uzyskać szukaną macierz A- 1 z odpowiedzi na powiększony problem. Waru-
nek regularności nałożony na M(n) mpewnia, że to powiększenie nie wpływa
na wzrost czasu działania algorytmu o więcej niż czynnik stały.
Załóżmy na chwilę, że macierz A wymiaru n X n jest symetryczna i dodat-
nio określona. Dzielimy A na cztery podmacierze wymiaru n/2 x n/2:

A=(~
~) (31.25)

Następnie przyjmując

(31.26)

jako resztę Schura A ze względu na B, uzysk.ujemy

(31.27)

ponieważ AA - 1 = /11, co łatwo sprawdzić, wykonując mnożenie macierzy. Ma-


cierze B- 1 i s- 1 istnieją., jeśli A jest macierzą symetryczną i dodatnio określo­
ną, zgodnie z lematami 31.13, 31.14 i 31.15 z pod.rozdz. 31.6, ponieważ zarów-
no B,jak. i Ssą symetryczne i dodatnio określone. Zgodnie z zadaniem 31.1-3,
B-•cT = (CB-l)T i B- 1 crs- 1 = (s- 1 cB- 1 )T. Równania (31.26) i (31.27)
mogą więc być użyte do utworzenia rekurencyjnego algorytmu wykonującego
4 mnożenia macierzy n/2 x n/2:
C · 0- 1

(CB- 1) • er
s- 1 • (CB- 1)

856
31.5. ODWRACANIE MACIERZV

Ponieważ możemy pomnożyć macierze n/2 x n/2, wykorzystując odpo-


wiedni algorytm dla macierzy n x n, odwracanie symetrycznych macierzy do-
datnio określonych można wykonać w czasie

l(n),; 2J(n/2) + 4M(n) + O(n')


- 2J(n/2) + O(M(n))
- O(M(n))

Pozostaje wykazać, że asymptotyczny czas potrzebny do pomnożenia


macierzy wystarcza również do ich odwrócenia, gdy A jest odwracalna, ale
nie jest symetryczna i dodatnio określona. Podstawowym spostrzeżeniem jest
to, że dla dowolnej macierzy nieosobliwej A macierz ATA jest symetryczna
(zgodnie z zad. 31.1-3) i dodatnio określona (zgodnie z tw. 31.6). Sztuka
polega więc na zredukowaniu problemu odwracania macierzy A do problemu
odwracania ATA. Opierając się na obserwacji, że jeśli A jest macierzą nie-
osobliwą n x n, mamy

ponieważ ((ATA)- AT)A = (ATA)- 1(ATA)= In i macierz odwrotna jest zawsze


1

wyznaczona jednoznacznie. Moi.ewy więc obliczyć A- 1 , mnożąc wpierw AT


przez A, po to by otrzymać ATA; następnie odwracając dodatnio określoną
macierz ATA, używając powyższego algorytmu typu „dziel i zwyciężaj",
a w końcu mnożąc wynik przez AT. Na każ.dy z tych trzech kroków potrzeba
O(M(n)) czasu, a w związku z tym każ.da macierz nieosobliwa rzeczywista
może zostać odwrócona w czasie O(M(n)).


Udowadniając twierdzenie 31.12, otrzymaliśmy nowy sposób rozwiązywa­
nia równania Ax = b bez osiowania, jeśli tylko macierz A jest nieosobliwa.
Mnożąc obie strony równania przez AT, otrzymujemy (ATA)x =Arb.To prze-
kształcenie nie prowadzi do błędu, gdyż AT jest odwracalna, możemy więc
rozłożyć symetryczną macierz dodatnio określoną ATA, obliczając dla niej roz-
kład LU. Następnie wystarczy użyć podstawiania do przodu i do tyłu, żeby
znaleźć x, biorąc jako prawą stronę ATb. Choć metoda ta jest teoretycznie
poprawna, do praktycznych zastosowań lepsza jest procedura LUP-DECOM-
POSITION. Wymaga ona mniejszej o stały czynnik liczby operacji i ma nieco
lepsze własności numeryczne.

857
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

ZADANIA

31.S-1, Niech M(n} oznacza czas potrzebny do pomnożenia macierzy n x n,


a S(n} - czas podniesienia do kwadratu macierzy n x n. Wykaż, że mnoże­
nie i podnoszenie do kwadratu macierzy jest tak. samo trudne: S(n} =
= ®(M(n)).
31.S-2. Niech M(n} oznacza czas potrzebny do mnożenia macierzy n x n,
a L(_n}- czas potrzebny do dokonania rozkładu LUP macierzy n x n.
Wykaż, że mnożenie i rozkładanie macierzy są tak samo trudne:
Li.n) = ®(M(n)).
31.S-3. Niech M(n) oznacza czas potrzebny do pomnożenia macierzy n x n,
a D(n} niech oznacza czas potrzebny do obliczenia wyznacznika macierzy
n x n. Udowodnij, że obliczanie wyznacznika nie jest trudniejsze od mno-
żenia macierzy
31.S-4. Niech M(n} oznacza cz.as potrzebny do pomnożenia boolowskich ma-
cierzy n x n, a Ttn} - czas potrzebny do znalezienia domknięcia przechod-
niego boolowsk.ich macierzy n x n. Wykaż, że M(n} = O(Ttn)} i T(n} =
= O(M(n)lgn).
31.S-S. Czy algorytm odwracania macierzy oparty na twierdzeniu 31.12 działa,
kiedy elementy macierzy należą do ciała liczb całkowitych module 2?
* 31.5-6. Uogólnij algorytm odwracania macierzy oparty na twierdzeniu 31.12,
tak by działał również na liczbach zespolonych. Udowodnij poprawność
tego uogólnienia. (Wskaz6wka: Z.amiast transpozycji macierzy A użyj
sprzężonej transpozycji A•, którą otrzymuje się z transpozycji A przez za-
stąpienie każdej liczby zespolonej liczbą z nią sprzężoną. Zamiast macierzy
symetrycznych rozważ macierze bennitowskie, które są takimi macierzami
A, że zachodzi A = A
0
).

31.6. Symetrycznemacierzedodatniookreślone i metoda


najmniejszychkwadratów
Symetryczne macierze dodatnio określone mają wiele interesujących i porząda­
nych właściwości. Są na przykład nieosobliwe, rozkład LU może być dla nich
wykonany bez ryzyka dzielenia przez O. W tym podrozdziale udowodnimy
wiele innych ważnych własności symetrycznych macierzy dodatnio określo­
nych i pokażemy ich interesujące z.astosowanie do dopasowywania krzywej
metodą najmniejszych kwadratów.
Pierwsza własność, którą udowodnimy, jest prawdopodobnie najprostsza.

LEMAT31.13.
Każda symetryczna macierz dodatnio określona jest nieosobliwa.

858
31.6. SYMETRYCZNE MACIERZE DODATNIO 0KRE$LONE I METODA ...

DOWÓD
Załóżmy, że macierz A jest osobliwa. Wówczas zgodnie z wnioskiem 31.3 ist-
nieje niezerowy wektor x tak.i, że Ax = O. Zatem xT Ax = O, macierz A nie
może więc być dodatnio określona.


Dowód, że można przeprowadzić rozkład LU symetrycznej macierzy do-
datnio określonej A bez dzielenia przez O, jest bardziej skomplikowany. Za-
czynamy od udowodnienia pewnych własności podmacierzy macierzy A. Zdefi-
niujmy w tym celu k-tą główną podmacierzmacierzy A jako macierz A1.zawie-
rającą przecięcie pierwszych k wierszy i k kolumn macierzy A.

LEMAT31.14.
JeśliA jest symetryczną macierzą dodatnio określoną, to każda główna pod-
macierz macierzy A jest również symetryczna i dodatnio określona.

DOWÓD
To, że każda główna podmacierz macierzy A1.jest symetryczna, jest oczywiste,
By udowodnić, że macierz A1.jest dodatnio określona, załóżmy, że x jest nieze-
rowym wektorem kolumnowym wymiaru k i niech podział macierzy A wyglą­
da następująco:

Następnie otrzymujemy

xTA,x~ (xT O) (i ~)(~)


~(xTO )A(~)
ponieważ macierz A jest dodatnio określona. Zatem macierz A 1 jest również
dodatnio określona.


Zwrócimy teraz uwagę
na pewne zasadnicze własności reszty Schura. Niech
A będzie symetryczną macierzą dodatnio określoną i niech A1.będzie główną
podmacierzą wymiaru k x k macierzy A. Dzielimy A w sposób następujący:

859
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

A=(i~) (31.28)

Następnie zdefiniujemy resztę Schura macietzy A ze względu na A" jako

(31.29)

(Z lematu 31.14 macierz A"jest symetryczna i dodatnio określona; zatem Ał 1


istnieje zgodnie z lematem 31.13, a Sjest dobrze zdefiniowane). Zauważmy, że
nasza wcześniejsza def10icja (31.23) reszty Schura jest zgodna z defmicją
(31.29), gdy podstawimy k =
1.
Z następnego lematu wynika, że reszty Schura symetrycznych macierzy
dodatnio określonych same też są symetryczne i dodatnio określone. Ten re-
zultat został wykorzystany w twierdzeniu 31.12, a wniosek z niego płynący jest
potrzebny do udowodnienia poprawności rozkładu LU dla symetrycmych ma-
cierzy dodatnio określonych.

LEMAT 31.15. (Lemat o resztach Schura)


JeśliA jest symetryczną macierzą dodatnio określoną i A" jest główną pod-
macierzą wymiaru k x k macierzy A, to reszta Schura macierzy A ze względu
na A" jest symetryczna i dodatnio określona.

DOWÓD
Symetria macierzy Swynika z zad. 31.1-7. Pozostaje wykazać, że Sjest macierzą
dodatnio określoną. Rozważmy podział macierzy A dany równaniem (31.28).
Zgodnie z założeniem, dla dowolnego niezerowego wektora x, mamy
xT Ax > O.Podzielmy wektor x na dwa podwektory y i z pasujące odpowiednio
do A" i C. Ponieważ Ał 1 istnieje, dostajemy

(31.30)

po wykonaniu paru „macierzowych z.aklęć" (sprawdź przemnażając). Ostatnie


równanie sprowadza się do uzupełniania kwadratu formy kwadratowej (patrz
zad. 31.6-2).
Ponieważ xT Ax > O zachodzi dla każdego niezerowego x, weźmy dowolny
niezerowy z, a następnie podstawmy y = -A; 1BTz. Spowoduje to, że pierw-
szy składnik w s1tmie (31.30) mik.nie, a wyrażenie przyjmie postać

860
31.6. SYMETRYCZNE MACIERZE DODATNIO 0KRE$LONE I METODA ...

Dla dowolnego z #:-O mamy więc zTSz = xT Ax > O, a zatem S jest macierzą
dodatnio określoną.

WNIOSEK31.16.
Rozkład LU symetrycznych macierzy dodatnio określonych nigdy nie prowa-
dzi do dzielenia przez O.

DOWÓD
Niech A będzie symetryczną macierzą dodatnio określoną. Udowodnimy fakt
silniejszy niż teza wniosku: każdy element osiowy jest dodatni. Pierwszy ele-
ment osiowy jest równy a 11 . Niech e 1 będzie pierwszym wektorem jednostko-
wym, zatem a 11 = e[Ae 1 >O.Ponieważ pierwszy krok rozkładu LU daje nam
resztę Schura macierzy A ze względu na A 1 = (a 11 ), z lematu 31.15 wynika
więc przez indukcję, że wszystkie elementy osiowe są dodatnie.


Metoda najmniejszych kwadratów
Dopasowywanie krzywych do danego zbioru punktów jest ważnym zastoso-
waniem macierzy symetrycznych dodatnio określonych. Niech dany będzie
zbiór m punktów

(x1, Y1), (xz, Y2), ..., (x., y.,J

przy czym wiemy, że na wartość y 1 mogły wpłynąć błędy pomiaru. Chcemy


określić funkcję F(x) taką, że

Y1= Ąxi) + '11 (31.31)

dla i= l, 2, ... , m, gdzie błędy 11


1 są małe. Postać funkcji F zależy od roz-
ważanego problemu. Będziemy tutaj zakładać, że ma ona formę liniowo wa-
• •
zoneJ sumy

"
l'{x) = L c,f;(x)
i"' 1

gdzie liczba składników n oraz określone funkcje bazowe /j są ustalone na


podstawie wiedzy o rozważanym problemie. Zwykły wybór, to Jj (x) = xi- 1 ,

co oznacza, ze

861
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

J<{x)= C1 + CzX + C3X 2 + ...+ c„x!'- 1


jest wielomianem stopnia n - 1 zmiennej x.
Wybierając n= m, możemy dokładnie obliczyć każde Yt w równaniu
(31.31). Tak.a funkcja Fwysokiego stopnia „dopasowuje się do szumu", a nie
tylko do danych, otrzymujemy więc w ogólności słabe wyniki, gdy używamy jej
do przewidywania y dla wcześniej nie znanych wartości x. ZazwyC'laj lepiej
wybrać n znacząco mniejsze niż m i mieć nadzieję, że dobrze dobierając współ­
C'lynniki c1, otrzymamy funkcję F, która znajduje .maczące prawidłowości
w danym układzie punktów, bez zwracania nadmiernej uwagi na szum. Istnieją
pewne teoretyC'lne podstawy wyboru n, ale są one poza zakresem tematycznym
tej książki. W każdym przypadku, gdy n jest wybierane, dostajemy nad.określo­
ny układ równań, który chcemy rozwiązać najlepiej jak się da. Pokażemy teraz,
jak to można zrobić.
Niech

••• f.(x,)
••• f.(x,)
A= • • •



• •

f,(x.) f,(x.) ••• f.(x,J

oznacza macierz wartości funkcji bazowych w danych punktach; czyli aiJ =


= f;(x 1). Niech c = (c,1;)oznacza wektor wymiaru n szukanych współczynni­
ków. Wówczas

f,(x,) f,(x,) ••• f.(x,) c,


f,(x,) f,(x,) ••• f.(x,) c,
Ac= • • • • •
• • • •
• •
f,(x,J f,(x,J ••• f.(x.) c,

=
•••
F(x,J

jest wektorem „przewidywanych wartości" y. Zatem

17=Ac-y

jest wektorem błędów przybliżeń.

862
31.6. SYMETRYCZNE MACIERZE DODATNIO OKRESLONE f METODA ...

Aby zminimalizować błędy przybliżeń, decydujemy się minimalizować no-


rmę wektora błędów r,. W wyniku otrzymamy rozwiązanie optymalne w sensie
najmniejszych kwadratów, gdyż

Ponieważ

11~11'
- IIAc - YII'- ,f,(;±:,,
c1-Y,)'
możemy zminimalizować llrrll,różniczkując 11'111
2
ze względu na każde ck, a na-
stępnie przyrównując wyniki do zera:

(31.32)

n równań (31.32) dla k = 1, 2, ... , n jest równoważnych pojedynczemu rów-


naniu macierzowemu

(Ac - y)TA - O

lub równaniu (patrz zad. 31.1-3)

AT(Ac-y)-0

co implikuje

(31 .33)

W statystyce równanie to nazywamy równaniem normalnym. Macierz ATA jest


symetryczna (patrz zad. 31.1-3) i jeśli A ma pełny rząd kolumnowy, to ATA
jest dodatnio określona. Istnieje zatem (ATA)- 1 , a rozwiązaniem równania
(Jl.Jl) jest
c- ((ATA)-'A')y

(31.34)
gdzie macierz A+= ((ATA)- 1 AT) nazywamy macierzą pseudoodwrotną macie-
rzy A. Pseudoodwrotność jest naturalnym uogólnieniem pojęcia macierzy od-
wrotnej do przypadku, w którym A nie jest kwadratowa (porównaj równanie

863
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

(31.34) jako przybliżone rozwiązanie równania Ac= y z A- 1 b jako dokładnym


rozwiązaniem równania Ax = b).
Chcąc rozważyć przykład dopasowywania metodą najmniejszych kwadra-
tów, załóżmy, że mamy danych 5 punktów

(-1, 2), (1, l), (2, l), (3, O), (5, 3)

zaznaczonych jako czarne kropki na rys. 31.3. Chcemy dopasować do tych


punktów wielomian kwadratowy

Tworzymy najpierw macierz wartości funkcji bazowych

l x, xł l -1 l
l x, xl l 1 l
A= l x, xl l 2 4
1 x. xi 1 3 9
1 x, xl 1 5 25

której pseudoodwrotność wynosi

0,500 0,300 0,200 0,100 -0,100


-0,388 0,093 0,190 0,193 -0,088
0,060 -0,036 -0,048 -0,036 0,060

Mnożąc y przez A+, dostajemy wektor współczynników

1,200
C = -0,757
0,214

Odpowiadają one wielomianowi kwadratowemu


F(x) = 1,200 - 0,757x + 0,214x'
który najlepiej pasuje do naszych danych w sensie metody najmniejszych
kwadratów.
W praktyce równanie normalne (31.33) rozwiązujemy, mnożąc y przez
macierz AT, a następnie znajdując rozkład LU macierzy ATA. Jeśli macierz
A ma pełny rząd, to macierz ATA na pewno nie będzie osobliwa, ponieważ jest
symetryczna i dodatnio określona (patrz zad. 31.1~3 i tw. 31.6).

864
31.6. SYMETRYCZNE MACIERZE DODATNIO OKRE$LONE I METODA ...

3,0

2,5

F(x) = 1,2- O,757 x + 0,214x 2


2,0

0,5

- l-------+-----"o"o-----1-----1--- ----'---- ~ X
-2 -1 O 1 2 3 4 5

Rys. 31.3. Dopa.llowanie metodą najmniejszych kwadratów wielomianu kwadratowego do zbioru


punktów {(-1, 2), (1, I), (2, 1), (3, O), (5, 3)}. C:mme kropki reprezentują te punkty, a białe kropki
są ich wartościami pnewidywanymi przez F(.x) = 1,2 - 0,757.x + 0,2I4x2 - wielomian kwadra-
towy, który minimalizuje sumę kwadratów błędów. Błąd przy każdym punkcie jest zamaczany
cieniowaną linią

ZADANlA
31.6-1. Udowodnij, że każdy element diagonalny symetrycznej macierzy do·
datnio określonej jest dodatni.
31.6-,2. Niech A=(: ~) będzie symetryczną macierzą 2 x 2 dodatnio okreś·
loną.
Udowodnij, że jej wyznacznik. ac - b2 jest dodatni, .,uzupełniając
kwadrat" w podobny sposób do tego użytego w dowodzie lematu 31.15.
31.6-,3. Udowodnij, że największy element w symetrycznej macierzy dodatnio
określonej leży na przekątnej.
31.6-4. Udowodnij, że wyznacznik każdej głównej pod.macierzy macierzy sy·
metrycznej dodatnio określonej jest dodatni.
31.6-S. Niech A1: oznacza k·tą główną pod.macierz symetrycznej macierzy
A dodatnio określonej. Udowodnij, że det(A1:)/det(A1:-1 ) jest k·tym ele·
mentem osiowym podczas rozkładu LU, przyjmując, że det(A0 ) = l.
31.6-6. Znajdź funkcję postaci

865
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

która najlepiej pasuje (w sensie metody najmniejszych kwadratów) do na-


stępujących punktów:

(I, I), (2, I), (3, 3), (4, 8)


31.~7. Udowodnij, że macierz pseudoodwrotna A+ spełnia następujące 4
' .
rownarua:

(AA+)r = AA+
(A+A)T=A+A

Problemy
31-1. Algorytm Shamira mnożenia macierzy boolowskich
W podrozdziale 31.3 zauważyliśmy, że algorytm Strassena mnożenia macierzy
nie może być użyty bezpośrednio do mnożenia macierzy boolowskich, ponie-
waż boolowski quasi-pierścień Q = ({O, I}, v, A, O, 1) nie jest pierścieniem.
Twierdzenie 31. l Owskazuje wszakże, że jeśli użyjemy wyłącznie operacji aryt-
metycznych na słowach O(lgn)-bitowych, to możemy zastosować metodę
Strassena do mnożenia macierzy boolowskich n x n w czasie O(rł 21 ). W tym
miejscu zajmiemy się metodą probabilistyczną, w której stosuje się wyłącznie
operacje na bitach, żeby otrzymać prawie tak samo dobre ograniczenie, ale
z małym prawdopodobieństwem błędu.

(a) Pokaż, że R ~ ({O, I}, (l), A, O, 1), gdzie (l) oznacza funkcję XOR (różnicę
symetryczną), jest pierścieniem.

Niech A = (au) i B = (bil) będą macierzami boolowskimi n x n i niech


C = (c;i) = AB w quasi-pierścieniu Q. Utwórz macierz A'= (a[1) z macierzy A,
używając następującej procedury losującej:

• Jeśli au= O, to niech ai1 = O.


• Jeśli aii = 1, to niech ai1 = 1 z prawdopodobieństwem 1/2 i niech ai1 = O
z prawdopodobieństwem 1/2. Losowe wybory dla każdej pozycji są nieza-
leżne.

(b) Niech C' w pierścieniu R. Pokaż, że cu = Oimplikuje c;1 = O.


= (cj1) = A'B
Pokaż, że cii = 1 implikuje c/1 = 1 z prawdopodobieństwem 1/2.
(c) Pokaż, że dla dowolnego e > O prawdopodobieństwo, że dane c/1 nigdy nie
przyjmie wartości c;i dla lg(n 2 /e) niezależnych wyborów macierzy A', wy-

866
PROBLEMY

nosi co najwyżej s/n2 • Pokaż, że prawdopodobieństwo, że wszystkie c;i


przyjmą poprawne wartości choć raz, wynosi 1 - s.
(d) Podaj probabilistyczny algorytm działający w czasie O(lfB1lgn), który obli-
cza iloczyn dwóch macierzy n x n w quasi-pierścieniu Q z prawdopodo-
bieństwem co najmniej 1 - 1/rł dla dowolnej stałej k > O.Jedyne dozwolo-
ne operacje na elementach macierzy to A , v i EB.

31-2. Trójdiagonalne układy równań liniowych


Rozważmy następującą macierz trójdiagonalną:

1 -1 o o o
-1 2 -1 o o
A- o -1 2 -1 o
o o -1 2 -1
o o o -1 2

(a) Znajdź rozkład LU macierzy A.


(b) Rozwiąż równianie Ax = (1 1 I 1 l)r, używając podstawień do przodu
i do tyłu.
(c) Znajdź odwrotność macierzy A.
(d) Pokaż, że dla dowolnej macierzy A wymiaru n x n, symetrycznej, dodatnio
określonej i trójdiagonalnej równanie Ax = b może zostać rozwiązane w cza-
sie O(n) przez wykonanie rozkładu LU. Wykaż, że żadna metoda oparta na
obliczaniu A- 1 nie jest asymptotycznie tańsza w najgorszym przypadku.
(e) Pokaż, że dla dowolnej macierzy A wymiaru n x n trójdiagonalnej i nieoso-
bliwej i dla dowolnego wektora b wymiaru n równanie Ax = b może być
rozwiązane w czasie O(n) za pomocą rozkładu LU.

31-3. Krzywe sklejane


Praktyczna metoda interpolacji zbioru p11nktów za pomocą krzywej opiera się na
użyciu krzywych sklejanych (ang. splines) trzeciego stopnia. Niech dany będzie
zbiór {(x;, Y;): i= O, I, ... , n} złożony z n+ 1 par punkt-wartość, gdiie
x 0 < x 1 < ... < x 11• Chcemy dopasować krzywą sklejaną trzeciego stopnia/(x) do
tych punktów, tzn. f(x) ma być utworzona z n wielomianów trzeciego stopnia
J; (x) = a1 + b1x + c1x 2 + d1x 3 dla i= O, I, ... , n - 1, gdzie jeśli x należy do
dziedziny X; ::,;; x::,;; x 1+ 1 , to wartość krzywej obliczamy za pomocą wzoru/(x) =
= J;(x - x 1). Punkty x 1, w których wielomiany trzeciego stopnia są sklejane,
nazywamy węzłami. Dla uproszczenia zakładamy, że X;= i dla i= O, 1, ..., n.
Aby zapewnić ciągłość f(x), wymagamy, by

f(x,) - f,(O) - Y,

867
ROZDZIAŁ 31. OPERACJE NA MACIERZACH

f(x 1+ 1) = J;(l) = Y1+1


dla i= O, 1, ... , n - I. Aby zapewnić, żef(x) jest wystarczająco gładka, wym.a~
gamy też ciągłości pierwszej pochodnej w każdym węźle:
f'(x,.,) = /,(1) = f,+ 1 (0)
dlai=O,l, ... ,n-1.

(a) Załóżmy, że dla i= O, 1, ..., n mamy dane nie tylko pary punkt~wartość
{(x;, yJ}, ale też pierwsze pochodne D 1 =f'(x 1) w każdym węźle. Wyraź
wszystkiewspółczynnikia 1 , b1, c1 orazd1 zapomocą wartościy 1 ,Y 1 + 1 , D 1iD;+ 1
(pamiętaj, że x 1 = r). Jak szybko można obliczyć 4n współczynników na
podstawie par punkt~wartość i pierwszych pochodnych?

Pozostaje problem, jak wybrać pierwsze pochodne f(x) w węzłach. Jedna z me-
tod polega na wymaganiu, by drugie pochodne były ciągłe w węzłach:

f"(x,.,) =/f(l) =/f+1(0)

dla i= O, 1, ... , n - 1. Dla pierwszego i ostatniego węzła zakładamy, że


f"(x 0 ) = fi(o) = O i f"(x,) = J;(l) = O. Z tych założeń wynika, że f(x) jest
naturalną krzywą sklejaną trzeciego stopnia.

(b) Użyj założeń o ciągłości drugiej pochodnej, by wykazać, że dla i= 1, 2, ... ,


n - 1 zachodzi

(31.35)

(c) Pokaż, że

2Do + D1 = 3(y1 - Yo) (31.36)

(31.37)
(d) Przepisz równania (31.35)-(31.37) jako równanie macierzowe z szukanym
wektorem D = (D 0 , D 1 , ... , D.,). Jakie cechy ma macierz w tym równaniu?
(e) Wykaż, że zbiór n + 1 par punkt-wartość może zostać przybliżony za po-
mocą naturalnej krzywej sklejanej trzeciego stopnia w czasie O(n) (patrz
problem 31-2).
(f) Pokaż, jak określić naturalną krzywą trzeciego stopnia interpolującą n + 1
punktów (x 1, y 1) takich, że x 0 < x 1 < ... < x.,, nawet gdy X; nie jest koniecz-
nie równe i. Jakie równanie macierzowe musi zostać rozwiązane i jak szyb-
ko działa algorytm?

868
UWAGI DO ROZDZIAŁU

Uwagi do rozdziału

Istnieje wiele doskonałych pozycji zawierających dokładniejsze opisy nume-


rycznych i naukowych obliczeń, niż mogliśmy to tu uczynić. Autorami szcze-
gólnie przystępnych prac są: George i Liu [81], Golub i Van Loan [89], Press,
Plannery, Teukolsky i Vetterling [161, 162] oraz Strang [81, 82].
Pojawienie się algorytmu Strassena w 1969 r. [183] spowodowało duże
poruszenie. Wcześniej bowiem trudno było wyobrazić sobie istnienie algoryt-
mu lepszego niż standardowy. Asymptotyczne ograniczenie górne złożoności
czasowej algorytmu mnożenia macierzy zostało od tego czasu znacząco po-
prawione. Obecnie asymptotycznie najbardziej wydajny algorytm mnożenia
macierzy n x n, działający w czasie O(n 2 •376 ), podali Coppersm.ith i Winograd
[52]. Graficzne przedstawianie algorytmu Strassena zawdzięczamy Patersono-
wi [88]. Fischer i Meyer [67] dostosowali algorytm Strassena do macierzy bo-
olowskich (tw. 31.10).
Eliminacja Gaussa, na której opierają się algorytmy dokonujące rozkładu
LU i LUP, była pierwszą systematyczną metodą rozwiązywania układów rów-
nań liniowych. Był to w ogóle jeden z pierwszych algorytmów numerycznych.
Choć algorytm ten był znany już wcześniej, jego odkrycie zwykle przypisuje się
C.F. Gaussowi (1777-1855). W swojej znakomitej pracy [183] Strassen pokazał
też, jak odwracać macierze n x n w czasie O(n1117 ). Winograd [203] pierwszy
dowiódł, że mnożenie macierzy nie jest trudniejsze niż ich odwracanie, a twier-
dzenie odwrotne pochodzi od Abo, Hopcrofta i Ullmana [4].
Strang [182] doskonale przedstawia zagadnienie symetrycznych macierzy
dodatnio określonych i liniową algebrę w ogóle. Na stronie 334 czyni następu­
jącą uwagę: ,,Moi uczniowie często pytają mnie o niesymetryczne macierze
dodatnio określone. Nigdy nie używam tego terminu."
Rozdział 32

Wielomianyi FFT

Prosta metoda dodawania dwóch wielomianów stopnia n wymaga czasu 0(n),


ale prosta metoda mnożenia wymaga czasu 0(n 2 ). W tym rozdziale pokażemy,
w jaki sposób zastosowanie szybkiego przekształcenia Fouriera, czyli FFT
(od ang. Fast Fourier Transform) może zmniejszyć czas mnożenia wielomianów
do 0(nlgn).

Wielomiany
Wielomian zmiennej x nad ciałem F to funkcja A(x), którą można przedstawić
jako
·-'
A(x) - L a;x'
j.o o

Liczbę n nazywamy ograniczeniem stopnia wielomianu, a wartości


a 0 , a 1 , ... ,
a11_ 1 - współczynnikami wielomianu. Współczynniki należą do ciała F, którym
jest zwykle zbiór C liczb zespolonych. Mówimy, że wielomian A(x) ma stopień
k, jeśli jego najwyższym niezerowym współczynnikiem jest a1 • Stopień wielo-
mianu o ograniczeniu stopnia n może być dowolną liczbą całkowitą zawartą
między O a n - l, włącznie. Z drugiej strony wielomian stopnia k jest wielo~
mianem o ograniczeniu stopnia n dla dowolnego n > k.
Dla wielomianów można zdefmiować wiele różnych operacji. Jeśli chodzi
o dodawanie wielomianów, to dla wielomianów A(x) i B(x) o ograniczeniu stop-
nia n ich swną nazywamy taki wielomian C(x), także o ograniczeniu stopnia n,
że C(x) = A(x) + B(x) dla dowolnego x należącego do ciała F. To znaczy, jeśli

·-'
A(x) - L a;x;
j= o

870
ROZDZIAŁ 32. WIELOMIANY 1 FFT

oraz
,-1
B(x) - L,b1xl
j =o

to
,-1
C(x) - L,c1x'
j=O

gdzie c1 = a1 + b1 dlaj= O, l, ..., n-1.Jeślinaprzykład A(x)= 6x 3 + 7x 2 +


- lOx + 9, a B(x) = - 2x 3 + 4x - 5, to C(x) = 4x 3 + 7x 2 - 6x + 4.
Jeśli chodzi o mnożenie wielomianów, to dla wielomianów A(x) i B(x)
o ograniczeniu stopnia n ich iloczynemnazywamy taki wielomian C(x) o ogra-
niczeniu stopnia 2n - l, że C(x) = A(x)B(x) dla dowolnego x należącego do
ciała F. Czytelnik zapewne wykonywał już wcześniej operacje mnożenia wie-
lomianów, wymnażając każdy składnik A(x) przez każdy składnik B(x) i łą­
cząc składniki o równych potęgach zmiennej x. Na przykład wielomiany
A(x) = 6x 3 + 7x 2 -10x + 9 i B(x) = -2x 3 + 4x - 5 możemy pomnożyć
w następujący sposób:

6x 3 + 7x' 10x + 9
2x 3 + 4x 5
30x 3 35x2 + 50x 45
24x" + 28x 3 40x 2 + 36x
-12x
.
6
---
-14x 5
--
+20x
- - -
4
- 18x3
- -- .. ----------
-12.x 6
-
5
l4x +44x4 20x 3 75x 2 + 86x 45
Innym sposobem przedstawienia iloczynu C(x) jest
2n- 2
C(x) - L, c1 od (32.1)
j=O

gdzie
I
ci = L a1r.bJ-1r. (32.2)
Ir.= o

Zauważmy, że stopień(C} = stopień(A) + stopień(B), skąd

ograniczenie-stopnia(C) = ograniczenie-stopnia(A) +
+ ograniczenie-stopnia(B) - 1
ograniczenie-stopnia(A) +
::s.;;
+ ograniczenie-stopnia(B)

871
ROZDZIAŁ 32. WIELOMIANY I FFT

Pomimo to będziemy mówić, że ograniczeniem stopnia C jest suma ograniczeń


stopni A i B, ponieważ jeśli ograniczeniem stopnia wielomianu jest liczba k, to
jest nim również k + 1.

Zawartość rozdziału

W podrozdziale 32.1 przedstawimy dwa sposoby reprezentacji wielomianu:


przez współczynniki i przez wartości w punktach. Zwykłe metody mnożenia
wielomianów - z wykorzystaniem równań (32.1) i (32.2) - zajmują czas 0(n 2),
jeśli wielomiany są reprezentowane za pomocą współczynników, ale tylko 0(n)
przy użyciu reprezentacji przez wartości w punktach. Możemy jednak mnożyć
wielomiany reprezentowane przez współczynniki w czasie 0(nlgn), dokonując
przejścia od jednej reprez.entacji do drugiej. Ż.Cby wyjaśnić działanie takiego
algorytmu, musimy najpierw wspomnieć o zespolonych pierwiastkach z jedno-
ści, co uczynimy w pod.rozdz. 32.2. Następnie, w tym samym podrozdziale,
zastosujemy FFT i przekształcenie odwrotne, aby dokonać wzmiankowanych
konwersji reprezentacji. W podrozdziale 32.3 pokażemy, jak zrealizować szyb-
ką implementację FFT w sekwencyjnym i równoległym modelu obliczeń.
W tym rozdziale będziemy często korzystać z liczb zespolonych, a symbol i
będzie omaczać wyłącznie v-·-r.
32.1. Reprezentacja
wielomianów
Reprezentacje wielomianów za pomocą współczynników i wartości w punktach
są w pewnym sensie równoważne; to znaczy, wielomian reprezentowany przez
wartości w punktach ma swój wyznaczony jednoznacznie cxipowiednik w re-
prezentacji przez współczynniki. W niniejszym podrozdziale wprowadzamy
formalnie obydwie te reprez.entacje i pokazujemy, jak wykorzystać je łącznie do
pomnożenia dwóch wielomianów o ograniczeniu stopnia n w czasie 0(nlgn).

Reprezentacjaprzezwspółczynniki

Reprezentacja przez wspólczynniki wielomianu


·-'
A(x) = L a;x' o ograniczeniu
i"" o
stopnia n to wektor współczynników a= (a 0 , a 1 , ••• , an- 1 ). W równaniach
macierzowych w tym rozdziale będziemy zwykle traktować wektory jak.o wek~
tory kolumnowe.
Reprez.entacja za pomocą współczynników jest dogodna przy niektórych
operacjach na wielomianach. Na przykład operacja ewaluacji wielomianu A(x)
w danym punkcie x 0 polega na obliczeniu wartości A(x 0 ). Ewaluację można
wykonać w czasie E>(n),korzystając z tzw. schematu Homera:

872
32.1. REPREZENTACJA WIELOMIANÓW

Podobnie, dodawanie dwóch wielomianów reprezentowanych przez wektory


współczynników a= (a0 , a 1 , .•• , a11_ 1 ) i b = (b 0 , b 1 , ••• , b11_ 1) zajmuje czas
0(n): wynik stanowi wektor c = (c 0 , c 1 , .•. , c11_ 1), gdzie ej= aj+ b1 dlaj= O,
l, ...,n-1.
Rozważmy teraz problem mnożenia dwóch wielomianów A(x) i B(x)
o ograniczeniu stopnia n, reprezentowanych przez współczynniki. Jeśli użyjemy
metody opisanej równaniami (32.l) i (32.2), mnożenie to zajmie czas 0(n 2),
gdyż każdy współczynnik wektora a trzeba pomnożyć przez każdy współczyn­
nik wektora b. Operacja mnożenia wielomianów reprezentowanych za pomocą
współczynników wydaje się być istotnie trudniejsza niż ewaluacja wielomianu
czy dodawanie dwóch wielomianów. Powstający wektor współczynników c,
dany równaniem (32.2), nosi też nazwę splotu wejściowych wektorów a i b,
oznaczonego jako c = a® b. Ponieważ mnożenie wielomianów i obliczanie
splotów to podstawowe problemy obliczeniowe o dużym znaczeniu praktycz-
nym, w rozdziale tym koncentrujemy się na efektywnych algorytmach służą­
cych do rozwiązywania tych problemów.

Reprezentacjaprzez wartości w punktach


Reprezentacja przez wartości w punktachwielomianu A(x) o ograniczeniu stop-
nia n to zbiór par punkt-wm teść
{(xo, Yo), (x1, Y1), ... , (x11-1, Y..-1)}
taki, że wszystkie x 1 są parami różne oraz
y, - A(xJ (32.3)
dla k = O, 1, ... , n - 1. Wielomian może mieć wiele różnych reprezentacji przez
wartości w punktach, ponieważ jako podstawy tej reprezentacji można użyć
dowolnego zbioru n różnych punktów x 0 , x 1 , ... , x,._ 1 .
Obliczanie omawianej reprezentacji dla wielomianu danego w reprezenta-
cji przez współczynniki jest proste, ponieważ wystarczy w tym celu wybrać
n różnych punktów x 0 , x 1 , ... , x,._ 1 , a następnie obliczyć A(x 1 ) dla k = O, I, ...,
n - l. Korzystając z metody Homera, można zrobić to w czasie 0(n 2 ). Jak się
później przekonamy, odpowiednio dobierając x 1, możemy zredukować czas
obliczeń do 0(nlgn).
Zadanie odwrotne do ewaluacji - wyznaczanie współczynników wielomia-
nu na podstawie reprezentacji przez wartości w punktach - nosi nazwę inter-
polacji. Poniższe twierdzenie mówi, że zadanie to jest dobrze określone, o ile
ograniczenie stopnia interpolowanego wielomianu jest równe liczbie danych
par punkt-wartość.

873
ROZDZIAŁ 32. WIELOMIANY I FFT

TwIERDZENIE
32.1. (Jednoznaczność wielomianuinterpolacyjnego)
Dla dowolnego zbioru {(x 0, y 0), (x 1, y 1), ... , (xn-l• Yn-i)} złożonego z n par
punkt-wartość istnieje dokładnie jeden wielomian A(x) o ograniczeniu stop-
nia n tak.i, że y 1 = A(x 1 ) dla k = O, 1, ..., n -1.

DOWÓD
Dowód opiera się na istnieniu odwrotności pewnej macierzy. Równanie (32.3)
jest równoważne z równaniem macierzowym

I x, Xi •••
.xi-1 a, Yo
x,
-
I xl ~-1 a,
••• Y,
• • • • • • (32.4)
• • • •
• • • • • • •
I Xn-1 '
Xn-1 ••• x:-'
·-' an- 1 Yn-1

Macierz po lewej stronie oznaczamy jako V(x 0 , x 1, ... , xn- 1) i nazywa~


my macierzą Vandermonde'a. Zgodnie z zad. 31.1-10 wyznacznikiem tej ma-
cierzy jest

zatem na mocy twierdzenia 31.5, jeśli xt są różne, to jest ona odwrac.alna (to
znaczy nieosobliwa). Współczynniki a1 można więc wyznaczyć jednoznacznie
na podstawie reprezentacji przez wartości w punktach:


Dowód twierdzenia 32.1 opisuje algorytm interpolacji polegający na rozwią­
zaniu układu (32.4) równań liniowych. Korzystając z algorytmu rozkładu LU
opisanego w rozdz. 31, możemy rozwiązać ten układ równań w czasie O(n3 ).
Szybszy algorytm interpolacji w n punktach opiera się na wzorze La-
grange'a:

A(x) -
.-,
"
L. Y,
t=O
.•.
CT(x-x
n'-(--
X1
- X)
)
1)
(32.5)
j,,;.l

Czytelnik może sprawdzić, że prawa strona równania (32.5) jest wielomianem


o ograniczeniu stopnia n, spełniającym równanie A(xJ = y 1 dla każdego k.
W zadaniu 32.14 prosimy o podanie metody obliczenia współczynnik.ów wie-
lomianu A ze wzoru Lagrange'a w czasie E>(n2 ).

874
32.1. REPREZENTACJA WIELOMIANÓW

Tak więc ewaluacja i interpolacja w n punktach są dobrze zdefiniowanymi,


wzajemnie odwrotnymi operacjami, realizującymi przejście między reprezenta-
cją wielomianu przez współczynniki a reprezentacją przez wartości w punk·
tach 1l. Opisane powyżej algorytmy dla tych problemów działają w czasie 0(n 2 ).
Reprezentacja przez wartości w punktach jest dość wygodna do użycia
przy wielu operacjach na wielomianach. W dodawaniu, jeśli C(x) = A(x) +
+ B(x), to C(x.1c)= A(xJ + B(xt;) w każdym punk.cie xk. Dokładniej, jeśli ma-
my daną reprezentację przez wartości w punktach wielomianu A

oraz wielomianu B

(zwróćmy uwagę, że wartości A i B podane są w tych samych n punktach), to


reprezentacją przez wartości w punktach wielomianu C jest

{(xo, Yo+ YO), (x1, Y1 + yJ.), ···, (x,._ 1, Y,.-1 + Y~- 1)}
Czas dodawania dwóch wielomianów o ograniczeniu stopnia n, zadanych
przez wartości w punktach, wynosi zatem 0(n).
Reprezentacja przez wartości w punktach jest równie dogodna do mnoże­
nia wielomianów. Jeśli C(x) = A(x)B(x), to C(xJ = A(x.1c)B(xJw każdym pun-
więc w celu otrzymania reprezentacji przez wartości w punktach wielo-
kcie X.1c,
mianu C możemy w każdym punkcie z osobna przemnożyć wartość wielo-
mianu A przez wartość wielomianu B. Musimy jednak uwzględnić to, że ogra-
niczenie stopnia wielomianu C jest sumą ograniczeń stopni wielomianów A i B.
Standardowa reprezentacja przez wartości w punktach dla A i B składa się
z n par punkt-wartość dla każdego wielomianu. Wymnażając wartości, do-
stajemy n par punkt-wartość dla C. Ponieważ jednak ograniczeniem stopnia
wielomianu C jest 2n, z twierdzenia 32.1 wynika, że do reprezentowania G' po-
trzebujemy 2n takich par. Musimy zatem wyjść od „rozszerzonych" reprezen-
tacji przez wartości w punktach dla A i B, z których każda będzie &ię składać
z 2n par punkt-wartość. Jeśli dane są rozszerzone reprezentacje przez wartości
w punktach dla A

t)Problem interpolacji jest bardzo subtelny pod względem numerycznej stabilności. Chociaż
opisywane tu metody są matematycznie poprawne, małe ró:znice wartości danych wejściowych lub
błędy zaokrąglenia podczas obliczeń mogą powodować duże różnice wyników.
ROZDZIAŁ 32. WIELOMIANY I FFT

oraz dla B

to reprezentacją dla C jest

Widać stąd, że dla dwóch wejściowych wielomianów w rozszerzonej reprezen-


tacji przez wartości w punktach czas potrzebny na obliczenie reprezentacji
przez wartości w punktach ich iloczynu wynosi @(n), a więc znacznie mniej niż
w przypadku reprezentacji przez współczynniki.
Rozważmy na koniec problem ewaluacji w nowym punk.cie wielomianu
zadanego przez wartości w punktach. Nie widać tu żadnego prostszego sposo-
bu niż przekształcenie wielomianu do reprezentacji przez współczynniki, a na-
stępnie obliczenie jego wartości w nowym punkcie.

Szybkie mnożenie wielomianów reprezentowanych


przez współczynniki
Czy możemy skorzystać z działającej w czasie liniowym metody mnożenia wie-
lomianów reprezentowanych przez wartości w punktach, żeby przyspieszyć
mnożenie wielomianów w reprezentacji przez współczynniki? Odpowiedź na to
pytanie zależy od tego, czy 1DD.iemyszybko wykonywać przekształcenie wielo-
mianu z reprezentacji przez współczynniki do reprezentacji przez wartości
w punktach (ewaluacja) i na odwrót (interpolacja).
Do obliczania wartości możemy użyć zupełnie dowolnych punktów, ale
jeśli wybierzemy je odpowiednio, będziemy mogli dokonywać konwersji mię­
dzy obiema reprezentacjami w czasie 0(n lg n). Jak: okaże się w podrozdz. 32.2,
jeśli jako owe punkty wybierzemy „zespolone pierwiastki z jedności", możemy
przejść do reprezentacji przez wartości w punktach, obliczając dyskretną trans-
formatę Fouriera (DFT, od ang. D-iscreteFourier Transform) wektora współ­
czynników. Operację odwrotną~ interpolację~ można wykonać, obliczając
transformatę odwrotną wektora wartości w punktach, w wyniku czego otrzy-
muje się wektor współczynników. W podrozdziale 32.2 pokażemy, jak za po-
mocą szybkiego przekształcenia Fouriera (FFT) wykonywać operacje DFT
i odwrotną DFT w czasie 0(nlgn).
Strategię tę ilustruje rys. 32.1. Należy jesz.cze poruszyć drobną kwestię
związaną z ograniczeniami stopni wielomianów. Iloczyn dwóch wielomianów
o ograniczeniu stopnia n jest wielomianem o ograniczeniu stopnia 2n. Przed
zmianą reprezentacji wejściowych wielomianów A i B podwajamy zatem naj~
pierw ich ograniczenie stopnia do wartości 2n, dodając n zerowych współczyn-

876
32.1. REPREZENTACJA WIELOMIANÓW

ników przy najwyższych potęgach. Ponieważ wektory mają po 2n elementów,


korzystamy z „zespolonych pierwiastków stopnia 2n z jedności", oznaczonych
na rys. 32.1 symbolami ro2n.

'\i• al'···• an-1 Zwykłe mnożenie Reprez.entacja


bo, bi, .... bn-1 Czas 0(n 2
)
'
I co, cl' .... ('2n-2
} przez współczynniki

Ewaluacja Interpolacja
Czas 0(nlgn) Czas 0(nlgn)

A(~n), B(~n) C(~n)


A(~n)' B(~n) Mnożenie po współrZ9(1.nych C(aiJ,.) Reprez.entacja przez
.. .. wartości w punktach
. Czas 0(n) .
A<fili:-1), B(fili:-1) C(@;:;»1l

Rys. 32.1. Graficzna ilustratja efektywnego sposobu mnożenia wielomianów. Wielomiany w górnej
części diagramu są reprezentowane przez współczynniki, a w dolnej - przez wartości w punktach.
Strzałki z lewej strony na prawą odpowiadają operacji mnożenia. Symbole w 2 • omaczają zespala~
ne pierwiastki stopnia 2n z jedności

Poniższa, korzystająca
z FFT procedura mnoży dwa wielomiany A(x)
i B(x) o ograniczeniu stopnia n w czasie 9(nlgn), przy czym wielomiany wej-
ściowe i wyjściowy są reprezentowane przez współczynniki. Zakładamy, że
n jest potęgą dwójki; warunku tego można zawsze dotrzymać, dostawiając
zerowe współczynniki przy najwyższych potęgach x.

1. Podwojenie ograniczenia stopnia: Rozszerz reprezentatje przez współczyn­


niki wielomianów A(x) i B(x) do ograniczenia stopnia 2n, dodając do każdej
po n zerowych współczynników przy najwyższych potęgach.
2. Ewaluacja: Oblicz reprezentacje przez wartości w punktach dla wielomia-
nów A(x) i B(x), stosując dwukrotnie FFT rzędu 2n. Reprezentacje te skła­
dają się z wartości wielomianów dla pierwiastków stopnia 2n z jedności.
3. Mnożenie po wsp6lrzędnych: Oblicz reprezentację przez wartości w punktach
wielomianu C(x) = A(x)B(x), wymnażając odpowiadające sobie wartości.
Reprezentacja ta składa się z wartości C(x) we wszystkich pierwiastkach
stopnia 2n z jedności.
4. Interpolacja: Utwórz reprezentację przez współczynniki wielomianu C(x),
stosując jednokrotnie FFT do wektora 2n wartości w celu obliczenia od-
wrotnej DFT.

Kroki I i 3 realizuje się w czasie 9(n), a 2 i 4 w czasie E>(nlgn). Jeśli więc


pokażemy, jak wykonywać FFT, udowodnimy następujące twierdzenie.

--------------- -----------
877
ROZDZIAŁ 32. WIELOMIANY 1 FFT

TwIERDZENIE32.2.
Iloczyn dwóch wielomianów o ograniczeniu stopnia n można obliczyć w czasie
0(nlgn), przy czym wielomiany wejściowe i wyjściowy są reprezentowane
przez współczynniki.

ZADANIA
32.1-1. Pomnóż wielomiany A(x) = 7x 3 - x 2 + x - 10 i B(x) = 8x 3 - 6x + 3,
stosując równania (32.1) i (32.2).
32.1-2. Ewaluacji wielomianu A(x) o ograniczeniu stopnia n w danym punkcie
x 0 można również dokonać, dzieląc A(x) przez wielomian (x - x 0 ) i otrzy-
mując jako iloraz wielomian q(x) o ograniczeniu stopnia n - 1 oraz resztę
r, takie że

A(x) - q(x)(x - x 0 ) +r
Widać, że A(x 0 ) = r. Pokaż, jak obliczać resztę r i współczynniki ą(x)
w czasie E>(n),mając x 0 i współczynniki wielomianu A.
32.1-3. Wyprowadź reprezentację przez wartości w punktach wielomianu
,-1
A""'(x) = L a,._ _ixi 1 z reprezentacji przez wartości w punktach wielo-
i"' o ,-1
mianu A(x) = L a1xj, przy założeniu, że żadnym z punktów nie jest O.
i"" o
32.1-4. Pokaż, jak korzystając
ze wzoru (32.5), wykonywać interpolację w cza-
sie 0(n 2 ). (Wskazówka: Oblicz najpierw fL(x- x,1)i fL(x 1 - x.J, a na-
stępnie obliczaj poszczególne składniki, dzieląc przez (x - xt) i (xi - x.J.
Patrz zad.32.1-2).
32.1-5. Wyjaśnij, dlac;Lego błędna jest „oczywista" metoda dzielenia wielomia-
nów w reprezentacji przez wartości w punktach. Rozpatrz oddzielnie przy-
padek, w którym otrzymuje się dokładny wynik dzielenia, i przypadek
przeciwny.
32.1-6. Rozważmy dwa zbiory A i B, każdy zawierający po n liczb całkowitych
z przedziału od O do IOn. Chcemy obliczyć sumę kartezjańską zbiorów
A i B, zdefiniowaną jako

c-(x+y:xeAiyeB)

Zauważmy, że liczby ze zbioru C są z przedziału od O do 20n. Chcemy


znaleźć wszystkie elementy zbioru C i określić, na ile sposobów każdy
z nich daje się zapisać jako suma elementów z A i B. Wykaż, że problem
ten można rozwiązać w czasie O(n lgn). (Wskazówka: Potraktuj A i B jako
wielomiany stopnia 10n).

878
32.2. DFT I FFT

32.2. DFT i FFT


W podrozdziale 32.1 zapowiedzieliśmy, że korzystając z zespolonych pierwiast-
ków z jedności, możemy wykonywać ewaluację i interpolację w czasie 0(n lgn}.
W tym podrozdziale defmiujemy zespolone pierwiastki z jedności i badamy ich
własności, definiujemy dyskretną transformatę Fouriera (DFT), a następnie
pokazujemy, w jaki sposób w czasie G>(nlgn) metodą FFI obliczać DFT
i transformatę odwrotną.

Zespolone pierwiastki z jedności


Zespolony pierwiastek n-tego stopnia z jedności to liczba zespolona ru taka, że

w"= 1
Istnieje dokładnie n zespolonych pierwiastków n-tego stopnia z jedności; są to
liczby e 2 'łtilr:fn dla k = O, 1, ... , n - 1. Żeby zinterpretować ten wzór, skorzystamy
z definicji funkcji wykładniczej zmiennej zespolonej:

e1w = cosu + i sin u


Na rysunku 32.2 widać, że n zespolonych pierwiastków z jedności jest rozmie-
szczonych w równych odstępach na okręgu o promieniu jednostkowym i środ­
ku w początku układu współrzędnych na płaszczyźnie zespolonej. Wartość
W
.-
_ ,2m/n
(32.6)
nazywamy głównym pierwiastkiem n-tego stopnia z jedności; wszystkie pozo-
stałe zespolone pierwiastki n-tego stopnia z jedności są potęgami run.

i IDi

-1

_,. ,,t
--,
Rys. 32.l. Wartości w~, w~, ..., w~ na pła.szczyżnie zespolonej, gdzie ru8 =~ 1
' jest głównym pier-
wiastkiem stopnia 8 z jedności
_____________________ __
,,

879
ROZDZIAŁ 32. WIELOMIANY I FFT

Zbiór n zespolonych pierwiastków n-tego stopnia z jedności

stanowi grupę ze względu


na mnożenie (patrz pod.rozdz. 33.3). Grupa ta ma
taką samą strukturę jak. grupa (Z 11, +} z działaniem dodawania modulo n, bo
skoro ro:=ro~=l, 11
to ro~ro~=ro~+.1::=roW+.1::)moc1
• Podobnie ro;;1 =ro:- 1 •
Podstawowe własności zespolonych pierwiastków n-tego stopnia z jedności
opisują poniższe lematy.

LEMAT32.3. (Lemat o skracaniu}


Dla dowolnych liczb całkowitych n ~ D, k ~ O i d > O zachodzi

(32.7)

DOWÓD
Lemat wynika bezpośrednio ze wzoru (32.6}, ponieważ

--w, .

WNIOSEK
32.4.
Dla dowolnej parzystej liczby n > D zachodzi

w:12 = ro2 = -1

DOWÓD
Przeprowadzenie dowodu pozostawiamy czytelnikowi jak.o zad. 32.2-1.


LEMAT32.5. (Lemat o redukcji)
Jeśli n > D jest parzyste, to zbiór kwadratów n zespolonych pierwiastków
n-tego stopnia z jedności to zarazem n/2 zespolonych pierwiastków stopnia n/2
z jedności.

DOWÓD
Na mocy lematu o skracaniu mamy (ro!}2 = ro!12 dla dowolnej nieujemnaj licz-
by całkowitej k. Zauważmy, że podnosząc do kwadratu wszystkie pierwiastki
n-tego stopnia z jedności, każdy pierwiastek stopnia n/2 z jedności dostajemy
dokładnie dwa razy, ponieważ

880
32.2. DFT I FFT

=
(w!+1112)2 w;k+11

= w2kw"
" "
-- w''
"
= (ru!)2
Zatem kwadraty w! i w!+ft/l są równe. Własność tę można wyprowadzić rów~
= -1 wynika, że w!+n/2 = -w!, czyli
nież z wniosku 32.4, gdyż z tego, że w:r1.
(w!+n/2)2 = (ru!)2.


Jak się przekonamy, lemat o redukcji ma podstawowe znaczenie w naszej
opartej na zasadzie „dziel i zwyciężaj" metodzie przechodzenia między reprezen-
tacjami wielomianów przez współczynniki i przez wartości w punktach, ponieważ
zapewnia, że rozwiązywane rekurencyjnie podproblemy są o połowę mniejsze.

LEMAT 32.6. (Lemat o sumowaniu)


Dla dowolnej liczby całkowitej n ;i, I i dowolnej nieujemnej liczby calkowitej k
niepodzielnej przez n zachodzi

·-'
I: cw:Y
~o
j=O

DOWÓD
Ponieważ wzór (3.3) można stosować do liczb zespolonych, mamy więc

(I)' - I

Założenie, żek nie dzieli się przez n zapewnia, że mianownik jest różny od zera,
ponieważ ro! = 1 tylko wtedy, kiedy k jest podzielne przez n.


Dyskretna transformata Fouriera (DFT)
Przypomnijmy, że chcemy dokonać ewaluacji wielomianu

881
ROZDZIAŁ 32. WIELOMIANY I FFT

·-'
A(x) - I
j=O
a1x'

·
o ogran1czen1u · n w pun kt ac h Wn,
· st oprua O w,u 1 Wn,
2 ... , Wnn-l(t o znaczy w n ze-
spolonych pierwiastkach n-tego stopnia z jedności} 1 ). Bez straty ogólności mo-
żemy założyć, że n jest potęgą 2, ponieważ dane ograniczenie stopnia można
zawsze powiększyć - zawsze możemy w miarę potrzeb dodawać zerowe współ­
czynniki przy najwyższych potęgach. Zakładamy, że wielomian A jest zadany
przez współczynniki: a= (a 0 , a 1 , ... , an_ 1 ). Zdefiniujmy wartości Y1;dla k = O,
1, ..., n - 1 wzorem

,- '
= L a1w!i (32.8)
j=O

Wektory= (y 0 , y 1 , ... , Yn- 1 ) jest dyskretną transformatą Fouriera (DFf) wek-


tora współczynników a= (a 0 , a 1 , ... , an_ 1 ). Piszemy także y = DFTn(a).

Szybkie przekształcenie Fouriera (FFT)


Stosując metodę znaną jako szybkie przekształcenie Fouriera (FF"I), korzys-
tają.cą ze szczególnych własności zespolonych pierwiastków z jedności, mo-
żemy obliczyć DFTn(a) w czasie 0(nlgn), chociaż zwykła metoda wymaga
czasu 0(n 2 ).
Metoda FFT opiera się na strategii „dziel i zwyciężaj", wyodrębniając
współczynniki o parzystych i nieparzystych indeksach i defmiując dwa nowe
wielomiany o ograniczeniu stopnia n/2, oznaczane jako AC0 1(x) i A!11(x):

AfOl(x)= ao + a2X + a4X2 + ...+ n-2Xn/2-1


At11(x) = a 1 + a3x + a5x 2 + ...+ a"_ 1xn/l-l
Wielomian A[OJ zawiera wszystkie współczynniki o parzystych indeksach
w A (binarna reprezentacja indeksu kończy się zerem), a wielomian Ar11 zawie-
ra wszystkie współczynniki o nieparzystych indeksach (binarna reprezentacja
indeksu kończy się jedynką). Wynika stąd, że

(32.9)

n Rozmiar n oznacza to samo co 211w pod.rozdz. 32.l, ponieważ przed ewaluacj11,podwajamy


ograniczenie stopnia wielomianu. W kontekście mnożenia wielomianów posługujemy się zatem
w rzeczywistości zespolonymi pierwiastkami stopnia 2n z jedności.

882
32.2. DFT I FFT

zatem problem ewaluacji A(x) w punktach w2,w,!, ..., w:-1 sprowadza się do:

(1) ewaluacji wielomianów Af01(x) i Af11(x) o ograniczeniach stopni n/2 w punM


ktach

(w,.")'' (w,.')' , ... , (w„,-')' (32.10)

a następnie

(2) połączenia wyników zgodnie ze wzorem (32.9).

Na mocy lematu o redukcji, lista (32.10) składa się nie z n różnych warto-
ści, ale tylko z n/2 zespolonych pierwiastków stopnia n/2 z jedności, z których
każdy występuje dokładnie dwa razy. Dokonujemy zatem rekurencyjnie ewalu-
acji wielomianów Af01 i Ar11 o ograniczeniu stopnia n/2 we wszystkich n/2
zespolonych pierwiastkach stopnia n/2 z jedności. Obydwa podproblemy są
dokładnie tej samej postaci co problem pierwotny, ale dwukrotnie mniejszego
rozmiaru. Udało nam się podzielić obliczenie n-elementowego DFT II na dwa
obliczenia n/2-elementowego DFT„ 12. Podział ten jest podstawą poniższego
rekurencyjnego algorytmu FFT, obliczającego DFT dla n-elementowego wek-
tora a = (a0 , a 1, •••, a11_ 1 ), gdzie n jest potęgą dwójki.

RECURSIVE-FFT(a)
1 n+-- length [a] t> n jest potęgą 2.
2ifn=1
3 tben return a
4 ru +-- e2«i/n
5 ru'+-- 1
6 a 101+--(a 0 , a 2 , •.. , 0 11_ 2 )
7 a r11+-- (a1, a3, ... , a"_ i)
8 yroi +-- RECURSIVE-FFT(a[Ol)
9 y[ll +-- RECURSIVE-FFT(a[ll)
10 for k+--0 to n/2 - 1
11 do Yt +-- Ylo1+ w Yl11
01 11
12 Yt+(n/2) +-- Yl - myl
13 w+--ww 11
14 returny t> y jest wektorem kolumnowym.

Procedura RECURSIVE-FFTdziała następująco. Wiersze 2-3 odpowiadają


największemu zagłębieniu rekursji; wartość DFT pojedynczego elementu jest
równa jemu samemu, bo wówczas

883
ROZDZIAŁ 32. WIELOMIANYI FFT

W wierszach 6-7 są definiowane wektory współczynników wielomianów Aro1


i Af11. Wiersze 4, 5 i 13 zapewniają poprawną aktualizację wartości ru, dzięki
czemu przy każdym wykonywaniu instrukcji w wierszach 11-12 mamy ru = ru!.
(Aktualizacja wartości ru zamiast obliczania ru! od początku w każdym prze-
biegu pętli for pozwala zaoszczędzić na czasie). W wierszach 8-9 obliczamy
rekurencyjnie DFT 1112 , kładąc dla k = O, 1, ... , n/2 - 1

Ytroi= AC01(ru!,2)
Jitl = Aftl(ru!,2)
lub
Ytro1= AfOl(ru;i)

J'I''- A11\ro;')

(ponieważ ru!11= ru;t na mocy lematu o skracaniu).


W wierszach 11-12 są łączone wyniki rekurencyjnych obliczeń . Dla
DFT 1111
_ 1 w wierszu Il obliczamy
Yo, Y1, ..., y 1111

~ A(ro!)

gdzie ostatnia równość wynika ze wzoru (32.9). Dla y 1111


, Yll/l+l• ... , Y11- 1 , przyj-
mując k = O, 1, ... , n/2 - I, w wierszu 12 obliczamy

_ roi .t r11
Yt+(nft) -Y1: - W11Y1:

884
32.2. DFT I FFT

Druga równość wynika z pierwszej, ponieważ w!+(n/l) = -w!. Czwarta rów-


ność wynika z trzeciej, bo z tego, że w:= 1, wynika, że 1
= w;1 +". Ostatnia w;
równość wynika ze wzoru (32.9). Wektory obliczany przez procedurę RECUR-
SIVE-FFT jest zatem rzeczywiście dyskretną transformatą Fouriera (DFT)
wejściowego wektora a.
W celu oszacowania C'lasu dzjałania procedury RECURSIVE-FFf zauważ­
my, że poza wywołaniami rekurencyjnymi wykonanie procedury zajmuje czas
E>(n),gdzie n jest długością wejściowego wektora. Równanie rekurencyjne na
złożoność czasową wygląda więc następująco:

T(n) - 2T(n/2) + @(n)


- 0(nlgn)
Korzystając z szybkiego przekształcenia Fouriera, możemy zatem dokonywać
ewaluacji wielomianu o ograniC'leniu stopnia n w zespolonych pierwiastkach
n-tego stopnia z jedności w C'lasie @(n lg n).

Interpolacjaw zespolonych pierwiastkachz jedności


Uzupełnimy teraz przedstawiony schemat mnożenia wielomianów, pokazując,
jak obliczać interpolację w zespolonych pierwiastkach z jedności, co pozwala
nam na przejście od reprezentacji wielomianu przez wartości w punktach z po-
wrotem do reprezentacji przez współczynniki. Wzór na interpolację wyprowa-
dzamy, zapisując DFT jako równanie macierzowe, a następnie analizując po-
stać macierzy odwrotnej.
Zgodnie ze wzorem (32.4) możemy przedstawić obliczanie DFT jako mnożenie
macierzy y = V..a,gdzie V" jest macierzą Vandermonde'a zawierającą odpo-
wiednie potęgi ro":

Yo I I I I ••• I •o
Y, I w, w' w' ••• w,,- ' a,
" "
Y, I w; w: w! •••
ro;<n-1) a,
Y, I w' w' w' •••
wl<n-1) a,
• • •
" " •
" •
"• •

Yn-1 I w,,- ' c,o2(n-1) w3(n-1J


•••
c,o(n- l)(n-1)
an-1
" " "
Element na pozycji (k,;) w macierzy V" to ro! 1 dlaj, k = O, 1, ..., n - l, ich
wykładniki tworzą więc tabliczkę mnożenia.
Operację odwrotną, którą zapisujemy jako a= DFT,;- 1 (y), wykonujemy,
y
mnożąc przez 1
v;
(macierz odwrotną do V,J.

885
ROZDZIAŁ 32. WlELOM IANY I FFT

TwlERDZENIE 32.7.
Dla j, k = O, 1, ... , n - 1 elementem na pozycji (), k) w macierzy v; 1 jest
w;kl/n.

DOWÓD
Pokażemy, że V; V11 = In, gdzie J11 jest macierzą jednostkową (identycznościo­
1

wą) n x n. Rozważmy pozycję (j, )') w macierzy V; 1 V":

·-'
1
[V; VJ)j' = L (w;ki/n)(w!i')
k=O

= ·-'
L rffńU'- J)/n
k=O

Suma ta jest równa I, jeśli)'= j, a O w przeciwnym razie, na mocy lematu


o sumowaniu (lemat 32.6). Zauważmy, że możemy ów lemat zastosować, bo
skoro -(n - 1) <)' - j < n - 1, to j' - j nie dzieli się przez n.


Znając postać macierzy odwrotnej v; 1 , wiemy, ze DFT; 1 (y) zadane
jest wzorem

(32.11)

dlaj = O, 1, ... , n - I. Porównując wzory (32.8) i (32.11), widzlmy, że transfor-


matę odwrotną do DFT można obliczyć za pomocą modyfikacji algorytmu
FFT, polegającej na zamianie rolami wektorów a i y, zastąpieniu w11 przez w; 1
i podzieleniu wartości każdej współrzędnej wyniku przez n (patrz zad. 32.2-4).
A więc DFT; 1 można obliczyć również w czasie @(nlgn).
Korzystając z FFT i odwrotnego przekształcenia FFT, możemy zatem dla
danego wielomianu o ograniczeniu stopnia n przechodzić od reprezentacji
przez współczynniki do reprezentacji przez wartości w punktach i z powrotem
w czasie @(nlgn). W kontekście mnożenia wielomianów udowodniliśmy na-
stępujące twierdzenie:

TwIERDZENIE 32.8. (Twierdzenie o splocie)


Dla dowolnej pary wektorów a i b długości n, gdzie n jest potęgą dwójki, mamy
a® b ~ DFT 2;(DFT ,.,(a)· DFT 2 ,(b))
gdzie wektory a i b są uzupełnione zerami do długości 2n, a ,, · " oznacza
mnożenie po współrzędnych dwóch 2n-elementowych wektorów. •
s'""s"'s
______________________ _
32.3. EFEKTYWNEIMPLEMENTACJE FFT

ZADANIA

32.2-1. Udowodnij wniosek 32.4.


32.2-2. Oblicz DFT wektora (O, I, 2, 3).
32.2-3. Wykonaj zad. 32.1-1, korzystając z metody działającej w czasie
®(nlgn).
32.2-4. Napisz pseudokod obliczania DFT; 1 w czasie 0(nlgn).
32.2-5. Opisz, jak uogólnić procedurę FFT na przypadek, w którym n jest
potęgą 3. Podaj równanie rekurencyjne na czas działania algorytmu i roz-
wiąż je.
* 32.2-6. Załóimy, że operację FFT na wektorach długości n (gdzie n jest liczbą
parzystą) wykonujemy nie nad ciałem liczb zespolonych, lecz nad pierś­
cieniem Zm liczb całkowitych modulo m, gdzie m = 2tt,,f2 + l, a t jest do-
wolną dodatnią liczbą całkowitą. Rolę ro", głównego pierwiastka n-tego
stopnia z jedności, pełni w= 2r. Udowodnij, że DFT i odwrotne DFT są
w tym systemie dobrze określone.
32.2-7. Pokaż,jak dla danego ciągu wartości z 0 , z 1 , ... , zn-i (być może z po-
wtórzeniami) znajdować współczynniki wielomianu P(x) o ograniczeniu
stopnia n, którego jedynymi pierwiastkami są z0 , z 1, ... , zn-l (być może
wielokrotnymi). Twój algorytm powinien działać w czasie O(n lg 2n).
(Wskazówka: Wielomian P(x) przyjmuje wartość O w punkcie zj wtedy
i tylko wtedy, gdy P(x) jest wielokrotnością (x - zi)).
* 32.2-8 . .Z -transformatą wektora a= (a0 , a 1 , ... , a"_ 1) jest wektory= Ó'o, y 1,
... , Yn- 1 ), gdzie Yt =
·-'
L aizti, a z jest dowolną liczbą zespoloną. DFT jest
j"' o
zatem szczególnym przypadkiem .Z -transformaty dla z= w". Udowodnij,
że .Z-transformatę można obliczać w czasie O(nlgn) dla dowolnej liczby
i.espolonej z. (Wskazówka: Skorzystaj ze wzoru

Yl = 7!'12·-'
L (a 1zi'l2)(z-(k-J)'f2)
j= o

i potraktuj !!l' -transformatę jako splot).

32.3. EfektywneimplementacjeFFT
Ponieważ praktyczne zastosowania DFT, tak.ie jak przetwarzanie sygnałów,
wymagają możliwie największej szybkości działania, w tym podrozdziale oma-
wiamy dwie efektywne implementacje metody FFT. Najpierw zajmiemy się
iteracyjną wersją algorytmu FFT, działającą w czasie 0(nlgn), ale z mniejszą
wartością stałej ukrytej w notacji 0 niż implementacja rekurencyjna z pod~

887
ROZDZIAŁ 32. WIELOMIANY I FFT

rozdz. 32.2. Następnie korzystając z intuicji, które doprowadziły nas do imple-


mentacji iteracyjnej, zbudujemy efektywny układ obliczający FFT równolegle.

IteracyjnaimplementacjaFFT
Zauważmy najpierw, że w pętli for w wierszach 10-13 procedury RECURSIVE-
-FFT wartość w!yL 1l jest obliczana dwukrotnie. Projektanci kompilatorów na-
zywają taką wartość wspólnym podwyrateniem.Możemy przekształcić pętlę
w taki sposób, żeby wartość ta była obliczana tylko raz i przechowywana
w pomocniczej zmiennej t.

for k-o to n/2-1


do t-wyL 11
01
Yt-YL +t
01
Yt+(n/2) +- YL - t
W+-WWn

Ciąg działań wykonywanych w tej pętli: mnożenie zmiennej w (równej w!)


przez 11, zapamiętanie wartości iloczynu w zmiennej t oraz dodanie i odjęcie t
yL
od yL01, nosinazwę operacji motylkowej i jest przedstawiony schematycznie
na rys. 32.3.

y~---..---
.,:
yfl
Rys. 32.3. Operacja motylkowa. Dwie wartości wejściowe wchodzą z lewej strony, w! zostaje
pomnożone przez yp 1, a suma i różnica wychodzą z prawej strony. Rysunek można interpretował
jak.o układ arytmetyczny

Pokażemy teraz, jak przerobić strukturę algorytmu FFT z rekurencyjnej


na iteracyjną. Na rysunku 32.4 widać wektory wejściowe w formie drzewa
w rekurencyjnych wywołaniach procedury RECURSIVE-FFT, przy początko­
wym wywołaniu dla n = 8. Z każdym wywołaniem procedury jest związany
jeden węzeł w drzewie, etykietowany odpowiednim. wektorem wejściowym.
Każde wywołanie procedury RECURSIVE-FFT wykonuje dwa dalsze wywoła­
nia rekurencyjne, chyba że jego wektor wejściowy jest już 1-elementowy.
Pierwsze wywołanie wykonujemy dla lewego syna, a drugie dla prawego syna.
Patrząc na to drzewo, można zauważyć, że jeśli ustawimy elementy począt­
kowego wektora a w takiej kolejności, w jakiej występują one w liściach, to
możemy naśladować działanie procedury RECURSIVE-FFT w następujący spo-

888
32.3. EFEKTYWNEIMPLEMENTACJEFFT

r,,,) "'7)
Rys. 32.4. Drzewo wejściowych wektorów dla rekurencyjnych wywołali. procedury RECUR.SIVE·FFT.
W wywołaniu zewnętrznym n = S

sób. Najpierw, rozważając pary kolejnych elementów, obliczamy DFT dla każ­
dej pary za pomocą pojedynczej operacji motylkowej i zastępujemy daną
parę obliczonym wynikiem. Wektor nasz składa się teraz z n/2 takich dwu-
elementowych wyników. Następnie bierzemy po dwie takie pary, obliczamy
DFT dla każdej otrzymanej w ten sposób czwórki elementów wektora za po-
mocą dwóch operacji motylkowych i zastępujemy owe dwa dwuelementowe
wyniki jednym czteroelementowym. Wektor zawiera teraz n/4 4--elementowych
wyników DFT. Postępujemy tak dopóty, dopóki wektor nie będzie składał
się z dwóch wyników DFT, każdy długości n/2, które możemy następnie po-
łączyć za pomocą n/2 operacji motylkowych w jeden wynikowy wektor DFT
o n elementach.
żeby przejść od tej obserwacji do kodu, użyjemy tablicy A [O.. n - l],
zawierającej początkowo elementy wejściowego wektora a w kolejności, w ja-
kiej występują one w liściach drzewa na rys. 32.4. (Pokażemy później, jak
wyznaczyć ową kolejność). Ponieważ łączenie fragmentów wektora trzeba
wykonywać na każdym poziomie drzewa, wprowadzimy zmienną s przecho-
wującą numer poziomu i zmieniającą się od 1 (na dole drzewa, kiedy łączymy
pary w dwuelementowe wyniki DF"f) do lgn w korzeniu (kiedy łączymy dwa
fragmenty długości n/2, otrzymując ostateczny wynik). Algorytm ma zatem
następującą strukturę:

1 fors+-1 to lgn
2 dofork+-Oton-lby2a
3 do połącz dwa 2a- 1 --elementowe fragmenty
A[k„k+ 2•-• - I] i A[k + 2•- 1 .. k+ 2' - I]
w jeden 2'-elementowy \1/}'nikDFT w A [k .. k + 21 - I]

Wnętrze pętli (wiersz 3) możemy opisać dokładniej. Kopiujemy zawartość


pętli for z procedury RECURSlVE-FFf, zamieniając y[Ol na A [k .. k + 2a- l - I]
i y[lJ na A [k + 2a- l .. k + 2' - lJ. Używana w każdej operacji motylkowej

889
ROZDZIAŁ 32. WIELOMIANY I FFT

wartość w zależy od wartości si wynosi wm, gdziem= 2'. (Zmienną m wpro-


wadzamy tylko dla zwiększenia czytelności). Wprowadzamy jeszcze jedną po-
mocniczą zmienną u, która pozwala nam wykonywać operację motylkową
,,w miejscu". W rezultacie otrzymujemy poniższy pseudokod, stanowiący pod-
stawę naszej ostatecznej iteracyjnej wersji algorytmu FFT, jak również imple-
mentacji równoległej, którą przedstawimy później.

FFT-BASE(a)
1 n+- length [a] t> n jest potęgą 2.
2 fors+-1 to lgn
3 dom+-2a
4 (JJ +- e2,rl/m
5

fork+-Oton-lbym
6 doro+-1
7 forj+-Otom/2-1
8 do 1-wA[k + j+m/2]
9 u-A[k + Jl
10 A [k + J] - u + I
Il A[k+j+m/2]-u-t
12 ro+- w w.,.

Przedstawimy teraz ostateczną wersję iteracyjną


algorytmu FFT, z zamie-
nioną kolejnością pętli wewnętrznych dla uniknięcia obliczania niektórych in-
deksów i korzystającą z pomocniczej procedury BIT-RBVERSE-COPY(a, A)
w celu skopiowania elementów wektora a do tablicy A w odpowiednim po-
rządku.

lTERATIVE-FFT(a)
1 BIT-REVERSE-COPY(a, A)
2 n+- length (a] t> n jest potęgą 2.
3 fors+-ltolgn
4 dom+-2'
5 w +- e 2mfm

6 ro+-1
7 forJ-Otom/2-1
8 dofork+-Jton-lbym
9 dot-wA[k+m/2]
10 u-A[k]
li A[k]-u+ I
12 A[k+m/2]-u-t
13 ro+-ww.,.
14 return A

890
32.3. EFEKTYWNE IMPLEMENTACJE FFT

W jaki sposób procedura BIT-REVERSE-COPY wstawia elementy wejścio­


wego wektora a na właściwe miejsca w tablicy A? Porządek, w jakim występują
liście na rys. 32.4, jest wyznaczony przez odwrócenie kolejności bitów w re-
prezentacji binarnej. Dokładniej, jeśli przez rev(k) oznaczymy lg n-bitową licz-
bę całkowitą powstałą przez odwrócenie kolejności bitów w binarnej reprezen-
tacji liczby k, to element a1; powinniśmy umieścić w tablicy na pozycji
A[rev(k)]. Na przykład na rys. 32.4 liście występują w kolejności O,4, 2, 6, 1, 5,
3, 7; w zapisie binarnym ciąg ten to OOO,100,010,110,001,101,011, 111,
a odwracając kolejność bitów otrzymujemy ciąg OOO,001, 010, 011, 100, 101,
11O, 111. Żeby uzasadnić, że również w ogólnym przypadku chodzi nam o po-
rządek z odwróconą kolejnością bitów w zapisie binarnym, zauważmy, że na
najwyższym poziomie drzewa indeksy, których najmniej znaczący bit jest rów-
ny O, są umieszczane w lewym poddrzewie, a indeksy, w których najmniej
znaczący bit jest równy 1, wędrują do prawego poddrzewa. Po odcięciu naj-
mniej znaczącego bitu na każdym poziomie proces ten jest kontynuowany
w poddrzewach dopóty, dopóki nie dojdziemy do liści w porządku z odwróco-
ną kolejnością bitów.
Ponieważ funkcję rev(k) nietrudno obliczyć, procedurę BIT-REVERSE-
-COPY można zapisać następująco:

BIT-REVERSE-COPY(a, A)
1 n..- /ength [a]
2 fork..-Oton-1
3 do A [rev(k)] .._ a1;

Iteracyjna implementacja FFf działa w czasie 0(nlgn). Jasne jest, że czas


działania wywołania procedury BIT-REVERSE-COPY(a, A) wynosi O(n lg n), po-
nieważ pętla wykonuje n obrotów, a lg n bitów liczby z przedziału od O do
n - 1 możemy odwrócić w czasie O(lgn). (W praktyce znamy zwykle zawczasu
początkową wartość n, możemy więc stablicować funkcję rev(k), dzięki czemu
procedura BTT-REVERSE-COPY będzie działać w czasie 0(n) z niewielką stałą
przy n. Możemy też ewentualnie użyć sprytnej metody odwróconego licznika
binarnego o zamortyzowanym koszcie liniowym, opisanej w problemie 18-1).
Żeby zakończyć dowód faktu, że procedura ITERATJVE-FFT działa w czasie
0(nlgn), pokażemy, że oznaczona przez U.n) liczba przebiegów najgłębiej za-
gnieżdżonej pętli (wiersze 9-12) wynosi 0(nlgn). Mamy bowiem

lgn 2•· 1-1 n


L(n)- L L ,
~=l }=O 2

891
ROZDZIAŁ 32. WIELOMIANY I FFT

- 0(nlgn)

Równoległy układ obliczający FFT


Wiele spośród własności, które pozwoliły nam zaimplementować efektywny
iteracyjny algorytm FFT, możemy wykorzystać do stworzenia efektywnej rów-
noległej wersji tego algorytmu. (Opis modelu obliczeń zwanego układem aryt-
metycznym znajduje się w rozdz. 29). Układ PARALLEL-FFT, obliczający FFT
dla n danych wejściowych, jest pokazany na rys. 32.5 dla n = 8. Działanie
układu zaczyna się od wykonania permutacji danych wejściowych zgodnie
z porządkiem odwróconych bitów, po czym następuje lgn faz, z których każda
składa się z n/2 wykonywanych równolegle operacji motylkowych. Głębokość
układu wynosi zatem 0(1g n).
Fragment układu PARALLEL-FFT z lewej strony wykonuje permutację od-
wracającą bity, a reszta naśladuje sekwencyjną procedurę FFT-BASE. Korzys-
tamy z faktu, że w każdym przebiegu zewnętrznej pętli for jest wykonywanych

------
a ------
"

• - w"

w"
'
w'-
+

w'
' ·• Y,
~~--~
s=3
Rys. 32.5. Układ arytmetyczny PARALLEL-FFTobliczający FFT dla fi= 8 danych wejściowych. Ety-
kiety fa.z składających się z operacji motylkowych odpowiadają iteracjom pętli zewnętrznej w pro-
cedurze FFf -BASE.FFf dla fi danych wejściowych można obliczyć za pomocą układu o głęboko­
ści 0(1gn) zawierającego 0(fllgfl) bramek

892
PROBLEMY

n/2 niezależnych operacji motylkowych, które można wykonywać równolegle.


Wartość zmiennej s w każdej iteracji w procedurze FFT-BASE odpowiada jed-
nej fazie operacji motylkowych, pokazanej na rys. 32.5. W fazie s, dla s = 1, 2,
..., lgn, mamy n/2• grup operacji motylkowych (odpowiadających wszystkim
wartościom k w procedurze FFT-BASE), w każdej grupie po 2•- 1 operacji
(odpowiadających wszystkim wartościom jw procedurze FFT-BASE). Bramki
na rys. 32.5 odpowiadają operacjom motylkowym w najgłębiej zagnieżdżonej
pętli (wiersze 8-11 w procedurze FFT-BASE). Zauwaimy też, że wchodzące do
bramek wartości w odpowiadają używanym w procedurze FFT-BASE: w fazie
.
s uzywamy o Wm,
Wm, lłl/2-1
l ... , w,.. , gd ziem
. -- 2' .
ZADANIA
32.3-1. Prześledź działanie procedury lTERATIVE-FFT obliczającej DFT dla
wektora (O, 2, 3, -1, 4, 5, 7, 9).
32.3-2. Pokaż, jak zaimplementować algorytm FFT wykonujący permutację
odwracającą bity na końcu, a nie na początku obliczeń. (Wskazówka: Roz-
waż transformatę odwrotną do DFT).
32.3-3. Ilu operacji dodawania, odejmowania i mnożenia elementów i użycia
ilu przewodów wymaga opisany w niniejszym podrozdziale układ PARAL-
LEL-FFT obliczający DFT 11? (Zakładamy, że do przeniesienia liczby zjed-
nego miejsca w drugie potrzebny jest jeden przewód).
* 32.3-4. Przypuśćmy, ie układy obliczające sumę (sumatory) w obwodzie FFT
ulegają czasem uszkodzeniom polegającym na tym, że niezależnie od war-
tości wejściowych jako wynik produkują zero. Załóimy, że dokładnie je-
den sumator jest uszkodzony, ale nie wiemy który. Opisz, w jaki sposób
wykryć uszkodzony sumator, wprowadzając do układu odpowiednie dane
wejściowe i obserwując obliczone wyniki. Twoja metoda powinna być
możliwie efektywna.

Problemy
32-1. Mnożenie metodą „dziel i zwyciężaj"

(a) Pokaż, jak pomnożyć dwa liniowe wielomiany a.x + b i ex + d za pomo-


cą jedynie trzech mnożeń. (Wskazówka: Jednym z mnożeń jest (a+ b) ·
·(c+d)).
(b) Podaj dwa oparte na zasadzie „dziel i zwyciężaj" algorytmy mnożenia
dwóch wielomianów o ograniczeniu stopnia n działające w czasie 0(n 1' 3).
Pierwszy algorytm dzieli współczynniki wejściowego wielomianu na stojące
przy mniejszych i przy większych potęgach, a drugi dzieli je w zależności
od tego, czy potęga, przy której stoją, jest parzysta, czy nieparzysta.

893
ROZDZIAŁ 32. WIELOMIANY I FFT

(c) Pokaż, że dwie n-bitowe liczby całkowite można pomnożyć w O(n 1113 ) kro-
kach, przy czym w każdym kroku operujemy co najwyżej stałą liczbą bitów.

32-2. Macierze Toeplitza


Macierz Toeplitza n x n to macierz A = (a11) taka, że au= a1_ 1, 1_ 1 dla i= 2, 3,
..., n oraz)= 2, 3, ... , n.

(a) Czy suma dwóch macierzy Toeplitza musi być macierzą Toeplitza? A ilo-
czyn?
(b) Opisz, jak reprezentować macierze Toeplitza, żeby dwie macierze Toeplitza
n x n można było dodawać w czasie O(n).
(c) Podaj działający w czasie O(nlgn) algorytm mnożenia macierzy Toeplitza
n x n przez wek.tor długości n. Wykorzystaj reprezentację z punktu (b).
(d) Podaj efektywny algorytm mnożenia dwóch macierzy Toeplitza n x n
i oszacuj czas jego działania.

32-3. Ewaluacja wszystkich pochodnych wielomianu w punkcie


Pochodną rzędu t wielomianu A(x) o ograniczeniu stopnia n defmiujemy wzorem

A(x), jeśli t =o
A<tl(x)= ·f A<•-''(x), jeśli l~t~n-1

o, jeśli t ;;i: n

Mając daną reprezentację przez współczynniki (a0 , a 1 , a11_ 1 ) wielomianu


.•• ,
A(x) i punkt x 0 , chcemy wyznaczyć wartości A1tl(x 0 ) dla t = O, 1, ... , n- 1.

(a) Mając dane współczynniki b0 , b 1 , ... , b,,__1 tak.ie, że

·-'
A(x) - L bl(x - x 0j
j=O

pokaż,
jak obliczyć A(tl(x0 ), dla t = O, I, ..., n - 1, w czasie O(n),
(b) Opisz, jak znaleźć b 0 , b 1, •.. , b,,__1 w czasie O(nlgn), mając dane
A(x 0 +w:)dlak=0, 1, ... ,n-1.
(c) Udowodnij, że

A(x, + w!) - :L:(~r


:L:fv)g(r
-1))
gdzie /(J) - al ·j!, a

894
PROBLEMY

g(I) - {x,'/(
O,
-1)!, jeśli

jeśli
-(n-1)
1 ~/~(n-I)
~/~O

(d) Opisz, jak obliczyć A(x 0 + w~), dla k = O, 1, ..., n - l, w czasie O(nlgn).
Wyprowadź stąd wniosek, że ewaluacji wszystkich nietrywialnych pochod-
nych wielomianu A(x) w punkcie x 0 można dokonać w czasie O(nlgn).

32.4. Ewaluacja wielomianu w wielu punktach


Jak wspominaliśmy, problem ewaluacji wielomianu o ograniczeniu stopnia
n - 1 w jednym punkcie można rozwiązać w czasie O(n) za pomocą schematu
Hornera. Wykazaliśmy tak.że, że algorytmem FFT można dokonać ewaluacji
takiego wielomianu we wszystkich n zespolonych pierwiastkach z jedności
w czasie O(n lgn). Teraz pokażemy, jak obliczyć wartości wielomianu o ograni-
czeniu stopnia n w n dowolnych punktach w czasie O(nlg 2 n).
Skorzystamy w tym celu z faktu (który pozostawimy bez dowodu), że
wielomian będący resztą z dzielenia jednego wielomianu przez drugi można
znaleźć w czasie O(n lgn). Na przykład reszta z d1ielenia 3x 3 + x 2 - 3x + I
przez x 2 +x + 2 to

(3x 3 + x2 - 3x + 1) mod (x 2 + x + 2) = 5x - 3
n -- 1
Mając daną reprezentację przez współczynniki wielomianu A(x) = L a1 ~
1„ o
oraz n punktów x 0, x 1 , ... , xn-l• chcemy obliczyć n wartości A(x 0 ), A(x 1), ... ,
;
A(xn- 1 ). Dla O~ i~ j ~ n - l zdefiniujmy wielomiany Pi1(x) = fi (x - x 1)
l=i
oraz Q;1{x) = A(x) mod Pu(x). Zwróćmy uwagę, że ograniczenie stopnia Q1J.x)
jest nie większe niż j - i.

(a) Udowodnij, że A(x) mod (x - z) = A(z) dla dowolnego z.


(b) Udowodnij, że Q11 (x) = A(x 1) oraz że Q 0 ,n_ 1 (x) = A(x).
(c) Udowodnij, że dla i~ k ~j zachodzi Q11(x) = Q1i(x) mod Pił.(x) oraz
Q,1(x) - Q,;(x) mod P,1(x).
(d) Podaj działający w czasie O(nlg 2 n) algorytm obliczania A(x 0 ), A(x 1 ),
..., A(x" _ 1).

32-5. FFf w arytmetyce modularnej


Zdefiniowana przez nas dyskretna transformata Fouriera wymaga użycia liczb
zespolonych, co może prowadzić do utraty dokładności związanej z błędami
zaokrągleń. W niektórych problemach wiadomo, że wyniki będą składały
się wyłącznie z liczb całkowitych, przydałby się więc wariant algorytmu FFT
oparty na arytmetyce modularnej, dający gwarancję, że obliczony wynik jest

895
ROZDZIAŁ 32. WIELOMIANY I FFT

dokładny. Przykładem takiego problemu jest mnożenie dwóch wielomianów


o współczynnikach całkowitych. W zadaniu 32.2-6 przedstawiliśmy podejście
oparte na obliczeniach modulo liczba rozmiaru O:(n) w celu wyznaczenia DFT
w n punktach. W niniejszym problemie prezentujemy inne podejście, w którym
korzysta się z liczby bardziej praktycznego rozmiaru O(lgn); do jego zrozumie-
nia konieczne jest opanowanie materiału z rozdz. 33. Niech n będzie potęgą 2.

(a) Przypuśćmy, że szukamy najmniejszego k takiego, że p = kn + 1 jest liczbą


pierwszą. Podaj proste heurystyczne uz.asadnienie, dlaczego możemy ocze-
kiwać, że k wyniesie około lgn. (Wartość k może być znacznie większa lub
mniejsza, ale mamy podstawy spodziewać się przebadania średnio O(lgn)
kandydatów na liczbę k). Jak oczekiwany rozmiar liczby p ma się do
rozmiaru n?

Niech g będzie generatorem Z~, a w= ,t mod p.

(b) Uzasadnij, że DFT i odwrotne DFf są dobrze zdefiniowanymi, wzajemnie


odwrotnymi operacjami w Z", jeśli jako głównego pierwiastka n-tego stop-
nia z jedności użyjemy w.
(c) Uzasadnij, że FFT i przekształcenie odwrotne można obliczać w ZP w cza-
sie O(nlgn), jeśli operacje na liczbach rozmiaru O(lgn) są wykonywane
w czasie jednostkowym. Zakładamy, że algorytm zna wartości pi w.
(d) Oblicz DFT module p = 17 dla wektora (O, 5, 3, 7, 7, 2, 1, 6). Generatorem
z~.,
jest g = 3.

Uwagi do rozdziału
Dobry opis szybkiego przekształcenia Fouriera i jego zastosowań podają Press,
Plannery, Teukolsky i Vetterling [161, 162]. Znakomite wprowadzenie w zaga-
dnienie przetwarzania sygnałów, będące popularnym obszarem zastosowań
FFT, stanowi praca Oppenheima i Willsky'ego [153].
Cooley i Tukey [51] to nazwiska, z którymi powszechnie wiąże się wynale-
zienie FFT w latach sześćdziesiątych. W rzeczywistości algorytm FF'T był już
wcześniej wielokrotnie odkrywany, ale z jego znaczenia nie zdawano sobie
w pełni sprawy w epoce poprzedzającej powstanie nowoczesnych maszyn cy-
frowych. Press, Plannery, Teukolsky i Vetterling za autorów tej metody uwa-
żają Rungego i Kóniga (1924).
Rozdział 33

Algorytmyteorioliczbowe

Teorię liczb traktowano niegdyś jako piękny, ale kompletnie bezużyteczny dział
czystej matematyki. Obecnie algorytmy teorioliczbowe znajdują szerokie zasto-
sowanie dzięki wynalezieniu systemów kryptograficznych bazujących na dużych
liczbach pierwszych. Możliwość praktycznego stosowania tych systemów opiera
się na tym, że umiemy łatwo znajdować duże liczby pierwsze, natomiast ich
bezpieczeństwo wynika z tego, iż nie potraftmy rozłożyć na czynniki iloczynu
duZych liczb pierwszych. W tym rozdziale przedstawimy nieco wiadomości
z teorii liczb i algorytmów stanowiących podstawę takich zastosowań.
W podrozdziale 33.1 wprowadzimy podstawowe pojęcia teorii liczb, jak
podzielność, przystawanie module i jednoznaczność rozkładu na czynniki.
W podroMziale 33.2 omówimy jeden z najstarszych algorytmów świata: al-
gorytm Euklidesa obliczania największego wspólnego dzielnika dwóch liczb
całkowitych. W podrozdziale 33.3 przypomnimy podstawy arytmetyki modu-
larnej, a w podrozdziale 33.4 zajmiemy się zbiorem wielokrotności danej licz-
by a modulo n i pokażemy, jak znaleźć wszystkie rozwiązania równania
ax = b (mod n), korzystając z algorytmu Euklidesa. W podrozdziale 33.5
przedstawimy chińskie twierdzenie o resztach, a w podrozdziale 33.6 rozważy­
my potęgi danej liczby a modulo n i zaprezentujemy algorytm szybkiego potę­
gowania, służący do efektywnego obliczania a" mod n dla danych a, b i n.
Operacja ta jest podstawą efektywnego sprawdzania, czy dana liczba jest liczbą
pierwszą. W podrozdziale 33.7 opiszemy system RSA, czyli kryptosystem
z kluczem jawnym. Z kolei w podrozdziale 33.8 przedstawimy probabilistyczny
algorytm sprawdrania, czy dana liczba jest pierwsza, którego można użyć do
efektywnego znajdowania dużych liczb pierwszych - podstawowej operacji
przy tworzeniu kluczy dla systemu RSA. Wreszcie w podrozdziale 33.9 omówi-
my prostą, ale efektywną heurystykę rozkładania na czynniki niewielkich liczb
całkowitych. Ciekawostką jest fakt, że wolelibyśmy, żeby rozkład na czynniki

897
ROZDZIAŁ 33. ALGORYTMY TEORl0LICZB0WE

był problemem trudno rozwiązywalnym, ponieważ bezpieczeństwo szyfru RSA


opiera się na trudności rozkładania dużych liczb na czynniki pierwsze.

Rozmiar danych wejściowych i koszt obliczeń arytmetycznych


Ponieważ będziemy operować dużymi liczbami całkowitymi, powinniśmy sko-
rygować nasze mniemanie o rozmiarze danych wejściowych i o koszcie pod-
stawowych operacji arytmetycznych.
W tym rozdziale określenie „duże dane wejściowe" będzie oznaczać
zazwyczaj dane składające się raczej z „dużych liczb", a nie z „wielu liczb" fjak
przy sortowaniu). Będziemy zatem określać rozmiar danych liczbą bitów
potrzebnych do reprezentowania tych danych, a nie tylko liczbą liczb wcho-
dzących w ich skład. Algorytm., którego danymi wejściowymi są liczby cał­
kowite a 1 , a2 , ••• , at, jest algorytmem wielomianowym,jeśli działa w czasie
wielomianowym ze względu na lga 1 , lga 2 , ... , lgat, to znaczy w czasie wie-
lomianowym ze względu na długość jego zakodowanych binarnie danych
wejściowych.
W większej części tej książki wygodnie było nam traktować podstawowe
operacje arytmetyczne (mnożenie, dzielenie, obliczanie reszty) jak.o operacje
pierwotne, których wykonanie zajmuje jedną jednostkę czasu. Zliczając takie
operacje arytmetyczne wykonywane przez algorytm, mamy podstawę do sza-
cowania rzeczywistego czasu pracy algorytm.u na komputerze. Podstawowe
operacje mogą być jednak czasochłonne, jeśli argumenty, na których działają,
są duże. Wygodniej będzie zatem zliczać wykonywane przez algorytm. teorio-
liczbowy operacje na bitach. W modelu tym pomnożenie dwóch /I-bitowych
liczb całkowitych zwykłą metodą wymaga 0(P 2 ) operacji na bitach. Podobnie
operację dzielenia liczby /I-bitowej przez krótszą liczbę lub operację brania
reszty z liczby /I-bitowej z dzielenia przez krótszą liczbę można zrealizować za
pomocą prostego algorytmu w czasie 0(P 2 ). (Patrz zad. 33.1-11). Znane są
szybsze metody. Na przykład prosta metoda mnożenia dwóch fi-bitowych liczb
całkowitych, oparta na zasadzie „dziel i zwyciężaj", działa w czasie 0(fl 18• 3 ),
a najszybsza ze znanych metod - w czasie 0(P lg plg lg fl). Jednak dla celów
praktycznych algorytm 0(ft 2) jest często najlepszy i tego właśnie ograniczenia
będziemy używać jako podstawy naszych analiz.
W niniejszym rozdziale algorytmy analizujemy zazwyczaj zarówno ze
względu na liczbę wykonywanych przez nie operacji arytmetycznych, jak i ope-
racji na bitach.

33.1. Podstawowepojęcia teorii liczb


Niniejszy podrozdziałstanowi krótki przegląd pojęć elementarnej teorii liczb,
zajmującej się badaniem zbioru liczb całkowitych Z={ ..., -2, -1, O, 1, 2, ... }
oraz zbioru liczb naturalnych N= {O, 1, 2, ... }.
33.1. PODSTAWOWE POJĘCIA TEORII LICZB

Podzielność i dzielniki

Podzielność jednej liczby całkowitej przez drugą jest podstawowym pojęciem


w teorii liczb. Zapis d I a (czytaj: ,,liczba d dzieli liczbę a") oznacza, że a = kd
dla pewnej liczby całkowitej k. Każda liczba całkowita dzieli liczbę O. Jeśli
a> O i d\ a, to ]dl:s;;lal.Jeśli dl a, to mówimy też, że liczba a jest wielokrotno-
ścią liczby d. Jeśli d nie dzieli a, to piszemy d A'a.
Jeśli d Ia i d ~ O, to mówimy, że liczba d jest dzie]nikiem liczby a. Zauważ­
my, że d!a wtedy i tylko wtedy, gdy -dla, nie tracimy więc na ogólności,
definiując dzielniki jako liczby nieujemne, ale pamiętając przy tym, że dowolny
dzielnik liczby a wzięty ze znakiem minus także dzieli a. Dzielnik liczby cał­
kowitej a jest równy przynajmniej I, ale nie większy niż lal. Przykładowo,
dzielnikami liczby 24 są 1, 2, 3, 4, 6, 8, 12 i 24.
Każda liczba całkowita a jest podzielna przez dzielniki trywialne: 1 oraz a.
Nietrywialne dzielniki liczby a są także zwane czynnikami liczby a. Na przy-
kład czynnikami liczby 20 są: 2, 4, 5 i 10.

Liczby pierwsze i złożone


Liczbę całkowitą a> 1, której jedynymi dzielnikami są trywialne
dzielniki
1 i a, nazywamy liczbą pierwszą. Liczby pierwsze mają wiele szczególnych włas­
ności i odgrywają zasadniczą rolę w teorii liczb. Kilkanaście kolejnych począt­
kowych liczb pierwszych to

2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, ...

(Celem zad. 33.1-1 jest wykazanie, że liczb pierwszych jest nieskończenie wie-
le). Liczbę całkowitą a> I, która nie jest liczbą pierwszą, nazywamy liczbą
złożoną. Na przykład 39 jest liczbą złożoną, bo 3 l 39. Liczba 1 nie jest
ani liczbą pierwszą, ani złożoną, podobnie jak O i wszystkie ujemne liczby
całkowite.

Twierdzenie o dzieleniu z resztą, reszty i przystawanie modulo


Dla ustalonej liczby n zbiór liczb całkowitych można podzielić na wielokrotno-
ści n i liczby nie będące wielokrotnościami n. Duża część teorii liczb jest oparta
na uściślaniu tego podziału, polegającym na klasyfikowaniu liczb nie będących
wielokrotnościami n ze względu na ich reszty z dzielenia przez n. Poniższe
twierdzenie jest podstawą tego uściślenia. Dowód tego twierdzenia pominiemy
(patrz np. Niven i Zuckerman [151]).

899
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

TwlERDZENIE 33.1. (fwierdzenie o dzieleniu z resztą)


Dla dowolnej liczby całkowitej a i dowolnej dodatniej liczby całkowitej n is-
tnieją wyznaczone jednoznacznie liczby całkowite q i r takie, że O ~ r < n
oraz a = qn + r.

Wartość q = La/nJjest ilorazem dzielenia. Wartość r = a mod n jest resztą



z dzielenia. Relacja n Ia zachodzi wtedy i tylko wtedy, gdy a mod n= O. Wy-
nika stąd, że

a= La/njn + (a mod n) (33.1)


czyli
a mod n= a- La/njn (33.2)

Dysponując dobrze Mefiniowanym pojęciem reszty z dzielenia jednej licz-


by całkowitej przez drugą, wygodnie jest przyjąć specjalną notację dla oznacze-
nia równości reszt. Jeśli (a mod n)= (b mod n), to piszemy a= b (mod n)
i mówimy, że liczba a przystaje do liczby bmodulo n (albo: a jest kongruentne
z b). Innymi słowy, a~ b (mod n), jeśli liczby a i b dają tę samą resztę z dziele-
nia przez n. Równoważnie, a= b (mod n) wtedy i tylko wtedy, gdy n I(b - a).
Piszemy a, b (mod n), jeśli a nie przystaje do bmodulo n. Na przykład 61 = 6
(mod 11). Także -13 E 22 E 2 (mod 5).
Liczby całkowite można podzielić na n klas równoważności ze względu
na ich reszty mod.uto n. Klasa równoważności modulo n zawierająca liczbę
a to zbiór
[a],={a+kn:kEZ}
Na przykład [3]7 = {..., -11, -4, 3, 10, 17, ,.. }; inne oznaczenia tego samego
zbioru to [ -4] 7 i [10}7 • Zapis aE[b],. oznacza to samo co a= b (mod n), Zbiór
wszystkich takich klas równoważności to

z,= {[a],:O,; a,; n -1) (33.3)

Często można spotkać się z definicją

Z,.={0,l, ...,n-1} (33.4)

równoważną z definicją (33.3) w tym sensie, że O reprezentuje zbiór [O),.,1 re-


preuntuje [1],. itd.; każda klasa jest reprezentowana przez swój najmniejszy
nieujemny element. Należy jednak pamiętać, że pojedyncza liczba oznacza tu
całą klasę. Jeśli na przykład odwołujemy się do -1 jako do elementu Z,.,
chodzi nam o [n - 1],., ponieważ -1 - n - 1 (mod n).

900
33.1. PODSTAWOWEPOJĘCIA TEORII LICZB

Wspólnedzielniki i największy wspólny dzielnik


Jeśli d jest dzielnikiem a, ale także dzielnik.iem b, to d jest wspólnym dzielnikiem
a i b. Na przykład dzielnikami liczby 30 są: I, 2, 3, 5, 6, 10, 15 i 30, więc
wspólnymi dzielnikami liczb 24 i 30 są: I, 2, 3 i 6. Zauważmy, że 1 jest wspól-
nym dzielnikiem dowolnych dwóch liczb całkowitych.
Ważną własnością wspólnych dzielników jest to, że

jeśli dla i dlb, to dl(a + b)i dl(a-b) (33.5)


Ogólniej
jeśli dla i dlb, to dl(ax + by) (33.6)

dla dowolnych liczb całkowitych x i y. Oprócz tego, jeśli a Ib, to albo lal ~ Ibi,
albo b = O, skąd wynika, że
jeślialhibla,toa= +b (33.7)
Największy wspólny dzielnik. (NWDt) dwóch liczb całkowitych a i b, które
nie są jednocześnie równe O, to największy spośród wspólnych dzielników a i b;
zapisujemy go jako gcd(a, b). Na przykład gcd(24, 30) - 6, gcd(5, 7) - 1,
a gcd(O, 9) = 9. Jeśli żadna z liczb a, b nie jest zerem, to gcd(a, b) jest liczbą
całkowitą z przedziału od 1 do min(lal, Ibi). Definiujemy gcd(O, O)jako O; dzięki
temu standardowe własności funkcji gccl (takie jak poniższa równość (33.11))
są zawsze prawdziwe.
Oto podstawowe własności funkcji gcd:

gcd(a, b) - gcd(b, a) (33.8)

gcd(a, b) - gcd(-a, b) (33.9)

gcd(a, b) - gcd(lal, Ibi) (33.10)

gcd(a, O) - lal (33.11)

gcd(a, ka)- lal dla kimlego keZ (33.12)

TwIERDZENIE 33.2.
Jeśli a i h są dowolnymi liczbami całkowitymi,
nie równymi jednocześnie zeru,
to gcd(a, b) jest najmniejszym dodatnim elementem zbioru {ax + by: x, y EZ}
kombinacji liniowych a i b.

' Tutaj będrie stosowany skrót gcd pochodzący od ang. greatest common dh!isor (przyp.
tłum.).

901
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

DOWÓD
Niech s będzie taką najmniejszą dodatnią kombinacją liniową a i b, czyli niech
s = ax + by dla pewnych x, yeZ. Niech q = La/sj. Z równania (33.2) wynika
wówczas, że

amods=a-qs

=a- q(ax + by)


= a(l - qx) + b(-qy)
a więc a mods także jest kombinacją liniową a i b. Ponieważ jednak a mod
s < s, zatem musi być a mod s = O, bo sjest najmniejszą dodatnią kombinacją
liniową. Zatem s Ia i, analogicznie, s Ib, więc sjest wspólnym dzielnikiem a i b,
czyli gcd(a, b) ~ s. Z równania (33.6) wynika, że gcd(a, b)ls, ponieważ
gcd(a, b) dzieli zarówno a, jak i b, s zaś jest kombinacją liniową a i b. Z tego,
że gcd(a, b) 1si s > O, wynika, że gcd(a, b) ~ s. Skoro gcd(a, b) ~ s oraz
gcd(a, b) ~ s, to gcd(a, b) = s; liczba s jest największym wspólnym dzielni-
kiem a i b.

WNIOSEK33.3.
Dla dowolnych liczb całkowitych a i b, jeśli dl a i dl b, to dl gcd(a, b).

DOWÓD
Wniosek ten wynika z równania (33.6), ponieważ gcd(a, b) jest kombinacją
liniową a i b na mocy twierdzenia 33.2.


WNIOSEK33.4.
Dla dowolnych liczb całkowitych a i b oraz liczby naturalnej n zachodzi
zależność

gcd(an, bn) = n gcd(a, b)


DOWÓD
Jeślin = O, jest to oczywiste. Jeśli n > O, to gcd(an, bn) jest najmniejszym do-
datnim elementem zbioru {anx + bny}, który jest równy pomnożonemu przez
n najmniejszemu dodatniemu elementowi zbioru {ax + by}.

WNIOSEK33.5.
Dla dowolnych dodatnich liczb calk.owitych n, a i b, jeśli n Iab oraz
gcd(a, n) = I, to n Ib.

902
33.1. PODSTAWOWE POJĘCłATEORII LICZB

DOWÓD
Przeprowadzenie dowodu pozostawiamy czytelnikowi jak.o zad. 33.1-4.

Liczby względnie pierwsze
Dwie liczby całkowite a i b są względnie pierwsze, jeśli ich jedynym wspólnym
dzielnikiem jest 1, tzn. jeśli gcd(a, b) = I. Na przykład liczby 8 i 15 są względ­
nie pierwsze, ponieważ dzielnikami liczby 8 są: I, 2, 4 i 8, a dzielniki liczby 15
to: 1, 3, 5 i 15. Poniższe twierdzenie mówi, że jeśli dwie liczby są względnie
pierwsze z trzecią liczbą p, to ich iloczyn jest także względnie pierwszy z p.

TwIERDZENIE 33.6.
Dla dowolnych liczb całkowitych a, bip, jeśli gcd(a, p) = 1 i gcd(b, p) = 1, to
gcd(ab, p) - I.

DOWÓD
Z twierdzenia 33.2 wynika, że istnieją liczby x, y, x' i y' takie, że

ax+py= 1
bx' + py' =1
Wymnażając te równania, po przekształceniu otrzymujemy
ab(xx') + p(ybx' + y'ax + pyy') - I
Liczba 1 jest więc dodatnią kombinacją liniową ab i p, zatem odwołanie do
twierdzenia 33.2 kończy dowód.

Mówimy, że liczby n 1 , n 2 , ... , n1 są parami względnie pierwsze,jeśli dla i cl j
mamy gcd(n;, ni)= 1.

Jednoznaczność rozkładu

Oto elementarny, ale ważny fakt dotyczący podzielności przez liczby pierwsze.

TwIERDZENIE 33. 7,
Dla dowolnej liczby pierwszej p i dowolnych liczb a, b, jeśli p Iab, to p Ia
lubpjb.

DOWÓD
Przypuśćmy przeciwnie, że p Iab, ale p A'a i p A'b. Zatem gcd(a, p) = I
i gcd(b, p) = 1, ponieważ jedynymi dzielnikami p są I i p, a z założenia pnie

903
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

dzieli a ani b. Z twierdzenia 33.6 wynika teraz jednak, że gcd(ab, p) = 1, co


przeczy naszemu założeniu, że p Iab, bo jeśli p Iab, to gcd(ab, p) = p. Sprzecz-
ność ta kończy dowód.


Konsekwencją twierdzenia 33.7 jest to, że każda liczba całkowita ma jed-
noznaczny rozkład na czynniki pierwsze.

TwlERDZENIE 33.8. (O jednoznaczności rozkładu)


Każdą dodatnią liczbę całkowitą a można na dokładnie jeden sposób zapisać
w postaci iloczynu
a=pi'Pi' ... p~·
gdzie p 1 są liczbami pierwszymi, p 1 < p 2 < ... < Pr, a e; są dodatnimi liczbami
całkowitymi.

DOWÓD
Przeprowadzenie dowodu pozostawiamy czytelnikowi jako zad. 33.1-10.

Na przykład liczbę 6000 można jednoznacznie zapisać jako 24 · 3 · 53 .

ZADANIA
33.1-1. Udowodnij, że istnieje nieskończenie wiele liczb pierwszych. (Wska-
zówka: Wykaż, że żadna z liczb pierwszych p 1 , p 2 , •••, Pt nie dzieli
{piJl, ...p,) + I).
33.1-2. Udowodnij, że jeśli alb i ble, to ale.
33.1-3. Udowodnij, że jeśli p jest liczbą pierwszą i O < k < p, to gcd(k, p) = 1.
33.1-4. Udowodnij wniosek 33.5.

33.1-5. Udowodnij, że jeśli p jest liczbą pierwszą i O < k < p, to p I(~)· Wy-
wnioskuj stąd, że dla dowolnych a, b oraz liczby pierwszej p zachodzi
zależność

(a + b)' = a'+ b' (mod p)


33.1-6, Udowodnij, że jeśli ai b są takie, że alb i b > O, to
(xmod b) mod a= xmod a
dla dowolnego x. Udowodnij, przy tych samych założeniach, że

jeśli x =y (mod b), to x =y (mod a)


dla dowolnych liczb x i y.

904
33.2. NAJWIĘKS2Y WSPÓLNY DZIELNIK

33.1-7. Dla dowolnej liczby całkowitej k >Omówimy, że liczba całkowita n


jest k-tą potęgą, jeśli istnieje liczba całkowita a taka, że tł-= n. Mówimy,
że n > 1 jest nietrywialną potęgą, jeśli jest k-tą potęgą dla pewnego k > l.
Opisz, jak w czasie wielomianowym ze względu na p sprawdzać, czy dana
p-bitowa liczba całkowita n jest nietrywialną potęgą.
33.1-8. Udowodnij równości (33.8)-(33.12).
33.1-9. Wykaż, że operacja gcd jest łączna, tzn. że dla dowolnych liczb cał­
kowitych a, b i c zachodzi zależność

gcd(a, gcd(b, c)) - gcd(gcd(a, b), c)

* 33.1-10. Udowodnij twierdzenie 33.8.


33.1-11. Podaj efektywne algorytmy dzielenia P-bitowej liczby całkowitej przez
mniejszą liczbę oraz brania reszty z dzielenia P-bitowej liczby całkowitej
przez mniejszą liczbę. Twoje algorytmy powinny działać w czasie O(P 2}.
33.1-12. Podaj efektywny algorytm konwersji danej P-bitowej (w zapisie binar-
nym} liczby całkowitej do reprezentacji dziesiętnej. Uzasadnij, że jeśli
mnożenie lub dzielenie liczb całkowitych długości co najwyżej P zajmuje
czas M(P}, to konwersję z postaci binarnej do dziesiętnej można wykonać
w czasie 0(M(P}lgP}. (Wskazówka: Wykorzystaj zasadę „dziel i zwycię­
żaj", obliczając lewą i prawą połowę wyniku w osobnych wywołaniach
rekurencyjnych}.

33.2. Największy wspólny dzielnik


W tym podrozdziale przedstawiamy algorytm Euklidesa, służący do efektyw-
nego oblicunia największego wspólnego dzielnika dwóch liczb całkowitych.
Analiza czasu działania ujawnia zadziwiający związek z liczbami Fibonacciego,
stanowiącymi najgorszy przypadek danych wejściowych dla tego algorytmu.
Nasze rozważania ograniczymy tutaj do liczb nieujemnych. Możemy tak
postąpić ze względu na równanie (33.10), mówiące, że gcd(a, b)- gcd(lal, Ibi}.
W zasadzie moglibyśmy obliczać gcd(a, b) dla dodatnich liczb a i b z ich
rozkładu na czynniki pierwsze. W istocie, jeśli

a - p'•p''
l 2 .. • p'•
r (33.13)

(33.14)

gdzie niektóre wykła-Oniki są zerami, żeby w rozkładzie a i b występowały te


same liczby pierwsze p 1 , p 2 , ••• , P,, to

gcd(a, b) = pfn(e,,/,J pf°(e,,/,) ... p~(e,./,) (33.15)

905
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBQWE

Jak okaże się w podrozdz. 33.9, najlepsze znane algorytmy rozkładu na czyn-
niki nie działają w czasie wielomianowym. Takie podejście do problemu ob-
liczania największych wspólnych dzielników nie wydaje się więc prowadzić do
efektywnego algorytmu.
Algorytm Euklidesa obliczania największego wspólnego dzielnik.a opiera
się na następującym twierdzeniu.

TwIERDZENIE 33.9. (Wzór rekurencyjny na największy wspólny dzielnik.)


Dla dowolnej nieujemnej liczby całkowitej a i liczby dodatniej b zachodzi
zależność

gcd(a, b) = gcd(b, a mod b)

Dowon
Pokażemy, że gcd(a, b) i gcd(b, a mod b) dzielą się nawzajem, więc na mocy
równania (33.7) liczby te muszą być równe (poniewai obydwie są nieujemne).
Najpierw pokażemy, że gcd(a, b) Igcd(b, a mod b). Jefili d = gcd(a, b), to
dla i dlb. Na mocy równania (33.2) mamy (a mod b) = a - qb, gdzie
q = La/bJ. Skoro więc (a mod b) jest kombinacją liniową a i b, z równania
(33.6) wynika, że dl (a mod b). Zatem, poniewai dl bi dl (a mod b), z wniosku
33.3 wynika, że dl gcd(b, a mod b) lub równoważnie

gcd(a, b) Igcd(b, a mod b) (33.16)

Dowód, że gcd(b, a mod b)) gcd(a, b) jest prawie identyczny. Jeśli teraz
d = gcd(b, a mod b), to dl b i dl (a mod b). Ponieważ a= qb + (a mod b),
gdzie ą = La/hJ,więc a jest kombinacją liniową bi (a mod b). Z równania
(33.6) wnioskujemy, że dl a. Paniewa.i dl b i dl a, więc na mocy wniosku 33.3
dl gcd(a, b) lub równoważnie

gcd(b, a mod b) I gcd(a, b) (33.17)

Zestawienie równań (33.16) i (33.17) i skorzystanie z równania (33.7) kończy


dowód.

AlgorytmEuklidesa
Poniższy algorytm obliczania największego wspólnego dzielnika został opisany
w Elementach Euklidesa, około roku 300 p.n.e., chociai jest być może jeszcze
starszy. Zapisany jest jako procedura rekurencyjna, oparta bezpośrednio na
twierdzeniu 33.9. Dane wejściowe a i b są dowolnymi nieujemnymi liczbami
całkowitymi.

906
33.2. NAJWIĘKSZV WSPÓLNY DZIELNIK

EUCLlD(a, b)
I Hb=O
2 tb.en return a
3 else return EUCLID(b, a mod b)

Jako przykład działania algorytmu Eucun rozważmy obliczenie gcd.(30, 21 ):

EUCL1D(30,21) = EUCL1D(2l, 9)
= EUCLID(9, 3)
= EUCLID(3,O)
=3

W obliczeniu tym mamy trzy rekurencyjne wywołania procedury Eucun.


Poprawność algorytmu EUCLID wynika z twierdzenia 33.9 i z faktu, że
jeśli algorytm zwraca wartość a w wierszu 2, to b = O, więc z równania
(33.11) wynika, że gcd(a, b) = gcd(a, O)= a. Ciąg wywalań rekurencyjnych
nie może być nieskończony, gdyż w każdym wywołaniu 1lllniejsza się wartość
drugiego argumentu. A zatem procedura EUCLID zawsze się kończy i oblicza
poprawny wynik.

Czasdziałania algorytmu Euklidesa


Zanalizujemy czas działania algorytmu EUCLID w najgorszym przypadku
jako funkcję długości liczb a i b. Nie tracąc wiele na ogólności, zakładamy,
że a > b ~ O. Założenie to uzasadnia obserwacja, że jeśli b > a ~ O, to
EUCLID(a, b) od razu rekurencyjnie wywołuje Eucun(b, a). Jeśli więc pierw-
szy argument jest mniejszy niż drugi, algorytm wykonuje jedno wywołanie
rekurencyjne, zamieniając swoje argumenty, i kontynuuje pracę. Podobnie,
jeśli b = a > O, procedura kończy działanie po jednym wywołaniu rekurencyj-
nym, ponieważ a mod b = O.
Całkowity czas działania algorytmu EUCLIDjest proporcjonalny do liczby
wykonywanych przez algorytm wywołań rekurencyjnych. W naszej analizie
będziemy korzystać z liczb Fibonacciego Ft, zdefiniowanych rekurencyjnym
wzorem (2.13).

LEMAT 33,10,
Jeślia > b ~ O i wywołanie EUCLID(a, b) prowadzi dok ~ 1 wywalań rekuren-
cyjnych, to a~ F1 + 2 i b ~ F 1 +i·

DOWÓD
Dowód przebiega przez indukcję względem k. W celu udowodnienia kroku
podstawowego indukcji przyjmijmy k = 1. Wówczas b ~ I = F 2 , a skoro

907
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

a > b, musi być a~ 2 = F 3 • Ponieważ


b > (a mod b), w każdym wywołaniu
rekurencyjnym pierwszy argument jest ostro większy niż drugi; założenie, że
a> b jest więc 7.achowane w każdym wywołaniu rekurencyjnym.
Przyjmijmy założenie indukcyjne, że lemat jest prawdziwy, jeśli wykonuje
się k - I wywołań rekwencyjnych; pokażemy, że zachodzi on także dla k wy-
wołań. Ponieważ k > O, mamy b > O, więc EUCLID(a, b) wywołuje rekurencyj·
nie EUCLID(b, a mod b), co z kolei prowadzi do k - I wywołań rekurencyj.
nych. Z założenia indukcyjnego wynika, że b ~ Fk+t (co dowodzi części tez~
lematu) i że (a mod b) ~ Fk. Mamy

b + (a mod b) -b + (a - La/b)Jb)

ponieważ skoro a> b > O, to La/bj ~ 1. Stąd

a;,b+(amodb)

Natychmiastowym wnioskiem z tego lematu jest poniższe twierdzenie.

TwIERDZENIE 33.11. (fwierdzenie Lamego)


Dla dowolnej liczby całkowitej k ~ 1, jeśli a> b ~ O oraz b < Fk+l• to wyko·
nanie EUCLID(a, b) powoduje mniej niż k wywołań rekwencyjnych.


Można pokazać, że górne ograniczenie z twierdzenia 33.11 jest najlepszym
możliwym os7.acowaniem. Najgorsze dane wejściowe dla algorytmu EUCLID
stanowią kolejne liczby Fibonacciego. Ponieważ przy obliczaniu Eucuo~
(F 3 , F 2 ) wykonuje się dokładnie jedno wywołanie rekwencyjne, a dla k ~ 2
zachodzi Fk+1 mod Fk = Fk- l• więc mamy

gcd(Fk+1 , Ft) = gcd(Ft, (Ft+1 mod Ft))

- gcd(F,, F,_ ,)

Zatem przy obliczaniu EUCLID(Ft+l• Ft) wykonuje się dokładnie k-1 wywo-
łań- tyle, ile wynosi górne ograniczenie z twierdzenia 33.11.
Ponieważ Fk to w przybliżeniu q,•'jJS,gdzie tp to „złota proporcja"
(I + J5)/2, zdefmiowana równaniem (2.14), liczba wywołań rekurencyjnych
w algorytmie EUCLID wynosi O(lg b). (Patrz zad. 33.2-5, aby otrzymać do-

908
33.2. NAJWIĘKSZV WSPÓLNY DZIELNIK

kladniejsze oszacowanie). Wynika stąd, że algorytm Eucun zastosowany do


dwóch liczb /I-bitowych wykona O(P) operacji arytmetycmych i O(P 3) operacji
na bitach (przy założeniu, że do mnożenia i dzielenia liczb /I-bitowych potrzeba
O(fl 2 ) operacji na bitach). W problemie 33.2 należy wykazać ograniczenie licz-
by operacji na bitach równe O(P 2 ).

Rozszerzonyalgorytm Euklidesa
Zmodyftk.ujemy teraz algorytm Euklidesa tak, żeby obliczał dodatkowo pewne
użyteczne informacje. Konkretnie, rozszerzymy go w tak.i sposób, żeby obliczał
całkowitoliczbowe współczynniki x i y tak.ie, że

d- gcd(a, b)- ax + by (33.18)

Zauważmy, że x iy mogą być


równe O lub ujemne. Współczynniki te przyda-
dzą się nam później do obliczania odwrotności modulo. Dane wejściowe dla
procedury EXTENDED-EUCLIDstanowi dowolna para liczb całkowitych,
a zwraca ona trójkę liczb (d, x, y) spełniającą równanie (33.18).

EXTENDED-EUCLID(a,b)
I ifb-0
2 then return (a, I, O)
3 (d', x', y') .- EXTENDED-EUCLID(b, a mod b)
4 (d, x, y) ~ (d', y', x' - La/bjy')
5 return (d, x, y)

Rysunek 33.1 ilustruje działanie procedury EXTENDED-EUCLID obliczają­


cej gcd(99, 78).
Procedura EXTENDED-EUCLIDjest rozszerzeniem procedury Eucuo.
Wiersz 1 odpowiada testowi „b = O" w wierszu 1 procedury Eucuo. Jeśli b = O,
a h La/hJ d X y
99 78 I 3 - li 14
78 21 3 3 3 - li
21 15 I 3 -2 3
15 6 2 3 I -2
6 3 2 3 o I
3 o 3 I o
Rys. 33.1. procedury ExTI!NDED-EUCLID
Przykład działania dla danych wejściowych 99 i 78. Każdy
wiersz odpowiada jednemu poziomowi rekursji i zawiera: wejściowe wartości a i b, obliczaną wartość
La/bJoraz zwracane wartości d, xi y. Zwracana trójka (d, x, y) staje się trójką (d', x',y') używaną do
obliczeń na wyższym poziomierek:ursji. W wyniku wywołania ElcrENDED-Eua.m(99, 78) otrzymuje-
my (3, -11, 14), zatem gcd(99, 78)=3 i gcd(99, 78)= 3 =99·(-11) +78·14

909
ROZDZIAŁ 33. ALGORYTMY TEORłOLICZBOWE

to ExrENDED-EUCLID w wierszu 2 zwraca nie tylko d = a, lecz także współ­


czynniki x = 1 oraz y = O, takie że a = ax + by. Jeśli b-# O, EXTENDED-
-Eucun oblicza najpierw trójkę (d', x', y') taką, że d' = gcd(b, a mod b) oraz

d' = bx' + (a mod b)y' (33.19)

Tak jak w procedurze Eucun, w tym przypadku d = gcd(a, b) = d' = gcd(b,


a mod b). Żeby znaleźć x i y takie, że d = ax + by, przepiszemy równanie
(33.19), korzystając z tego, że d = d' i z rówoania (33.2):

d = bx' + (a - La/bJb)y'
= ay' + b{x' - La/bjy')

Jeśli zatem weźmiemy x = y' i y = x' - La/bjy', równanie d = ax + by będzie


spełnione, co dowodzi poprawności procedury BXTENDED-EUCLID.
Ponieważ liczba wywołań rekurencyjnych wykonywanych przez procedury
EUCLID i EXTENDED-EUCLID jest identyczna, czasy działania tych procedur są
takie same, z dokładnością do stałego czynnika. Jeśli a> b > O, to liczba wy-
wołań rekurencyjnych wynosi O(lgb).

ZADANIA

33.2-1. Udowodnij, że z równań (33.13}-{33.14)wynika równanie (33.15).


33.2-2. Znajdź wartości (d, x, y) obliczone w wywołaniu ExTENDED-
-EUCL1D(899,493).
33.2-3. Udowodnij, że dla dowolnych liczb całkowitych a, k i n zachodzi
zależność

gcd(a, n)= gcd(a + kn, n)


33.2-4. Zapisz procedurę EUCLID w postaci iteracyjnej, używającej jedynie sta-
łej ilości pamięci (tzn. przechowującej jedynie stalą liczbę wartości całko­
witoliczbowych).
33.2-5. Przy założeniu, że a> b ~ O, wykaż, iż obliczanie EUCLID(a, b) prowa-
dzi do co najwyżej 1 + log,b wywołań rekurencyjnych. Popraw to oszaco-
wanie do 1 + log,(b/gcd(a, b)).
33.2-6. Co otrzymamy w wyniku wywołania EXTENDED-EUCLID(F.1;+ 1, FJ?
Uzasadnij poprawność swojej odpowiedzi.
33.2-7. Sprawdź poprawność wyniku (d, x, y) działania procedury EXTEN-
DED-EUCLID(a, b), wykazując, że jeśli dl a, dl b i d = ax + by, to
d = gcd(a, b).
33.2-8• .zdefiniujmy funkcję gcd dla więcej niż dwóch argumentów za pomocą
równania rekurencyjnego gcd(a 0 , a 1 , ••• ,a,.)= gcd(a0 , gcd(a 1 , ••• , a 11)). Wy~

910
33.3. ARYTMETYKA MODULARNA

każ, żefunkcja gcd daje ten sam wynik niezale-1:nieod kolejności podania
jej argumentów. Opisz, jak znalei.ć x 0 , x 1 , ... , xft takie, że gcd(a 0 , a 1 , ... ,
a,.)= a0 x 0 + a 1x 1 + ...+ a,.x". Wykaż, że liczba dzieleń wykonywanych
przez Twój algorytm to O(n + lg(max a 1)).
'
33.2-9. Zdefmiujmy lcm(a 1 , a 2 , .•. , an) jako najmniejszą wspólną wielokrotność
liczb całkowitych a 1 , a 2 , .•. , an, tzn. najmniejszą nieujemną liczbę całkowi­
tą, będącą wielokrotnością każdej spośród liczb a1• Pokaż, jak efektywnie
obliczać lcm(a 1 , a 2 , .•• , an), korzystając z (dwuargumentowej) operacji gcd
jako procedury pomocniczej.
33.2-10. Udowodnij, że liczby n 1 , n2 , n 3 i n4 są parami względnie pierwsze
wtedy i tylko wtedy, gdy gcd(n 1 n 2 , n 3 n4 ) = gcd(n 1n 3 , n2nJ = 1. Ogólniej,
wykaż, że liczby n 1 , n2 , ••• , n" są parami względnie pierwsze wtedy i tylko
wtedy, gdy pewnych llgkl par liczb będących iloczynami liczb n1 jest
względnie pierwszych.

33.3. Arytmetykamodularna
Nieformalnie możemy myśleć o arytmetyce modularnej jak o zwykłej arytme-
tyce liczb całkowitych, z tą różnicą, że ponieważ nasze obliczenia prowadzimy
modulo n, każdy otrzymywany wynik zastępujemy elementem zbioru {O,1, ... ,
n- 1} przystającym do x modulo n (tzn. x zastępujemy przez x mod n). Ten
nieformalny model wystarcza nam, jeśli ograniczamy się do operacji dodawa-
nia, odejmowania i mnożenia. Bardziej formalny model arytmetyki modular-
nej, który teraz przedstawimy, najlepiej opisywać w ,języku" teorii grup.

Grupy skończone

Grupa (S, EB)to zbiór S wraz ze zdefiniowaną w S dwuargumentową operacją


EB o następujących własnościach.

1. Domkniętość: Dla dowolnych a, be S element a EBbe S.


2. Element neutralny: Istnieje element ee S taki, że e EBa = a EBe = a dla do-
wolnego aeS.
3. Łączność: Dla dowolnych a, b, ceS zachodzi (a EBb) EBc = a EB(b EBc).
4. Element odwrotny: Dla kazdego aeS istnieje dokładnie jeden element beS
taki, że a EBb = b 9 a = e.

Jako przykład rozważmy znaną nam już grupę (Z, +) liczb całkowitych
Z z działaniem dodawania: O jest elementem neutralnym, zaś elementem od-
wrotnym do elementu a jest -a. Jeśli w grupie (S, EB)jest spełnione prawo

911
ROZDZIAŁ 33. ALGORYTMY TE0Rl0LICZB0WE

aEBb = bEBa dla dowolnych a, beS, to jest ona grupą prze-


Ji1:ze1oienności
mienną (abelową). Jeśli grupa (S, EB) spełnia nierówność ISI < oo, to nazywa-
my ją grupą skończoną,

Grupy definiowane za pomocą dodawania i mnożenia


modularnego
Możemy zdefmiować dwie skończone grupy przemienne za pomocą dodawa-
nia i mnożenia modulo n, gdzie n jest dodatnią liczbą całkowitą. Elementy tych
grup to klasy równoważności liczb całkowitych modulo n, zdefmiowane
w podrozdz. 33.1.
Żeby zdefiniować grupę na zbiorze Z", potrzebujemy odpowiedniej dwuar-
gumentowej operacji, którą otrzymujemy, przedefiniowując zwykłe operacje
dodawania i mnożenia. Latwo zdefiniować dodawanie i mnożenie w Z", po-
nieważ klasy równoważności dwóch liczb całkowitych jednoznacznie wyzna-
czają klasę równoważności sumy i iloczynu tych liczb, tzn. jeśli a= a' (mod n)
i b = b' (mod n), to

a+ b = a' + b' (mod n)

ab - a'b' (mod n)

Definiujemy zatem dodawanie i mnożenie modulo n, oznaczane +" i ·11,


w następujący sposób:

[a], +, [b], - [a+ b],


[a], ·, [b], - [ab],

(Odejmowanie w Z 11można zdefiniować podobnie wzorem [0] 11- " [b]11=


= [a - b]", ale - jak się przekonamy - problem dzielenia jest bardziej skom-
plikowany). Fakty te usprawiedliwiają powszechną i wygodną praktykę uży­
wania przy obliczeniach w Z„ jako reprezentanta klasy równoważności jej naj-
mniejszego nieujemnego elementu. Dodawanie, odejmowanie i mnożenie wy-
konuje się w zwykły sposób na reprezentantach, ale każdy wynik działania
x zastępuje się reprezentantem jego klasy (tzn. liczbą x mod n).
Korzystając z powyższej definicji dodawania modulo n, definiujemy grupę
addytywną modulo n jako (Z 11, +.,). Rozmiar tej grupy to IZ"I = n. Rysu-
nek 33.2a zawiera tabelę działania w grupie (Z 6 , +6 ).

Tw!ERDZENIE33.12.
System (Z,., +.,) jest skończoną grupą przemienną.

912
33.3. ARYTMETYKA MODULARNA

DOWÓD
Łączność i przemienność operacji + 11 wynikają z łączności i przemienności
operacji +:

Ua}, +, [b},) +, [c], - [(a+ b) + c],

- [a + (b + c)],
- [a],+, Ub],+, [c],)

[a], +, [b], - [a+ b].

-[b + al,,
- [b], +" [a],

+, o I 2 3 4 5 ,, I 2 4 7
--··-
8 II
...·-- ------ .
13 14
o •o I 2 3 4 5 I I 2 4 7 8 II 13 14
I - I 2 3 4 5 o 2 2 4 8 14 I 7 I I 13
2 : 2 3 4 5 o I 4 4 8 13I 2 14 7 II
3 i 3 4 5 o I 2 7 7 14 13 4 11 2 I 8
4 :4 5 o I 2 3 8 8 I 2 II 4 13 14 7
5 o I 2 3 4 Il Il 7 14 2 13 I 8 4
I' 13 13 11 7 I 14
14 14 13 Il 8 7 '
4
4
2
2
I
(a) (b)

Rys. 33.2. Dwie grupy skończone. Klasy równoważności są oznaczone przez reprezentujące je ele-
menty. (a) Grupa (Z 6 , + 6 ). (b) Grupa (Z~~· ·1 ,)

Elementem neutralnym w (Z 11, +11 ) jest O (tzn. [0]11 ). Elementem odwrot-


nym (względem dodawania) do elementu a (tzn. [aJ11 )jest -a (tzn. [-a] 11 albo
[n - a],), ponieważ [a], +, [ - a], - [a - a], - [O],.

Korzystając z definicji mnożenia modulo n, defmiujemy grupę multyplika-
tywną modulo n jako (z:, ·
11). Elementy tej grupy to zbiór tych elemen- z:
tów Z 11, które są względnie pierwsze z n:

z; - {[a],e Z,: gcd(a, n) - I}

żeby sprawdzić, że zbiór z:jest


dobrze zdefiniowany, zauważmy, że dla
O :s;;a < n zachodzi a= (a + kn) (mod n) dla dowolnej liczby całkowitej k.

913
ROZDZIAŁ 33. ALGORYTMY TEOR!OL!CZBOWE

Zatem - zgodnie z zad. 33.2-3 - z tego, że gcd.(a, n) = I, wynika, że gcd(a + kn,


n)= 1 dla dowolnej liczby całkowitej k, Ponieważ [a]11 = {a+kn:keZ},
zbiór z:
jest dobrze ulefiniowany. Przykładem takiej grupy jest

z;,- {I, 2, 4, 7, 8, Jl, 13, 14}

gdzie działaniem grupowym jest mnożenie modulo 15. (Element [a]15 oznacza-
my tu jako a). Na rysunku 33.2b jest przedstawiona grupa (Z~s, ·15 ). Na
przykład 8 · 11 = 13 (mod 15). Elementem neutralnym w tej grupie jest l.

TWIERDZENIE 33.13.
System (Z:, ·11) jest skończoną. grupą przemienną.

DOWÓD
Z twierdzenia 33.6 wynika, że zbiór z:
jest zamknięty ze względu na opera-
cję ·11 • Łączność i przemienność ·11 można udowodnić tak jak dla + 11 wdowo-
dzie twierdzenia 33.12. Elementem neutralnym jest [1}11• W celu wykazania
istnienia elementu odwrotnego weźmy dowolny element a zbioru z:
i niech
(d, x, y) będzie wynikiem wywołania procedury ExTENDEO-EUCLID(a, n).
Wówczas d = 1, gdyż a Ez:,oraz
ax+ny= l
lub równoważnie

ax = 1 (mod n)
Liczba [x]11 jest zatem odwrotnością [a]11 ze względu na mnożenie modulo n.
Dowód, że elementy odwrotne są wyznaczone jednoznacznie, odłożymy do
wniosku 33.26.

W dalszej części tego rozdziału, zajmując się grupami (Z 11, +11) i (Z 11, •11),
będziemy stosowali dogodną praktykę oznaczania klas równoważności przez
reprezentujące je elementy oraz zapisywania operacji + 11 i ·11 za pomocą zwykłej
arytmetycznej notacji, odpowiednio + i · (lub po prostu zapisywania czynni-
ków iloczynu koło siebie). Przystawanie modulo n można także interpretować
jako równość w Z 11• Na przykład poniższe dwa zapisy są równoważne:

ax = b (mod n)

[a],·, [x], - [b],


W ramach jeszcze dalej idącego uproszczenia oznaczeń będziemy czasem
odwoływać się do grupy (S, EB), pisząc po prostu S, kiedy działanie grupowe

914
33.3. ARYTMETYKA MODULARNA

będzie wynikało z kontekstu. Możemy zatem odwoływać się do grup (Zn, +


11
)

i (z:, ·,Jodpowiednio jako do z" i z:.


Odwrotność (względem mnożenia) elementu a oznacz.amy jako (a- 1
mod n). Dzielenie w z:
jest zdefiniowane równaniem a/b - ab- 1 (mod n). Na
przykład w z~~ mamy 7- 1 SE 13 (mod 15), bo 7· 13 = 91 -1 (mod 15), zatem
4/7 = 4·
13 - 7 (mod 15).
Rozmiar grupy z:
oznaczamy symbolem q,(n). Funkcja ta, zwana funkcją
Eulera, spełnia równanie

(33.20)

gdzie p przebiega wszystkie liczby pierwsze dzielące n (włącznie z samym n, jeśli


n jest liczbą pierwszą). Nie będziemy tutaj dowodzić tego wzoru. Intuicyjnie
można go wytłumaczyć następująco: zaczynamy od listy n reszt {O, 1, ...,
n - 1}, a następnie dla każdej licz6y pierwszej p dzielącej n wykreślamy z tej
listy wszystkie wielokrotności p. Jeśli na przykład dzielnikami pierwszymi licz-
by 45 są 3 i 5, to

q,(45) - 45 ( 1 - !)( !)1-

Jeśli p jest liczbą pierwszą, to Z~ = {I, 2, ... , p - 1} i


q,(p) - p - 1 (33.21)
Jeśli n jest liczbą złożoną, to q,(n) < n - 1.

Podgrupy
Jeśli (S, EB)jest grupą, S' c S i (S', EB)także jest grupą, to (S', El))nazywamy
podgrupą (S, ffi). Liczby parzyste na przykład tworzą podgrupę grupy liczb
całkowitych z operacją dodawania. Poniższe twierdzenie stanowi skuteczne
narzędzie rozpoznawania podgrup.

TwIERDZENIE 33.14. (Zamknięty podzbiór grupy skończonej jest podgrupą)


Jeśli (S, (ł)) jest grupą skończoną, a S' jest podzbiorem S takim, że a ffi be S'
dla dowolnych a, beS', to (S', (!))jest podgrupą (S, EB).

915
ROZDZIAŁ 33. ALGORYTMY TE0Rl0LJCZB0WE

DOWÓD
Przeprowadzenie dowodu pozostawiamy czytelnikowi jako zad. 33.3-2.

Na przykład zbiór {O,2, 4, 6} tworzy podgrupę Z 8 , ponieważ jest nmknię­
ty ze względu na operację + (a ściślej +8 ).
Poniższe bardzo pożyteczne twierdzenie mówi o warunku, jaki musi speł­
niać rozmiar podgrupy.

TWIERDZENIE33.15. (Twierdzenie Lagrange'a)


Jeśli (S, EB)jest grupą skończoną, a (S', EB)jest podgrupą (S, EB), to IS'I jest
dzielnikiem 1s1.

Podgrupę
S' grupy S nazywamy podgrupą właściwą, jeśli S' =I-S. Z poniż­
szego wniosku skorzystamy w podro:zdz. 33.8 przy analizie algorytmu Mille-
ra-Rabina służącego do sprawdzania, czy liczba jest liczbą pierwszą.

WNIOSEK33.16.
Jeśli S' jest właściwą podgrupą grupy skończonej S, to IS'I ~ ISl/2.

Podgrupy generowane przez element
Z twierdzenia 33.14 wynika interesujący sposób tworzenia podgrupy grupy
skończonej (S, EB): wybrać element a i wziąć wszystkie elementy, które
można uzyskać z a za pomocą działania grupowego. ściślej, zdefiniujmy aCt.J
dla k ;, I jako

1 •
a<>= EBa=aEBaEB ... EBa
I= 1

Jeśli na przykład weźmiemy a= 2 w grupie Z 6 , to ciąg a<1l, aC2>,...wygląda tak:

2, 4, O, 2, 4, O, 2, 4, O, ...

W grupie Z„ mamy atll = ka mod n, w grupie z:


zaś mamy atll = tł mod
n. Podgrupę generowaną przez a, oznaczaną symbolem (a) lub ((a), EB), de-
finiujemy jako

(a) - {d'':k;, I}

916
33.3. ARYTMETYKA MODULARNA

Mówimy, że
element a generuje podgrupę (a) albo że a jest generatorem (a).
Ponieważ zbiór Sjest skończony, więc (a) jest skończonym podzbiorem S, być
może zawierającym cały zbiór S. Ponieważ z łączności operacji EB wynika, że

a<OE9aU>= au+})

zatem zbiór (a) jest zamknięty ze względu na działanie grupowe, czyli - na


mocy twierdzenia 33.14 - jest podgrupą S. Na przykład w Z 6 mamy

<O>= {o)
(!) ={O,!, 2, 3, 4, 5)
(2) = {O,2, 4)

Podobnie, w z; mamy
(!) = {!}
(2) = {!, 2, 4)
(3) = {!, 2, 3, 4, 5, 6)

Rząd elementu a (w grupie S), oznaczany przez ord(a), definiujemy jak.o


najmniejsze t > O takie, że a(r>= e.

TwlERDZENIE 33.17.
Dla dowolnej grupy skończonej (S, EB)i dowolnego a e S rząd elementu a jest
równy rozmiarowi generowanej przez niego grupy, tzn. ord(a) = l(a)I-

Dowóo
Niech t = ord(a). Ponieważ a<tJ= e i fi.t+t) = d,1l EBa!"J = d,"l dla k ;i, 1, więc
jeśli i > t, to a11J= d,IJ dla pewnego j < i. Po a<r)nie pojawiają się już zatem
żadne nowe elementy, czyli (a)= {a<1l, a<2i, ... , a<tl}. Aby wykazać, że
l(a)j = t, przypuśćmy przeciwnie, że a<fJ= aU) dla pewnych i, j spełniających
I~ i<}~ t. Wówczas a<l+tJ = tiJ+lJ dla k ;i, O. Wynika stąd jednak., że
aU+<r-J))= tiJ+(r-JJJ = e, co stanowi sprzeczność, gdyż i+ (t- 1) < t, at jest
najmniejszą liczbą dodatnią taką, że d,1l = e. Zatem wszystkie elementy ciągu
a(1 >,a12l, ... , a 1tJ są różne, więc l(a)I = t.


WNIOSEK33.18.
Ciąg at1 l, a12>,...jest okresowy z okresem t = ord(a); tzn. a0> = d,l) wtedy i tyl-
ko wtedy, gdy i - j (mod 1).

917
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

W myśl powyższego wniosku należy przyjąć a!0 >jako e oraz a(J)jako a!lmodt
dla dowolnej liczby całkowitej i.

WNIOSEK 33.19.
Jeśli(S, EB)jest grupą skończoną z elementem neutralnym e, to dla dowolnego
a ES zachodzi zależność
tf1Sll= e

DOWÓD
Z twierdzenia Lagrange'a wynika, że ord(a) I IS!,zatem IS!- O (mod t), gdzie
t - ord(a).

ZADANIA
33.3--1. Wypisz tabele działań grupowych dla grup (Z 4 , + J i (Z;, · 5). Wykaż,
że grupy te są izomorficzne, wskazując wzajemnie jednoznaczną odpowie-
dniość a: między ich elementami taką, że a + b = c (mod 4) wtedy i tylko
wtedy, gdy •(a)· •(b) = •(c) (mod 5).
33.3--2. Udowodnij twierdzenie 33.14.
33.3--3. Wykaż, że jeśli p jest liczbą pierwszą, e zaś jest liczbą całkowitą dodat-
nią, to zachodzi zależność

q,(p')- p'-'(p -1)


33.3-4. Wykaż, że dla dowolnego n > 1 i dla dowolnego ae funkcja z:
fu.: z:-z:
zdefiniowana wzoremfu.(x) = axmod n jest permutacją zbioru
z:.
33.3-5. Wypisz wszystkie podgrupy grup Z 9 i Z~ 3 •

33.4. Rozwiązywanie liniowych równań modularnych


Zajmiemy się teraz zadaniem znajdowania rozwiązań równania
ax ss b (mod n) (33.22)
gdzie n> O, stanowiącym problem o dużym praktycznym znaczeniu, Zakłada­
my, że a, b i n są dane, szukamy zaś liczb x mod ul o n, które spełniają równanie
(33.22). Rozwiązań takich może być zero, jedno lub więcej.
Niech (a) oznacza podgrupę Zn generowaną przez a. Ponieważ
(a)={at"'l:x>O}={axmodn:x>O}, równanie (33.22) ma rozwiązanie
wtedy i tylko wtedy, gdy be (a). Twierdzenie Lagrange'a (tw. 33.15) mówi, że
l(a)] musi być dzielnikiem n. Poniższe twierdzenie daje nam dokładną cha-
rakterystykę grupy (a).

918
33.4. ROZWIĄZVWANIE LINIOWYCH RÓWNAŃ MODULARNYCH

TWIERDZENIE33.20.
Dla dowolnych dodatnich liczb całkowitych a i n, jeśli d = gcd(a, n), to
(a> - (d) - {O,d, 2d, ..., ((n/d) - I)d) (33.23)
a zatem
l(a>I - n/d
DOWÓD
Zaczniemy od pokazania, że de(a). Wywołując procedurę EXTENDED-
-EUCLID(a, n), otrzymujemy liczby x' i y' takie, że ax' + ny' = d. Zatem ax' d
(mod n), więc de (a).
Ponieważ de (a), również każda wielokrotność d należy do (a), bo wielo-
krotność wielokrotności a jest wielokrotnością a. Tak więc (a) zawiera każdy
element zbioru {O,d, 2d, ..., ((n/d) - I)d), tzn. (d) c (a>.
Pokażemy teraz, że (a) c (a). Jeśli me(a), tom= ax mod n dla pew-
nego całkowitego x, a więc m = ax + ny dla pewnego całkowitego y. Ponie-
waż jednak d I a i d I n, to na mocy równania (33.6) d I m. Zatem me (a).
Wiemy już, że (a)= (d'). Aby udowodnić, że l(a)I = n/d, zauważmy, iż
między O a n - l włącznie znajduje się dokładnie n/d wielokrotności liczby d.


WNIOSEK33.21.
Równanie ax-= b (mod n) jest rozwiązywalne ze względu na niewiadomą
x wtedy i tylko wtedy, gdy gcd(a, n) Ib.

WNIOSEK 33.22.
Równanie ax = b (mod n) albo ma d różnych rozwiązań modulo n, gdzie
d = gcd(a, n), albo wcale nie ma rozwiązań.

DOWÓD
Jeśli równanie ax - b (mod n) ma rozwiązanie, to be (a). Ciąg ai mod n dla
i= O, 1, ... na mocy wniosku 33.18 jest okresowy z okresem l(a)I = n/d. Jeśli
be (a), to b pojawia się w ciągu ai mod n dla i= O, 1, ... , n - I dokładnie
d razy, ponieważ blok rozmiaru (n/d) elementów (a) powtarza się dokładnie
d razy dla i przebiegającego wartości od O do n - I. Pozycje x tych d wystąpień
są rozwiązaniami równania ax - b (mod n).


TWIERDZENIE 33.23.
Niech d = gcd(a, n) i załóżmy, że d = ax' + ny' dla pewnych całkowitych x'
i y' (na przykład wyliczonych za pomocą procedury EXTENDED-EUCLID). Jeśli

919
ROZDZIAŁ 33. ALGORYTMY TEORIOLłCZBOWE

d I b, to jednym z rozwiązań równania ax = b (mod n) jest wartość x0 okreś­


lona wzorem

x0 - x'(b/d) mod n

DOWÓD
Ponieważ ax' - d (mod n), więc mamy

ax 0 = ax'(b/d) (mod n)
- d!_b/d)(mod n)
- b (mod n)

zatem x 0 jest rozwiązaniem równania ax: b (mod n).



TwlERDZENIE33.24.
Załóżmy, że równanie ax E b (mod n) jest rozwiązywalne (to znaczy d I b, gdzie
d = gcd(a, n)) i że x 0 jest dowolnym rozwiązaniem tego równania. Wówczas
równanie to ma dokładnie d różnych rozwiązań module n, danych wzorem
x 1 =x 0 + i(n/d)dla i= 1, 2, ..., d-1.

DoWOD
Ponieważ n/d > O i O:s;;i(n/d) < n dla i= O, 1, ..., d- 1, wartości x 0 , x 1 , ... ,
x 4 _ 1 są parami różne, modulo n. Z okresowości ciągu ai mod n (wniosek
33.18) wynik.a, że jeśli x 0 jest rozwiązaniem równania ax = b(mod n), to jest
nim także każde Xt. Na mocy wniosku 33.22 rozwiązań jest dokładnie d, są to
więc właśnie x 0 , x 1 , ... , x 4 _ 1 .


Przedstawiliśmyaparat matematyczny potrzebny do rozwiązania równa-
nia ax = b (mod n); poniższy algorytm wypisuje wszystkie rozwiązania tego
równania. Dane wejściowe a i b są dowolnymi liczbami całkowitymi, n zaś jest
dowolną dodatnią liczbą całkowitą.

MODULAR-LINEAR-EQUATION-SOLVER(a, b, n)
1 (d, x', y') +- EXTENDED-EUCLID(a, n)
2 ifdlb
3 then x 0 +- x'(b/d) mod n
4 fori+-Otod-1
5 do wypisz (x 0 + i(n/d)) mod n
6 else wypisz „brak rozwiązań"

920
33.4. ROZWIĄZYWANIE LINIOWYCH RÓWNAŃ MODULARNYCH

Jako przykład działania tej procedury rozważmy równanie 14x =


- 30 (mod 100) (mamy tu a= 14, b = 30 i n= 100). Wywołując w wierszu
1 procedurę EXTENDED-EUCLID, otrzymujemy (d, X, y) = (2, -7, 1). Ponie-
waż 2130, wykonywane są wiersze 3-5. W wierszu 3 obliczamy x0 =
= (-7)(15) mod 100 = 95. W pętli w wierszach 4-5 są wypisywane dwa roz-
wiązania: 95 i 45.
Procedura MODULAR-LINEAR-EQUATION-SOLVERdziała w następujący
sposób. W wierszu 1 jest obliczane d = gcd(a, n), jak również wartości x' i y'
takie, że d = ax' + ny', co świadczy o tym, że x' jest rozwiązaniem równania
ax' = d (mod n). Jeśli dnie dzieli b, to równanie ax = b (mod n) nie ma rozwią­
zań, na mocy wniosku 33.21. W wierszu 2 sprawdzamy, czy d I b; jeśli nie,
w wierszu 6 jest wypisywana informacja o braku rozwiązań. W przeciwnym
razie w wierszu 3 jest obliczane rozwiązanie x 0 równania (33.22), zgodnie
z twierdzeniem 33.23. Gdy mamy jedno rozwiązanie, twierdzenie 33.24 mówi,
że pozostałych d - 1 rozwiązań można otrzymać, dodając do niego wielokrot-
ności (n/d) modulo n. Pętla for w wierszach 4-5 wypisuje wszystkich d rozwią­
zań, poczynając od x 0 , przy czym kolejne są odległe od siebie o (n/d), modulo n.
Czas działania procedury MODULAR-LINEAR-EQUATION-SOLVER to
O(lgn + gcd(a, n)) operacji arytmetycznych, ponieważ algorytm EXTENDED-
-EUCLID wykonuje O(lgn) operacji arytmetycznych, natomiast w każdym
obrocie pętli for w wierszach 4-5 jest wykonywana stała liczba operacji aryt-
metycznych.
Poniższe wnioski z twierdzenia 33.24 opisują jego szczególnie ważne
przypadki.

WNIOSEK 33.25.
Dla dowolnego n> 1, jeśli gcd(a, n)= 1, to równanie ax - b (mod n) ma
dokładnie jedno rozwiązanie modulo n.
+
W często spotykanym i ważnym przypadku, gdy b = 1, element x, którego
szukamy, to multyplik.atywna odwrotność a modulo n.

WNIOSEK
33.26.
Dla dowolnego n> l, jeśli gcd(a, n)= 1, to równanie
ax = 1 (mod n) (33.24)
ma dokładnie jedno rozwiązanie modulo n. W przeciwnym razie nie ma roz-
. .
w1ązan1a.
+
Wniosek 33.26 pozwala nam na używanie oznaczenia (a- 1 mod n) w odnie-
sieniu do jedynej multyplikatywnej odwrotności a mod ul o n, jeśli a i n są względ-

921
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

nie pierwsze. Jeśli gcd(a, n) = 1, to rozwiązaniem równania ax = l (mod n) jest


liczba x zwracana przez procedurę EXTENDED-EUCUD, bo z równania
gcd(a, n)= I = ax + ny
wynika ax = 1 (mod n). Zatem (a- 1 mod n) można efektywnie obliczać za
pomocą algorytmu ExrENDED-EUCLID.

ZADANIA
33.4-1. Znajdź wszystkie rozwiązania równania 35x = 10 (mod 50).
33.4-2. Udowodnij, że z równania ax = ay (mod n) wynika x = y (mod n), jeśli
tylko gcd(a, n)= 1. Wykaż, że warunek gcd(a, n)= 1 jest konieczny, po-
dając kontrprzykład, w którym gcd(a, n)> 1.
33.4-3. Dokonajmy następującej zmiany w 3 wierszu procedury MODULAR-
-LINEAR-EQUATION-SOLVER:
3 tben x 0 - x'(b/a) mod (n/a)
Czy procedura pozostanie poprawna? Wytłumacz, dlaczego tak lub dla-

czego nie.
* 33.4-4. Niech f(x) =fo +f 1 x + ... + J;X (mod p) będzie wielomianem stop-
nia t o współczynnikach J; wziętych z z,,,gdzie p jest liczbą pierwszą.
Mówimy, że aE z„ jest pierwiastkiem!, jeśli/(a) = O (mod p). Udowodnij,
że jeśli a jest pierwiastkiem f, to f(x) - (x - a)g(x) (mod p) dla pewnego
wielomianu g(x) stopnia t - I. Udowodnij przez indukcję względem t, że
wielomian /(x) stopnia t może mieć co najwyżej t różnych pierwiastków
modulo liczba pierwsza p.

33.5. Chińskie twierdzenieo resztach


Około roku 100 n.e. chiński matematyk Sun-Tsii rozwiązał problem znajdowa-
nia tych liczb całkowitych, które przy dzieleniu przez 3, 5 i 7 dają reszty,
odpowiednio, 2, 3, i 2. Jednym z takich rozwiązań jest x = 23, pozostałe są
postaci 23 + 105kdla dowolnej liczby całkowitej k. Tak zwane „chińskie twier-
dzenie o resztach" wskazuje zależność między układem równań mod ul o pe-
wien zbiór liczb parami względnie pierwszych (np. 3, 5, 7) a równaniem modu-
Io ich iloczyn (tutaj 105).
Chińskie twierdzenie o resztach ma dwa główne zastosowania. Niech licz-
ba n= n 1n 2 ... n1 , gdzie liczby n1 są parami względnie pierwsze. Po pierwsze,
chińskie twierdzenie o resztach jest ,,twierdzeniem strukturalnym", opisującym
Strukturę Zn jako iloczyn kartezjański Zn X Z" X ... X Zn Z dodawaniem
i mnożeniem po współrzędnych (modulo ni na ' i-tej' współrzędnej).
' Po drugie,
korzystając z tego opisu, można często uzyskiwać efektywne algorytmy, ponie-

922
33.5. CHtNSKIE TWIERDZENIE O RESZTACH

waż obliczenia w każdym z systemów Z,._mogą być efektywniejsze (w sensie


'
liczby operacji na bitach) od obliczeń modulo n.

TWIERDZENIE 33.27. (Chińskie twierdzenie o resztach)


Niech n= n 1n2 ..• nt, gdzie n1 są parami względnie pierwsze. Rozważmy współ­
zależność

(33.25)

dla i= I, 2, ... , k. Wówczas odwzorowanie (33.25) stanowi wzajemnie jedno-


znaczną odpowiedniość (bijekcję) między Z,._ a iloczynem kartezjańskim
Z,._ x Z,._ x ... x Z,._. Działania wykonywane na elementach Z,._można równo-
'
ważnie '
wykonywać 'na odpowiadających im k-ciągach, na każdej współrzędnej
niezależnie, wykonując działania z danego systemu. To znaczy, jeśli

to
(a + b) mod n -c-+ ((a 1 + b 1 ) mod n1 , ... , + bJ mod nJ
(a.1;: (33.26)

(a - b) mod n-c-+((a 1 - b 1 ) mod n 1 , ... , (a.1;:


- bJ mod nJ (33.27)

(33.28)

DOWÓD
Przekształcenia między tymi dwiema reprezentacjami są dosyć proste. Przejście
wymaga jedynie k dzieleń. Obliczenie a, mając (a 1 , a2 ,
od a do (a 1 , a 2 , ••• , a.1;:)
jest niemal równie proste przy użyciu poniższego wzoru. Niech
..., a.1;:),
m; = n/n 1 dla i= 1, 2, ... , k. Ponieważm 1 = n 1 n2 ••. n;_1 n1+ 1 ••• n1;:,
mamy m; - O
(mod ni) dla wszystkich} -=I-i. Zatem przyjmując

(33.29)

dla i= 1, 2, ... , kmamy

(33.30)

923
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

Równanie (33.29) jest dobrze określone, gdyż m; oraz n1 są względnie pierwsze


(na mocy twierdzenia 33.6), zatem z wniosku 33.26 wynika, że dobrze zdefinio-
wana jest wartość (m1- 1 mod nJ. żeby sprawdzić równanie (33.30), zauważmy,
że c1 = m1 = O (mod nJ jeślij =I-i, i że c1 = 1 (mod n1). Mamy zatem zależność

c,+-+(O,O, ..., O, 1, O, ..., O)

czyli C; odpowiada wektorowi o wszystkich współrzędnych równych O z wyjąt­


kiem i-tej równej 1. Wektory c1 tworzą w pewnym sensie „bazę" tej reprezen-
tacji. Dla dowolnego i mamy więc

(mod n,)

(mod n1)

Ponieważ przekształcenie działa


w obie strony, odpowiedniość jest wzajemnie
jednoznaczna. Równania (33.26)-(33.28) wynikają bezpośrednio z zad. 33.1-6,
gdyż x mod n1 = (x mod n) mod n1 dla dowolnego x oraz i= 1, 2, ..., k.


Z poniższych wniosków będziemy korzystać w dalszej części tego rozdziału.

WNIOSEK 33.28.
Jeśli n 1 , n 2 , ... , nt są parami względnie pierwsze i n= n1n2 ••• n,.,to dla dowol-
nych liczb całkowitych a 1 , a 2 , ... , at układ równań

x = a1 (mod n1)
dla i= 1, 2, ..., k ma dokładnie jedno rozwiązanie mod.ula n ze względu na
niewiadomą x.

WNIOSEK 33.29.
Jeśli n 1 , n 2 , .•• , nt są parami względnie pierwsze i n= n 1n 2 ... nt, to dla dowol-
nych liczb całkowitych x i a zachodzi

dla i= l, 2, ..., k wtedy i tylko wtedy, gdy

x = a(mod n)


924
33.5. CHll'ilSKIE TWIERDZENIE O RESZTACH

Jako przykład na chińskie twierdzenie o resztach rozpat1any dwa równania:

a=2(mod 5)

a= 3 (mod 13)
skąd a 1 = 2, n 1 = m 2 = 5, a2 = 3 oraz n 2 = m 1 = 13. Chcemy obliczyć a mod
65, bo n= 65. Ponieważ 13- 1 = 2 (mod 5) i 5- 1 = 8 (mod 13), więc mamy
c1 = 13(2 mod 5) = 26
c 2 = 5(8 mod 13) = 40
oraz
a= 2·26 + 3·40 (mod 65)
- 52 + 120 (mod 65)
= 42 (mod 65)

Ilustracjęzastosowania chińskiego twierdzenia o resztach do obliczeń modulo


65 stanowi rys. 33.3.

o l 2 3 4 5 6 7 8 9 10 11 12
o o 40 15 55 30 5 45 20 60 35 10 50 25
l 26 l 41 16 56 31 6 46 21 61 36 11 51
2 52 27 2 42 17 57 32 7 47 22 62 37 12
3 13 53 28 3 43 18 58 33 8 48 23 63 38
4 39 14 54 29 4 44 19 59 34 9 49 24 64

Rys. 33.3. llustratja chińskiego twierdzenia o resztach dla n 1 = 5 i n2 = 13. W tym przykładzie
c1 = 26, a c2 = 40. W i-tym wierszu i j-tej kolumnie znajduje się ta.ka wartość a moduJo 65, że
(a mod 5) = i oraz (a mod 13) ""j. Zwróćmy uwagę, że przecięcie wiersza O i kolumny O zawiera
wartość O. Podobnie, w wierszu 4 i kolumnie 12 majduje się 64 (róv.noważne -1). Poniewai:
cl= =
26, przejście o jeden wiersz w dół zwiększa wartość a o 26. Analogicmie, c2 40 oznacza, że
przejście w prawo o jedną kolumnę zwiększa a o 40. Zwiększenie a o 1 odpowiada przejściu po
skosie w dól i w prawo, przy zawinięciu dolnego brzegu tabeli na górny i prawego na lewy

Możemy zatem realizować


obliczenia modulo n albo bezpośrednio, albo
po przekształceniu, wykonując działania modulo n1 , jak nam wygodniej.
Obydwa sposoby są całkowicie równoważne.

ZADANIA
33.5-1. wszystkie rozwiązania równań x - 4 (mod 5) i x = 5 (mod 11).
Znajdź
33.5-2. Znajdź wszystkie liczby x dające reszty I, 2, 3, 4, 5 przy dzieleniu przez,
odpowiednio, 2, 3, 4, 5, 6.

925
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

33.5-3, Uzasadnij, że (przy omacz.eniach jak w twierdzeniu 33.27) jeśli


gcd(a, n) - I, to
1 1
(a- mod n)+-+((al mod n 1), (a2 1 mod n2 ), ••• , (a.t 1 mod 11.1))

33.5-4. Korzystając z oznaczeń jak w twierdzeniu 33.27, udowodnij, że liczba


pierwiastków równania/(x) - O(mod n) jest równa iloczynowi liczby pier-
wiastków wszystkich równań f(x) = O (mod n 1), f(x) = O (mod 112 ), •••,
f(x) s O (mod n,).

33.6. Potęgi elementu


Tak. jak. naturalną rzeczą jest rozważać wielokrotności danego elementu a mo-
dulo n, tak samo można również rozważać ciąg potęg a moduł o n, gdzie a Ez::
o 1 2 J
a,a,a,a, ..., (33.31)

modulo n. Numerację w tym ciągu zaczniemy od O; zerową wartością ciągu


jest a 0 mod n = 1, a i-tą wartością jest a 1 mod n. Na przykład potęgami
3 modulo 7 są

i o I 2 3 4 5 6 7 8 9 IO Il ...
3;mod 7 1 3 2 6 4 5 I 3 2 6 4 5 ...
a potęgami 2 modulo 7 są

I o I 2 3 4 5 6 7 8 9 10 11 ...
21 mod 7 1 2 4 I 2 4 I 2 4 I 2 4 ...
W tym podrozdziale (a) oznacza podgrupę z:
generowaną przez a, nato-
miast ordn(a) (,,rząd elementu a modulo n") oznacza rząd a w Na przykład z:,
(2) = {I, 2, 4} w z;,
a ord.,(2) = 3. Korzystając z definicji funkcji Eulera tp(n)
jak.o rozmiaru grupy z:
(patrz pod.rozdz. 33.3), zastosujemy wniosek 33.19
do z:,otrzymując twierdzenie Eulera, a w szczególnym przypadku grupy z;,
gdzie p jest liczbą pierwszą, twierdzenie Fermata.

TWIERDZENIE 33.30. (Twierdzenie Eulera)


Dla dowolnej liczby całkowitej n > 1 zachodzi zależność

al"(n) = 1 (mod n) dla każdego aeZ: (33.32)



926
33.6. POTĘGI ELEMENTU

TwlERDZENIE33.31. (fwierdzenie Fermata)


Jeśli p jest liczbą pierwszą, to

aP- 1 = 1 (mod p) dla każdego atz; (33.33)

DOWÓD
Na mocy równania (33.21), jeśli p jest liczbą pierwszą, to cp(p) = p - I.


Wniosek ten stosuje się do każdego elementu ZP z wyjątkiem O, ponieważ
Ofz;. Dla każdego aEZP zachodzi natomiast aP = a (mod p), o ile p jest
liczbą pierwszą.
Jeśli ordn(g) = 1z:1,
to każdy element grupy z: jest pewną potęgą g ma-
duło n i mówimy, że g jest pierwiastkiem pierwotnym lub generatorem z:.Na
przykład 3 jest pierwiastkiem pierwotnym modulo 7. Jeśli grupa ma pier- z:
wiastek pierwotny, to mówimy, że jest ona grupą cykliczną. Dowód poniższego
twierdzenia, autorstwa Nivena i Zuckermana [85), pominiemy.

TwlERDZENIE33.32.
Wartości n> 1, dla których grupa z:jest cykliczna, to 2, 4, pe i 2pe dla
wszystkich nieparzystych liczb pierwszych p i dowolnych dodatnich liczb cał­
kowitych e.


Jeśli g jest pierwiastkiem pierwotnym z:,
zaś a jest dowolnym elementem
z:, to istnieje z takie, że 1f - a (mod n). Takie z nazywamy logarytmem dys-
kretnym albo indeksem elementu a modulo n przy podstawie g; wartość tę
oznaczamy przez indn, 9 (a).

TWIERDZENIE33.33. (fwierdzenie o logarytmie dyskretnym)


Jeśli g jest pierwiastkiem pierwotnym z:,
to równanie 15- g 1 (mod n) jest speł­
nione wtedy i tylko wtedy, gdy zachodzi x - y (mod cp(n)).

DOWÓD
Załóżmy najpierw, że x =e y (mod cp(n)).Wówczas x = y + kcp(n)dla pewne-
go k. Zatem
~ - gY+ką,(n) (mod n)
- gY. (g"'lnl)k(mod n)
= g'· I' (mod n)
= gY (mod n)
927
ROZDZIAŁ 33. ALGORYTMY TEOR10L1CZB0WE

w celuudowodnienia przeciwnej implikacji załóżmy, żer= g>'(mod n).


Ponieważ w ciągu potęg g występuje każdy element (g) i l(g)I = rp(n), z wnios-
ku 33.18 wynika, że ciąg potęg g jest okresowy z okresem rp(n). Jeśli zatem
g" = g>'(mod n), to musi zachodzić X= y (mod tp(n)).


Przejście do logarytmów dyskretnych może e7.asem uprościć rozumowanie
dotyczące równań modularnych, co ilustruje dowód poniż.szego twierdzenia.

TWIERDZENIE 33.34.
Jeśli p jest nieparzystą liczbą pierwszą i e ~ 1, to równanie
x' - I (mod p') (33.34)
ma dokładnie dwa rozwiązania, a mianowicie x = 1 i x = -1.

DOWÓD
Niech n= pe. Z twierdzenia 33.32 wynika, że z:zawiera pierwiastek pierwotny
g. Równanie (33.34) można zapisać jak.o

(i"'·•'"')'= g'"'···'''
(mod n) (33.35)
Zauważmy, że skoro ind"_,(1) = O, to z twierdzenia 33.33 wynika, że równanie
(33.35) jest równoważne z równaniem
2 · ind,,,(x) - O (mod q,(n)) (33.36)
Do rozwiązania tego równania ze względu na niewiadomą ind",,(x) za-
stosujemy metody z podrozdz. 33.4. Jeśli przyjmiemy d - gcd(2, q,(n)) -
= gcd(2, (p- l)pe~i) = 2, to ponieważ d I O, z twierdzenia 33.24 wynika, że
równanie (33.36) ma dokładnie dwa rozwiązania, a bezpośrednio można
sprawdzić, że są nimi x = 1 i x = -1.


Liczba x jest nietrywialnym pierwiastkiem kwadratowym z 1 modulo n, jeśli
spełnia równanie x 2 = 1 (mod n), ale x nie przystaje do żadnego z „trywial-
nych" pierwiastków kwadratowych: 1 ani -1 modulo n. Na przykład 6 jest
nietrywialnym pierwiastkiem kwadratowym z 1 modulo 35. Poniższy wniosek
z twierdzenia 33.34 wykorzystamy w dowodzie poprawności algorytmu Mil-
lera-Rabina służącego do sprawdzania, czy dana liczba jest liczbą pierwszą
(patrz podrozdz. 33.8).

WNIOSEK33.35.
Jeśli istnieje nietrywialny pierwiastek kwadratowy z 1 modulo n, to n jest
liczbą złożoną.

--·----------------------------
928
33.6. POTĘGI ELEMENTU

DOWÓD
Wniosek ten powstaje po prostu z zaprzeczenia twierdzenia 33.34. Jeśli istnieje
nietrywialny pierwiastek kwadratowy z 1 modulo n, to n nie może być liczbą
pierwszą ani potęgą liczby pierwszej.


Potęgowanie przez wielokrotne podnoszenie do kwadratu

W obliczeniach teorioliczbowych często występującą operacją jest podnoszenie


jednej liczby do potęgi modulo druga liczba, zwane też potęgowaniem mo-
dularnym. Dokładniej, chcielibyśmy w efektywny sposób obliczać ab mod n,
gdzie a i b są nieujemnymi liczbami całkowitymi, a n jest dodatnią liczbą
całkowitą. Potęgowanie modularne jest podstawową operacją w wielu pro-
cedurach sprawdzania, czy dana liczba jest liczbą pierwszą, a także w RSA
- kryptosystemie z kluczem jawnym. Metoda wielokrotnego podnoszenia do
kwadratu stanowi efektywne rozwiązanie tego problemu z wykorzystaniem
binarnej reprezentacji b.
Niech (b 1 , b1 _ 1, ... , b 1 , h 0 ) będzie binarną reprezentacją b. (Składa się ona
z k + 1 bitów, z których b1 jest najbardziej, a b0 najmniej znaczący). Poniższa
procedura oblicza a 0 mod n dla wartości c zwiększających się od O do b przez
podwajanie i zwiększanie o 1.

MODULAR-EXPONENTIATION(a,b, n)
I c.,_O
2 d .....1
3 niech (b", b"_ 1, ... , h 0 ) będzie binarną reprezentacją h
4 for i+- k downto O
5 doc+-2c
6 d+-(d·d)modn
7 ifb1=l
8 thenc+-c+l
9 d+-(d·a)modn
10 return d

Każdy z kolejno obliczanych wykładników jest albo podwojeniem po-


przedniego wykładnika, albo poprzednim wykładnikiem zwiększonym o 1;
o tym, którą operację wykonać, decydujemy, przeglądając binarną reprezen-
tację b od strony prawej do lewej. W każdym przebiegu pętli korzystamy
z jednej z tożsamości
a 20 mod n = (a} 2 mod n
a 20 + 1 mod n= a· (a0) 2 mod n

929
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

zależnie od tego, czy b1 = O czy 1. Wykonywana w każdym przebiegu pętli


operacja podnoszenia do kwadratu tłumaczy nazwę „wielokrotne podnoszenie
do kwadratu". Bezpośrednio po wczytaniu i przetworzeniu bitu b1 wartość c jest
równa preftksowi (b 1, b1 _ 1, ... , b1) binarnej reprezentacji b. Na przykład dla
a= 7, b = 560 i n= 561 procedura oblicza ciąg wartości pokazany na rys. 33.4;
ciąg odpowiadających im wykładników jest zawarty w wierszu c tabeli.

; I 9 8 7 6 5 4 3 2 I o
,, I o o o I I o o o o
I 2 4 8 17 35 70 140 280 560
'
d 7 49 157 526 160 241 298 166 67 I

Ry11.33.4. Wyniki działania procedury MooULAR-EXPONENTIATION obliczającej ab (mod 11),gdzie


a = 7, b = S60 = ( I OOO
110000) i 11= 561. Pokazane są, wartości po każdym przebiegu pętli ror.
Ostatecznym wynikiem jest 1

Zmienna c nie jest do niczego potrzebna w samym algorytmie, ale pomaga


w jego wyjaśnieniu: algorytm zachowuje niezmiennik d = acmod n, zwiększa­
jąc c przez podwajanie i dodawanie 1 do chwili, gdy c = b. Jeśli dane wejściowe
a, b i n są. liczbami /1-bitowymi, to łączna liczba niezbędnych operacji aryt-
metycznych wynosi O(ff), a całkowita liczba operacji na bitach to 0(/1 3 ).

ZADANIA
33.6-1. Wypełnij tabelę zawierającą rzędy wszystkich elementów grupy Z~ 1 •
Znajdź najmniejszy pierwiastek pierwotny g i utwórz tabelę zawierającą
wartości ind 11 ,,(x) dla wszystkich xeZ~ 1 .
33.6-2. Podaj algorytm potęgowania modularnego przeglądający bity liczby
b od strony prawej do lewej zamiast od lewej do prawej.
33.6-3. Wyjaśnij, jak obliczać a- 1 mod n dla dowolnego aez:,
korzystając
z proc.edury MODULAR-EXPONENTIATION, przy założeniu, że znasz war-
tość <p(n),

33.7. Systemkryptograficznyz kluczemjawnym RSA1


Systemu kryptograficznego (w skrócie: kryptosystemu) z kluczem jawnym
moina używać do szyfrowania informacji przesyłanych między dwiema poro-
zumiewającymi się stronami tak, żeby przeciwnik, który podsłuchał przekazy-
waną wiadomość, nie mógł jej zdekodować. Kryptosystem z kluczem jawnym
pozwala także dołączyć na koniec przesyłanej elektronicznie wiadomości nie-

t Nazwa pochodzi od nazwisk trzech twórców: Rivesta, Shamira i Adlemana (przyp. red.).

930
33.7. SYSTEM KRYPTOGRAFICZNY Z KLUCZEM JAWNYM RSA

możliwy do podrobienia „podpis cyfrowy". Podpis taki jest elektroniczną wer-


sją ręcznego podpisu na papierowym dokumencie. Każdy może go z łatwością
sprawdzić, nikt nie może go podrobić, a traci ważność, jeśli zmieniony zostanie
jakikolwiek bit przesyłanej wiadomości. Stanowi on zatem certyfikat zarówno
tożsamości podpisującego, jak. i treści podpisanej wiadomości. Jest on ideal-
nym narzędziem do tworzenia elektronicznych wersji kontraktów, czeków, za-
mówień i innych dokumentów, które muszą być uwiarygodnione.
Kryptosystem z kluczem jawnym RSA jest oparty na zasadniczej różnicy
między łatwością znajdowania dużych liczb pierwszych a trudnością rozłożenia
na czynniki iloczynu dwóch dużych liczb pierwszych. W podrozdziale 33.8
opiszemy efektywną metodę znajdowania dużych liczb pierwszych, a w pod-
rozdz. 33.9 omówimy problem rozkładu na czynniki dużych liczb.

Systemy kryptograficzne z kluczem jawnym


W systemie z kluczem jawnym każdy użytkownik posiada zarówno klucz jaw-
ny, jak i klucz tajny. Klucz to pewien zestaw informacji. W systemie RSA na
przykład każdy klucz składa się z pary liczb naturalnych. W kryptograficznych
przykładach użytkownikom tradycyjnie nadaje się imiona „Alicja" i „Bob";
ich klucze jawne i tajne będziemy oznaczali odpowiednio: PA• SA dla Alicji
oraz P 8 , S8 dla Boba.
Każdy użytkownik tworzy własny klucz jawny i tajny. Każdy trzyma swój
klucz tajny w ukryciu, natomiast klucz jawny może zdradzić każdemu albo
wręcz go opublikować. W istocie, czasem wygodnie jest zakładać, że wszystkie
klucze jawne są umieszczone w publicznie dostępnym katalogu, tak. że dowol-
ny użytkownik systemu może bez trudu uzyskać klucz jawny każdego innego
użytkownika.
Klucze jawny i tajny określają funkcje, które można stosować do dowolnej
wiadomości. Niech fJ oznacza zbiór dopuszczalnych wiadomości. Mógłby to
być na przykład zbiór wszystkich skończonych ciągów bitów. Chcemy, żeby
klucze jawny i tajny określały funkcje wzajemnie jednoznaczne z fJ w siebie.
Funkcję odpowiadającą kluczowi jawnemu PA Alicji oznaczamy przez P,t.(),
a funkcję odpowiadającą jej kluczowi tajnemu SA oznaczamy przez S ,t.(). Funk-
cje P,4.() i S_,t.()są zatem permutacjami zbioru fJ. Zakładamy, że funkcje P,4.()
i S ,t() dają się efektywnie obliczać, o ile dany jest odpowiedni klucz PA.lub SA.·
Klucze jawny i tajny każdego użytkownika stanowią „uzupełniającą się
parę" w tym sensie, że określają funkcje, które są naw1.ajem swoimi odwrotno-
ściami. To znaczy

M - S ,.(P,.(M)) (33.37)

M- P,.(S,.(M)) (33.38)

931
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

dla dowolnej wiadomości Me~. Przekształcając M kolejno za pomocą dwóch


kluczy P_. i SA.,dostajemy z powrotem M.
Podstawową właściwością systemu kryptograficznego z kluczem jawnym
jest to, że nikt oprócz Alicji nie jest w stanie obliczać funkcji SA.()w rozsądnym
czasie. Tajemnica korespondencji zaszyfrowanej i przesłanej do Alicji oraz wia-
rygodność jej podpisu cyfrowego opiera się na założeniu, że jedynie Alicja
potrafi obliczać SA(). Dlatego właśnie Alicja trzyma S _. w tajemnicy; gdyby
tego nie robiła, nie dysponowałaby unikalną informacją, więc system nie mógł­
by zapewnić jej unikalnych możliwości. Założenie, że jedynie Alicja potrafi
obliczać S_.(), musi być spełnione, pomimo że każdy zna PA.i może efektywnie
obliczać P _.() - funkcję odwrotną do S _.(). Główna trudność w projektowaniu
działającego w praktyce kryptosystemu z kluczem jawnym leży w znalezieniu
sposobu na stworzenie takiego systemu, w którym możemy ujawnić przekształ­
cenie P _.(), nie zdradzając przy tym, jak obliczać odpowiadające mu przekszta-
łcenie odwrotne S_.().
Szyfrowanie w systemie z kluczem jawnym odbywa się następująco. Przy-
puśćmy, że Bob chce wysłać Alicji wiadomość M zaszyfrowaną tak, że dla
podsłuchującego przeciwnika będzie ona kompletnie niezrozumiała. Scenariusz
przesyłania wiadomości jest taki.

• Bob pobiera klucz jawny P _. Alicji (z publicznego katalogu lub bezpośred­


nio od Alicji).
• Bob oblicza tekst zaszyfrowany C = PA.(M)odpowiadający wiadomości M
i przesyła tekst C Alicji.
• Alicja, otrzymawszy zaszyfrowany tekst C, stosuje do niego swój klucz taj-
ny s,.,otrzymując pierwotną wiadomość: M = S_.(C).
Proces ten ilustruje rys. 33.5. Ponieważ S_.() i P_.() są funkcjami odwrotny-
mi, Alicja może obliczyć M, mając C. Ponieważ jedynie Alicja potrafi obli-

Bob Alicja
Kanał przepływu informacji
Szyfrowanie Deszyfrowanie

M
.
--+-łt:,1-!'~~\iJ· ___ C=PA(M)
_:__;_c__:_~ c----1„
I.·
SA . M

Podsłuchujący przeciwnik

C

Rys. 33.5. Szyfrowanie w systemie z kluczem jawnym. Bob szyfruje wiadomość M, używając klucza
jawnego PA AJitji i przesyła Alicji otrzymany teht zaszyfrowany C = P,t(M). Przeciwnik.,który
przechwycił przesyłany tek.st zaszyfrowany, nie otrzymuje żadnej informacji o M. Alicja otrzymuje
tekst C i odszyfrowuje go za pomocą. swojego klucza tajnego, otrzymując pierwotną wiadomość
M = S,ł(C)

932
33.7. SYSTEM KRYPTOGRAFICZNY Z KLUCZEM JAWNYM RSA

czać S,1(), tylko ona jest w stanie obliczyć M, mając C. Zaszyfrowanie M za


pomocą P,1() utajniło M przed każdym z wyjątkiem Alicji.
Równie łatwe do zaimplementowania w systemach kryptograficznych
z kluczem jawnym są podpisy cyfrowe. Załóżmy teraz, że Alicja chce wysłać
Bobowi podpisaną cyfrowo odpowiedź M'. Scenariusz podpisu cyfrowego wy-
gląda następująco.

• Alicja oblicza swój podpis cyfrowy a dla wiadomości M' za pomocą swojego
klucza tajnego S,1jako a= S,1(M').
• Alicja wysyła do Boba parę wiadomość/podpis (M', a).
• Kiedy Bob otrzymuje parę (M', a), może sprawdzić, czy naprawdę pochodzi
ona od Alicji, korzystając z klucza jawnego Alicji i badając, czy zachodzi
równość M' = P,1(0). (Zakładamy, że M' zawiera imię Alicji, dzięki czemu
Bob wie, czyjego klucza jawnego użyć). Jeśli równość zachodzi, to Bob
może przyjąć, że wiadomość M' została faktycznie podpisana przez Alicję.
Jeśli nie, Bob wnioskuje, że wiadomość M' lub podpis cyfrowy a uległy
uszkodzeniu wskutek błędów transmisji albo też para (M', a) stanowi próbę
podszycia się pod Alicję.
Proces ten jest zilustrowany na rys. 33.6. Ponieważ podpis cyfrowy zapewnia
zarówno potwierdzenie tożsamości podpisującego, jak i autentyczności treści
podpisanej wiadomości, stanowi on odpowiednik ręcznego podpisu podpisem-
nym dokumentem.
Ważną własnością podpisu cyfrowego jest to, że jego autentyczność może
zweryfikować każdy, kto ma dostęp do klucza jawnego osoby podpisującej.
Podpisana wiadomość może zostać sprawdzona przez jedną osobę, a następnie
przekazana innym osobom, które także mogą ją sprawdzić. Wiadomość może
być na przykład elektronicznym czekiem Alicji wystawionym na Boba. Bob po
sprawdzeniu podpisu Alicji na czeku może przesłać ów czek do swojego banku,
który także sprawdzi podpis i zrealizuje stosowny przelew,

Alicja Bob

Podpisywanie
,S~-·:O"=SA(M')
i ,,

Akceptacja
(M',CT) M'
M'-_J_----~~---'"--""---L--''.'___J
Kanał przepływu informacji

Rys. 33.6. Podpis cyfrowy w systemie z kluczem jawnym. Alicja podpisuje wiadomość M', dołączając
do niej swój cyfrowy podpis (1 = S,.(M'). Przesyła do Boba parę wiadomość/podpis (M', (1),a ten
sprawdza.ją., badając, czy M' = P,4((1).Jeśli za.chodzi równość, Bob traktuje (M', IT)jako wiadomość
podpisaną przez Alitję

-·"--------------------------------
933
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

Zauważmy, że podpisana wiadomość nie jest zaszyfrowana - jest podana


„tekstem jawnym", nie zabezpieczona przed niepowołanym odczytem. Łącząc
powyższe protokoły szyfrowania i podpisywania, możemy tworzyć wiadomości,
które są jednocześnie podpisane i zaszyfrowane. Podpisujący najpierw dołącza
swój podpis cyfrowy do wiadomości, a następnie szyfruje otrzymaną parę wia-
domość/podpis kluczem jawnym planowanego adresata wiadomości. Odbiorca
rozszyfrowuje przysłany mu tekst swoim kluczem tajnym, otrzymując zarówno
pierwotną wiadomość,jak i jej cyfrowy podpis. Może teraz sprawdzić podpis za
pomocą klucza jawnego osoby podpisującej. Odpowiadający temu schematowi
proces operujący na dokumentach papierowych polega na ręcznym podpisaniu
wiadomości i umieszczeniu jej w kopercie, którą otworzyć może jedynie adresat.

System kryptograficzny RSA


W kryptosystemiez kluczemjawnym RSA użytkownicy tworzą swoje klucze
jawne i tajne za pomocą następującej procedury.
1. Wybierz losowo dwie duże liczby pierwsze pi q. Mogą one mieć, powiedz-
my, po 100 cyfr w zapisie dziesiętnym każda.
2. Oblicz n = pq.
3. Wybierz niewielką nieparzystą liczbę e względnie pierwszą z <p(n),na mocy
równania (33.20) wynoszącym (p - l)(ą - I).
4. Oblicz d będące multyplikatywną odwrotnością e modulo <p(n).(Na mocy
wniosku 33.26 d istnieje i jest wyznaczone jednoznacznie).
5. Udostępnij publicznie parę P = (e, n) jako swój klucz jawnyRSA.
6. Zachowaj w tajemnicy parę S = (d, n) jako swój klucz tajny RSA.
W schemacie tym zbiorem ?A dopuszczalnych wiadomości jest Z,,. Prze-
kształceniem wiadomości M odpowiadającym kluczowi jawnemu P = (e, n)jest

P(M) - M'(rnod n) (33.39)


Przekształceniem tek.stu zaszyfrowanego C odpowiadającym kluczowi tajnemu
S - (d, n) jest
S(C)- C'(rnod n) (33.40)
Równania te służą zarówno do szyfrowania, jak i do podpisów cyfrowych.
W celu utworzenia podpisu użytkownik stosuje swój klucz tajny do samej
podpisywanej wiadomości, a nie do tekstu zaszyfrowanego. Żeby sprawdzić
podpis, klucz jawny osoby podpisującej należy wówczas zastosować tylko do
podpisu, a nie do całej zaszyfrowanej wiadomości.
Operacje związane z kluczami jawnym i tajnym można zaimplementować
za pomocą procedury MODULAR~EXPONENTIATION, opisanej w podrozdz.
33.6. Żeby zanalizować złożoność tych operacji, załóżmy, że klucze jawny (e, n)

934
33.7. SYSTEM KRYPTOGRAFICZNY Z KLUCZEM JAWNYM RSA

i tajny (d, n) spełniają - [ni - p. Wówczas użycie klu-


zależności lei- 0(1), 1<>1
cza jawnego wymaga 0(1) mnożeń modularnych, czyli 0(/3 2 ) operacji na bi-
tach. Użycie klucza tajnego wymaga 0(/J) mnożeń modularnych, czyli O(JJ3 )
operacji na bitach.

'fWIERDZENIE 33.36. (Poprawność RSA)


Równania RSA (33.39) i (33.40) definiują wzajemnie odwrotne przekształcenia
Z,._,spełniające równania (33.37) i (33.38).

DOWÓD
Z równań (33.39) i (33.40) wynika, że dla dowolnego ME Z,._zachodzi

P(S(M)) - S(P(M)) - M°'(mod n)

Ponieważ e i d są swoimi multyplik.atywnymi odwrotnościami module


~(n) - (p - l)(q - I}, więc

ed-1 +k(p- l)(q-1)

dla pewnego całkowitego k. Wówczas jednak, jeśli M ~ O (mod p), to (korzys-


tając z twierdzenia 33.31) mamy

Mu = M(MP- 1)~(q- tJ (mod p)

= M(I}''•- '' (mod p)


- M (modp}

Również jeśli M = O (mod p), to Mu - M (mod p). Zatem


M"' - M (mod p)
dla dowolnego M. Podobnie
M"' - .M (mod q)
dla dowolnego M. Zatem na mocy wniosku 33.29 z chińskiego twierdzenia
o resztach mamy
M"' - M (mod n)
dla każdego M.

Bezpieczeństwo
systemu RSA opiera się w dużej mierze na trudności roz-

kładania na czynnik.i dużych liczb. Jeśli nasz przeciwnik potrafi rozłożyć na
czynniki liczbę n z klucza jawnego, to może na podstawie klucza jawnego
------------------------------
935
ROZDZIAŁ 33. ALGORYTMY TEOR10LJCZB0WE

obliczyć klucz tajny, korzystając ze znajomości czynników p i q, w taki sam


sposób, w jaki zrobił to autor klucza jawnego. Jeśli zatem łatwo jest rozkładać
duże liczby na czynniki, łatwo również złamać kryptosystem RSA. Twierdze-
nia odwrotnego, mówiącego, że jeśli rozkładanie dużych liczb na czynniki jest
trudne, to złamanie RSA tez jest trudne, dotychczas nie udowodniono. Jednak
pomimo kilkunastu lat badań nie znaleziono lepszej metody łamania systemu
RSA niż przez rozkład na czynniki liczby n, jak zaś przekonamy się w pod-
rozdz. 33.9, problem rozkładu dużych liczb na czynniki jest zadziwiająco trud-
ny. Wybierając losowo i mnożąc przez siebie dwie 100-cyfrowe liczby pierwsze,
każdy może utworzyć klucz jawny, którego nie da się „złamać" w rozsądnym
czasie przy wykorzystaniu współcześnie dostępnej techniki. Wobec braku za-
sadniczego przełomu w dziedzinie algorytmów teorioliczbowych stosowanie
systemu kryptograficznego RSA może zapewnić wysoki poziom bezpieczeń­
stwa przekazu informacji.
Żeby jednak osiągnąć bezpieczeństwo w systemie RSA, należy posługiwać
się liczbami o przynajmniej 100-200 cyfrach, gdyż rozkład na czynniki mniej-
szych liczb nie jest zadaniem nierealnym. Trzeba zwłaszcza wnieć znajdować
efektywnie duże liczby pierwsze, żeby można było tworzyć klucze odpowied-
niej długości. Problemem tym zajmujemy się w podrozdz. 33.8.
Z uwagi na efektywność systemu RSA często używa się w trybie „hybry-
dowym" albo „zarządzania kluczami" wespół z szybkimi kryptosystemami bez
klucza jawnego, W systemach takich do szyfrowania i deszyfrowania używa się
tego samego klucza. Jeśli Alicja chce wysłać do Boba długą wiadomość M z za-
chowaniem tajności, wybiera losowy klucz K dla szybkiego kryptosysternu bez
klucza jawnego i szyfruje M za pomocą klucza K, otrzymując tekst zaszyfro-
wany C. Tekst C jest tutaj tego rozmiaru co M, ale K jest całkiem krótki.
Następnie Alicja szyfruje K za pomocą jawnego klucza RSA Boba. Ponieważ
Kjest krótki, obliczenie Ps(KJ odbywa się szybko (znacznie szybciej niż obli-
czenie Ps(M)). Alicja przesyła teraz parę (C, PB(K)) do Boba, który deszyfruje
PB(K), otrzymując K, za pomocą którego deszyfruje C, otrzymując M.
Podobnej mieszanej techniki używa się do efektywnej realizacji podpisów
cyfrowych. W metodzie tej RSA łączy się z jednokierunkową funkcją skrótut
h - funkcją, którą łatwo obliczać, ale dla której nierealne pod względem ob-
liczeniowym jest znalezienie dwóch różnych wiadomości M i M' takich, że
h(M) - h(MJ. Wartość h(M) jest krótkim (powiedzmy 128-bitowym) ,,odcis-
kiem palca" wiadomości M. Jeśli Alicja chce podpisać wiadomość M, stosuje
najpierw funkcję h do M, otrzymując „odcisk palca" h(M), który następnie
podpisuje swoim tajnym kluczem. Jako podpisaną wersję wiadomości M wysy-
ła Bobowi parę (M, S,t(h(M))). Bob może zweryftk.ować podpis, obliczając

t Używane jest również określenie jednokierunkowa funkcja haszują.ca, pochodzące bezpoś­


rednio od terminu ang. one-way hashJunction (przyp. red.).

936
* 33.8. SPRAWDZANIE, CZY LICZBA JEST LICZBĄ PIERWSZĄ

h(M) i sprawdzając, czy w efekcie zastosowania P14 do otrzymanego tekstu


S 14(h(M)) rzeczywiście dostaje się h(M). Ponieważ nikt nie potrafi utworzyć
dwóch wiadomości mających ten sam „odcisk palca", nie można zmienić treści
podpisanej wiadomości przy zachowaniu ważności podpisu.
Wspomnijmy wreszcie o idei certyfikatów, znacznie ułatwiającej rozpo-
wszechnianie kluczy jawnych. Zalóimy na przykład, że istnieje „powszechnie
uznany autorytet" T, którego klucz jawny znają wszyscy. Alicja może otrzy-
mać od T podpisaną wiadomość (jej certyfikat) mówiącą, że „kluczem jawnym
Alicji jest P 14." Certyfikat ten sam potwierdza swoją autentyczność, ponieważ
klucz Pr jest znany każdemu. Alicja może dołączać swój certyfikat do pod-
pisywanych przez siebie wiadomości, dzięki czemu odbiorca ma od razu dostęp
do klucza jawnego Alicji i może sprawdzić jej podpis. Ponieważ jej klucz został
podpisany przez T, odbiorca wie, że klucz Alicji naprawdę należy do niej.
ZADANlA

33.7-1. Rozważmy szyfr RSA, w którymp = 11, q = 29, n= 319, e = 3. Jakiej


wartości d należy użyć jako klucza tajnego? Jaki jest tekst zaszyfrowany
dla wiadomości M = 100?
33.7-2. Udowodnij, że jeśli wykładnikiem w kluczu jawnym Alicji jest e równe
3, a przeciwnik zdobył wykładnik d z jej klucza tajnego, to może rozłożyć
na czynniki liczbę n w czasie wielomianowym ze względu na liczbę bitów
w n. (Ciekawym faktem, chociaż nie prosimy tutaj o jego dowód, jest to, że
wynik ten pozostaje prawdziwy również bez założenia, że e = 3. Patrz Mil-
ler [147]).
* 33.7-3. Udowodnij, że szyfr RSA jest multyplikatywny w tym sensie, że

P,(M,)P ,(M,) = P ,(M,M,) (mod n)

Wykorzystaj ten fakt w dowodzie, że jeśli przeciwnik ma procedurę, za


pomocą której potrafi efektywnie deszyfrować 1°/owiadomości wybranych
losowo z Z 11 i zaszyfrowanych kluczem P14, to może on zastosować al-
gorytm probabilistyczny, deszyfrujący każdą wiadomość zaszyfrowaną
kluczem P14 z dużym prawdopodobieństwem.

*33.8. Sprawdzanie,czy liczbajest liczbą pierwszą


W tym podrozdziale rozważamy problem znajdowania dużych liczb pierw-
szych. Zaczniemy od omówienia gęstości rozmieszczenia liczb pierwszych, po-
tem zbadamy obiecujące (choć nie całkiem skuteczne) podejście do problemu
sprawdzania, czy liczba jest liczbą pierwszą, a następnie przedstawimy efektyw-
ną metodę probabilistyczną dla tego problemu, autorstwa Millera i Rabina.

937
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

Gęstość rozmieszczenialiczb pierwszych


W wielu zastosowaniach (takich jak kryptografia} musimy znajdować duże
„losowe" liczby pierwsze. Na szczęście duże liczby pierwsze nie są szczególnie
rzadkie, dlatego nie jest zbyt czasochłonne sprawdzanie losowo wybranych
liczb całkowitych odpowiedniego rozmiaru, dopóki nie traflIDy na liczbę
pierwszą. Funkcja rozmieszczenia liczb pierwszych n(n} określa liczbę liczb
pierwszych mniejszych bądź równych n. Na przykład 1t{lO}= 4, bo istnieją
4 liczby pierwsze mniejsze bądź równe l O, a mianowicie 2, 3, 5 i 7. Twierdzenie
o liczbach pierwszych daje użyteczne oszacowanie funkcji x(n).

TwlERDZENIE 33.37. (Twierdzenieo liczbach pierwszych)

. n(n)
hm ----- = 1
11.... «> n/Inn


Oszacowanie n/In n daje stosunkowo dokładne oszacowanie wartości x(n)
już dla niewielkich n. Na przykład dla n= 109 różnica wynosi mniej niż 6%,
bo x(n) = 50 847 478, a n/ln n = 48 254942. (Dla naukowca zajmującego się
teorią liczb 109 to mała liczba).
Korzystając z twierdzenia o liczbach pierwszych, prawdopodobieństwo te-
go, że losowo wybrana liczba n okaże się liczbą pierwszą, możemy oszacować
przez 1/lnn. W celu znalezienia liczby pierwszej tej samej długości co n będzie­
my zatem musieli przebadać około In n losowo wybranych liczb w pobliżu n.
Na przykład znalezienie 100-cyfrowej liczby pierwszej wymagałoby sprawdze-
nia około In 10100 ~ 230 losowo wybranych liczb 100-cyfrowych. (Liczbę tę
można zmniejszyć o połowę, wybierając tylko liczby nieparzyste).
W dalszej części tego podrozdziału zajmiemy się problemem sprawdzania,
czy dana duża nieparzysta liczba całkowita n jest liczbą pierwszą. Dla wygody
przyjmiemy, że rozkładem n na czynniki jest

n -p'•p'•
1 2 ... p'·
r (33.41)

gdzie r ~ 1, a p 1 , p 2 , ... , p, są różnymi czynnikami pierwszymi n. Oczywiście


n jest liczbą pierwszą wtedy i tylko wtedy, gdy r = 1 i e 1 = 1.
Najprostsze podejście do problemu sprawdzania, czy liczba jest liczbą
pierwszą, polega na dzieleniu do skutku. Próbujemy dzielić n przez kolejne
liczby 2, 3, ... , LJ~J. (fak jak przy losowaniu, liczby parzyste większe od 2
można pominąć). Łatwo sprawdzić, że liczba n jest liczbą pierwszą wtedy i tyl-
ko wtedy, gdy nie dzieli się przez żadną z nich. Przy założeniu, że każde takie
dzielenie zajmuje czas stały, czas sprawdzania w najgorszym przypadku wy-

938
* 33.8. SPRAWDZANIE, C2Y LICZBA JEST LICZBĄ PIERWSZĄ

nosi 0(.Jfl.), jest więc wykładniczy ze względu na długość liczby n. (Przypom-


nijmy, że jeśli liczba n jest zakodowana binarnie za pomocą p bitów, to
.J
p = flg(n + 1)1, a więc n = 0(2 1712 )). Metoda dzielenia do skutku działa za-
tem dobrze jedynie wtedy, gdy n jest bardzo małe albo ma mały czynnik pierw-
szy. Jeśli metoda działa, to ma przy tym tę zaletę, że nie tylko rozstrzyga, czy n
jest liczbą pierwszą czy złożoną, ale w tym drugim przypadku wyznacza także
rozkład na czynniki pierwsze.
Tutaj jesteśmy zainteresowani wyłącznie stwierdzeniem, czy dana liczba
n jest liczbą pierwszą; jeśli n jest liczbą złożoną, nie zajmujemy się jej rozkła­
dem na czynniki. Jak przekonamy się w podrozdz. 33.9, znalezienie rozkładu
liczby na czynniki pierwsze jest kosztowne pod względem obliczeniowym. Dość
zaskakujący jest fakt, że znacznie łatwiej rozstrzygnąć, czy dana liczba jest
liczbą pierwszą, niż wyznaczyć jej rozkład na czynniki, jeśli jest liczbą złożoną.

Sprawdzanie, czy liczba jest liczbą pseudopierwszą


Zajmiemy się teraz metodą sprawdzania, ci;y liczba jest liczbą pierwszą, która
jest „prawie skuteczna" i w istocie w wielu praktycznych zastosowaniach wy-
starczająca. Później omówimy ulepszenie tej metody, eliminujące jej drobną
wadę. Niech z:oznacza zbiór niezerowych elementów Z,.:

z-:={1,2, ...,n-1}

Jeśli n jest liczbą pierwszą, to z: = z:.


Mówimy, że liczba n jest pseudopierwsza przy podstawie a, jeśli n jest liczbą
złożoną oraz

a"-' - I (mod n) (33.42)

Z twierdzenia Fermata (tw. 33.31) wynika, że jeśli n jest liczbą pierwszą,


to spełnia równanie (33.42) dla każdego a należącego do z:.
Jeśli zatem mo-
żemy znaleźć jakiekolwiek aEZ: takie, że n nie spełnia równania (33.42),
to liczba n na pewno jest złożona. Co zadziwiające, stwierdzenie odwrotne
jest prawie zawsze spełnione; kryterium to stanowi zatem niemal doskonały
test rozstri;ygający, czy liczba jest liczbą pierwszą. Sprawdzamy, czy n spełnia
równanie (33.42) dla a = 2. Jeśli nie, stwierdzamy, że n jest liczbą złożoną.
W przeciwnym razie odpowiadamy, że n jest liczbą pierwszą (chociaż tak na-
prawdę wiemy jedynie, że liczba n jest albo pierwsza, albo pseudopierwsza
przy podstawie 2).
Poniższa procedura w ten właśnie sposób udaje, że sprawdza, czy n jest
liczbą pierwszą. Korzysta ona z procedury MODULAR-EXPONENTIATION po-
danej w pod.rozdz. 33.6. O wejściowej liczbie n zakładamy, że jest większa od 2.

939
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

PSEUDOPRIME(n)
l if M0DULAR-EXPONENTIATION(2, n - I, n);/; l (mod n)
2 tben return ZŁOŻONA t> Na pewno.
3 else return PIERWSZA t> Miejmy nadzieję!

Procedura ta może popełniać błędy, ale tylko jednego rodzaju. Jeśli udziela
odpowiedzi, że n jest liczbą złożoną, jest to zawsze prawda. Jeśli oświadcza,
że n jest liczbą pierwszą, to myli się tylko wtedy, gdy n jest liczbą pseudopierw-
szą przy podstawie 2.
Jak często nasza procedura się myli? Zaskakująco rzadko. Wśród n mniej-
szych niż 1OOOOsą tylko 22 wartości, dla których się to zdarza; pierwsze cztery
z nich to 341,561,645 i 1105. Można pokazać, że prawdopodobieństwo popeł­
nienia błędu przez powyższy program dla losowo wybranej liczby P-bitowej
dąży do zera przy p --+ oo. Pomerance (90] podaje dokładniejsze oszacowanie,
z którego wynika, iż jest mniej niż jedna szansa na milion, że losowo wybrana
liczba 50-cyfrowa, którą powyższa procedura określi jak.o pierwszą, okaże się
pseudopierwsza przy podstawie 2, a dla losowo wybranej liczby I DO-cyfrowej
szansa ta jest mniejsza niż jeden na 1013 .
Niestety, nie uda się nam wyeliminować wszystkich błędów, sprawdzając po
prostu, czy spełnione jest równanie (33.42) dla kolejnej podstawy, powiedzmy
a= 3, ponieważ istnieją liczby złożone n, które spełniają równanie (33.42) dla
każdego a Ez:. Liczby te znane są pod nazwą liczb Carmichaela. Pierwsze trzy
liczby Carmichaela to 561, 1105 i 1729.Liczby Carmichaela występują niesłycha­
nie rzadko; na przykład wśród liczb mniejszych od 100 OOO OOO jest ich zaledwie
255. W zadaniu 33,8-2 będzie wyjaśnione, dlaczego są one taką rzadkością.
Pokażemy teraz, jak ulepszyć metodę sprawdzania, czy liczba jest pierw-
sza, żeby liczby Carmichaela nie mogły spowodować jej błędnego działania.

Probabilistyczny test Millera-Rabina sprawdzający,


czy liczba jest pierwsza
Test Millera-Rabina sprawdzający, czy liczba jest pierwsza. radzi sobie z kło­
potami prostego testu PSEUDOPRIMEdzięki dwóm modyfikacjom:
• Sprawdza nie jedną, lecz kilka losowo wybranych wartości podstawy a.
• Podczas obliczania każdego modularnego potęgowania algorytm sprawdza,
czy nie został wykryty jakiś nietrywialny pierwiastek kwadratowy z 1 modu-
lo n. Jeśli tak, to zatrzymuje się z odpowiedzią ZŁOŻONA. Wniosek 33.35
stanowi uzasadnienie takiego sposobu wykrywania liczb złożonych.
Dalej zamieszczamy pseudokod testu Millera-Rabina (procedura MIL-
LER-RABIN). Wejściowa nieparzysta liczba n> 2 to ta, co do której należy
rozstrzygnąć, czy jest liczbą pierwszą, s zaś to liczba losowo wybranych war-

940
* 33.8. SPRAWDZANIE, CZY LICZBA JEST LICZBĄ PIERWSZĄ

tości podstawy ze zbioru z: do sprawdzenia.


Procedura korzysta z generatora
liczb losowych RANDOM opisanego w pod.rozdz. 8.3: wywołanie RANDOM
(1, n - 1) zwraca losowo wybraną liczbę całkowitą a taką, że 1 ~ a ~ n - l.
Jest tu także zastosowana pomocnicza funkcja WITNESS. Wartością WIT-
NESS(a, n)jest TRUE wtedy i tylko wtedy, gdy a jest „świadectwem" złożoności
liczby n - tzn. jeśli można użyć a do udowodnienia (w sposób, o którym zaraz
powiemy), że n jest liczbą złożoną. Test WITNESs(a, n) jest podobny, chociaż
skuteczniejszy od testu sprawdzającego, czy

a"-' ,t 1 (mod n)

na którym opierała się (dla a= 2) procedura PSEUDOPRIME.Najpierw przed-


stawimy i uzasadnimy konstrukcję procedury WITNESS, a następnie pokażemy,
jak wykorzystuje się ją w teście Millera-Rabina.

WITNESs(a, n)
1 niech (b1;, bt-l• ..., b0 ) będzie binarną reprezentacją liczby n -1
2 d,f----1
3 for i ,.__k downto O
4 do x,.__d
5 d+-(d·d)modn
6 ifd=lix#lix=#:n-1
7 then return TRUE
8 ifb,-1
9 then d,.__(d·a) mod n
10 ifd,'l
11 then return TRUE
12 return FALSE

Powyższy pseudokod jest oparty na pseudokodzie procedury MODULAR-


-EXPONENTIATION. W wierszu 1 wyznaczamy binarną reprezentację liczby
n - 1, z której skorzystamy, podnosząc a do potęgi n - l. W wierszach 3-9 jest
obliczane d jak.o (l'- 1 mod n. Zastosowana metoda jest taka sama jak w proce-
durze MODULAR-EXPONENTIATION.Przy każdym podnoszeniu do kwadratu
(w wierszu 5) sprawdzamy jednak. dodatkowo w wierszach 6-7, czy nie został
wykryty nietrywialny pierwiastek kwadratowy z 1. Jeśli tak, algorytm zatrzy-
muje się i zwraca wartość TRUE. W wierszach 10-11 jest zwracana wartość
TRUE, jeśli obliczona wartość a"- 1 mod n nie jest równa I, podobnie jak
w procedurze PSEUDOPRIME,zwracającej w tym przypadku wartość ZŁOŻONA.
Wykażemy teraz, że jeśli wywołanie WITNESS(a, n) zwraca wartość TRUE,
to korzystając z a, można udowodnić, że liczba n jest złożona.

941
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

Jeśli procedura WITNESS zwraca wartość TRUE w wierszu 11, to wiadomo,


że d = a"- 1 mod n ,;. l. Jeśli jednak n jest liczbą pierwszą, to na mocy twier~
dzenia Fe1mata (tw. 33.31) zachodzi a"- 1 = 1 (mod n) dla każdego aez;.
Zatem liczba n nie może być liczbą pierwszą, to zaś, że a"- 1 mod 1 # 1, jest
dowodem tego faktu.
Jeśli procedura WITNESS zwraca wartość TRUE w wierszu 7, to wykryła
ona, że x jest nietrywialnym pierwiastkiem kwadratowym z 1 module n, ponie-
waż zachodzi wówczas x ~ + l (mod n), ale x 2 = 1 (mod n). Wniosek 33.35
mówi, że nietrywialny pierwiastek z 1 module n może istnieć tylko wtedy,
kiedy n jest liczbą złożoną, zatem wykazanie, że x jest nietrywialnym pierwiast-
kiem kwadratowym z 1 module n, stanowi dowód, że n jest liczbą złożoną.
Kończy to dowód poprawności procedury WITNESS.Jeśli wywołanie WIT"
NESS(a, n) zwraca wartość TRUE, to n jest na pewno liczbą złożoną, a dowód
tego faktu można łatwo wyprowadzić, korzystając z liczb a i n. Przedstawimy
teraz test Millera-Rabina sprawdzający, cr.y liczba jest pierwsza, który korzy-
sta z procedury WITNESS,
MILLER-RABIN(n, s)
1 forJ+--1 tos
2 do a+--R.ANDOM(l, n-1)
3 if WITNESS(a, n)
4 then return ZŁOŻONA t> Na pewno.
5 return PIERWSZA t> Prawie na pewno.
Procedura MILLER-RABIN polega na probabilistycznym poszukiwaniu do-
wodu, że liczba n jest złożona. W głównej pętli (zaczynającej się w wierszu 1)
jest wybieranych s losowych wartości a ze zbioru z: (wiersz 2). Jeśli jedna
z wybranych wartości a jest świadectwem złożoności n, to procedura MILLER-
-RABIN zwraca wartość ZŁOŻONA w wierszu 4. Odpowiedź taka jest zawsze
zgodna z prawdą, co wynika z poprawności procedury WITNESS. Jeśli po
s próbach nie udało się znaleźć żadnego świadectwa, procedura MILLER-RA-
BIN przyjmuje, iż stało się tak, ponieważ takich świadectw w ogóle nie ma, bo
n jest liczbą pierwszą. Przekonamy się, że odpowiedź taka jest z dużym praw-
dopodobieństwem prawdziwa, jeśli sjest dostatecznie duże, ale istnieje niewiel-
ka szansa, że to wybór wartości a był pechowy, a świadectwa istnieją, chociaż
żadne nie zostało znalezione.
Działanie procedury MILLER-RABIN zilustrujemy na przykładzie, w któ-
rym n jest liczbą Carmichaela 561. Przypuśćmy, że jako podstawa została wy-
brana liczba a= 1. Z rysunku 33.4 widać, że procedura WITNESS w ostatnim
kroku podnoszenia do kwadratu znajduje nietrywialny pierwiastek kwadrato~
wy z 1, ponieważ a 280 = 67 (mod n), zaś a560 = 1 (mod n). Liczba a= 1 jest
zatem świadectwem złożoności n, wywołanie WITNESS(7, n) zwraca wartość
TRUE, a odpowiedź procedury MILLER-RABIN brzmi ZLOŻONA.

942
* 33.8. SPRAWDZANIE, CZY LICZBA JEST LICZBĄ PIERWSZĄ

Jeśli
n jest liczbą ,B-bitową, procedura MILLER-RABIN wykonuje O(s,B)
operacji arytmetycznych i O(s,83) operacji na bitach, ponieważ związana z nią
praca jest asymptotycznie nie większa niż przy .vmodularnych potęgowaniach.

Prawdopodobieństwo błędu w teście Millera-Rabina


Jeśli procedura MILLER-RABIN udziela odpowiedzi PIERWSZA,to istnieje nie-
wielka szansa, że popełniła ona błąd. Jednak w odróżnieniu od procedury
PSEUDOPRIMEprawdopodobieństwo błędu nie zależy od n; w tym wypadku
nie ma żadnych złych danych wejściowych. Możliwość powstania błędu zależy
raczej od liczby prób s oraz „szczęścia w losowaniu" podczas wybierania war-
tości podstawy a. Oprócz tego, ponieważ każdy z testów jest silniejszy niż
proste sprawdzenie równania (33.42), możemy się ogólnie spodziewać, że pro-
cent błędów dla losowo wybieranych liczb n powinien być niewielki. Poniższe
twierdzenie uściśla te oczekiwania.

TWIERDZENIE 33.38.
Jeśli n jest nieparzystą liczbą złożoną, to liczba.świadectw złożoności n wynosi
przynajmniej (n - 1)/2.

DOWÓD
Pokażemy, że liczba liczb nie będących świadectwami nie przekracza (n - 1)/2,
skąd wynika teza twierdzenia.
Zauważmy najpierw, że każda liczba nie będąca świadectwem musi być
elementem z:,
ponieważ dla każdej takiej liczby a zachodzi d'- 1 - I (mod n),
a jeśli gcd(a, n)= d> 1, to na mocy wniosku 33.21 równanie ax = 1 (mod n)
nie ma rozwiązania x. (W szczególności rozwiązaniem nie jest x = tł'- 2). Za-
tem każdy element zbioru z,,.- z:
jest świadectwem złożoności n.
żeby zakończyć dowód, wykażemy, że wszystkie liczby nie będące świade­
ctwami są zawarte we właściwej podgrupie B grupy z:.
Na mocy wniosku
33.16 mamy wówczas IBI::,;: 1z:112.Ponieważ 1z:1::,;:n - 1, dostajemy IBI~
::,;:(n - 1)/2. Liczba liczb nie będących świadectwami nie przekracza zatem
(n - 1)/2, więc świadectw jest przynajmniej (n - 1)/2.
Pokażemy teraz, jak znaleźć właściwą podgrupę B grupy Z~ zawierającą
wszystkie liczby nie będące świadectwami. Dowód rozbijemy na dwa przypadki.

Przypadek 1: Istnieje element xez: tak.i, że


x"-' ;/ć 1 (mod n) (33.43)
Przyjmijmy B = {be z::
b"'- 1 = 1 (mod n)}. Ponieważ zbiór B jest zamknięty
ze względu na mnożenie modulo n, na mocy twierdzenia 33.14 B jest pod-
grupą z:,
Zauważmy, że każda liczba nie będąca świadectwem należy do B, bo

~----------------------9~43
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

dla każdej takiej liczby a zachodzi a"- 1


Eo 1 (mod n}. Ponieważ xE z:- B,
grupa B jest właściwą podgrupą z:.
Przypadek 2: Dla każdego XE z:zachodzi
x•- 1 =I (mod n) (33.44)
W tym przypadku n nie może być potęgą liczby pierwszej. Dowodząc nie
wprost, przyjmijmy, że n= p~, gdzie p jest nieparzystą liczbą pierwszą ie> l.
Z twierdzenia 33.32 wynika, iż grupa z:
zawiera element g taki, że
ord.(g) = 1z:1= <p(n)= (p- l)p'- 1 . Wówczas jednak z równania (33.44)
i z twierdzenia o logarytmie dyskretnym (tw, 33.33, przy y = O) wynika, że
n - I s O (mod <p(n)),czyli że

Warunek ten nie zachodzi dla e > 1, gdyż lewa strona dzieli się pr:rez p, a pra-
wa nie. Liczba 11 nie jest zatem potęgą liczby pierwszej.
Ponieważ n nie jest potęgą liczby pierwszej, rozłóżmy ją na iloczyn n 1n 2 ,
gdzie n1 i 112 są większe niż 1 i względnie pierwsze. (Może istnieć wiele sposo-
bów takiego rozkładu i nie ma znaczenia, który z nich wybierzemy. Jeśli na
przykład 11 = p'j_•
p1•... p;·, to możemy wybrać 111 = p'j_•i n2 = p1•P~'... p;·).
2.defmiujmy t oraz u tak, że n - 1 = 2'u, gdzie t ~ I, u zaś jest nieparzyste.
Dla dowolnego a EZ: rozważmy ciąg

(33.45)

którego wszystkie elementy są obliczanemodulo 11. Ponieważ 2t In - 1, w binar-


nej reprezentacji liczby n - 1 występuje na końcu t zer, a elementy ciągu ó. to
ostatnich t + l wartości d obliczanych w procedurze WITNESSw trakcie wyzna-
czania wartości a'- 1 mod n; ostatnich t operacji to podnoszenie do kwadratu.
Weźmy teraz jE{O, 1, ..., t} takie, że istnieje vez: spełniające warunek
v iu = - 1 (mod n); liczba j powinna być największa z możliwych. Takiej na
2

pewno istnieje, ponieważ u jest nieparzyste: można przyjąć v = -1 i j = O.


Ustalmy v spełniające powyższy warunek i przyjmijmy

B= {xEZ::x 2'u =+I (mod 11)}

Ponieważ zbiór B jest zamknięty


ze względu na operację mnożenia module n,
jest on podgrupą z:, wobec czego IBI dzieli 1z:1. Każda liczba nie będąca
świadectwem musi należeć do B, gdyż utworzony dla takiej liczby ciąg (33.45)
musi albo składać się z samych jedynek, albo zawierać -1 nie dalej niż naj-tej
pozycji, z uwagi na to, że j jest maksymalne.

944
* 33.8. SPRAWDZANIE, CZY LICZBA JEST LICZBĄ PIERWSZĄ

Faktu istnienia v użyjemy teraz do wykazania, że istnieje element


wez:- B. Ponieważ v21": -1 (mod n), na mocy wniosku 33.29 mamy
v2 i" s -1 (mod n 1 ). Z wniosku 33.28 wynika, że istnieje w spełniające jedno-
cześnie obydwa równania:

w= 1 (mod n 2)
Stąd

w2 i., - - 1 (mod n 1 )

w2i" - 1 (mod n2 )

W połączeniu z wnioskiem 33.29 z równań tych wynika, że

w2i" '.f:.+ 1 (mod n) (33.46)

a zatem wr/B.Ponieważ vez:, wiemy, że vez:,. Zatem wez:, czyli


wez: - .B. Stąd wniosek, że B jest podgrupą właściwą grupy z:.
W obydwu przypadkach wykazaliśmy, że liczba świadectw złożoności licz-
by n wynosi przynajmniej (n - 1)/2.


TWIERDZENIE 33.39.
Dla dowolnej nieparzystej liczby n > 2 i dodatniej liczby s prawdopodobień­
stwo tego, że procedura MILLER-RABIN(n, s) udzieli błędnej odpowiedzi, nie
przekracza 2 - •.

DOWÓD
Z twierdzenia 33.38 wiemy, że jeśli n jest liczbą złożoną, to w każdym przebie-
gu pętli w wierszach 1-4 prawdopodobieństwo znalezienia świadectwa x złożo­
ności n jest równe przynajmniej 1/2. Procedura MILLER-RABIN popełnia błąd
tylko wtedy, gdy w żadnym z s przebiegów głównej pętli nie trafi na świade­
ctwa złożoności n. Prawdopodobieństwo takiego ciągu niepowodzeń nie prze-
kracza 2-•.

Przyjęcie s = 50 powinno
zatem wystarczyć w niemal każdym zastosowa-
niu, jakie sobie mo.żna wyobrazić. Jeśli próbujemy znajdować duże liczby
pierwsze, stosując algorytm MILLER-RABIN do losowo wybranychdużych liczb,
to można pokazać (chociaż tego dowodu tu nie przedstawimy), że już przy
bardzo małych wartościach s (powiedzmy s = 3) szansa na błędny wynik jest

945
ROZDZIAŁ 33. ALGORYTMY TE0Rł0LICZB0WE

znikoma. Oznacza to, że dla losowo wybranej nieparzystej liczby złożonej


n oczekiwana liczba liczb nie będących świadectwami złożoności n jest z dużym
prawdopodobieństwem znacznie mniejsza niż (n - 1)/2. Jeśli jednak liczby
n nie wybieramy losowo, można co najwyżej udowodnić, że liczba liczb nie
będących świadectwami nie przekracza (n - 1)/4, wzmacniając w ten sposób
twierdzenie 33.38. Co więcej, istnieją liczby n, dla których liczba liczb nie będą­
cych świadectwami jest równa (n - 1)/4.

ZADANIA
33.8-1. Udowodnij, że jeśli n> 1 nie jest liczbą pierwszą ani potęgą liczby
pierwszej, to istnieje nietrywialny pierwiastek kwadratowy z 1 module n.
* 33.8-2. Można nieco „wzmocnić" twierdzenie Eulera do następującej postaci:

a 1<nl- 1 (mod n) dla wszystkich a Ez:

gdzie dla n= pi• ... p~· liczba l(n) jest zdefiniowana wzorem
l(n) - lcm(ą,(pj•), ... , ą,(p;•)) (33.47)

(Przypomnijmy, że symbol Iem oznacza najmniejszą wspólną wielokrot-


ność zbioru liczb). Udowodnij, że ,ł.(n)] cp(n), Liczba złożona n jest liczbą
Carmichaela, jeśli l(n) 1n - 1. Najmniejszą liczbą Carmichaela jest
561 - 3 · 11 · l 7; tutaj l(n) - lcm(2, 10, 16) - 80, a 80 dzieli 560. Udowod-
nij, że liczby Carmichaela muszą jednocześnie być „bezkwadratowe" (nie-
podzielne przez kwadrat żadnej liczby pierwszej) i być iloczynem przynaj-
mniej trzech liczb pierwszych. To wyjaśnia, dlaczego nie występują one
zbyt często,
33.8-3. Udowodnij, że jeśli x jest nietrywialnym pierwiastkiem kwadratowym
z I modulo n, to zarówno gcd(x - 1, n), jak i gcd(x + 1, n) są nietrywial-
nymi dzielnikami n.

*33.9. Rozkład na czynniki


Przypuśćmy, że mamy daną liczbę całkowitą n, którą chcemy rozłożyć
na czyn-
niki, tzn. przedstawić w postaci iloczynu liczb pierwszych. Opisany w poprzed-
nim podrozdziale test sprawdzający, czy liczba jest liczbą pierwszą, powie nam,
czy n jest liczbą złożoną, ale nie poda czynników pierwszych liczby n. Rozkład
na czynniki dużej liczby całkowitej n wydaje się być znacznie trudniejszym
zadaniem niż samo rozstrzygnięcie, czy n jest liczbą pierwszą czy złożoną.
Nawet korzystając ze współczesnych superkomputerów i najlepszych znanych
dziś algorytmów, nie jesteśmy w stanie rozłożyć na czynniki dowolnej liczby
200wcyfrowej.

946
* 33.9. ROZKŁAD NA CZYNNIKI

Heurystyka „ro" Pollarda

Dzieląc do skutku przez wszystkie liczby aż do B, rozłożymy całkowicie na


czynniki każdą liczbę aż do B 2 • Wykonując taką samą pracę, poniższa proce-
dura rozłoży na czynniki każdą liczbę aż do .84-(chyba że będziemy mieli
pecha). Ponieważ procedura ta jest jedynie heurystyką, nie można za.gwaran-
tować ani czasu jej działania, ani tego, że zakończy się sukcesem, chociaż
w praktyce jest ona bardzo efektywna.

POLLARD-RHO(n)
1 i+- I
2 x 1 +-RANDOM(O,n - 1)
3 y +- X 1
4 k+-2
5 while TRUE
6 doi+-i+l
7 x 1 +-(xf_ 1 -l)modn
8 d~ gcd(y- x,, n)
9 ifd:;ćlid"#n
IO then wypisz d
Il ifi-k
12 theny+-x 1
13 k~2k

Procedura działa
w następujący sposób. W wierszach 1-2 są nadawane
wartości początkowe: miiennej i jest przypisywana wartość I, a x 1 otrzymuje
losowo wybraną wartość ze zbioru Z". W nieskończonej pętli while szukamy
czynników w rozkładzie n. W każdym przebiegu pętli while,korzystając z reku-

rencY)nego wzoru

xi+-(xf- 1 -l)modn (33.48)

w wierszu 7 tworzymy kolejną wartość x 1 nieskończonego ciągu

(33.49)

zwiększając przy tym odpowiednio wartość i w wierszu 6. Dolnych indeksów


przy zmiennych x; użyliśmy jedynie w celu poprawienia czytelności kodu,
a program działa tak samo po usunięciu wszystkich indeksów, ponieważ prze-
chowywać trzeba tylko ostatnią wartość x 1•
Co jakiś czas program zapamiętuje w miiennej y ostatnio utworzoną war-
tość x 1• Ściślej, zapamiętywane wartości to te o indeksach będących potęgami 2:

947
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

Wartość x 1 jest zapamiętywana w wierszu 3, a w wierszu 12 jest zapamiętywa­


na wartość xk za każdym razem, kiedy i jest równe k. Zmiennej kw wierszu 4
jest nadawana wartość początkowa 2, a przy każdej zmianie wartości y w wier-
szu 13 wartość k się podwaja. Zatem wartość k przebiega kolejne elementy
ciągu 1, 2, 4, 8, ... i zawsze jest równa indeksowi następnej wartości x 1 do
zapamiętania w zmiennej y.
W wierszach 8-10 próbujemy znaleźć czynnik w rozkładzie n, korzystając
z zapamiętanej wartości y oraz bieiącej wartości x 1• Dokładniej, w wierszu 8
obliczamy najmniejszy wspólny dzielnik d = gcd(y - x 1, n). Jeśli d jest nietry-
wialnym dzielnikiem n (co sprawdzamy w wierszu 9), to w wierszu 10 wy-
pisujemy d.
Powyższa procedura znajdowania czynnika rozkładu liczby może począt­
kowo wyglądać dosyć tajemniczo. Zauważmy jednak, że procedura POLLARD-
-RHO nigdy nie udziela błędnej odpowiedzi; każda z wypisywanych przez nią
liczb jest nietrywialnym dzielnikiem n. Może się za to zdarzyć, że POLLARD-
-RHO w ogóle nic nie wypisze; nie ma gwarancji, że da ona jakiekolwiek wy-
niki. Jak się jednak przekonamy, mamy podstawy oczekiwać, że POLLARD-
-RHO wypisze czynnik p rozkładu n po około JP iteracjach pętli while. Jeśli
zatem n jest liczbą złożoną, to możemy się spodziewać, że nasza procedura
znajdzie dość dzielnik.ów, żeby całkowicie rozłożyć n po około n 114 przebie-
gach, ponieważ wszystkie czynniki pierwsze p liczby n, z wyjątkiem być może
największego, są mniejsze niż J----;;.
Przeanalizujemy zachowanie powyższej procedury badając, po jakim czasie
w losowym ciągu modulo n jakaś wartość się powtarza. Ponieważ Zn jest zbio-
rem skończonym, a każda wartość w ciągu (33.49) zależy tylko od poprzedniej,
kolejne wyrazy ciągu (33.49) zaczną się w końcu powtarzać. Kiedy dojdziemy
do X; takiego, że X; = xi dla pewnego j < i, oznacza to, że znaleźliśmy się
w cyklu, ponieważx 1 + 1 = X;+ 1 , x 1+ 2 = x 1+ 2 itd. Nazwa „heurystyka ro" bierze
się stąd, że - jak widać na rys. 33.7 - ciąg x 1 , x 2 , •••, x _ 1 można narysować jako
1
,,ogonek", a cykl x 1, xi+l• ... , x, jako „główkę" greckiej litery ro (p).
Zajmiemy się teraz odpowiedzią na pytanie, po jakim czasie ciąg wartości
x 1 zaczyna się powtarzać. Nie tego dokładnie potrzebujemy, ale później zoba-
czymy, jak należy zmodyftlcować argumentację.
Na potrzeby naszego oszacowania przyjmijmy, że funkcja (x 2 - 1) mod n
zachowuje się jak funkcja „losowa." Nie jest ona oczywiście naprawdę losowa,
ale będące konsekwencją takiego założenia wyniki są zgodne z obserwowanym
zachowaniem procedury POLLARD-RHO.Możemy zatem traktować każde X;
jako wylosowane niezależnie ze zbioru Zn z prawdopodobieństwem o rozkła­
dzie jednostajnym na Zn. W myśl analizy paradoksu dnia urodzin z podrozdz.
6.6. l oczekiwana liczba kroków przed wystąpieniem cyklu wynosi 0( J---;; ).
948
* 33.9. ROZKŁAD NA C2YNNIKI

996 ---- 3 l O
/ ',._
814 396

I
.,·, 177
\ 84
x,"

x6
1
1186 120
l
x, I\ 1194
/
I
.r, 8 ,, " 8

,, 3I ,,' x,"
I3
I2 X'' 2
.I
x, 2
"
mod 1387 mod 19 mod 73

(•) (b) (c)

Rys. 33.7. Heurystyka ,,ro" Pollarda. (•) Wartości utworzone za pomocą wzoru rekurencyjnego
x 1+ 1 +--(xf - l) mod 1387, poczynając od x 1 = 2. Roiklad na czynniki pierwsze liczby 1387 to
19· 73. Grube strzałki oznaczają
iteracje wykonywane przed znalezieniem czynnika 19. Cienkie
strzałki wskazują wartości, które nie zostały osiągnięte, żeby zilustrować kształt litery „ro". Liczby
widocme na szarym tle to wartości y zapamiętywane przez procedurę PoLLARD-RHo.Czynnik 19
zostaje znaleziony po osiągnięciu x 7 = 177, kiedy zostaje obliczona wartość gcd(63-177,
1387) = 19. Pierwsza powtarzają.ca się wartość x to 1186, ale czynnik 19 zostaje malez.iony prt.ed
jej osiągnięciem. (b) Wartości obliczone za pomocą tego samego wzoru rekurencyjnego modulo 19.
Każda wartość x 1 pcxiana w punkcie (a) przystaje modulo 19 do pokazanej tu wartości x;.Na
przykład zarówno x 4 = 63, jak i x 7 = 177 przystają do 6 modulo 19. (c) Wartości obliczone za
pomocą lego samego wzoru rekurencyjnego mod.ula 73. Kai,da wartość x 1 z punktu (a) przystaje
mod ulo 73 do pokazanej tu wartości x;.
Na mocy chińskiego twierdzenia o resztach każdy element
w punkcie (a) odpowiada parze elementów, jednemu z punktu (b) i jednemu z (c)

Omówmy jeszcze niezbędną modyfikację. Niech p będzie nietrywialnym


czynnikiem w rozkładzie n takim, że gcd(p, n/p) = 1. Jeśli na przykład roz-
kładem n jest n= p!' pt' ...p~·. to jako p możemy przyjąć pt•. (Dobry przykład
to przypadek e1 = 1, kiedy top jest po prostu najmniejszym czynnikiem pierw-
szym liczby n). Ciąg (x 1) indukuje związany z nim ciąg (xj) module p, gdzie
xJ=x;modp
dla każdego i. Dalej, z chińskiego twierdzenia o resztach wynika, że

949
ROZDZIAŁ 33. ALGORYTMY TE0Rl0L1CZB0WE

xl+1 = (x/ 2 - 1) modp (33.50)


ponieważ zgodnie z zad. 33.1-6

(x mod n) mod p = xmodp


Rozumując jak poprzednio, stwierdzamy, że oczekiwana liczba kroków,
:zanim ciąg (xi) zacznie się powtarzać, wynosi 0(J p ). Jeśli p jest małe w po-
równaniu z n, ciąg (xj) może zacząć się powtarzać znacznie szybciej niż ciąg
(x 1). W rzeczywistości ciąg (x[) zaczyna się powtarzać już od chwili, w której
dwa elementy ciągu (x 1) przystają do siebie module p, a nie dopiero wtedy,
kiedy przystają modulo n. Sytuację tę ilustruje rys. 33.7b i c.
Niech t oznacza indeks pierwszej powtarzającej się wartości w ciągu (x/)
i niech u > O będzie długością utworzonego w ten sposób cyklu. Znaczy to,
żet i u> O są najmniejszymi liczbami takimi, że x;+ 1 = x;+ 11+ 1 dla
każdego i~ O. Zgodnie z wcześniejszą argumentacją wartości oczekiwane
t oraz u można oszacować jako @(J p ). Zauważmy, że jeśli x;+ 1 = x;+ 11+1, to
PI(Xr+u+1 - X1+1). Zatem gcd(xt+u+i - Xr+l• n)> I.
Jeśli więc procedura POLLARD-RHO zapamiętała w zmiennej y jakąś war-
tość xl taką, że k ;;:i,t, to y mod p leży zawsze na cyklu module p. (Jeśli
w zmiennej y zostaje zapamiętana nowa wartość, znajduje się ona tak.że na
cyklu module p). W końcu zmienna k przyjmuje wartość większą niż u, a pro-
cedura obchodzi wówczas cały cykl module p bez zmiany wartości y. Czynnik
liczby n zostaje znaleziony, kiedy X; ,,wpada" na poprzednio zapamiętaną war-
tość y module p, tzn. kiedy x 1 = y (mod p).
Znalezionym czynnikiem jest najprawdopodobniej p, chociaż może się cza-
sem zdarzyć, że trafnny na wielokrotność p. Ponieważ oczekiwane wartości
zarówno t, jak i u wynoszą @(J p ), oczekiwana liczba kroków potrzebnych do
wyznaczenia czynnika p wynosi €J(J p ).
Istnieją dwa powody, dla których algorytm ten może działać nie całkiem
tak, jak się spodziewamy. Po pierwsze, heurystyczna analiza jego czasu działa­
/J.
nia nie jest ścisła, a cykl wartości module p może być znacznie dłuższy niż J
Wtedy algorytm działa poprawnie, ale znacznie wolniej, niż powinien. W prak-
tyce nie jest to jednak sprawa zasadnicza. Po drugie, może się zdarzyć, że
znajdowany przez algorytm dzielnik będzie zawsze jednym z dwóch trywial-
nych dzielników 1 i n. Załóżmy na przykład, że n = pq, gdzie pi q są liczbami
pierwszymi. Może się zdarzyć, że wartości t i u dla p będą takie same jak
wartości tiu dla q, więc czynnikp będzie rawsze wykrywany przy wykonywa-
niu tej samej operacji obliczania gccl, która wykrywa czynnik q. Ponieważ
obydwa czynniki zostają wykryte jednocześnie, znajdowany jest bezużyteczny
trywialny czynnik pq = n. Również i to nie wydaje się być poważnym prob-
lemem w praktyce. Jeśli trzeba, naszą heurystykę można zastosować jeszcze

950
PROBLEMY

raz, korzystając z innego wzoru rekurencyjnego postaci x 1+ 1 +- (xf - c) mod n.


(Z powodów, w które nie będziemy tutaj wnikać, nie należy używać wartości
c = O ani c = 2, ale pozostałych już można).
Oczywiście, przedstawiona heurystyczna analiza nie jest ścisła, ponieważ
ciąg zadany wzorem rekurencyjnym nie jest naprawdę „losowy." Mimo wszyst-
ko algorytm w praktyce działa dobrze i wydaje się być równie efektywny, jak
owa analiza na to wskazuje. Do znajdowania małych czynników pierwszych
dużej liczby warto używać tej właśnie metody. Żeby całkowicie rozłożyć na
czynniki ,B-bitową liczbę złożoną n, wystarczy znaleźć wszystkie czynniki pierw-
sze mniejsze niż Ln 1J, więc można oczekiwać, że procedura POLLARD-RHO
1 2

będzie potrzebowała do tego celu co najwyżej n 114 = 2flt4 operacji arytmetycz-


p
nych i co najwyżej n 1 14 3 = 2/J1
4 p3 operacji na bitach. Najbardziej atrakcyjną

własnością procedury POLLARD-RHOjest to, że potrafi ona znaleźć niewielki


czynnik p liczby n za pomocą średnio 0( ..;·p) operacji arytmetycznych.

ZADANIA
33.9-1. Kiedy w przykładzie na rys. 33.7a procedura POLLARD-RHOwypisze
czynnik 73 liczby 1387?
33.9-2. Załóżmy, że marny daną funkcję/: Z"-+ Z" oraz początkową wartość
x 0 EZ". Zdefiniujmy x 1 =f(x 1_ 1) dla i=l, 2, ... Niech t i u>O będą
najmniejszymi wartościami takimi, że Xr+J = xt+ ..+i dla i= O, 1, ... W termi-
nologii algorytmu „ro" Pollarda t jest długością „ogonka", u zaś jest długo­
ścią cyklu stanowiącego „główkę" litery ro. Podaj efektywny algorytm
wyznaczania dokładnych wartości t i u oraz przeanalizuj czas jego działania.
33.9-3. Ilu kroków będzie potrzebowała procedura POLLARD-RHOdo znale-
7jenia czynnika postaci p", gdzie p jest liczbą pierwszą, a e > l?
* 33.9-4. Wadą procedury POLLARD-RHOw przedstawionej postaci jest to, że
wymaga ona jednego obliczenia gcd dla każdego elementu ciągu rekuren-
cyjnego. Istnieje możliwość grupowania obliczeń gcd przez obliczenie ilo-
czynu pewnej porcji kolejnych x 1, a następnie wyznaczenie gcd tego iloczy-
nu i zapamiętanej wartości y. Opisz dokładnie, jak zaimplementowałbyś tę
ideę, dlaczego jest ona poprawna i jaki rozmiar porcji wybrałbyś jako
najefektywniejszy, jeśli liczba n jest ,B-bitowa.

Problemy
33-1. Binarny algorytm gcd
Na większości komputerów operacje odejmowania, sprawdzania, czy dana
liczba binarna jest parzysta, oraz dzielenia przez 2 można wykonać znacznie
szybciej niż obliczanie reszt. Niniejszy problem dotyczy binarnego algorytmu
gcd, który w odróżnieniu od algorytmu Euklidesa nie wymaga obliczania reszt.

951
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

(a) Udowodnij, że jeśli zarówno a, jak i b są parzyste, to gcd(a, b) = 2gcd(a/2,


b/2).
(b) Udowodnij, że jeśli a jest nieparzyste, a b jest parzyste, to gcd(a, b) =
= gcd(a, b/2).
(c) Udowodnij, że jeśli zarówno a, jak i b są nieparzyste, to gcd(a, b) =
= gcd((a - b)/2, b).
(d) Zaprojektuj efektywny binarny algorytm gcd dla liczb całkowitych a i b,
gdzie a~ b, działający w czasie O(lg(max(a, b))). Przyjmij, że ka.me
odejmowanie, testowanie parzystości i dzielenie przez 2 można wykonać
w czasie jednostkowym.

33-2. Analiza operacji oa bitach w algorytmie Euklidesa

(a) Wykaż, że zwykły „szkolny" algorytm dzielenia -dzielenie a przez b, dają­


ce iloraz q i resztę ,-wymaga 0((1 + lgq)lgb) operacji na bitach.
(b) z.definiujmy µ(a, b) = (1 + lga)(l + 1gb). Wykaż, że liczba operacji na bi-
tach wykonywanych przez procedurę EUCLID przy redukcji problemu ob-
liczenia gcd(a, b) do problemu obliczenia gcd(b, a mod b) nie przekracza
c(µ(a, b) - µ(b, a mod b)) dla pewnej dostatecznie dużej stałej c > O.
(c) Wykaż, że wykonanie procedury Eucuo(a, b) wymaga O(p(a, b)) operacji
na bitach w ogólnym przypadku, a O(P 2 ) operacji na bitach, jeśli stosujemy
ją do dwóch liczb p-bitowych.

33-3. Trzy algorytmy dla liczb Fibonacciego


W problemie tym chodzi o porównanie efektywności trzech metod obliczania
n-tej liczby Fibonacciego F11 dla danego n. Załóżmy, że koszt dodawania, odej-
mowania czy mnożenia dwóch liczb jest stały, niezależny od rozmiaru liczb.

(a) Wykaż, że czas działania bezpośredniej rekurencyjnej metody obliczania


F" na podstawie wzoru rekurencyjnego (2.13) jest wykładniczy ze względu
na n.
(b) Pokaż, jak obliczać F" w czasie O(n) z pomocą metody spamiętywania.
(c) Pokaż, jak obliczać F 11 w czasie O(lgn), stosując wyłącznie operacje doda-
wania i mnożenia liczb całkowitych. (Wskazówka: Rozważ macierz

i jej potęgi).
(d) Załóżmy teraz, że dodawanie dwóch liczb P-bitowych zajmuje czas 0(P),
a ich mnożenie zajmuje czas 0(P 2 ). Jak.ie jest oszacowanie czasu działania
powyższych trzech metod przy użyciu tej bardziej realistycmej miary kosz-
tu podstawowych operacji arytmetycznych?

952
UWAGI DO ROZDZIAŁU

33-4. Reszty kwadratowe


z;
Niech p będzie nieparzystą liczbą pierwszą. Liczba ae jest resztą kwadratową,
jeśli równanie x 2 = a (mod p) ma rozwiązanie ze względu na niewiadomą x.

(a) Wykaż, że istnieje dokładnie (p- 1)/2 reszt kwadratowych modulo p.


(b) Jeśli p jest liczbą pierwszą, definiujemy symbol Legendre'a (;) dla ae z;
jako 1, jeśli a jest resztą kwadratową modulo p, zaś - I w przeciwnym
razie. Wykaż, że jeśli aez;, to

(;) = a!p- l}/ 2 (mod p)

Podaj efektywny algorytm rozstrzygania, czy dana liczba a jest resztą kwa-
dratową modulo p. Dokonaj analizy efektywności swojego algorytmu.
(c) Wykaż, że jeśli p jest liczbą pierwszą postaci 4k + 3, a zaś jest resztą kwad-
ratową w z;,to a1:.+ 1 mod p jest pierwiastkiem kwadratowym z a modu-
Io p. Ile czasu potrzeba na znalezienie pierwiastka kwadratowego z reszty
kwadratowej a modulo p?
(d) Opisz efektywny probabilistyczny algorytm znajdowania niereszty kwad-
ratowej modulo dowolna liczba pierwsza p. Jaka jest średnia liczba opera-
cji arytmetycznych wykonywanych przez Twój algorytm?

Uwagi do rozdziału
Znakomite wprowadzenie do elementarnej teorii liczb stanowi książka Nivena
i Zuckermana [151). Książka Knutha [122] zawiera dobre omówienie algoryt-
mów znajdowania największego wspólnego dzielnika, a także i innych pod-
stawowych algorytmów teorioliczbowych. Bliższy współczesności przegląd ob-
liczeniowej teorii liczb stanowią prace Riesela [168] i Bacha [16J. Dixon [56]
przedstawia zarys metod rozkładu na czynniki i sprawdzania, czy liczba jest
liczbą pierwszą. Sprawozdania z konferencji pod redakcją Pomerance'a [159]
zawierają kilka ciekawych artykułów przeglądowych.
W książce [122] Knuth omawia powstanie algorytmu Euklidesa. Pojawił
się on w księdze 7 (twierdzenia I i 2) dzieła greckiego matematyka Euklidesa,
zatytułowanego Elementy, napisanego około roku 300 p.n.e. Opis Euklidesa
mógł być wzorowany na algorytmie autorstwa Eudoksusa, datowanym około
roku 375 p.n.e. Algorytm Euklidesa jest być może najstarszym nietrywialnym
algorytmem; rywalizować z nim może jedynie algorytm mnożenia, zwany al-
gorytmem rosyjskich wieśniaków (patrz rozdz. 29), który był już znany staro-
żytnym Egipcjanom.

953
ROZDZIAŁ 33. ALGORYTMY TEORIOLICZBOWE

Sformułowanie szczególnego przypadku chińskiego twierdzenia o re-


sztach K.nuth przypisuje chińskiemu matematykowi Sun-TsU, który żył mię­
dzy rokiem 200 p.n.e. a 200 n.e. - dokładna data nie jest znana. Ten sam
szczególny przypadek przedstawił grecki matematyk Nichomachus około ro-
ku 100 n.e., a uogólnił w 1247 r. Chhin Chiu-Shao. Ostateczne sformuło­
wanie chińskiego twierdzenia o resztach i jego dowód w całej ogólności podał
L. Euler w 1734 r.
Zaprezentowany tu probabilistyczny algorytm sprawdzania, czy liczba jest
liczbą pierwszą pochodzi od Millera [147] i Rabina [166]; jest to najszybszy
(z dokładnością do stałego czynnika) ze znanych probabilistycznych algoryt-
mów dla tego problemu. Dowód twierdzenia 33.39 stanowi adaptację dowodu
zaproponowanego przez Bacha [15]. Dowód silniejszego wyniku dla algoryt-
mu MILLER-RABIN podał Monier [148, 149]. Randomizacja wydaje się ko-
nieczna do uzyskania wielomianowego algorytmu sprawdzania, r::z:yliczba jest
liczbą pierwszą. Najszybszy znany deterministyczny algorytm dla tego prob-
lemu to wersja Cohena-Lenstry [45] testu Adlemana, Pomerance'a i Rume-
ly'ego [3]. Czas sprawdzania pierwszości liczby n rozmiaru rJ.g(n+ 1)1 wynosi
jest więc nieco większy niż wielomianowy.
(lgn)o(lglgJgnl,
Dobre omówienie problemu znajdowania dużych „losowych" liczb pierw-
szych zawiera artykuł Bćauchemina, Brassarda, Crepeau, Goutiera i Pome-
rance'a [20].
Pomysł kryptosystemu z kluczem jawnym pochodzi od Diffiego i Hellma-
na [54]. Kryptosystem RSA zaproponowali w 1977 r. Rivest, Shamir i Ad-
leman [169]. Od tego czasu następuje gwałtowny rozwój kryptografii. Pojawiło
się zwłaszcza wiele nowych technik dowodzenia bezpieczeństwa kryptosyste-
mów. Goldwasser i Micali [86] pokazują na przykład, że randomizacja może
być efektywnym narzędziem w projektowaniu bezpiecznych metod szyfrowa-
nia z kluczem jawnym. Goldwasser, Micali i Rivest [88] przedstawiają schemat
podpisu cyfrowego, dla którego o każdym możliwym sposobie fałszerstwa
można udowodnić, że jest nie łatwiejszy niż problem rozkładu na czynniki.
Ostatnio Goldwasser, Micali i Rack:off [87] wprowadzili klasę schematów szyf-
rowania „z wiedzą zerową", dla których można pokazać (przy pewnych roz-
sądnych założeniach), że żadna z komunikujących się stron nie dowie się pod-
czas wymiany informacji więcej, niż powinna.
Heurystyka „ro" rozkładania liczb całkowitych na czynniki została wyna-
leziona przez Pollarda [I 56]. Przedstawiona tutaj wersja to wariant zapropono-
wany przez Brenta [35].
Najlepsze znane algorytmy rozkładania na czynniki dużych liczb działają
mniej więcej w czasie wykładniczym ze względu na pierwiastek kwadratowy
z rozmiaru liczby n, którą należy rozłożyć. Najefektywniejszy w ogólnym przy-
padku dla dużych danych jest chyba pochodzący od Pomerance'a [158] al-
gorytm sita kwadratowego. Chociaż trudno podać jego ścisłą analizę, przy

954
UWAGI DO ROZDZIAŁU

rozsądnych założeniach można wyprowadzić oszacowanie jego czasu działa­


nia równe L(n) 1 + 0 t1 >, gdzie L(_n)= ~- Zaproponowana przez Lenstrę
[137] metoda krzywej eliptycznej może być dla pewnych danych wejściowych
efektywniejsza niż metoda sita kwadratowego, ponieważ - podobnie jak me-
toda „ro" Pollarda - pozwala ona dość szybko znależć mały czynnik pierw-
szy p. W metodzie tej czas potrzebny na znalezienie p można oszacować
przez L(p)J 2+ 0<1 J.
Rozdział 34

Wyszukiwanie
wzorca

Problemem, który często pojawia się w programach do redagowania tekstów,


jest znajdowanie wszystkich wystąpień wzorca w tekście. W typowej sytuacji
tekstem jest redagowany dokument, natomiast wzorcem jest konkretne słowo
podane przez użytkownika. Efektywne algorytmy dla tego problemu mogą
znacznie usprawnić program redagowania tekstu. Algorytmy wyszukiwania
wzorca są również używane na przykład przy szukaniu specjalnych wzorców
w sekwencjach DNA.
Problem wyszukiwania wzorca sformalizujemy następująco. Zakładamy, że
tekst jest tablicą T[l .. n] długości n, a wzorzec jest tablicą P[l .. m) długości m.
Ponadto zakładamy, że elementami tablic P i T są symbole należące do pew~
nego skończonego alfabetu I. Może to na przykład być E = {O, 1} lub I=
= {a, b, ... , z}. Teksty Pi T są także często nazywane słowami.
Mówimy, że wzorzec P występuje z przesunięciem s w tekście T (lub, rów-
noważnie, że wzorzec P występuje, począwszy od pozycji s + 1), gdy
O.; s<; n-m oraz T[s + I .. s + m]- P[I .. m] (tzn. gdy T[s + j] - PU] dla
I ~ja:::;;m). Jeśli P występuje z przesunięciem sw T, to s nazywamy poprawnym
przesunięciem; w przeciwnym razie s nazywamy niepoprawnym pnesunięciem.
Problem wyszukiwania wzorca polega na znajdowaniu wszystkich popraw-
nych przesunięć dla danego wzorca P w ustalonym tekście T. Rysunek 34.1
ilustruje te definicje,
W tym rozdziale przedstawimy kilka algorytmów dla problemu wyszuki-
wania wzorca. W podrozdziale 34.1 zajmiemy się algorytmem „naiwnym"
o złożoności pesymistycmej O((n - m + l)m), W podrozdziale 34.2 omówimy
interesujący algorytm opracowany przez Rabina i Karpa, którego złożoność
pesymistyczna również wynosi O((n - m + l)m), ale który działa znacznie le-
piej w sensie złożoności średniej i w praktyce. Ponadto algorytm ten można
łatwo rozszerzyć na inne problemy. W podrozdziale 34.3 opiszemy algorytm,

956
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

Tekst T a b C b c a b a c

s=3
Wzorzec P

Rys. 34.1, Problem wyszukiwania wzorca. Celem jest znalezienie wszystkich wystąpień wzorca P =
= abaa w tekście T = abcabaabcabac. Wzorzec występuje dokładnie raz, z przesunięciem s = 3.
Przesunięcie s = 3 jest nazywane poprawnym. Pojedyncze symbole wzorca są połączone pionowy"
mi liniami z odpowiadającymi im symbolami w tekście; symbole, które do siebie pasują, są przed-
stawiane na szarym tle

który rozpoczyna działanie od konstrukcji automatu skończonego przysto-


sowanego do szukania wystąpień wzorca P w tekście. Algorytm ten działa
w czasie O(n + mlII). Podobny, chociaż znacznie bardziej skomplikowany
algorytm Knutha-Morrisa-Pratta (w skrócie KMP) zaprezentujemy w pod-
rozdz. 34.4; algorytm ten działa w czasie O(n + m). Wreszcie w podrozdz.
34.5 przedstawimy algorytm autorstwa Boyera i Moore'a, który jest często
najlepszym wyborem w praktyce, mimo że jego pesymistyczny czas działania
(podobnie jak. w algorytmie Rabina-Karpa) nie jest lepszy niż czas działania
algorytmu naiwnego.

Notacja i terminologia
Przez I' oznaczamy zbiór wszystkich tekstów (słów) utworzonych z symboli
alfabetu E. W tym rozdziale rozważamy tylko słowa o skończonej długości.
Słowo o długości zero, nazywane słowem pustymi oznaczone przeze, też należy
do E'. Długość słowa x oznaczamy przez lx!. Konkatenacja(złożenie) dwóch
słów x i y (oznaczona przez xy) jest słowem długości lx\+ lYI,składającym się
z symboli x, za którymi występują symbole y.
Mówimy, że słowo w jest prefiksemsłowa x (co oznaczamy wcx), gdy
x = wy dla pewnego słowa y EJ;'. Zauważmy, że jeśli w c x, to lwi .s.;;lxl. Po-
dobnie, mówimy, że słowo w jest sufiksemsłowa x (co oznaczamy w:::ix), gdy
x = yw dla pewnego yei::•. Zależność w::ix implikuje lwi .s.;;lxl. Słowo puste e
jest jednocześnie prefiksem i sufiksem każdego słowa. Na przykład mamy
abcabcca oraz cca:::iabcca. Warto zauważyć, że dla każdych słów x i y oraz
każdego symbolu a mamy X::JY wtedy i tylko wtedy, gdy xa::Jya. Zauważmy
również, że c oraz :J są relacjami przechodnimi. Następujący lemat przyda
. ' , . .
nam się pozrueJ.

LEMAT34.1. (Lemat o nierozłącznych sufiksach)


Załóżmy, że x, y i z są słowami takimi, że x :::iz i y ::iz. Jeśli lx) .s.;;lYI,to x :::iy.
Jeśli lxl ~ !YI,to y ::i x. Jeśli lxl = lYIto x = y.

957
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

'
y

I I
~
ł

X XL,__
' X
'

Yc__ y y

(a) (b) (o)

Rys. 34.2. Graficzny dowód lematu 34. l, Zakładamy, że x:::::izi y::iz. Trzy części rysunku odpowiada-
ją trzem przypadkom lematu. Pionowe I.iniełączą pasujące do aiebie segmenty (S7Aiykolor) tekstu.
= =
(a) Jesli jxl " IYI to x ::Jy. (b) Jeśli lxl )< IY!,to Y::J x. (c) Jeśli lxl lyl to x y

DOWÓD
Poglądowy dowód jest przedstawiony na rys. 34.2.

Dla uproszczenia zapisu oznaczamy k-symbolowy prefiks P[l .. k] wzorca
P[l „ mJprzez P1 . Zatem P 0 = e oraz Pm = P = P[l .. mJ.Podobnie, oznacza-
my k-symbolowy prefiks tekstu T przez T1 . Używając tej notacji, możemy
wyrazić problem wyszukiwania wzorca jako problem znajdowania wszystkich
przesunięć s w przedziale O ~ s ~ n - m takich, że P ::J T~+111•
W naszym pseudojęzyku programowania przyjmujemy, że porównywanie
dwóch tekstów tej samej długości jest operacją elementarną. Jeśli teksty są
porównywane od strony lewej do prawej i proces ten zatrzymuje się w chwili
niezgodności dwóch symboli, to przyjmujemy, że czas takiego testu jest propo-
rcjonalny do liczby porównywanych symboli. Bardziej formalnie: test „x = y"
potrzebuje (z defmicji) czasu 8(t + I), gdzie t jest długością najdłuższego sło­
wa z takiego, że zcx i zcy.

34.1. Algorytm ,,naiwny" wyszukiwaniawzorca


Algorytm „naiwny" znajduje wszystkie poprawne przesunięcia, korzystając
z pętli, w której jest sprawdzany warunek P{l .. m] = T[s + 1 .. s + m] dla każ­
dej z n - m + 1 możliwych wartości s.

958
34.1. ALGORYTM „NAIWNY"' WYSZUKIWANIA WZORCA

-• C • • b
·-···
C • C
• • b C
L, '
-] s=2
c"_ • b ' • • bł

(a) (b) (c) (d)

Rys. 34.3. Działanie „naiwnego" algoryl.mu wyszukiwania wzorca dla P = aab i 1· = acaabc. Wyob~
raimy sobie wzorzec P jako „okienko", które przesuwamy nad tekstem. Części (a)-(d) ilustrują
cztery kolejne testy. W każdej z nich pionowe linie łączą odpowiadające sobie zgodne segmenty
(szary kolor na rysunku), a zygzakowana linia wskazuje pierwszą niezgodność (o ile laka istnieje).
Znalezione zostaje jedno wystąpienie wzorca z przesunięciem s = 2, pokazanym w części (c)

NAIVE-STRING-MATCHER(T, P)
1 n+- length [T]
2 m +- length [P]
3 fors+-Oton-m
4 do if P[l .. m] - T[s + I „ s + m]
5 then wypisz „Wzorzec występuje z przesunięciem'' s

,,Naiwny" algorytm szukania wzorca można sobie wyobrazić jak.o przesu-


wanie nad tekstem „okienka" zawierającego wzorzec i sprawdzanie, dla jakich
przesunięć wszystkie symbole w okienku są zgodne z odpowiadającymi im
symbolami w tekście,jak jest to poka:rane na rys. 34.3. W pętli for zaczynającej
się w wierszu 3 jest rozważane bezpośrednio każde przesunięcie. Test w wier-
szu 4 służy do sprawdzenia, czy dane przesunięcie jest poprawne; test ten za-
wiera wewnętrzną pętlę sprawdzającą, czy odpowiednie symbole są zgodne do
chwili, gdy sprawdzimy cały wzorzec lub znajdziemy niezgodność. Wiersz 5 za-
pewnia wypisanie każdego poprawnego przesunięcia s.
Procedura NAIVE-STRING-MATCHER działa w czasie E>((n - m + l)m)
w przypadku pesymistycznym. Rozważmy na przykład tekst an (ciąg n sym-
boli a) i wzorzec am.Dla każdej z n - m + 1 możliwych wartości przesunięcia s
wewnętrma pętla w wierszu 4 musi być wykonywana m razy, żeby sprawdzić
poprawność przesunięcia. Pesymistyczny czas wynosi zatem E>((n - m + I)m),
czyli ®(n'), jeślim - Ln/2J.
Jak wkrótce zobaczymy, procedura NAIVE-STRING-MATCHER nie jest op-
tymalna. W istocie, w rozdziale tym pokażemy algorytm o pesymistycznym
czasie działania O(n + m). ,,Naiwne" szukanie wzorca jest nieefektywne, po-
nieważ informacja o tekście uzyskana dla jednej wartości s jest całkowicie
ignorowana przy następnych wartościach s. Jednakże informacja taka może
mieć pewną wartość. Jeśli na przykład P = aaab i stwierdzamy, że s = O jest
poprawne, to wtedy żadne z przesunięć 1, 2 lub 3 nie jest poprawne, gdyż
T[4] = b. W następnych podrozdziałach rozważymy kilka sposobów wykorzy-
stania takiej informacji.

959
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

ZADANIA

34.1-1. Pokaż, jakie porównania wykonuje algorytm „naiwny", szukając


wzorca P = 0001 w tekście T = 00001 0001 01 0001 .
34.1-2. Wykaż, zepesymistycznyczas działania algorytmu ,,naiwnego" znajdują­
cego pierwsze wystąpienie wzorca w tekście wynosi 0((n - m + l)(m - 1)).
34.1-3. Załóżm.y, że wszystkie symbole we wzorcu P są parami różne. Pokaż,
jak przyspieszyć procedurę NAIVE-STRING-MATCHER, aby działała w cza-
sie O(n) dla n-literowego tekstu T.
34.1-4. Załóżm.y, że wzorzec Pi tekst T są losowo wybranymi słowami długo­
ści odpowiednio m oraz n nad d-elementowym alfabetem I"= {O, 1, ... ,
d - 1}, gdzie d ~ 2. Pokaż, że średnia liczba porównań par pojedynczych
symboli wykonywanych w wierszu 4 algorytmu „naiwnego" wynosi

1- a-m
(n - m + I) --1 - - a- 1 "..._,2(n - m + I)

(Zakładamy, że algorytm „naiwny" w chwili znalezienia pierwszej niezgo-


dności przestaje sprawdzać dalej). Zatem dla losowo wybranych tekstów
algorytm „naiwny" jest dość efektywny.
34.1-S. Załóżmy, że wzorzec P może zawierać pewną liczbę wystąpień tzw.
symbolu uniwersalnego O, który pasuje do dowolnego ciągu symboli (być
może pustego). Na przykład wzorzec abObaOc występuje w tekście
cabccbacbacabjako

C ab CC ba cba c ab
ab o ba o C

oraz jako

C ab ccbac ba C ab
ab o ba o C

Zauważmy, że symbol uniwersalny może występować we wzorcu wielo-


krotnie, ale z założenia nie występuje w tekście. Podaj wielomianowy al-
gorytm sprawdzania tego, czy wzorzec P występuje w danym tekście T,
oraz zanalizuj złożoność swojego algorytmu.

34.2. AlgorytmRabina-Karpa
Rabin i Karp zaproponowali algorytm wyszukiwania wzorca, który zachowuje
się świetnie w praktyce oraz daje się łatwo modyfikować dla innych pokrew-
nych problemów, takich jak szukanie wzorców dwuwymiarowych. Pesymis-
34.2. ALGORYTM RABINA-KARPA

tyczny czas działania algorytmu Rabina-Karpa wynosi O((n - m + l)m), ale


średni czas jest znacznie mniejszy.
W algorytmie tym korzysta się z takich elementarnych pojęć teorii liczb,
jak przystawanie dwóch liczb modulo pewna trzecia liczba. (Odsyłamy do pod-
rozdz. 33.1 po odpowiednie definicje).
W celu uproszczenia prezentacji przyjmujemy, że I= {O, 1, 2, ... , 9}; ina-
czej mówiąc, każdy symbol jest cyfrą dziesiętną. (W przypadku ogólnym może­
my przyjąć, że każdy symbol jest cyfrą w systemie o podstawie d, gdzie d = IE!).
Możemy zatem interpretować tekst k symboli jako liczbę k-cyfrową w układzie
dziesiętnym. Tak więc tekst 31415 odpowiada liczbie dziesiętnej 31,415. Mo-
żemy zatem utożsamiać (w tym podrozdziale) symbole z cyframi dziesiętnymi.
Dla danego wzorca P[l .. m] niech p oznacza odpowiadającą mu wartość
dziesiętną. W podobny sposób, dla danego tekstu T[l .. n] niech t, oznacza
wartość dziesiętną podsłowa T[s + 1 .. s + m] długości m, dla s = O, 1, ... ,
n - m. Oczywiście t, = p wtedy i tylko wtedy, gdy T[s + 1 .. s + m] = P[l .. m);
zatem sjest poprawnym przesunięciem wtedy i tylko wtedy, gdy t, = p. Jeśli
możemy obliczyć p w czasie O(m) oraz wszystkie wartości t 1 w sumie w czasie
O(n), to możemy wtedy wyznaczyć wszystkie poprawne przesunięcia s w czasie
O(n), porównując p z każdą z wartości t,. (Na razie nie martwmy się tym, że p
i t, mogą być zbyt dużymi liczbami).
Możemy obliczyć p w czasie O(m), używając reguły Hornera (patrz pod-
rozdz. 32.1 ):
p - P[m] + IO(P[m - I]+ IO(P[m - 2] + ... + IO(P[2] + !OP[!])...))

Podobnie znając T[l .. m], wartość t 0 można obliczyć w czasie O(m).


W celu wyliczenia pozostałych wartości t 1 , t 2 , ••• , t,._m w czasie O(n - m)
wystarczy zauważyć, że t,+ 1 może być otrzymane z t, w stałym czasie, po-
.
ruewaz
.
t,+, - IO(t, - Jo•-'T[s +I])+ T[s + m + I] (34.1)

Jeśli na przykład m = 5 i t, = 31415, to w celu obliczenia t,+ 1 usuwamy naj-


bardziej znaczącą cyfrę T[s + I] = 3 oraz wstawiamy najmniej znaczącą cyfrę
(zaló:b.ny, że jest nią T[s + 5 + I]= 2), aby otrzymać

I,+, - 10(31415 - 10000·3) +2


- 14152

Odjęcie 10"'- 1 T[s + 1] usuwa


najbardziej znaczącą cyfrę z t~, przemnożenie
wyniku przez 10 przesuwa cyfry liczby o jedną pozycję w lewo, natomiast
dodanie T[s+ m + 1] wstawia najmniej znaczącą cyfrę. Jeśli stała 10"'- 1 jest
wcześniej obliczona (można to zrobić w czasie O(lgm), używając metod

961
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

235902 141!f) 6 7 3 9 9 2 1

mooIJ

,.,

••• ••• mod 13


8 9 3 11 O
Poprawne Niezgodność
wystąpienie

(b)

Poprzednia Nowa Poprzednia Nowa


najbardziej znacząca najmniej znacząca najbardziej znacząca najmniej znacząca
cyfra cyfra Przesunięcie

\ cyfra I cyfra

2
\
14152 "' (31415 - 3. HXlOO)·IO
l /
+ 2 (mod 13)
.. {7-3·3)·10+2 (mod13)
"" 8 (mod 13)

,,,
Rys. 34.4. Algorytm Rabina-Karpa. Każdy symbol jest cyfrą dziesiętną, a obliczamy wartości modu-
Io 13. (a) Tekst i wyróznione szarym kolorem okienko długości 5. Wartość numeryczna szarej
liczby obliczana modulo 13 wynosi 7. (b) Ten sam tekst z obliczonymi wartościami modulo 13 dla
każdej możliwej pozycji okienka długości S. Zakładając, że mamy wzorzec P = 3141S, szukamy
okienek, których wartość modulo 13 jest równa 7, ponieważ 3141S = 7 (mod 13). Dwa takie
malezione okienka są omaczone na rysunku kolorem sz.arym.Pierwsze z nich, zaczynają.ce się na
pozycji 7, jest faktycznym wystąpieniem wzorca, podczas gdy drugie, zaczynają.ce się na pozycji 13,
jest błędnym „strzałem". (c) Obliczanie wartości okienka w stałym czasie, na podstawie wartości
poprzedniego okienka. Pierwsze okienko ma wartość 3141S. Usuwając najbardziej znaczą.cą cyfrę
3, przesuwając w lewo (mnożąc przez 10), a następnie wstawiając najmniej maczącą cyfrę 2,
otrzymujemy nową wartość 14152. Obliczenia są wykonywane modulo 13, zatem wartością ob-
liczoną dla pierwszego okienka jest 7, a dla drugiego okienka~ 8

z podrozdz. 33.6, chociaż zastosowanie metody o koszcie O(m) jest wystar-


czające), to każdorazowe zastosowanie wzoru (34.1) wymaga stałej liczby ope-
racji arytmetycznych. Tak więc pi t 0 , t 1 , ... , tn-m mogą być obliczone w czasie
O(n + m) oraz możemy znaleźć wszystkie wystąpienia wzorca P[l „ m] w tek-
ście T[l .. n] w czasie O(n + m).

962
34.2. ALGORYTM RABINA-KARPA

Jedyną trudnością w tej procedurze jest to, że p i t, mogą być zbyt duże.
Jeśli P zawiera m symboli, to przyjmowanie, że każda operacja arytmetyczna
dla p (które składa się z m cyfr) zajmuje „stały czas", nie jest rozsądne. Na
szczęście można sobie z tym prosto poradzić, jak to jest pokazane na rys. 34.4:
obliczamy pi t, modulo q dla odpowiednio dobranego mniejszego q. Ponieważ
obliczenia p, ! 0 i wzoru (34.1) mogą być wykonane module q, widzimy, że
pi wszystkie t 1 mogą być obliczone module q w czasie O(n + m). Jak.o q wybie-
ramy przeważnie taką liczbę pierwszą, że IOą mieści się akurat w słowie kom-
putera, co pozwala wykonywać wszystkie operacje arytmetyczne z pojedynczą
precyzją. Zazwyczaj dla d-elementowego alfabetu {O,1, ..., d - 1} wybieramy
ą tak, że dq mieści się w słowie komputera, i dostosowujemy wzór (34.1) do
obliczeń modulo q, otrzymując w ten sposób

t,+ 1 = (d(t, - T[s + l]h) + T[s + m + 1]) mod q (34.2)

gdzie h - dm- i (mod q) jest wartością cyfry „1" na najbardziej znaczącej pozy-
cji w liczbie m-cyfrowej.
Działanie w arytmetyce modulo q może prowadzić teraz do błędu ze
względu na to, że t, = p (mod q) nie implikuje t, =
p. Z drugiej strony, jeśli
t, "lep (mod q), to z pewnością wiemy, że t, #- p i że przesunięcie sjest niepo-
prawne. Możemy więc użyć testu ! 1 = p (mod q) jako szybkiego testu heurys-
tycznego do eliminowania niepoprawnych przesunięć s. Każde przesunięcie s,
dla którego t~ p (mod q), musi być jeszcze zweryfikowane, tzn. musimy spra-
wdzić, czy sjest rzeczywiście poprawne, czy też „spudłowaliśmy". Testowanie
takie można wykonać przez bezpośrednie sprawdzenie warunku P[l .. m] =
= T[s + 1 .. s + m]. Jeśli q jest dostatecznie duże, to możemy się spodziewać,
że „spudłujemy" wystarczająco rzadko, żeby koszt dodatkowego sprawdzania
był mały.
Powyższa idea jest zrealizowana w następującej procedurze, której dany-
mi wejściowymi są tekst T, wzorzec P, liczba d (zwykle równa II]) i liczba

pierwsza q.

RABIN-KARP-MATCHER(T, P, d, q)
1 n +- /ength [[]
2 m +- length [P]
3 h+-dm- 1 modq
4 p+-0
5 t0 +-O
6 fori+-1 tom
7 do p- (dp + P[i]) mod q
8 ! 0 ...._ (dt 0 + T[i]) mod q
9 fors+-Oton-m
------------- --· ..,-, ----
963
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

10 do if p = I,
11 lhen if P[l .. m] = T[s + 1 .. s+ m]
12 tben wypisz „Wzorzec występuje z przesunięciem" s
13 ifs<n-m
14 then /1 + 1 +-(d(t 1 - T[s + l]h) + T[s + m + ID mod q

Procedura RABIN-KARP-MATCHER działa następująco. Wszystkie symbo-


le są interpretowane jako cyfry w systemie o podstawie d. Indeksy w t są
umieszczone tylko dla przejrzystości; program działa poprawnie, jeśli wszystkie
indeksy zostaną usunięte. W wierszu 3 określamy wartość początkową h jak.o
wartość najbardziej znaczącej cyfry w m-cyfrowym okienku. W wierszach 4-8
obliczamy p jak.o wartość P[l .. m] mod q oraz t 0 jako wartość T[l .. m] mod q.
Pętla for, rozpoczynająca się w wierszu 9, jest iterowana dla wszystkich moż­
liwych przesunięć s. Pętla ta ma następujący niezmiennik: przy każdym wyko-
naniu wiersza 10 zachodzi t, = T[s + 1„s + m] mod ą. Jeśli w wierszu 10
p = t 1 , to w wierszu 11 sprawdzamy, czy P[l .. m] = T[s + l .. s + m], aby wy-
eliminować możliwość błędnego „strzału". Każde poprawne przesunięcie jest
wypisywane w wierszu 12. Jeśli s < n - m (co jest sprawdzane w wierszu 13),
to pętla for będzie wykonywana przynajmniej jeszcze raz, najpierw więc jest
wykonywany wiersz 14, aby zapewnić zachowanie niezmiennika przy ponow-
nym osiągnięciu wiersza 10. W wierszu 14 obliczamy w czasie stałym wartość
t,+ 1 mod q, znając wartość / 1 mod q, bezpośrednio z równania (34.2)
Pesymistyczny czas działania procedury RABIN-KARP-MATCHER wynosi
E>((n- m + l)m), ponieważ (podobnie jak w algorytmie „naiwnym") algorytm
Rabina-Karpa sprawdza każde poprawne przesunięcie w sposób bezpośredni.
Jeśli P = ami T = an, to sprawdzenia zajmują czas E>((n- m + l)m), ponieważ
każde spośród n - m + 1 możliwych przesunięć jest poprawne. (Zauważmy
także, że obliczanie dm- l mod q w wierszu 3 oraz pętli w wierszach 6-8 wyma-
ga czasu O(m) = O((n - m + l)m)),
W wielu zastosowaniach spodziewamy się niewielkiej liczby poprawnych
przesunięć (być może jedynie 0(1)), zatem oczekiwany czas algorytmu wynosi
O(n + m) plus czas potrzebny do weryfikacji błędnych „strzałów". Możemy
oprzeć analizę heurystyczną na założeniu, że redukcja wartości modulo q dzia-
ła jak losowe odwzorowanie z r• w zbiór Z,r (Patrz rozważania związane
z używaniem dzielenia w haszowaniu w podrozdz. 12.3.1. Trudno jest sfor-
malizować i ściśle udowodnić takie założenie, chociaż. sensownym założeniem
może być to, że q jest wybrane losowo ze zbioru liczb odpowiedniego roz-
miaru. Nie będziemy wchodzić głębiej w tego typu formalizację). Możemy za-
tem oczekiwać, że liczba błędnych „strzałów" wynosi O(n/q), ponieważ praw-
dopodobieństwo tego, że dowolny symbol t, będzie przystawał do p modulo q,
nie przekracza 1/q. Tak więc oczekiwany czas działania algorytmu Rabina-
-Karpa wynosi

964
34.3. WYSZUKIWANIE WZORCA Z WYKORZYSTANIEM AUTOMATÓW SKOlilCZONYCH

O(n) + O(m(v + n/q))


gdzie v jest liczbą poprawnych przesunięć. Czas ten wynosi O(n),jeśli wybierze-
my q ;i, m. Oznacza to, że jeśli oczekiwana liczba poprawnych przesunięć jest
mała (0(1)), a liczba pierwsza q jest większa niż długość wzorca, to algorytm
Rabina-Karpa działa w czasie O(n + m).

ZADANIA
34.2-1. Ile błędnych „strzałów" wykona algorytm Rabina-Karpa, szukając
wzorca P = 26 w tekście T= 3141592653589793 i wykonując obliczenia
modulo q = 11?
34.2-2. Jak można rozszerzyć metodę Rabina-Karpa dla problemu jednoczes-
nego szukania k zadanych wzorców?
34.2-3. Pokaż, jak można rozszerzyć metodę Rabina-Karpa dla problemu szu-
kania wzorca wymiaru m x m w tablicy n x n. (Wzorzec można przesuwać
pionowo lub poziomo, ale nie można go obracać).
34.2-4. Alicja ma kopię pliku składającego się z n bitów A = (a,._ 1, a11_ 2 , ... ,
a 0 ), a Bob podobnie ma n-bitowy plik B = (b 11_ 1 , b11_ 2 , ••• , b 0 ). Alicja
i Bob chcą sprawdzić, czy ich pliki są identyczne. W celu uniknięcia prze-
syłania sobie całych plików A lub B używają oni następującego testu pro-
babilistycznego. Wybierają wspólnie liczbę pierwszą q > 1000n i losową
liczbę x ze zbioru {O,1, ..., n - I}. Następnie Alicja oblicza

A(x) - (,f, x')mod


a, q

a Bob podobnie oblicza B(x). Udowodnij, że jeśliA =f. B, to istnieje co


najwyżej jedna szansa na 1000, iż A(x) = B(x). (Wskazówka: Patrz
zad. 34.4-4).

-----·--------------------
34.3. Wyszukiwaniewzorcaz wykorzystaniemautomatów
skończonych
W niektórych algorytmach wyszukiwania wzorca są budowane automaty skoń­
czone, które przeglądają tekst Tw celu znalezienia wszystkich wystąpień wzor-
ca P. W tym podrozdziale przedstawimy metodę budowy takiego automatu.
Automaty szukające wzorca są bardzo efektywne: badają każdy symbol tekstu
dokładnie raz, przeznaczając stały czas dla pojedynczego symbolu. Zatem czas
działania algorytmu - gdy automat jest już zbudowany -wynosi 0(n). Jednak-
że czas konstruowania automatu może być długi, gdy alfabet I jest duży.
W podrozdziale 34.4 opiszemy sprytny sposób ominięcia tego problemu.

965
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

Zaczniemy ten podrozdział od podania definicji automatu skończonego.


Następnie zbadamy szczególny automat wyszukiwania wzorca i zobaczymy,
jak może on być wykorzystany do znajdowania wszystkich wystąpień wzorca
w tekście. Nasze rozważania będą również dotyczyć szczegółów symulacji au-
tomatu na danym tekście. Na zakończenie pokażemy, jak skonstruować auto-
mat wyszukiwania wzorca dla danego wzorca wejściowego.

Automaty skończone
Automatem skończonym M nazywamy uporządkowaną piątkę (Q, q0 , A, E,
c5),w której
• Q jest skończonym zbiorem stanów automatu,
• q 0 EQ jest stanem początkowym,
• A c: Q jest zbiorem stanów akceptujących,
• E jest alfabetem wejściowym,
• c5jest funkcją Q x E: -+ Q, zwaną funkcją przejść automatu M.
Automat skończony rozpoczyna działanie w stanie q0 , a następnie wczytu-
je kolejne symbole słowa wejściowego. Jeśli automat jest w stanie q i czyta
symbol wejściowy a, to przechodzi on od stanu q do stanu c5(ą, a). Jeśli bieżący
stan q jest elementem A, to mówimy, że automat M akceptuje wczytany do-
tychczas tekst. Tekst wejściowy, który nie jest zaakceptowany, jest „odrzuco-
ny" przez automat. Rysunek 34.5 obrazuje powyższe definicje na przykładzie
prostego automatu o dwóch stanach.
Dla automatu M oznac2n:1yprzez tj,:i;•-+ Q tak.zwaną rozszenooą funkcję
przejść, zdefiniowaną w ten sposób, że tj,(w)jest stanem, do którego przechodzi

Wejście •
Stan • b o
o •
I tHE
o b

(•) (b)

Rys. 34.5. Przykład prostego dwustanowego automatu skończonego u zbiorem stanów Q = {O, I},
stanem początkowym q0 = O i a1fabetem wejściowym X= {a, b}. (a) Tablicowa reprezentacja
funkcji przejść d. (b) Diagram opisujący automat. Stan I jest jedynym stanem akc.eptującym (kolor
czarny na rysunku). Krawędzie skierowane reprezentują przejścia. Na przykład krawędź od stanu
I do stanu O etykietowana symbolem b odpowiada prujściu d(l, b) =O.Automat ten akc.eptuje
zbiór tekstów kończących się nieparzystą liczbą symboli a. Formalnie, tekst x jest akceptowany
wtedy i tylko wtedy, gdy x = yz, gdzie y = i luby kończy się literą b, a z= ar. i k jest nieparzyste.
Na przykład ciąg.iem kolejnych stanów dla tekstu abaaa (włącmie u stanem początkowym) jest
(O, I, O, 1, O, 1), tak więc automat akc.eptuje ten tekst. Dla tekstu abbaa ciągiem stanów jest (O, I,
O, O, I, O), zatem automat odrzuca ten tekst

966
34.3. WYSZUKIWANIE WZORCA Z WYKORZYSTANIEM AUTOMATÓW SKOŃCZONYCH

M po wczytaniu tekstu w. Tak więc M akceptuje w wtedy i tylko wtedy, gdy


cp(w)eA. Funkcja <Pjest zdefiniowana rekurencyjnie:

</>(,)= ą,

</>(wa)=ó(</>(w),a) dla we I°, aeI

Automaty wyszukiwania wzorca


Dla każdego wzorca P możemy skonstruować automat wyszukiwania tego
wzorca, zanim jeszcze rozpoczniemy przeszukiwanie tekstu. Na rysunku 34.6
widać konstrukcję takiego automatu dla wzorca P = ababaca. Od tej chwili
będziemy zakładać, że wzorzec P jest ustalony, i dla uproszczenia będziemy
pomijać zależność od P.
Aby skonstruować automat wyszukiwania wzorca P[l .. m], musimy naj-
pierw zdefiniować pomocniczą funkcję a-,nazywaną funkcją sufiksową wzorca
P. Funkcja u jest odwzorowaniem z .r• w zbiór {O,1, ... , m} takim, że u(x) jest
długością najdłuższego prefiksu wzorca P, który jest jednocześnie sufiksem x:

a(x) = max {k: P, :::ix)


Funkcja sufiksowa u jest dobrze zdefiniowana, gdyż tekst pusty P O = e jest
sufiksem każdego tekstu. Na przykład dla wzorca P = ab mamy a-(e) = O,
u(ccaca) = I i u(ccab) = 2. Natomiast dla wzorca P długości m mamy
u(x) = m wtedy i tylko wtedy, gdy P:::Jx. Z definicji funkcji sufiksowej wynika,
że jeśli X:::JY,to u(x) ~ o{y).
Automat wyszukiwania danego wzorca P[l .. m] definiujemy następująco.
• Zbiorem stanów jest Q = {O, 1, ... , m}. Stanem początkowym jest q0 = O,
a stan m jest jedynym stanem akceptującym.
• Funkcja przejść ó dla każdego stanu q i symbolu a jest zdefiniowana
, .
rownaruem

b(q, a) = a(P, a) (34.3)

Intuicyjnie możemy wyjaśnić definicję ó(q, a)= u(P"a) następująco. Niezmien-


nikiem działania automatu jest

</>(T,)= a(T 1) (34.4)

Fakt ten jest udowodniony poniżej w twierdzeniu 34.4. Inaczej mówiąc, po


wczytaniu i symboli tekstu T automat jest w stanie </>(TJ= q, gdzie q = u(T;)
jest długością najdłuższego sufiksu T;, który jest jednocześnie prefiksem wzorca

967
ROZDZ!AŁ 34. WYSZUKIWANIE WZORCA

• •
• b • C

b
b

(a)

Wejście
p
Stan • b C

o o o •
l 2 o b
2 o o •
3 4. o b
4 o o •
5 l 4 6 l 2 3 4 5 6 7 8 9 10 11
1 o o
C
' ·i, :i.'.,.i"li.f·\·:
.~.--
•'
6
• T[i J
• b
3 .,,4_, 5,_ 6 Ili 2 •
4·"'5 0
b
7 l 2 o Stan 1/)(T.) o l 2 3

(b) (c)

Rys. 34.6. (11)Diagram przejśc dla automatu wyszukiwania wzorca akceptującego wszystkie teksty,
których sufiksem jest wzorzec 11bab11ca.Stanem początkowym jest O, natomiast stan 7 (kolor czarny
na rysunku) jest jedynym stanem akceptującym. Krawędź skierowana od stanu i do stanu j z ety-
ldetą a repreuntuje przejście ,Xi, a) =j. Krawędzie skierowane na prawo tworzą „szkielet" auto-
matu (pogrubione krawędzie na rysunku); odpowiadają one pozytywnym porównaniom z sym-
bolami wejściowymi. Krawędzie skierowane na lewo odpowiadają negatywnym porównaniom.
Niektóre krawędzie prowadzące do stanu O pominęliśmy. (b) Funkcja przejść ó i wzorzec
P = ab11b11ca.Miejsca odpowiadające pozytywnym porównaniom są pokazane na szarym tle. (c)
Działanie automatu dla tekstu T = abababaceba. Pod każdym symbolem T[11jest zapisany stan
!p(TJ, w którym automat znajduje się po wczytaniu prefiksu Jj. Znalezione zostaje jedno wystąpie­
nie wzorca, kończące się na pozycji 9

P. Jeśli następnym wczytanym symbolem jest T[i + I]= a, to stan zmienia się
na a(T;+ 1 ) = a(T 1a). Dowód twierdzenia pokazuje, że a(T 1a) = a(Pł a). W celu
obliczenia długości najdłuższego sufiksu T1a, który jest prefiksem P, możemy
obliczyć najdłuższy sufiks P'1.a,
który jest prefiksem P. W każdym stanie automat
musi jedynie znać najdłuższy prefiks P będący sufiksem dotychczas wczytanego
tekstu. Zatem, przyjmując ó(q, a)= u(P<1.a), zachowujemy wymagany niezmien-
nik (34.4). To nieformalne rozumowanie spróbujemy wkrótce sformalizować.
W automacie wyszukiwania wzorca z rys. 34.6 mamy na przykład
ó(5, b) = 4. Wynika to stąd, że jeśli automat wczyta b w stanie q = 5, to
Pt b = ababab, a najdłuższy prefiks P, który jest również sufiksem ababab wy-
nosi P 4 = abab.

968
34.3. WYSZUKIWANIE WZORCA Z WYKORZYSTANIEM AUTOMATÓW SKONCZONYCH

W celu sprecyzowania działania automatu wyszukiwania wzorca podamy


teraz prosty, efektywny program symulujący zachowanie się takiego automa·
tu (reprezentowanego przez funkcję przejść ó) przy wyszukiwaniu wystą·
pień wzorca P długości m w tekście wejściowym T[l .. n]. Podobnie jak dla
każdego automatu wyszukiwania wzorca długości m, zbiorem stanów jest
Q = {O, I, ... , m}, stanem początkowym jest O, a jedynym stanem akceptują·
cym jest stan m.

FINITE·AUTOMATON·MATCHER(T,ó, m)
1 n +- length [T]
2 q+-0
3 fori+-lton
4 do q - o(q, T[i])
5 ifq=m
6 tbens+-i-m
7 v,,ypisz „ Wzorzec występuje z przesunięciem" s

Z prostej strukury pov,,yższej procedury wynika, że jej czas działania


dla tekstu długości n v,,ynosi O(n). Jednakże czas ten nie uwzględnia kosztu
obliczenia funkcji przejść ó. Problemem tym zajmiemy się później, naj·
pierw wykażemy poprawność działania procedury FINITE·AUTOMATON·
·MATCHER.
Rozważmy działanie automatu dla tekstu wejściowego T[l „ n]. Pokaże·
my, że automat jest w stanie u(T 1) po wczytaniu symbolu T[i]. Ponieważ
u(Tj = m wtedy i tylko wtedy, gdy P ::JT1, automat jest w staniem wtedy
i tylko wtedy, gdy wzorzec P właśnie został wczytany. Aby to udowodnić,
posłużymy się następującymi dwoma lematami o funkcji sufiksowej u.

LEMAT 34.2. (Nierówność dla funkcji sufiksowej)


Dla każdego tekstu x i symbolu a zachodzi nierówność u(xa) ~ u(x) + I.

DOWÓD
Zgodnie z rys. 34.7, niech r = u(xa). Jeśli r = O, to nierówność r ~ u(x) + I
zachodzi w sposób trywialny ze względu na nieujemność a(x). Załóżmy zatem,
żer> O. W tym wypadku P,::Jxa zgodnie z definicją a. Tak więc P,_ 1 ::JX
(usuwamy a z końca P, oraz z końca xa). Zatem r - 1 ~ o{x), ponieważ u(x)
jest największym k, dla którego Pk ::i x.

LEMAT 34.3. (Rekurencja dla funkcji sufiksowej)
Dla każdego tekstu x i symbolu a, jeśli q = o{x), to 11(xa)= u(Pąa).

969
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

Rys. 34.7. Ilustratja dowodu lematu 34.2. Na rysunku widać, żer ,i,;;a(x) + I, gdzie r = ,r(xa)

DOWÓD
Z definicji funkcji CJmamy PIJ.~x. Jak widać na rys. 34.8, Pąa~xa. Jeśli
przyjmiemy r = CJ(xa),to r ~ q + I z lematu 34.2. Ponieważ Pqa~ xa, P, ~ xa
i !Pr J ~ IPIJ.aj,więc lemat 34.1 implikuje, że P,-::JPqa.Dlatego też r ~ CJ(Pqa),
tzn. że CJ(xa)~ CJ(PIJ.a).Zachodzi również CJ(Pąa) ~ CJ(xa),ponieważ Pąa-::Jxa.
Zatem CJ(xa)= a(Pqa).

X
- ..-,
- . ''
·•I
'

'
'
' ',
' •'
'. ' ' '
' ' '

. .,,.: ,_- . ,,
,,,
.. ,,;~ .',:
' ,,,
.. ,., 1j\ '"''
.·,,r"-.•~, ' .. ,'
' ', ' ' ' •' ' •a

,,;,
,_,..,.~
. ·''
,, ; ' ,,
• •
., '""
" o'
'
,,

Rys. 34.8. Ilustratjadowodu lematu 34.3. Na rysunku widać, żer = u(P,a), gdzie q = a(x) ir = ,r(xa)


Jesteśmy
teraz gotowi do przeprowadzenia dowodu głównego twierdzenia
charakteryzującego zachowanie się automatu wyszukiwania wzorca. Jak stwier-
dziliśmy wcześniej, twierdzenie to mówi, że automat w każdym kroku pamięta
najdłuższy prefiks wzorca będący sufiksem dotychczas wczytanego tekstu.

TWIERDZENIE 34.4.
Jeślir/>jest rozszerzoną funkcją przejść automatu wyszukiwania wzorca dla
danego wzorca P, a T[l .. n] jest tekstem wejściowym dla automatu, to
,f,(T1) = u(T,)
dla i= O, 1, ... , n.

DOWÓD
Dowód przebiega przez indukcję względem i. Dla i= O twierdzenie jest w oczy-
wisty sposób prawdziwe, ponieważ T 0 = s. Zatem r/>(T0 ) = CJ(T
0 ) = O.

970
34.3. WYSZUKIWANIE WZORCA Z WYKORZYSTANIEM AUTOMATÓW SKOl'ilCZONYCH

Załóżmy teraz, że (p(T1) = u(T 1);


udowodnimy, że </J(T;+1 ) = u(T 1+ 1).
Niech q oznacza (p(T1) i niech a oznacza T[i + l]. Mamy więc

<f,(T,+,) - <f,(T,a) (z definicji T1+ 1 i a)


- ó(<f,(T,),a) (z definicji </J)

- li(ą, a) (z definicji q)

- a(P,a) (z definicji (34.3) funkcji li)


- a(T,a) (z lematu 34.3 i indukcji)

= u(T1+1) (z definicji T; + 1 )

Twierdzenie zostało udowodnione przez indukcję.


Z twierdzenia 34.4 wynika, że jeśli automat przechodzi do stanu q w wier-
szu 4, to q jest największą wartością taką, że Pą :JT;. Mamy zatem q = m
w wierszu 5, gdy wystąpienie wzorca P zostało właśnie wykryte. Wynika stąd,
że procedura FINITE-AlITOMATON-MATCHER działa poprawnie.

Obliczaniefunkcji przejść

Następująca procedura oblicza funkcję przejść tJ dla danego wzorca P[l .. m].

COMPUTE-TRANSITION-FUNCTION(P,l')
1 m +- /ength [P]
2 forą+-Otom
3 doforaeI
4 dok+-min(m+l,ą+2)
5 repeatk+-k-1
6 until Pt:JPąa
7 li(ą, a)~k
8 return tJ

Procedura ta oblicza ó(q, a), korzystając w bezpośredni sposób z definicji.


W zagnieżdżonych pętlach zaczynających się w wierszach 2 i 3 są rozważane
wszystkie stany q i symbole a, w wierszach 4-7 jest zaś przypisywana funkcji
tJ(q, a) największa wartość k taka, że Pt :JPą a. Program rozpoczyna działanie
z największą sensowną wartością k, którą jest min(m, q + 1), a następnie
zmniejsza każ Pt:JPąa.
Czas działania tej procedury wynosi O(m 3 1II), ponieważ pętle zewnętrzne
mają sumaryczny koszt ml.El, wewnętrzna pętla repeat może być wykonywana

971
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

co najwyżej m + 1 razy, a test Pl-:JPąa w wierszu 6 wymaga porównania co


najwyżej m symboli. Istnieją szybsze algorytmy; czas obliczania funkcji ó może
być zmniejszony do O(mjII) przy wykorzystaniu pewnych informacji obliczo-
nych dla wzorca P (patrz zad. 34.4-6). Przy użyciu takiej szybszej procedury
obliczania ó całkowity czas działania algorytmu, służącego do znajdowania
wszystkich wystąpień wzorca o długości m w tekście o długości n nad alfa-
betem E, wynosi O(n + mil'!).

ZADANIA
34.3-1. Skonstruuj automat wyszukiwania wzorca P = aabab i przetestuj jego
działanie dla tekstu T = aaababaabaababaab.
34.3-2. Narysuj diagram przejść automatu wyszukiwania wzorca ababbabba-
babbababbabb nad alfabetem I= {a, b}.
34.3-3. Wzorzec P nazywamy ssmorozlączoym, gdy Pl-:JP, implikuje k = O
lub k = q. Opisz strukturę automatu wyszukiwania tego typu wzorca.
* 34.3-4. Dla danych dwóch wzorców Pi P' opisz konstrukcję automatu skoń­
czonego wyszukującego wystąpienia każdego z nich. Spróbuj zminimalizo-
wać liczbę stanów takiego automatu.
34.3-5. Dla danego wzorca P zawierającego symbole uniwersalne (patrz zad.
34.1-5) pokaż, jak zbudować automat skończony wyszukujący P w tekście
Tw czasie O(n), gdzie n= ITI.

34.4. Algorytm Knutha-Morrisa-Pratta


Przedstawimy teraz liniowy algorytm wyszukiwania wzorca opracowany przez
Knutha, Morrisa i Pratta. Algorytm ten osiąga czas 0(n + m) przez pominię­
cie obliczania funkcji przejść ó, używając zamiast niej funkcji pomocniczej
n:[l .. m] obliczonej dla danego wzorca w czasie O(m), Tablica n; pozwala na
efektywne obliczanie funkcji przejść {J (w sensie zamortyzowanym) ,,w biegu"
tylko wtedy, kiedy potrzeba. Z grubsza rzecz biorąc, dla każdego stanu q =
= O, 1, ... , mi symbolu a EI wartość n:[q] zawiera informację niezależną od a,
ale użyteczną przy obliczaniu ó(q, a). (Uwaga ta będzie wkrótce rozwinięta).
Ponieważ tablica 1t ma tylko m elementów, podczas gdy {J ma O(m1I!) elemen-
tów, zaoszczędzamy czynnik IEIprzy obliczaniu n; zamiast ó.

Funkcja prefiksowa dla wzorca


Funkcja prefiksowa dla wzorca zawiera informacje związane z porównywa-
niem wzorca z samym sobą. Informacja ta może zostać użyta do uniknięcia
zbytecznych testów w algorytmie „naiwnym" lub w czasie wykorzystywania
funkcji {J dla automatu wyszukiwania wzorca.

972
34.4. ALGORYTM KNUTHA-MORRISA-PRATTA

Rozważmy działanie algorytmu „naiwnego". Na rysunku 34.9a widać


konkretne przesunięcie s okienka, zawierającego wzorzec P = ababaca, wzglę­
dem tekstu T. W przykładzie tym mamy q = 5 symboli wzorca pasujących do
tekstu, ale szósty symbol wzorca nie pasuje do odpowiadającego mu symbolu
tekstu. Informacja o q symbolach sprawdzonych pozytywnie wyznacza jedno-
znacznie pewne symbole tekstu. Znając tych q symboli, możemy stwierdzić
bezpośrednio niepoprawność pewnych przesunięć. W przykładzie na rysunku
przesunięcie s + l jest z pewnością niepoprawne, ponieważ pierwszy symbol
wzorca „a" byłby porównywany z symbolem tekstu, o którym wiadomo, że
pasuje do drugiego symbolu wzorca „b". Przesunięcie s + 2, pokazane w części
(b) rysunku, powoduje porównanie pierwszych 3 symboli wzorca z 3 symbola-
mi tekstu, które muszą do nich pasować. W ogólności może się przydać znajo-
mość odpowiedzi na następujące pytanie:

c b a b T

C a p

(o)

bacbab a b C b T

b a c a P

(b)

(c)

Rys. 34.9. Funkcja prefiksowa n:. (a) Wzor~ P = ababaca jest przystawiony do tekstu T tak, że
pierwszych q = 5 symboli pasuje do s.iebie.Pasujące symbole, pokazane na szarym tle, są połącza"
ne pionowymi liniami. (b) Korzystając z tego, że 5 symboli pasuje, wnioskujemy, że pr:z.esunięcie
:;+ I jest niepoprawne, natomiast przesunięcie s' = s + 2 jest zgodne z nasz11dotychczasową wie-
dzą o tekście i jest potencjalnie poprawne. (c) Informacja użyteczna w powyższym rozumowaniu
może być obliczona wcześniej dla samego wzorca. Widzimy tutaj, że najdłuższym preftk.semP bę­
dą.cym sufiksem P, jest P 3 • Informacja ta jest obliczona i zapamiętana w tablicy n, a więc 1t [5] = 3,
Wiedząc, że ą symboli pasuje przy przesunięciu s, wnioskujemy, że następnym potencjalnie po-
prawnym pr:z.esunięciem jest l = s + (q - n [ąl)

973
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

Zakładając, że symbole wzorca P[l „ q] pasują do symboli tekstu T[s + 1 .. s +


+ q], jakie jest najmniejsze przesunięcie s' > s takie, że

P[l .. k] - T~' + 1 .. s' + k] (34.5)

gdzie s' + k = s + q?
Tak.ie przesunięcie s' jest następnym przesunięciem większym niż s, które
może okazać się poprawnym zgodnie z naszą wiedzą o T[s + 1 .. s + q]. W naj-
lepszym przypadku mamy, że s' = s + q, a przesunięcia s + l, s + 2, ... ,
s + q - I są od razu wyeliminowane. W każdym razie, dla nowego przesunię­
cia s' nie musimy sprawdzać pierwszych k symboli P wzorca z odpowiadający­
mi im symbolami tekstu T, ponieważ wiemy, że pasują one do siebie zgodnie
z równaniem (34.5).
Potrzebna informacja może być obliczona przez porównanie wzorca z so-
bą samym, jak jest to pokazane na rys. 34.9c. Ponieważ T[s' + 1 .. s' + k] jest
częścią znanego segmentu teksu, jest ono sufiksem tekstu P.,. Równanie (34.5)
może być zatem interpretowane jako pytanie o największe k < q takie, że
Pt=iPą. Tak więc s' = s + (q -k) jest następnym potencjalnie poprawnym
przesunięciem. Okazuje się, że bardziej się opłaca pamiętać liczbę k symboli,
które pasują względem nowego przesunięcia s', zamiast zapamiętywać s' - s.
Informacja ta może być użyta do przyspieszenia działania zarówno algorytmu
,,naiwnego", jak i algorytmu wykorzystującego automat skończony.
Opiszemy teraz dokładniej wstępne obliczenia dla wzorca. Dla danego
wzorca P[l .. m] funkcjaprefiksowa

n: {1, 2, ... , m}~ {O, 1, ..., m - 1}

jest zadana równaniem

n[ą] - max{k: k< q i P, :JP,)

Tak więc n[q] jest maksymalną długością prefiksu wzorca P będącego właś­
ciwym sufiksem Pą. Na przykład na rys. 34.lOa jest pokazana pełna funkcja
n dla wzorca ababababca.
Algorytm Knutha-Morrisa-Pratta jest opisany poniżej nieformalnie jako
procedura K.MP-MATCHER. Algorytm zasadniczo symuluje procedurę FINI-
TE-AUTOMATON-MATCHER.Procedura KMP-MATCHER wywołuje pomocni-
czą procedurę COMPUTE-PREFIX-FUNCTIONobliczającą n.

KMP-MATCHER(T,P)
1 n+- length [f]
2 m +- length (P]
··----
974
34.4. ALGORYTM KNUTHA-MORRISA·PRATTA

3 :n:- COMPUTE-PREFIX-FUNCTION(P)
4 ą-o
5 fori-lton
6 do while q > O i P[q + I] # T[i]
7 do q - :n:[qJ
8 ifP[q+IJ-T[i]
9 tbeną-ą+l
IO if q - m
11 then wypisz „Wzoruc występuje z przesunięciem" i- m
12 q- n[q]

COMPUTE-PREFIX-FtJNCTION(P)
1 m-length[PJ
2 n[tJ-o
3 k-o
4 forą-2tom
5 do while k > O i P[k + I] P # [q]
6 dok- n[k]
7 i!P[k+l]-P[q]
8 tbenk-k+l
9 n[q]-k
1O return :n:

Rozpoczniemy od zanalizowania złożoności czasowej obydwu procedur.


Dowód poprawności jest bardziej skomplikowany.

Analiza czasu działania procedur


Czas działania procedury COMPUTE-PREFIX-FUNCTION wynosi O(m), co wy-
nika z analizy kosztu zamortyzowanego (patrz rozdz. 18). Wiążemy potenc-
jał k z bieżącą wartością zmiennej k. Potencjał ten ma wartość początkową O,
nadaną w wierszu 3. Przy każdym wykonaniu wiersza 6 wartość k jest zmniej-
szana, ponieważ n[k] < k. Ze względu na to, że :n:[k]~ O dla każdego k, war-
tość k jest zawsze nieujemna. Poza tym k jest modyfikowane jedynie w wier-
szu 8, w którym zwiększamy k co najwyżej o I podczas każdego wykonania
treści pętli for. Ponieważ k < q przy wejściu do pętli for i ą jest zwiększane
w każdej iteracji pętli for, więc zawsze mamy k < q. (Stąd wynika, że n[q] < q,
zgodnie z wierszem 9). Koszt każdego wykonania pętli while w wierszu 6 amor-
tyzujemy zmniejszeniem potencjału, ponieważ :n:[k]< k. W wierszu 8 zwięk­
szamy potencjał co najwyżej o 1, zatem zamortyzowany koszt jednej iteracji
wierszy 5-9 wynosi 0(1). Ponieważ liczba zewnętrznych iteracji wynosi O(m)
i ponieważ końcowa wartość potencjału jest nie mniejsza niż jego wartość

975
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

początkowa, całkowity rzeczywisty czas działania procedury COMPUTE-PRE·


FIX-FUNCTION w najgorszym przypadku wynosi O(m).
Algorytm Knutha-Morrisa-Pratta działa w czasie O(m + n). Jedno wywo-
łanie procedury COMPUTE-PREFIX-FUNCTION wymaga czasu O(m), a z po-
dobnej analizy kosztu zamortyzowanego, w której używamy q jak.o potencjału,
wynika, że reszta procedury KMP-MATCHER wymaga czasu O(n).
w porównaniu z procedurą FINITE-AUTOMATON-MATCHER, używając
w procedurze K.MP-MATCHER funkcji n zamiast ó, zredukowaliśmy czas prze-
twarzania wzorca z O(m]II) do O(m), zachowując liniowe oszacowanie czasu
samego wyszukiwania wzorca.

Poprawność obliczania funkcji prefiksowej


Rozpoczniemy od istotnego lematu pokazującego, że iterowanie funkcji n ge-
neruje wszystkie prefiksy P1 będące sufiksami danego prefiksu Pą. Niech

s[q] - {q, n(q], n 2 [q], n 3 (q], ..., n'[q])

gdzie ni oznacza i-krotne złożenie funkcji n, a więc n°{ą] = q i n 1+ 1 [q] =


= n[ni[q]] dla i> 1, przy czym zakładamy, że ciąg n·[ą] kończy się, gdy zostaje
osiągnięte n 1{q] = O.

LEMAT 34.5. (Lemat o iteracji funkcji prefiksowej)


Niech P będzie wzorcem długości m z funkcją prefiksową n. Wtedy dla
q - I, 2, ..., m mamy n'[q] - {k: P,::iP,).

DOWÓD
Udowodnimy najpierw, że

ien·[ą] implikuje P1 :JPą (34.6)

Jeśli ien"[q], to i= nu[q] dla pewnego u. Udowodnimy zależność (34.6) przez


indukcję względem u. Dla u= O mamy i= q; stąd wynika nasza teza, ponieważ
Pą :J Pą. Korzystając z relacji P,ql] :J P1 i przechodniości relacji ::i, otrzymujemy
tezę dla wszystkich iw n'[q]. Zatem n'[q] c {k:P,::iP,}.
Udowodnimy przez sprowadzenie do sprzeczności, że {k: P1 ::iPą} c n'[q].
Załóimy (zaprzeczając naszej tezie), że istnieje liczba całkowita w zbiorze
{k:P,1;:::iPą} - n·[q]. Niechj będzie największą taką wartością. Ponieważ q jest
elementem zbioru {k: P,1; ::JPą} n n·[ą], mamy j < q. Niechj' oznacza najmniej·
szą liczbę w n·[ą] większą odj. (Możemy przyjąćj' = q,jeśli nie ma innej liczby
w n"[q], która jest większa od J). Mamy: P1::JP",ponieważ je {k: P1 ::JP"},oraz
P1 ,:::JPą, ponieważ j'en:·[ą]; zatem P1::JPr z lematu 34.1. Co więcej, j jest

976
34.4. ALGORYTM KNUTHA-MORRISA-PRATTA

największą liczbą o tej własności. A więc musi zachodzić n[/1 = j orazjEtt.[q].


Ta sprzeczność kończy dowód lematu.

Rysunek 34.1 O ilustruje ten lemat. •


1 2 3 4 5 6 7 8 9 10
'
P[i] • b • b • b • b C •
11:[1] o o 1 2 3 4 5 6 o I
(a)

• b

a. b C a 11:(8]=6

11:[6]= 4

P, a. b a. b & b C a. tt[4] "'2

eia. bab ab ab C a n[2J = O


i
'
(b]

Rys. 34.10. Ilustracja lematu 34.5 dla wzorca P = ababababca i q = 8. (a) Funkcja 11. Ponieważ
11[8]= 6, 11(6]= 4, 11[4]= 2 oraz 11[2}=0, iterując 11 otrzymujemy 11°[8]= {8, 6, 4, 2, O}. (b)
Przesuwamy okien.ko zawierające wzorzec P na prawo. Przyjrzyjmy się, kiedy prefiks P1 wzorca
P pasuje do właściwego sufiksu P 8 ; zachodri to dla k = 6, 4, 2 i O. Na rysunku pierwszy wiersz
zawiera P, przerywana linia pionowa jest narysowana dokładnie za P 8. Kolejne wiersze pokazują
wszystkie przesunięcia P, które powodują, że pewien prefiks Pt wzorca Ppasuje do pewnego sufiksu
P8 . Kolejno pasujące symbole są umieszczone na szarym tle. Pionowe linie łączą pasujące symbole.
2.atem {k:Pl::JP,} = {8, 6, 4, 2, O}.Lemat mówi, że n"[q] = {k:Pl::JP,} dla wszystkich q

Procedura CoMPUTE-PREFIX-FUNCTION oblicza n[q] dla ą 1, 2, ..., m. =


Przypisanie n[l] = O w wierszu 2 tej procedury jest niewątpliwie poprawne,
ponieważ n[q] < q dla wszystkich q. Następujący lemat i wniosek będą użyte
w dowodzie poprawności obliczania n[ą] dla q > 1 w procedurze COMPUTE-
-PREFIX-FUNCTION.

LEMAT 34.6.
Niech P będzie wzorcem długości mi niech n będzie funkcją prefiksową dla P.
Wtedy dla q = l, 2, ... , m, jeśli n[q] > O, to zachodzi n[ą] -1 E n•[q - 1].

977
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

DOWÓD
Jeśli k=n[q]>O, to P1 -=iPą, a zatem P1 _ 1 -=iPą-i (przez pominięcie ostat-
niego symbolu z P„ i Pą). Z lematu 34.5 wynika, że k - 1 En-.[q -1].

Dla q = 2, 3, ... , m zdefiniujmy podzbiór E 4 _ 1 s n·[q -1] jako



E,_, - {k:ken'[q - I] i P[k + I] -P[ą]}
Zbiór Eq_-l składa się z tych wartości k, dla których P1 ~Pą-t (z lematu 34.5);
ponieważ P[k + 1] = P[q], więc ponadto dla tych wartości k zachodzi
Pk+t ::iPq_. Intuicyjnie, Eq_-t składa się z tych wartości kEn.[q - l], dla któ-
rych możemy rozszer.lyć P1 do P 1 + 1 i otrzymać sufiks Pą·

WNIOSEK 34. 7,
Niech P będzie wzorcem długości mi niech n- będzie funkcją prefiksową dla P.
Dla q = 2, 3, ..., m zachodzi

o, jeśli E4 _ 1 = 0
n[q] - {l + max{kEEq_ 1 }, jeśli Eą-t ie 0

DOWÓD
Jeślir = n[q], to P, ::i Pą, a więc r ;:i: 1 implikuje P[r] = P[q]. Z lematu 34.6
wynika zatem, że jeśli r ;;i: I to

r-1 +max{ken'[ą-1]:P[k+ IJ-P[ą]}

Ale przecież zbiorem, z którego wybieramy maksimum jest Eq_-i, a więc


r= l +max{kEEą_ 1 } i zbiór E 4 _ 1 jest niepusty. Jeśli r=O, to nie ma
kEn.[q - I], dla którego możemy rozszerzyć P1 do Pt+i i otrzymać sufiks Pą,
ponieważ w tak.im wypadku mielibyśmy n[q] > O. Zatem E4 _ 1 = 0.


Skończymy teraz dowód poprawności obliczania funkcji n przez procedurę
COMPUTE-PREFIX-FUNCTION. w procedurze tej na początku każdej iteracji
pętli for w wierszach 4-9 mamy k = n[q - 1]. Warunek ten jest wymuszony
w wierszach 2 i 3, kiedy pierwszy raz wchodzjmy do pętli, oraz zachodzi w każ­
dej kolejnej iteracji na skutek wiersza 9. W wierszach 5-8 jest modyfikowane
k tak, że staje się ono poprawną wartością n[q]. W pętli obejmującej wiersze
5-6 są przeglądane wszystkie wartości kEn *[q - I] do chwili znalezienia takiej,
która spełnia zależność P[k + 1] = P[q]; wtedy wiemy, że k jest największą.
wartością w zbiorze Eq-i· Zatem na mocy wniosku 34.7 przypisujemy na n[q]
wartość k + 1. Jeśli nie ma takiego k, tok= O w wierszach 7-9, a n[ą] otrzymu-

978
34.4. ALGORYTM KNUTHA-MORRISA-PRATTA

je wartość O. Kończy to nasz dowód poprawności procedury COMPUTE-PRE-


FIX-FUNCfION.

Poprawność algorytmu KMP


Procedura KMP-MATCHER może być interpretowana jako inna implementa-
cja procedury FINJTE-AUTOMATON-MATCHER.w szczególności udowodni-
my, że instrukcje w wierszach 6-9 procedury KMP-MATCHER są równoważne
wierszowi 4 procedury FINITE-AUTOMATON-MATCHER, która przypisuje
zmiennej q wartość b(q, T[i]). Zamiast korzystać z zapamiętanej wartości
b(q, T[i]), wartość ta jest ponownie obliczana (jeśli jest potrzebna) z funkcji n.
Jeśli pokażemy, że procedura KMP-MATCHER symuluje działanie procedury
FINITE-AUTOMATON-MATCHER, to jej poprawność wynika z poprawności
procedury FINITE-AlJTOMATON-MATCHER (chociaż zobaczymy za chwilę,
dlaczego wiersz 12 w procedurze KMP-MATCHER jest niezbędny).
Poprawność procedury KMP-MATCHER wynika stąd, że albo b(q, T[z1)= O,
albo b(q,T[i]) ~ 1 En·[ą]. W celu udowodnienia powyższego faktu przyjmijmy
k = b(q, T[i]). Wtedy P1 ::::iP,T[i] z definicji funkcji ci oraz a. Zatem albo k = O,
albo k ~ 1 i P,:_1 ~Pą przez usunięcie ostatnich symboli z obu tekstów P,:i PąT[i]
(w tym wypadku k - ) cn'[ą]). Tak więc albo k - O, albo k - ) c,'[ą], co
dowodzi rozważanego faktu.
Z faktu tego korzystamy, jak następuje. Niech q' oznacza wartość q, kiedy
wchodzimy do wiersza 6. Wykorzystujemy równoważność n·[ą] = {k: P,:~P,},
aby wykazać, że iteracja ą +- x[q] przegląda elementy {k: Pk~Pą,}. W wier-
szach 6-9 wyznaczamy b(q', T[i]), przeglądając elementy 11:·[ą'] w kolejności
malejącej. Algorytm korzysta z rozważanego faktu i zaczyna od q = tp(T1_ 1) =
= u(T;_ 1 ), a następnie wykonuje iteracje q+- n[q], aż zostanie znalezione q ta-
kie, że ą - O lub P[ą + l] - T[i]. W pierwszym przypadku b(q', T[i]) - O;
natomiast w drugim przypadku q jest maksymalnym elementem w E 4 , takim,
że b(q', T[i]) - q + I (z wniosku 34.7).
Wiersz 12 jest konieczny w KMP-MATCHER, aby uniknąć możli,\'ych od-
wołań do P[m + I] w wierszu 6 po wykryciu wystąpienia P. (Równość ą =
= u(T 1_ 1) zachodzi po wykonaniu wiersza 6, jak to wynika ze wskazówki
podanej w zad. 34.4-6: ó(m, a)= ó(n[m], a) lub, równoważnie, a(Pa) =
= a(P "rm1a) dla każdego aE I.) Poprawność algorytmu Knutha-Morrisa-Pratta
wynika z poprawności procedury FINITE-AUTOMATON-MATCHER, ponie-
waż pokazaliśmy, że KMP-MATCHER symuluje zachowanie się FINITE-AUTO-
MATON-MATCHER.

ZADANIA
34.4-1. Wyznacz funkcję prefiksową ,r dla wzorca ababbabbababbababbabb,
gdy alfabetem jest I= {a, b}.

979
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

34.4-l. Podaj górną granicę na rozmiar n' [ q] jako funkcję zależną od q. Pokaż
na przykładzie dokładność swojego oszacowania.
34.4-3. Opisz, jak można wyznaczyć wystąpienia wzorca P w tekście T za
pomocą funkcji n dla słowa PT (słowo o długości m + n będące konkate~
nacją P i 7).
34.4-,J. Pokaż, jak można ulepszyć procedurę KMP-MATCHER, zastępując
funkcję n w wierszu 7 (ale nie w wierszu 12) przez n', gdzie n' jest zdefinio-
wana rekurencyjnie dla q = l, 2, ... , m:

o, jeśli rr[ą] - O
rr'[ą] - rr'[rr[ą]], jeśli rr[ą] #a O i P[rr[ą] + I] - P[q + I]
rr[ą], jeśli rr[ą] #a O i P[rr[ą] + I] #a P[q + I]

Wyjaśnij,
dlaczego zmodyfikowany algorytm jest poprawny oraz w jakim
sensie modyfikacja ulepsza algorytm.
34.4-5. Skonstruuj liniowy algorytm sprawdzający, czy tekst T jest cykliczną
rotacją danego tekstu T'. Na przykład arc i car są swoimi cyklicznymi
rotacjami.
* 34.4-6. Skonstruuj efektywny algorytm obliczający funkcję przejść ó dla auto-
matu szukającego wzorca P. Twój algorytm powinien działać w czasie
O(mll:I). (Wskazówka: Udowodnij, że li(q, a) - li(rr[ą], a), jeśli q - m lub
P[q + I] #a a).

----------------------------
* 34.5. Algorytm Boyera-Moore'a
Jeśli wzorzec P jest względnie długi, a alfabet I jest dostatecznie duży, to
algorytm opracowany przez Roberta S. Boyera i J. Strothera Moore'a jest
prawdopodobnie najbardziej praktycznym algorytmem.

BOYER-MOORE-MATCHER(T,P, I}
l n .._ length [f]
2 m-length[P]
3 ,1..._ CoMPUTE-LAST-0CCURRENCE-FUNCTI0N(P,m, I)
4 y .._ COMPUTE-GOOD-SUFFIX-FUNCTION(P,m)
5 s-o
6 whiles~n-m
7 do)-m
8 wbilej > Oi PU] - T[s + j]
9 do)-J-1
IO ifj-0

980
* 34.5. ALGORYTM BOYERA-MOORE'A

11 tben wypisz „Wzorzec występuje z przesunięciem" s


12 s+-s+y[O]
13 else s - s + max(y[j], j ~ ,\[T[, + j]])

Pomimo tajemniczego wyglądu A.i y, program ten przypomina „naiwny"


algorytm wyszukiwania wzorca. Istotnie, jeśli usuniemy wiersze 3-4 i zastąpimy
modyfikację s w wierszach 12-13 przez proste zwiększanie wartości:

12 S+-S + I
13 elses+-s+ 1

to zmodyfikowany program wygląda zupełnie tak jak algorytm „naiwny".


W pętli while zaczynającej się w wierszu 6 jest rozważane po kolei każde
z n - m + 1 możliwych przesunięć s, a w pętli while zaczynającej się w wier-
szu 8 jest sprawdzany warunek P[l .. m] = T[s + 1 .. s + m] przez porównanie
P[j] z T[s + j] dlaj = m, m - 1, ...,I.Jeśli pętla się kończy z wartościąj = O,
to znalezione jest poprawne przesunięcie s i instrukcja w wierszu 11 powoduje
wydrukowanie wartości s. W tym momencie jedyną wyróżniającą się własno­
ścią algorytmu Boyera-Moore'a jest to, że porównuje on wzorzec i tekst od
strony prawej do lewej, oraz to, że zwiększa przesunięcie s w wierszach 12-13
o wartość czasami większą niż I.
Algorytm Boyera-Moore'a wykorzystuje dwie heurystyki, co pozwala na
pominięcie znacznej części pracy wykonywanej przez poprzednio przedstawio-
ne algorytmy wyszukiwania wzorca. Heurystyki te są są na tyle efektywne, że
umożliwiają pominięcie w algorytmie sprawdzania wielu symboli w tekście.
Heurystyki te są znane jak.o „heurystyka niezgodności" i „heurystyka dobrego
sufiksu''. Są one graficznie przedstawione na rys. 34.11. Można je traktować
tak, jak gdyby działały niezależnie i jednocześnie. W chwili pojawienia się nie-
zgodności wzorca z tekstem każda z heurystyk dostarcza możliwe wartości
przesunięcia s. Algorytm Boyera-Moore'a wybiera większą z nich i odpowied-
nio zwiększa s w wierszu 13. Heurystyka niezgodności daje s = j - A.[T[s + j]],
natomiast heurystyka dobrego sufiksu daje s = y[j].

Heurystyka niezgodności
W sytuacji pojawienia się negatywnego wyniku porównania heurystyka nie-
zgodności korzysta z informacji o położeniu niezgodnego symbolu T[.v+ j] we
wzorcu Geśli jest jakiekolwiek) w celu zaproponowania odpowiedniego przesu-
nięcia. W najlepszym przypadku niezgodność może wystąpić przy pierwszym
porównaniu (P[m] c!-T[s + m]) i niezgodny symbol T[.~+ m] w ogóle nie wy-
stępuje we wzorcu. (Wyobraźmy sobie szukanie amw tekście b".) W tym wypa-
dku możemy wykonać przesunięcie m, ponieważ każde przesunięcie mniejsze
_____________________ ,_____
,,.,,_,,
_____ ~=
981
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

Niezgodny symbol l r Dobry sufiks

••• w r t e n t h a t ···
~

r a m i n i

(,)

.
••• w r i t t • n
- n o t ',łJ C • - t h • t •••
I
>+4
r • m i

(b)
"'I
n ., , a o • n o •

••• w r i t t
• n
- n o t i ·•·· • '(,f,
- t h a I t I •••

,+3
r • m i n i a !"O.;;". n o •
(c)

Rys. 34.11. llustracja heurystyk w algorytmie Boyem-Moore' a. (a) Szukanie wzorca ,eminiscence w tek-
ście przez porównywanie symboli od strony prawej do lewej. Przesunięcie sjest niepoprawne; chociaż
,,dobry sufiks'' ce wzorca pasuje do odpowiadających mu symboli tekstu {kolor szary na rysunku),
jednak w tekście został wykryty „niezgodny symbol" i, który nie pasuje do symbolu n we wzorcu.
{b) Heurystyk.a niezgodności „proponuje" przesu~e wzorca. w prawo,jeśli można, o wielkość, która
zagwarantuje, że niezgodny symbol tekstu będzie pasował do pierwszego od prawej wystąpienia tego
symbolu we wzorcu. W tym przykładzie przesunięcie wzorca o 4 pozycje w prawo powoduje to, że
symbol I w tekście będzie pasował do prawostronnego wystąpienia i we wzorcu, na pozycji 6. Jeśli
niezgodny symbol nie występuje we wzorcu, to wzorzec może zostać całkowicie przesunięty poza ten
symbol. Jeśli prawostronne wystąpienie niezgodnego symbolu we wzorcu jest na prawo od pozycji
bieżącego niezgodnego symbolu, to heurystyka ta się nie stosuje. (c) W przypadku heurystyki dobrego
sufiksu, wzorzec jest przesunięty na prawo o tyle pozycji aby zagwarantować, że w ten sposób nie
pomijamy żadnego potencjalnego wystąpienia zgodnego ze sprawdzonym właśnie sufiksem. W przy-
kładzie, przesuwając wzorzec o 3 pozycje na prawo, spełniamy ten warunek. Ponieważ heurystyka
dobrego sufiksu sugeruje przesunięcie o 3 pozycje, podczas gdy druga heurystyka daje przesunięcie
równe 4, więc aJgorytm Boyera-Moore'a wykonuje przesunięcie o 4 pozycje

niż m przystawi do wzorca nie pasujący symbol (którego nie ma we wzorcu),


powodując niezgodność. Jeśli taki najlepszy przypadek występuje często, to
algorytm Boyera-Moore'a przegląda jedynie 1/m część całego tekstu, ponieważ
każdy napotkany symbol powoduje niezgodność oraz daje przesunięciem. Ten
optymalny przypadek pokazuje przewagę porównywania symboli od strony
prawej do lewej nad porównywaniem symboli w kieninku przeciwnym.

982
* 34,5. ALGORYTM BOYERA-MOORE'A

Ujmując rzecz ogólnie, heurystyka niezgodności działa następująco. Załóż­


my, że wykryliśmy właśnie niezgodność: P[J] #:-T[s + j] dla pewnego j, gdzie
1 ~j ~ m. Wtedy niech k będzie takim największym indeksem w przedziale
1 ~ k ~ m, że T[s + j] = P[k], jeśli jakiekolwiek takie k istnieje. Jeśli nie, to
przyjmujemy k = O. Twierdzimy, że możemy bezpiecznie przesunąć wzorzec
oj - k. Aby to wykazać, musimy rozważyć trzy przypadki, jak to ilustruje
rys. 34.12.
• k = O:Jak na rys. 34.12a, niezgodny symbol T[s + j] nie występuje
widać
we wzorcu i możemy wykonać bezpieczne przesunięcie oj, nie pomijając
żadnego poprawnego wystąpienia wzorca.
• k <J: Jak widać na rys. 34.12b, istnieje prawostronne wystąpienie niezgod-
nego symbolu na lewo od pozycji j, tak że j - k > O musi być przesunięty
j - k symboli w prawo, zanim niezgodny symbol będzie pasować do sym-
bolu we wzorcu na jakiejkolwiek pozycji. Możemy zatem wykonać bez-
pieczne przesunięcie oj - k.
• k > j: Jak. widać na rys. 34.12c,j - k < O, a więc pr1.esunięcie proponowane
przez heurystykę niezgodności może być zignorowane, ponieważ nie jest
dodatnie.
Poniższy
prosty program definiuje ...l.[a]jak.o indeks położonej najbardziej
na prawo pozycji wzorca, zawierającej symbol a dla każdego aEE. Jeśli a nic
ma we wzorcu, to A.[a]= O. Funkcję ...1.nazywamy funkcją ostatniego wystąpie­
nia. Przy tej definicji wyrażenie j - ...l.[T[s+ j]] w wierszu 13 procedury BOY-
ER-MOORE-MATCHER realizuje heurystykę niezgodności. (Ponieważ
j - A.[T[s + j]] jest ujemne, jeśli najbardziej na prawo położone wystąpienie
niezgodnego symbolu T[s + j] jest we wzorcu na prawo od pozycji}, bazujemy
na dodatniości funkcji y[j], związanej z heurystyką dobrego sufiksu; dzięki
temu zapewnione jest sensowne działanie algorytmu).

COMPUTE-LAST-0CCURRENCE-FUNCTI0N(P,m, E)
1 for każdy symbol aEE
2 do .![a] - O
3 forJ-1tom
4 do .![P[j]J - j
5 return A

Czas działania powyższej procedury wynosi O(IEI + m).

Heurystyka dobrego sufiksu


Definiujemy relację Q .....,
R (czytaj „Q jest podobne do R") dla tekstów Q i R;
relacja ta oznacza, że Q :::iR lub R :::iQ.Jeśli dwa słowa są podobne, to możemy

983
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

Niezgodny symbol ł
.,. J: • V i o n i n

' i n i •

ł
...i:; I• Iv IO 11 Iu It Ii IO I• I_Ii I• I_It Ih I• I_It Ir I• I• It I• I• In It I_Io I< I···
s + 11
"irj ejmji lnli I• IcI•I nicl• I
,.,
••• w r i t n o t

' r • • i

I•
••• w r i t n o t C
• t h • t • ••
,,, i n • C
• n C

{b)

•.. 9 o l o
' f ...

' i n i •

,,,
Rys. 34.12. Przypadki heurystyki niezgodności. (a) Niezgodny symbol h nie występuje we wzorcu, tak
więc wzorzec może być przesunięty oj= 11 symboli, przesuwając się poza niezgodny symbol.
(h) Prawostronne wystąpienie niezgodnego symbolu we wzorcu jest na pozycji k <}, tak że wzo-
nec może być przesunięty oj- k symboli. Ponieważ j = 10 i k = 6 dla niezgodnego symbolu i,
wzorzec może zostać przesunięty o 4 pozycje, zanim symbole i będą pasować. (c) Prawostronne
wystąpienie niezgodnego symbolu we wzorcu jest na pozycji k > j. W tym przykładzie j = 10
i k = 12 dla niezgodnego symbolu e. Heurystyka niezgodnego symbolu proponuje teraz niedodat-
nie przesunięcie, które jest zignorowane

przystawić jedno do sufiksu drugiego i otrzymać zgodne teksty. Relacja,,-"


jest symetryczna: Q,.., R wtedy i tylko wtedy, gdy R,.., Q. Z lematu 34.1
wynika, że

Q=.iR i S=.iR implikuje Q - S (34.7)

984
* 34.5. ALGORYTM BOYERA-MOORE"A

Jeślistwierdzimy, że P[j] :-IoT[s + Jl, gdzie j < m, to heurystyka dobrego


sufiksu mówi, że możemy bezpiecznie przesunąć wzorzec o

y[JJ-m-max{k:O,;; k<m i P[J+ 1 .. m] - P,)

Oznacza to, że y[j] jest najmniejszym przesunięciem s, które zagwarantuje,


że symbole T[s + j + I .. s + m] będą się zgadzać przy następnym przystawie~
niu wzorca. Funkcja y jest dobrze zdefiniowana dla każdego j, gdyż
P[j + 1 .. m] "'P 0 dla wszystkich): tekst pusty jest podobny do każdego teks-
tu. Funkcję y nazywamy funkcją dobrego suftk.su dla wzorca P.
Pokażemy teraz, jak obliczyć funkcję y. Zauważmy najpierw, że
y[j] =s:;m - n[m] z następującego powodu. Jeśli w= n[m], to P w.:::iPz defi-
nicji TL Ponadto, ponieważ P[j + l „ mJ::::iP dla każdego j, więc mamy
Pw,.., P[J + 1 .. m], na mocy równania (34.7). Zatem y[Jl =s:;m- n[m].
Definicję funkcji ')' możemy teraz zapisać w postaci

y[j] - m - max{k: n[m],;; k < m i P[j + 1 .. m] - P,)

Warunek P[j + l .. m]"' P1 zachodzi, jeśli P[j + 1 .. m] ::::iPi lub


Pk::::iP[J+ 1 .. m]. Drugi człon alternatywy implikuje Pi.:::JP, jak również
k ~ n:[m], z definicji n. W tym przypadku nie możemy zmniejszyć wartości y[j]
poniżej m - n[m]. Możemy zatem przedstawić definicję: ')' następująco:

y[JJ-m-max({n[m])u{k:n[m]<k<m i P[J+ l .. m]::iP,})

(fen drugi zbiór może być pusty). Warto zauważyć, że z definicji wynika nieró-
wność y[j] > O dla wszystkich j = I, 2, ... , m, co gwarantuje, że algorytm
Boyera-Moore'a wykona dodatnie przesunięcie.
Aby jeszcze bardziej uprościć opis funkcji y, definiujemy P' jako odwróco-
ny wzorzec P, a n' jako jego funkcję prefiksową. To znaczy, P'[1] =
= P[m - i+ I] dla i= 1, 2, ... , m, a n-'[tljest maksymalnym u takim, że u< t
oraz P~.:::JP;.
Jeśli k jest największą możliwą wartością taką, że P[j + 1 .. m] ~Pk, to
twierdzi.my, iż

n'[/] - m - j (34.8)

gdzie/= (m - k) + (m - ;). Zauważmy, że wartość n'[/] jest dobrze zdefinio~


wana, gdyż P[j + I .. mJ.:::JPkimplikuje m - j ~ k, a zatem /-::;;_
m. Ponadto
j <mik-::;_ m, a więc l ~ 1. Równość (34.8) udowodnimy następująco. Ponie-
waż P[j + I „m].:::iPi, mamy P~-j.:::JP;. Stąd n'[/]~ m - j. Załóżmy teraz, że
p > m - }, gdzie p = n'[l]. Wtedy z definicji n' mamy, że P;-:-JP; lub (równo-

985
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

ważnie) P'(l .. p] =P'[l - p + 1 .. 1]. Przepisując to równanie z wykorzysta-


niem P zamiast P', mamy P[m - p + 1 .. m] = P[m-l + 1 .. m - I+ p]. Pod-
stawiając / = 2m - k - j, otrzymujemy P[m - p + 1 .. m] = P[k - m + j +
+ 1 .. k - m + j + p], co implikuje P[m - p + 1 .. m] ::iPk-m+J+p· Ponieważ
p> m-j, mamy j+ I >m-p+ 1, a więc P[j+ 1 .. m]:::JP[m-p+ l .. m],
co implikuje P[j + 1 .. m] :::JPk-m+J+P na mocy przechodniości relacji ::J. Wre-
szcie, ponieważ p > m - j, mamy k' > k, gdzie k' = k - m + j + p, co przeczy
wyborowi k jako maksymalnej wartości takiej, że P[j + 1 .. m] :::JP1 . Ta spne-
czność oznacza, że nie może zachodzić p > m - j, a więc p = m - j, co kończy
dowód równości (34.8).
Korzystając z równości (34.8) oraz biorąc pod uwagę, że n'[/] = m - J
implikuje j = m - n'[/] i k = m - I+ n'[l], możemy następująco zmodyfiko-
wać definicję y:

y[j] - m - max({n[m]}
u {m - I+ n'[/]: 1 ~ I~ m i j - m - n'[/]})

- min({m - n[m])
u{l-n'[l]:l~/~m i J-m-n'[I]}) (34.9)

Znowu może się okazać, że drugi zbiór jest pusty.


Jesteśmy teraz gotowi do analizy procedury obliczającej funkcję y.

COMPUTE-Gooo-SUFFIX-FUNCTION(P, m)
1 1t +- COMPUTE-PREFIX-FUNCTION(P)
2 P' +- odwrócone P
3 n'+- COMPUTE-PREFIX-FUNCTION(P')
4 forj+-Otom
5 do y[J]-m- n[m]
6 forl+--ltom
7 doj+--m-n'[/]
8 il y[J] > I - n'[/]
9 then y[j] - I - n'[/]
1O return y

Powyższa procedura jest bezpośrednią implementacją równania (34.9). Jej


czas działania wynosi O(m).
Pesymistyczny czas działania algorytmu Boyera-Moore'a to niewątpli­
wie O((n - m + l)m + III), gdyż procedura COMPUTE-LAST-0CCURRENCE-
-FUNCTI0N wymaga czasu O(m + III), procedura COMPUTE-GOOD-SUFFIX-
-FUNCTION wymaga czasu O(m), a algorytm Boyera-Moore'a (podobnie jak

986
PROBLEMY

Rabina-Karpa) poświęca O(m) czasu, sprawdzając każde poprawne przesunię­


cie s. Jednakże w praktyce algorytm Boyera-Moore'a jest często dobrym wy-
borem.

ZADANIA
34.S-1. Oblicz funkcje ,t i y dla wzorca P = 0101101201 i alfabetu E =
- {O, I, 2}.
34.5-2. Podaj przykłady demonstrujące, że przy zastosowaniu kombinacji obu
heurystyk (niezgodności i dobrego sufiksu) algorytm Boyera-Moore'a
działa znacznie lepiej niż wtedy, kiedy jest w nim wykorzystywana sama
heurystyka dobrego sufiksu.
* 34.5-3. Ulepszenie podstawowej procedury Boyera-Moore'a, które jest często
używane w praktyce, polega na zastąpieniu funkcji y funkcją y' zdefinio-
waną następująco:

y'[j] = m - max{k: O :s;;:k <mi P[j + 1„ m],...,Pk i


(k - m + j > O implikuje P[j] * P[k - m + j]))
Oprócz zagwarantowania tego, że dobry sufiks będzie zgodny po przesu-
nięciu, funkcja y' zapewnia również to, że taki sam symbol wzorca nie
będzie porównywany z niezgodnym symbolem tekstu. Pokaż, jak efektyw-
nie obliczać funkcję y'.

Problemy
34-1. Wyszukiwanie wzorca związane z powtarzającymi się podslowami
Niech yi oznacza konkatenację słowa y ze sobą i razy. Na przykład
(ab) 3 = ababab. Mówimy, że słowo x E E ma czynnik powtóneń r, jeśli x = y
0

dla pewnego y Ei:• i pewnego r > O. Niech p(x) oznacza największe r takie, że
x ma czynnik powtórzeń r.
-
(a) Skonstruuj efektywny algorytm, który dla zadanego wzorca P[l „ m] obli-
cza p(P;) dla i= 1, 2, ... , m. Jaki jest czas działania Twojego algorytmu?
(b) Dla każdego wzorca P[l .. m] niech p•(P) będzie zdefiniowane jako

max 1 1,.,,,p(Pi). Udowodnij, że jeśli wzorzec P jest wybrany losowo ze
zbioru wszystkich ciągów binarnych długości m, to oczekiwaną wartością
p'(P)jest 0(1).
(c) Uzasadnij, dlaczego następujący algorytm wyszukiwania wzorca znajduje
poprawnie wszystkie wystąpienia wzorca P w tekście T[l .. n] w czasie
O(p '(P)n + m).

987
ROZDZIAŁ 34. WYSZUKIWANIE WZORCA

REPETITION-MATCHER(P, 7)
I m - length [PJ
2 n +- length [T]
3 k-1 +p'(P)
4 ą+-0
5 s+-0
6 whiles~n-m
7 do if T[s + q +I]= P[q + 1]
8 thenq+-q+l
9 ifq=m
IO then wypisz „Wzorzec występuje z przesunięciem" s
11 il q = m lub T[s + q + 1] a' P[q + I]
12 thens-s+max(l,1q/kl)
13 q +- O

Algorytm ten opracowali Gali! i Seiferas. Uogólniając ideę tego algorytmu


otrzymali oni liniowy algorytm wyszukiwania wzorca używający 0(1) pa-
mięci poza pamięcią potrzebną do przechowywania tablic P i T (tablice te
można tylko czytać).

34-2. Równoległe wyszukiwanie wzorca


Rozważmy problem wyszukiwania wzorca na komputerze równoległym.
Załóżmy, że mamy już automat szukania wzorca M ze zbiorem stanów q.
Niech <Pbędzie rozszerzoną funkcją przejść dla Mi niech tekstem wejściowym
będzie T[l .. n]. Chcemy obliczyć q,(Ti) dla i= 1, 2, ... , n; tzn. chcemy wy-
znaczyć końcowy stan dla każdego prefiksu. Nasza strategia polega na rów-
noległym obliczaniu sum preftksowych, tak.jak to zostało opisane w podrozdz.
30.1.2.
Dla każdego tekstu wejściowego x defmiujemy funkcję óx: Q __.Q taką, że
jeśli M rozpoczyna działanie w stanie q i wczytuje x, to M kończy działanie
w stanie óx(q).

(a) Udowodnij, że óYo óx = óxy• gdzie o oznacza złożenie funkcji:

<•,oa,)(ą) = a,(a,(ą))
(b) Udowodnij, że o jest operacją łączną.
(c) Udowodnij, że óxy może być obliczone z tablicowej reprezentacji óx i óY
w czasie 0(1) na CREW PRAM. Wyraź liczbę potrzebnych procesorów
jako funkcję IQI.
(d) Udowodnij, że <P(T1) = óT ,(ą 0 ), gdzie ą 0 jest stanem początkowym auto-
matu M.

988
UWAGI DO ROZDZIAŁU

(e) Pokaż, jak można znaleźć wystąpienia wzorca w tekście długości n w czasie
O(lgn) na CREW PRAM. Zakładamy, że wzorzec jest podany w postaci
odpowiadającego mu automatu skończonego.

Jwagi do rozdziału
Związek wyszukiwania wzorca z teorią automatów skończonych jest rozważa­
ny przez Abo, llo_pcrofta i Ullmana w [4]. Algorytm Knutha-Morrisa-Pratta
[125) był opracowany niezależnie przez Knutha i Pratta oraz przez Morrisa;
opublikowali oni wspólną pracę na ten temat. Algorytm Rabina-Karpa był
podany przez Rabina i Karpa [117], natomiast algorytm Boyera-Moore'a po-
chodzi od Bayera i Moore'a [32]. Galil i Seiferas [78] podają interesujący al-
gorytm wyszukiwania wzorca w pamięci 0(1) (poza tą używaną do przechowy-
wania wzorca i tekstu, która nie może być modyfikowana).
Rozdział 35

Geometriaobliczeniowa
'

Geometria obliczeniowa jest działem informatyki zajmującym się algorytmami


służącymi do rozwiązywania problemów geometrycznych. We współczesnej in-
żynierii i matematyce geometria obliczeniowa znajduje zastosowanie między
innymi w grafice komputerowej, projektowaniu układów VLS1, robotyce, sys~
ternach projektowania wspomaganego komputerowo i statystyce. Dane wej-
ściowe w problemie z geometrii obliczeniowej stanowi zazwyczaj opis zbioru
obiektów geometrycznych, takich jak punkty, odcinki czy wierzchołki wielo-
kąta podane w porządku przeciwnym do ruchu wskazówek zegara. Rozwiąza­
nie to często odpowiedź na pytanie dotyczące obiektów, jak to czy którekol-
wiek z danych prostych się przecinają, albo też nowy obiekt geometryczny, jak
na przykład wypukła otoczka zbioru punktów (najmniejszy zawierający je wie-
lokąt wypukły).
W tym rozdziale przedstawimy kilka algorytmów geometrii obliczeniowej
w dwóch wymiarach, tzn. na płaszczyźnie. Każdy rozważany obiekt będzie
reprezentowany przez zbiór punktów {pJ,a każdy punkt to para p 1 = (xi, y;),
gdzie X;, y 1e R. Na przykład n-wierzchołkowy wielokąt P będzie reprezentowa-
ny przez ciąg <Po, p 1, p 2, ••• , Pn-i) swoich wierzchołków w takiej kolejności,
w jakiej występują one na brzegu P. Można również zajmować się geometrią
obliczeniową w trzech wymiarach czy nawet w przestrzeniach wyższych wy-
miarów, ale takie problemy i ich rozwiązania bywają bardzo trudne do zob-
razowania. Już w przypadku dwuwymiarowym mama jednak przedstawić sze-
roką gamę metod stosowanych w geometrii obliczeniowej.
W podrozdziale 35.1 wyjaśnimy, jak efektywnie i dokładnie odpowiadać
na proste pytania dotyczące odcinków: czy pierwszy z dwóch odcinków
o wspólnym końcu leży zgodnie czy przeciwnie do ruchu wskazówek zegara
w stosunku do drugiego, w którą stronę skręcamy, przechodząc z jednego
odcinka na drugi przez wspólny koniec, albo czy dwa odcinki się przecinają.

990
35.1. WŁASNOSCI ODCINKÓW

W podroz.dziale 35.2 przedstawimy metodę zwaną „zamiataniem", z której


skorzystamy przy konstruowaniu działającego w czasie O(n lg n) algorytmu
sprawdzania, czy w zbiorze n odcinków występują przecięcia. W podrozdziale
35.3 omówimy dwa algorytmy „obrotowego zamiatania", znajdujące wypukłą
otoczkę zbioru n punktów (najmniejszy zawierający je wielokąt wypukły): al-
gorytm Grahama, działający w czasie O(nlgn), oraz algorytm Jarvisa, d7iałają­
cy w czasie O(nh), gdzie hjest liczbą punktów na otoczce. Wreszcie w podroz-
dziale 35.4 przedstawimy oparty na zasadzie „dziel i zwyciężaj" i działający
w ci.asie O(n lg n) algorytm znajdowania pary najmniej odległych spośród
n punktów na płaszczyźnie.

35.1. Własności odcinków


Niektóre z przedstawionych w tym. rozdziale algorytmów geometrii obliczenio-
wej będą wymagały rozwiązania problemów dotyczących własności odcinków.
Wypukłą kombinacją dwóch różnych punktów p 1 = (x 1, y 1) i p 2 = (x2 , y 2) jest
dowolny punkt p 3 = (x 3, y 3) taki, że dla pewnej liczby rxz przedziału O ~ rx ~ 1
zachodzi x 3 = !XX1 + (1 - rx)x2 oraz y 3 = rxy1 + (1 - rx)y2 • Piszemy wówczas, że
p 3 = rxp1 + (1 - rx)p2• Intuicyjnie, p 3 jest dowolnym. punktem na prostej prze-
chodzącej przez p 1 i p 2 , leżącym między p 1 a p 2 (lub będącym jednym z nich).
Dla danych dwóch punktów p 1 i p 2 odcinek p 1p 2 to zbiór wypuk.łych kom-
binacji p 1 i p 2 • Punkty p1 i p2 nazywamy końcami odcinka p,-fti. Czasami ma
znaczenie kolejność p 1 i p 2 ; mówimy wtedy o odcinku skierowanymp 1p 2 • Jeśli
p 1 jest początkiem układu współrzędnych (O, O), to możemy traktować odcinek
skierowany p 1p 2 jako wektorp 2 •
W tym podrozdziale zajmiemy się znalezieniem odpowiedzi na następujące
pytania:
I. Czy dla danych dwóch odcinków skierowanych p 0 p 1 i p 0 p 2 odcinek p 0 p 1
jest położony zgodnie z ruchem wskazówek zegara w stosunku do p 0 p 2
względem ich wspólnego końca p 0?
2. Czy mając dane dwa odcinki p 1p~ i /J2p 3 i przechodząc ft1p 2, a potem j, 2p),
w punkcie p 2 skręcamy w lewo?
3. Czy odcinki p 1p 2 i p 3p; się przecinają?
Na punkty nie nakładam;:._żadnych ograniczeń.
Na każde z pytań możemy odpowiedzieć w czasie 0(1), co nie powinno
być zaskakujące, ponieważ rozmiar danych wejściowych dla każdego pytania
jest stały. Co więcej, będziemy korzystać jedynie z operacji dodawania, odej-
mowania, mnożenia i porównywania. Nie potrzebujemy ani dzielenia, ani
funkcji trygonometrycznych - operacji kosztownych i podatnych na błędy za-
okrągleń. Na przykład „bezpośrednia" metoda sprawdzania, czy dwa odcinki

991
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

się pr7.ecinają
- wyznaczenie dla każdego odcinka równania prostej zawierają­
cej ten odcinek postaci y = mx + b (m jest współczynnikiem kierunkowym,
b zaś jest przesunięciem na osi y), znalezienie punktu przecięcia prostych
i sprawdzenie, r:zy ten punkt należy do obu odcinków - wymaga zastosowania
dzielenia przy znajdowaniu punktu przecięcia. Jeśli odcinki są prawie równo-
ległe, to metoda ta jest bardzo wrażliwa na dokładność operacji dzielenia na
komputerze. Opisana w tym podrozdziale metoda, w której unika się dzielenia,
jest znacznie dokładniejsza.

Iloczyn wektorowy
Podstawę naszych metod badania odcinków stanowi obliczanie iloczynu wek-
torowego. Rozważmy wektory p 1 i p 2, pokazane na rys. 35.la. Iloczyn wek-
torowy p 1 x p 2 może być interpretowany jako wyposażone w znak pole rów-
noległoboku utworzonego przez punkty (O, O), p 1, p 2 i p 1 + p 2 = (x 1 + x2,
y 1 + y 2). Równoważna, ale bardziej praktyczna definicja określa iloczyn wek-
torowy jako wyznacznik macierzy 1l

p 1 xp 2 =det
x, x,)
( Y1 Yi

= -P2 XPi
Jeśli wartość p 1 x p 2 jest dodatnia, to punkt p 1 jest położony zgodnie z ruchem
wskazówek zegara w stosunku do p 2 względem początku układu (O, O); jeśli
iloczyn wektorowy jest ujemny, to p 1 leży przeciwnie do ruchu wskazówek
zegara w stosunku do p2• Na rysunku 35.lb widać obszary zgodny i przeciwny
do ruchu wskazówek zegara względem wektora p. Jeśli iloczyn wektorowy jest
równy O, mamy do czynienia z sytuacją brzegową; wektory są wtedy współ­
liniowe i mają ten sam lub przeciwny kierunek.
żeby sprawdzić, czy odcinek skierowany p 0p 1 jest położony zgodnie z ru-
chem wskazówek zegara w stosunku do odcinka skierowanego p 0 p 2 względem
ich wspólnego końca p 0 , stosujemy translację punktu p 0 do początku układu.
To znaczy, oznaczamy jako p 1 - Po wektor pi= (xJ.,yf), gdzie xi = x 1 - Xo,
a y { = y 1 - Yo,i podobnie definiujemy p 2 - p 0 • Następnie obliczamy iloczyn
wektorowy
(p, - p,) x (p, - p 0 ) - (x 1 - x 0 )(y, - y 0 ) - (x, - x,)(y, - y,)
--------
!) Iloczyn wektorowy jest tak naprawdę obiektem przestrzeni trójwymiarowej. Jest to wektor
prostopadły zarówno do p 1, jak i p.,, o zwrocie zgodnym z ,,regułą prawej ręki" i długości
lxiYi - XzY11. W tym rozdziale jOOnak wygodnie będzie nam traktować iloczyn wektorowy po
prostu jako wartośc x 1y 1 - X:i}'p

992
35.1. WŁASNQ$C! ODCINKÓW

(0,0) X
(a) (b)
Rys. 35.1. {a) Iloczyn wektorowy wektorów p 1 i p 2 to pole równoległoboku ze znakiem. (b) Jasnoszary
obszar zawiera wektory położone zgodnie z ruchem wskazówek zegara względem p. Ciemnoszary
obszar składa się z wektorów położonych przeciwnie do ruchu wskazówek zegara względem p

Jeśli
jego wartość jest dodatnia, to wektor p 0 p 1 jest położony zgodnie
z ruchem wskazówek zegara w stosunku do p 0 p 2 ; jeśli ujemna, to przeciwnie.

Sprawdzanie, czy przechodząc do sąsiedniego odcinka, skręcamy


w lewo czy w prawo
W naszym następnym problemie pytamy, czy przechodząc przez wspólny ko-
niec p 1 dwóch odcinków p 0jj 1 i p 1P2 , skręcamy w lewo czy w prawo. Inaczej
mówiąc, potrzebna jest nam metoda sprawdzania, w którą stronę skręcamy
pod danym kątem <p 0 p 1p 2• Użycie iloczynów wektorowych pozwala nam od-
powiedzieć na to pytanie bez obliczania kąta. Jak widać z rys. 35.2, spraw-
dzamy po prostu, czy odcinek skierowany p 0 p 2 leży zgodnie czy przeciwnie do
ruchu wskazówek zegara w stosunku do odcinka skierowanego p 0 p 1 • Oblicza-
my w tym celu iloczyn wektorowy (p 2 - p 0 ) x (p 1 - p0 ). Jeśli jest on ujemny,
to odcinek p 0 p 2 leży przeciwnie do ruchu wskazówek zegara w stosunku do
p 0 p 1 , a więc w punkcie p 1 skręcamy w lewo. Dodatnia wartość iloczynu ozna-
cza orientację zgodną z ruchem wskazówek zegara i skręt w prawo. Iloczyn
wektorowy równy O oznacza, że punkty p 0 , p 1 i p 2 są współliniowe.

P, Pe
Orientacja przeciwna Orientacja zgodna
do ruchu z ruchem
wskazówek zegara wskazówek zegara
Po Po
(a) (b)

Rys. 35.2. Wykorzystanie iloczynu wektorowego do sprawdzania, w którą slronę skręca.my w punk-
do PiPi-Sprawdr.amy, czy odcinek skierowany p-;;;:,
cie p 1, przechodząc z odcinka PrJJ, Jeży zgodnie
czy pr1.eciwnie do ruchu wskazówek zegara w stosunku do odcinka skierowanego p---;p;_. (a) Jeśli
przeciwnie, to skręcamy w lewo. (b) Jeśli zgodnie, to skręcamy w prawo

993
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

Sprawdzanie, czy dwa odcinki się przecinają

Proces sprawdzania, czy dwa odcinki się przecinają, składa się z dwóch kro-
ków. Pierwszy krok to szybka eliminacja:odcinki nie mogą się przecinać, jeśli
nie przecinają się ich prostokątne ograniczenia. Prostokątne ograniczeniefigury
geometrycznej to najmniejszy prostokąt o bokach równoległych do osi układu
współrzędnych zawierający tę figurę. Prostokątne ograniczenie odcinka Pl.Pi
to prostokąt (ft1, jJ2) o lewym dolnym rogu jJ 1 = (.X1, j\) i prawym górnym rogu
Pi= (X2 , .Y2), gdzie .X1 = min(x 1, x 2), .Y1 = min(J, 1, y 2), X2 = max:(x1, xJ, a .Y2 =
= max:(y1, y 2). Dwa prostokąty, reprezentowane przez swój lewy dolny i prawy
górny róg (ft1, fi2) i (ft3 , j) 4), przecinają się wtedy i tylko wtedy, gdy prawdziwa
jest koniunkcja
(Xi~ .X3)A (.i4 ~ Xi) A (Ji2~ f3) A {Ji4~ .Pi)
Prostokąty muszą się przecinaćw obydwu wymiarach. Pierwsze dwa z powyż­
szych porównań służą do sprawdzania, czy prostokąty przecinają się na współ­
rzędnych x; drugie dwa dotyczą przecinania się na współrzędnych y.
Drugi krok sprawdzania, czy dwa odcinki się przecinają, polega na zbada-
niu, cey każdy odcinek przecina prostą zawierającą ten drugi. Odcinek p1p 2

(p4-P1}x(p2-P1) < O
(p3-P1)X(p2-P1) <O
P,
P;
P,
(P4-P1)X(p2-P1) >O
P, P,
(,) (b)

(P3-P1)>1.(p2-P1l <O
P, ,.. . • • • p
(p4-P1)x{p2-P1)"' O
''
'' '
'
' '
P, P, ' ______'',

(p4-P1)X(p,-p1) =0
P;
:.·-'1
p'
P, r, (P3-P1)x(p2-P 1) = O p,V,.:
(cl (d) (,)

Rys. 35.3. Sprawdzanie czy odcinek p..,p~przecina prostą zawierającą odcinek PiPi· (a) Jeśli tak, to
znaki iloczynów wektorowych (p3 - p 1} x (p2 - p 1)i (p, - p 1} x (p 2 - p 1) są różne. (b} Jeśli nie, to
znaki tych iloczynów są takie same. (c)-(d) Przypadki brzegowe, w których przynajmniej jeden
z iloczynów wektorowych jest zerem, a odcinek przecina prostą. (e) Przypadek brzegowy, w któ-
rym odcinki są współliniowe, aJe s.ię nie przecinają. Obydwa iloczyny wektorowe są równe zero, ale
nasz algorytm nie będzie ich obliczał, ponieważ odcinki nie przechodzą, testu szybkiej eliminacji
- ich prostokątne ograniczenia się nie przec:inają

994
35-1. WŁASN0$C! ODCINKÓW

przecina prostą, jeśli punkt p 1 leży po jednej stronie prostej, a punkt p 2 po drugiej.
Dopuszczamy tak.że sytuację, w której p 1 lub p 2 leży na prostej. Dwa odcinki
przecinają się wtedy i tylko wtedy, gdy przechodzą z wynikiem pozytywnym test
szybkiej eliminacji i każdy z nich przecina prostą zawierającą drugi odcinek.
Do sprawdzania, czy odcinek p 3 ft4 przecina prostą przechodzącą przez
punkty p 1 i p 2 , możemy wykorzystać iloczyn wektorowy. Idea, co widać na
rys. 35.3a i b, polega na sprawdzeniu, czy odcinki skierowane p 1p 3 i p 1p 4 mają
przeciwne orientacje względem p 1p 2 . Jeśli tak, to nasz odcinek przecina prostą.
Wzajemną orientację możemy zbadać za pomocą iloczynu wektorowego, spra-
wdzając po prostu, czy znaki iloczynów (p3 - p 1) x (p 2 - p 1) i (p 4 - p 1) x
><(p 2 - p 1) są różne. Z sytuacją brzegową mamy do czynienia, gdy któryś
z iloczynów jest zerowy. Wtedy punkt p 3 lub p 4 leży na prostej zawierającej
odcinek p1--ji1_.Ponieważ nasze dwa odcinki przeszły już test szybkiej eliminacji,
jeden z punktów p 3 i p 4 musi naprawdę leżeć na odcinku p 1p 2 • Dwie takie
sytuacje są pokazane na rys. 35.3c i d. Przypadek, w którym dwa odcinki są
współliniowe, ale się nie przecinają, przedstawiony na rys. 35.3e, zostaje wyklu-
czony przez test szybkiej eliminacji. Ostatnia sytuacja brzegowa występuje, gdy
jeden lub obydwa odcinki mają długość O,tzn. gdy końce odcinka się pokrywa-
ją. Jeśli oba odcinki mają długość O, to wystarcza test szybkiej eliminacji. Jeśli
tylko jeden odcinek, powiedzmy [)3 P4,ma długość O, to odcinki się przecinają
wtedy i tylko wtedy, gdy iloczyn wektorowy (p 1 - p 1) x (p2 -p 1)jest równy O.

Inne zastosowania iloczynów wektorowych


W dalszych częściach tego raz.działu przedstawimy kolejne zastosowania ilo-
czynów wektorowych. W podrozdziale 35.3 trzeba będzie posortować zbiór
punktów ze względu na ich współrzędne kątowe w biegunowym układzie
współrzędnych o danym początku. Do wykonywania porównań w procedurze
sortującej można wykorzystać iloczyny wektorowe, co należy wykazać w zad.
35.1-2. W podrozdziale 35.2 będziemy używać drzew czerwono-czarnych do
przechowywania uporządkowanego w pionie zbioru nie przecinających się od-
cinków. Zamiast w sposób jawny przechowywać w węzłach wartości kluczy,
będziemy zastępować każde porównanie kluczy w algorytmach zarządzania
drzewami czerwono-czarnymi obliczeniem iloczynu wektorowego, mającym na
celu sprawdzenie, który z dwóch odcinków przecinających daną pionową pros-
tą leży powyżej drugiego odcinka.

ZADANIA
35.1-1. Udowodnij, że jeśli wartość p 1 x p 2 jest dodatnia, to wektor Pi jest
położony zgodnie z ruchem wskazówek zegara w stosunku do wektora p 2
względem punk.tu (O, O), a jeśli wartość tego iloczynu wektorowego jest
ujemna, to Pi leży przeciwnie do ruchu wskazówek zegara w stosunku do p 2•

995
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

35.1-2. Napisz pseudokod procedury sortowania ciągu n punktów (pi, p 2,


..., Pn> względem ich współrzędnych kątowych w biegunowym układzie
współrzędnych o początku w danym punkcie p 0• Twoja procedura powin-
na działać w czasie O(n lg n) i do porównywania kątów wykorzystywać
iloczyny wektorowe.
35.1-3. Pokaż, jak w czasie O(n 2 lgn) sprawdzać, r:zy w zbiorze n punktów są
trzy punk.ty współliniowe.
35.1-4. Profesor Amundsen proponuje następującą metodę sprawdzania, czy
ciąg n punktów (p 0 , p 1 , ... , Pn-i> stanowi kolejne wierzchołki wielokąta
wypukłego. (Definicje dotyczące wielokątów można znaleźć w pod-
rozdz. 16.4). Odpowiadamy „tak", jeśli zbiór { ~PJ11 + 1P 1+ 2 :i= O, l, ...,
n - 1}, gdzie dodawanie indeksów odbywa się modulo n, nie zawiera jed-
nocześnie skrętów w lewo i w prawo; w przeciwnym razie odpowiadamy
„nie." Wykaż, że chociaż metoda ta działa w czasie liniowym, nie zawsze
daje poprawną odpowiedź. Zmodyfikuj metodę profesora tak, żeby zawsze
dawała poprawną odpowiedź w czasie liniowym.
35.1-5. Dla danego punktu Po= (x 0 , y0) prawy poziomy promień z Po to zbiór
punktów {p;= (x 1, y;):x 1 ~ x 0 i y 1 = y 0 }, tzn. zbiór punktów na poziomej
prostej na prawo od Po wraz z samym punktem p 0 • Pokaż, jak sprawdzać,
czy dany prawy poziomy promień zp 0 przecina odcinek p;p 2 w czasie 0(1),
sprowadzając ten problem do sprawdzania, czy dwa odcinki się przecinają.
35.1-6. Jednym ze sposobów zbadania, czy punkt p 0 leży wewnątrz prostego
(tzn. bez samoprzecięć) - choć niekoniecznie wypuk.lego -wielokąta P, jest
poprowadzenie dowolnego promienia wychodzącego z p 0 i sprawdzenie, czy
promień ten przecina brzeg P nieparzystą liczbę razy, a sam punkt p 0 nie leży
na brzegu P. Pokaż, jak w czasie 0(n) obliczyć, czy punkt p 0 leży wewnątrz
n-wierzchołkowego wielokąta P. (W.vkaz6wka: Skorzystaj z zad. 35.1-5.
Twój algorytm ma być poprawny również wtedy, kiedy promień przecina
brzeg wielokąta w wierzchołku i kiedy nakłada się na bok wielokąta).
35.1-7. Pokaż, jak w czasie 0(n) obliczać pole n-wierzchołkowego prostego,
choć niekoniecznie wypukłego, wielokąta.

35,2, Sprawdzanie,czy jakakolwiekparaodcinków


' '
się przecina

W niniejszym podrozdziale przedstawiamy algorytm sprawdzania, czy jakie-


kolwiek dwa odcinki w danym zbiorze odcinków się przecinają. W algorytmie
tym jest wykorzystywana metoda zwana „zamiataniem," często spotykana
w algorytmach geometrii obliczeniowej. Co więcej, jak wynika z zadań zamie-
szczonych na końcu podrozdziału, tego algorytmu lub jego prostych warian-
tów można użyć do rozwiązywania innych problemów geometrii obliczeniowej.

996
35.2. SPRAWDZANIE, CZY JAKAKOLWIEK PARA ODCINKÓW SIĘ PRZECINA

Algorytm działa w czasie O(nlgn), gdzie n jest liczbą odcinków. Sprawdza


on tylko, czy istnieją jakiekolwiek przecięcia, nie wypisuje zaś wszystkich prze-
cięć.ew myśl zad. 35.2-1 znalezienie wszystkich przecięć w zbiorze n odcinków
zajmuje w najgorszym przypadku czas 0:(n 2)).
W metodzie zamiatania wyimaginowana pionowa prosta zamiatająca
(,,miotła") jest przesuwana wzdłuż danego zbioru obiektów geometrycznych,
zazwyczaj od strony lewej do prawej. Wymiar przestrzenny, wzdłuż którego
przesuwa się prosta zamiatająca, w tym wypadku wymiar x, jest traktowany
jako oś czasu. Zamiatanie stanowi metodę systematycznego przeglądania obie-
któw geometrycznych, zwykle przez umieszczanie ich w dynamicznej struktu-
rze danych, i wykorzystywania zależności między nimi. Algorytm sprawdzania
przecięć odcinków opisywany w tym podrozdziale rozważa wszystkie końce
odcinków w kolejności od strony lewej do prawej i sprawdza, czy nie nastąpiło
przecięcie, za każdym razem, kiedy napotyka koniec jakiegoś odcinka.
W naszym algorytmie sprawdzania, czy którekolwiek dwa spośród n od-
cinków się przecinają, poczynimy dwa upraszczające założenia. Po pierwsze
zakładamy, że żaden z wejściowych odcinków nie jest pionowy, a po drugie
przyjmujemy, że żadne trzy wejściowe odcinki nie przecinają się w jednym
punkcie. ew zadaniu 35.2-8 prosimy o opisanie implementacji działającej po-
prawnie nawet wówczas, gdy powyższe założenia nie są spełnione). W rzeczy-
wistości pozbycie się takich upraszczających założeń i uwzględnienie szczegól-
nych przypadków jest często najtrudniejszą rzeczą w programowaniu algoryt-
mów geometrii obliczeniowej i dowodzeniu ich poprawności.

Uporządkowanie odcinków
Ponieważ zakładamy, że nie ma pionowych odcinków, każdy z wejściowych
odcinków przechodzących przez daną pionową prostą zamiatającą przecina ją
w jednym punkcie. Możemy zatem uporządkować odcinki przecinające piono-
wą prostą zamiatającą ze względu na współrzędne y punktów przecięcia.
Ujmując rzecz dokładniej, rozważmy dwa nie przecinające się odcinki s 1
i s2• Mówimy, że odcinki te są porównywalnew x 0 , jeśli pionowa prosta zamia-
tająca o współrzędnej x równej x 0 przecina obydwa z nich. Mówimy, że s 1 leży
powyżej s2 w x, co zapisujemy jako s 1 >x s2, jeśli s 1 i s2 są porównywalne w x,
a przecięcie s1 z prostą zamiatającą w x znajduje się wyżej niż przecięcie s2 z tą
samą prostą zamiatającą. Przykładowo na rys. 35.4a zachodzą relacje a>, c,
a> 1 b, b > 1 c, a> 1 c i b >., c. Odcinek d nie jest porównywalny z żadnym
innym odcinkiem.
Dla dowolnego ustalonego x relacja ,, > x" jest porządkiem liniowym
(patrz pod.rozdz. 5.2) w zbiorze odcinków, które przecinają prostą zamiatającą
o współrzędnej x. Porządek ten może być różny dla różnych wartości x, ponie-
waż jedne odcinki wchodzą do owego zbioru, a inne go opuszczają. Odcinek
___________
____ _ ,,

997
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

wchodzi do zbioru, kiedy prosta zamiatająca napotyka jego lewy koniec,


a opuszcza zbiór, kiedy trafiamy na jego prawy koniec.
Co się dzieje, kiedy prosta zamiatająca przechodzi przez punkt przecięcia
dwóch odcinków? Jak widać na rys. 35.4b, ich pozycje w porządku liniowym
się zamieniają. Proste zamiatające v i w leżą, odpowiednio, na lewo i na prawo
od punktu przecięcia odcinków ei/i zachodzie > 0 /oraz/>.,, e. Zauważmy,
że ponieważ zakładamy, iż żadne trzy odcinki nie przecinają się w tym samym
punkcie, musi istnieć pewna pionowa prosta zamiatająca x taka, że przecinają­
ce się odcinki e i f są sąsiednie w liniowym porządku >". Dla dowolnej prostej
zamiatającej przechodzącej przez szary obszar na rys. 35.4b, takiej jak z, od-
cinki e i f są sąsiednie w związanym z nią porządku.

'
a .,'
d~ g ;
,, h
'
'' ' J'' '
' '' ' '
t
' (,)
" ' '
(b)
w

Rys. 35.4. Uporządkowanie odcinków na różnych pionowych prostych zamiatających. (a) Zachodzą
relacje a >, c, a >, h, h >, c, a >, c i b >. c. Odcinek d nie jest porównywalny z żadnym
z pozostałych narysowanych odcinków. (b) Kiedy odcinki ei f się przecinają, ich kolejność się
cxiwraca: mamy e >, /, alef>~ e. Dla dowolnej prostej zamiatającej (takiej jak z), przechodzącej
przez szary obsz.ar, odcinki ei/ sąsjadują ze sobą w związanym z nią. porządku liniowym

Przesuwanieprostejzamiatającej
W algorytmach, w których wykorzystuje się metodę zamiatania, są zazwyczaj
używane dwa zbiory danych:

I. Struktura stanu prostej zamiatającej, określająca relacje między obiektami


przecinanymi przez prostą zamiatającą.
2. Harmonogramzdarzeń, to ciąg uporządkowanych od strony lewej do prawej
współrzędnych x punktów określających pozycje zatrzymania dla prostej
zamiatającej. Każdą taką pozycję zatrzymania nazywamy zdarzeniem.
Zmiany w strukturze stanu prostej zamiatającej mogą zachodzić jedynie
w takich właśnie punktach.
W niektórych algorytmach (np. w algorytmie, o którym mowa w zad.
35.2-7) harmonogram zdarzeń jest wyznaczany dynamicznie w miarę działania
algorytmu. Opisywany algorytm wyznacza jednak owe zdarzenia statycznie,
wyłącznie na podstawie prostych własności danych wejściowych. Konkretnie,

998
35,2. SPRAWDZANIE, CZY JAKAKOLWIEK PARA ODCINKÓW SIĘ PRZECINA

zdarzeniem jest każdy koniec odcinka. Sortujemy końce odcinków rosnąco ze


względu na współrzędną x i przetwarzamy je od strony lewej do prawej. Wsta-
wiamy odcinek do struktury stanu prostej zamiatającej, kiedy napotykamy
jego lewy koniec, a usuwamy go ze struktury, kiedy napotykamy jego prawy
koniec. Za każdym razem, kiedy dwa odcinki po raz pierwszy stają się sąsia­
dami w liniowym porządku, sprawdzamy, czy się przecinają.
Struktura stanu prostej zamiatającej to liniowo uporządkowany zbiór T,
na którym wykonuje się następujące operacje:
• lNSERT(T, s): wstaw odcinek s do T.
• DELETE(T, s): usuń odcinek s z T.
• ABovE(T, s): zwróć odcinek bezpośrednio powyżej odcinka s w T.
• BELOW(T, s): zwróć odcinek bezpośrednio poniżej odcinka s w T.

Jeślina wejściu jest n odcinków, każdą z powyższych operacji możemy wykonać


w czasie O(lgn), korzystając z drzew czerwono-czarnych. Przypomnijmy, że
operacje na drzewach czerwono-czarnych w ro7.dz. 14 wymagały porównywania
kluczy. Porównania kluczy możemy zastąpić porównaniami iloczynów wektoro-
wych, rozstrzygającymi o kolejności dwóch odcinków (patrz zad. 35.2-2).

Pseudokod algorytmu sprawdzania przecinania się odcinków


Poniższy algorytm otrzymuje jako dane wejściowe zbiór S składający się
z n odcinków, a zwraca logiczną wartość TRUE, jeśli jakaś para odcinków
w S się przecina, FALSE zaś w przeciwnym razie. Liniowo uporządkowany
zbiór T jest zaimplementowany za pomocą drzewa czerwono-czarnego.

ANY-SEGMENTS-INTERSECT(S)
1 T +- 0
2 posortuj końce odcinków w S od lewej do prawej, rozstrzygając remisy
na korzyść punktów o mniejszej współrzędnej y
3 for każdy punkt p na posortowanej liście końców odcinków
4 do if p jest lewym końcem odcinka s
5 then INSERT(T, s)
6 if (ABoVE(T, s) istnieje i przecina s) lub (BELOW(T, s) istnieje
i przecina s)
7 then returnTR UE
8 if p jest prawym końcemodcinka s
9 then if oba odcinki ABOVE(T, s) i BELOW(T, s) istnieją i ABOVE(T, s)
przecina BELOW(T, s)
1O then returnTRUE
11 DELETE(T,s)
12 return FALSE

999
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

''
'
,' a d
' '
'
' ''
''
'
I
b

a a a d
b , a d '
' d
b ' b '
b b

°'"'
Rys. 35.5. Działanie algorytmu ANY-SEGMENTS-lNTER!iECT.
Każda linia przerywana to prosta zamia-
tającadla pewnego zdarzenia, a kolejność nazw odcinków pod każdą prostą zamiatającą to po-
rządek w zbiorze T po przebiegu pętli for, przetwarzającym odpowiednie Warzenie. Przecięcie
odcinków di b zostaje wykryte przy usuwaniu odcinka c

Działanie algorytmu ilustruje rys. 35.5. W wierszu 1 jest utworzony pusty


zbiór liniowo uporządkowany. W wierszu 2 wyznaczamy harmonogram zda-
rzeń, sortując 2n końców odcinków od strony lewej do prawej i rozstrzygając
remisy na korzyść punktów o mniejszej współrzędnej y. Można to wykonać,
sortując leksykograficznie końce odcinków jako pary (x, y).
W każdym przebiegu pętli for w wierszach 3-11 jest przetwarzane jedno
zdarzenie p. Jeśli p jest lewym końcem odcinka s, w wierszu 5 dodajemy s do
zbioru, a w wierszach 6-7 jest zwracana wartość TRUE, jeśli s przecina któryś
z odcinków sąsiadujących z nim w porządku liniowym definiowanym przez
prostą zamiatającą przechodzącą przez p. (Szczególna sytuacja występuje wte-
dy, kiedy p należy do innego odcinka s'. Wówczas musimy jedynie zapewnić,
ie s i s' będą umieszczone w T jako sąsiedzi). Jeśli p jest prawym końcem
odcinka s, to s będzie usunięty ze zbioru T. W wierszach 9-10 jest zwracana
wartość TRUE, jeśli zostało znalezione przecięcie odcinków otaczających s w li-
niowym por:r.ądku określonym przez prostą przechodzącą przez punkt p; od-
cinki te staną się sąsiada.mi po usunięciu s ze struktury. Jeśli odcinki te się nie
przecinają, to w wierszu 11 odcinek s zostaje usunięty ze zbioru T. Wreszcie,
jeśli podczas przetwarzania wszystkich 2n zdarzeń nie znaleziono żadnych
przecięć, w wierszu 12 jest zwracana wartość FALSE.

Poprawność algorytmu
Poniższe twierdzenie mówi, że algorytm ANY-SEGMENTS-INTERSECTjest po-
prawny.

1000
35.2. SPRAWDZANIE, CZV JAKAKOLWIEK PARA ODCINKÓW SIĘ PRZECINA

TWIERDZENIE 35.1.
Wywołanie procedury ANY-SEGMENTS-lNTERSECl'(S)zwraca wartość TRUE
wtedy i tylko wtedy, gdy któreś odcinki ze zbioru S się przecinają.

DOWÓD
Procedura może zadziałać niepoprawnie albo zwracając wartość TRUE, jeśli nie
ma żadnych przecięć, albo zwracając FALSE, jeśli istnieje co najmniej jedno
przecięcie. Pierwszy przypadek nie może wystąpić, ponieważ procedura ANY-
-SEGMENTS-INTERSECTzwraca wartość TRUE jedynie wtedy, kiedy znajduje
przecięcie dwóch wejściowych odcinków.
Żeby wykazać, że drugi przypadek również nie może zajść, w celu doprowa-
dzenia do sprzeczności załóżmy, że istnieje przynajmniej jedno przecięcie, ale
procedura ANY-SEGMENTS-INTERSECTzwraca wartość FALSE.Niech p będzie
pierwszym z lewej strony punktem przecięcia, przy czym remisy rozstrzygamy na
korzyść punk.tu o mniejszej współrzędnej y, i niech a i b będą odcinkami przeci-
nającymi się w punk.ciep. Ponieważ na lewo od p nie ma żadnych przecięć,
porządek określony przez T jest taki sam we wszystkich punktach na lewo odp.
Ponieważ żadne trzy odcinki nie przecinają się w tym samym punkcie, istnieje
prosta zamiatająca z, na której a i b stają się sąsiadami w liniowym porządku l.
1

Co więcej, z leży na lewo odp lub przechodzi przez p. Na prostej zamiatającej


z leży koniec pewnego odcinka q, stanowiący punkt, w którym odcinki a i b stają
się sąsiadami w liniowym porządku. Jeślip leży na prostej z, to q = p. Jeśli nie,
to q znajduje się na lewo odp. W obydwu przypadkach porządek w T jest
poprawny tuż przed przetworzeniem q. (Korzystamy tutaj z tego, że p jest
najniższym spośród leżących najbardziej na lewo punktów przecięcia. Ze wzglę­
du na leksykograficzny porządek przetwarzania zdarzeń, nawet jeśli p leży na
prostej zamiatającej z i na z istnieje inny punkt przecięcia p', to punkt q = p jest
przetwarzany, zanim drugi punkt przecięcia p' może zaburzyć liniowy porządek
w T). Są tylko dwie możliwe do podjęcia akcje związane ze 7.darzeniem q:
1. Odcinek a albo b jest wstawiany do T, a drugi odcinek znajduje się bezpo-
średnio powyżej lub poniżej niego w porządku liniowym. Przypadek ten jest
wykrywany w wierszach 4-7.
2. Odcinki a i b są już w T, a rozdzielający je w liniowym porządku odcinek
zostaje usunięty, czyniąc a i b sąsiadami. Sytuacja taka jest wykrywana
w wierszach 8-11.
W obydwu przypadkach punkt przecięcia p zostaje znaleziony, co przeczy za-
łożeniu, że procedura zwraca wartość FALSE.

IJ Jeśli dopuścimy przecinanie się trzech odcinków w jednym punkcie, może istnieć położony
między rrimi odcinek c, przecinają.cy jednocześnie a i h w punkcie p. To maczy, mo.Ze zachodzić
a <,. c i c <,. b dla wszystkich prostych zamiatających w na lewo odp, dla których a <w b.

1001
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

Czasdziałania algorytmu
Jeślizbiór s zawiera n odcinków, to algorytm ANY-SEGMENTS-INTERSECT
działa w czasie O(nlgn). Czas wykonywania instrukcji w wierszu I to 0(1).
Wykonanie operacji w wierszu 2 zajmuje czas O(n lg n), jeśli użyjemy algoryt-
mu mergesort lub heapsort. Ponieważ jest w sumie 2n zdarzeń, pętla for
w wierszach 3-11 wykona co najwyżej 2n obrotów. Każdy przebieg pętli zaj-
muje czas O(lgn), gdyż każdą operację na drzewie czerwono-czarnym wykonu-
je się w czasie O(lgn), a korzystając z metod opisanych w podrozdz. 35.1,
sprawdzenie czy dwa odcinki się przecinają, można wykonać w czasie 0(1).
Łączny czas wynosi zatem O(nlgn).

ZADANIA
3S.2-1. Wykaż, że w zbiorze n odcinków może być 0(n 2 ) przecięć.
3S.2-l. Pokaż, jak za pomocą iloczynów wektorowych dla danych dwóch nie
przecinających się odcinków a i b, porównywalnych w x, sprawdzić w cza-
sie 0(1), która z relacji a >" b czy b >" a jest spełniona.
35.2-3. Profesor Maginot proponuje tak zmodyfikować procedurę ANY-SEG.
MENTS-lNTERSECT,żeby zamiast kończyć działanie po znalezieniu przecię­
cia wypisywała ona przecinające się odcinki i przechodziła do następnego
przebiegu pętli for. Profesor nazywa tak otrzymaną procedurę PROC-IN-
TERSECTING-SEGMENTS i twierdzi, że wypisuje ona wszystkie przecięcia
od strony lewej do prawej, zgodnie z ich występowaniem w zbiorze odcin-
ków. Wykaż, że profesor popełnił dwa błędy w rozumowaniu, podając
przykład zbioru odcinków, w którym pierwsze przecięcie znalezione przez
procedurę PROC-INTERSECTING-SEGMENTS nie jest pierwszym z lewej
strony, oraz zbioru odcinków, w którym PROC-lNTERSECTING-SEGMENT
nie znajduje wszystkich przecięć.
3S.l-4. Podaj działający w czasie O(nlgn) algorytm sprawdzania, czy n-wierz-
chołkowy wielokąt jest prosty.
3S.2-S. Podaj działający w czasie O(nlgn) algorytm sprawdzania, czy dwa pro-
ste wielokąty zawierające w sumie n wierzchołków się przecinają.
3S.2-6. Kolo jest to okrąg plus jego wnętrze. Można je reprezentować przez
punkt środkowy i promień. Dwa koła przecinają się, jeśli mają jakiś punkt
wspólny. Podaj działający w czasie O(nlgn) algorytm sprawdzania, czy
którekolwiek dwa ze zbioru n kół się pr:,.ecinają.
35.2-7. Pokaż, jak dla danego zbioru n odcinków, zawierającego w sumie
k przecięć, wypisać wszystkie k przecięć w czasie O((n + k)lg n).
35.2-8. Opisz,jak zaimplementować operacje na drzewach czerwono-czarnych,
żeby procedura ANY-SEGMENTS~INTERSECT działała poprawnie, nawet
jeśli niektóre odcinki są pionowe lub więcej niż dwa odcinki przecinają się
w jednym punkcie. Udowodnij poprawność swojej implementacji.

1002
35.3. ZNAJDOWANIE WYPUKŁEJ OTOCZKI

35.3. Znajdowanie
wypuklejotoczki
Wypukła otoczka zbioru punktów Q to najmniejszy wielokąt wypukły Ptaki, że
każdy punkt ze zbioru Q leży albo na brzegu P, albo w jego wnętrzu. Wypukłą
otoczkę zbioru Q oznaczamy przez CH(Q). Odwołując się do intuicji, możemy
wyobrazić sobie punkty ze zbioru Q jako wystające z deski gwoździe. Kształt
wypuklej otoczki przybierze wówczas gwnka obejmująca ciasno wszystkie gwoź­
dzie. Na rysunku 35.6 jest przedstawiony zbiór punktów i jego wypukła otoczka.
W tym podrozdziale przedstawiamy dwa algorytmy obliczania wypuk.lej

• •
• • • P,
P„ P9 • P; P;
P, • P,
P„ P,
P,•
P,
Po
Rys. 35.6. Zbiór punktów Q wraz z zaznaczoną na sraro swoją wypukłą otoczką CH(Q)

otoczki zbioru n punktów. Obydwa algorytmy wyznaczają wierzchołki wypuk-


łej otoczki w kolejności przeciwnej do ruchu wskazówek zegara. Pierwszy, zwa-
ny algorytmem Grahama, działa w czasie O(nlgn). Drugi, algorytm Jarvisa,
działa w czasie O(nh), gdzie h jest liczbą punktów na otoczce. Jak widać
z rys. 35.6, każdy wierzchołek otoczki CH(Q) jest punktem ze zbioru Q. Oby-
dwa algorytmy korzystają z tej własności, decydując, które punkty z Q za-
chować jako wierzchołki otoczki, a które wyrzucić.
W rzeczywistości istnieje wiele metod obliczania wypukłej otoczki w czasie
O(nlgn). Zarówno w algorytmie Grahama, jak i w algorytmie Jarvisa stosuje
się metodę zwaną „zamiataniem obrotowym", polegającą na przetwarzaniu
wierzchołków w kolejności występowania kątów, jakie tworzą z ustalonym
punktem i przechodzącą przez niego osią. Oto niektóre z pozostałych metod.

• W metodzie przyrostowej punkty sortuje się od strony lewej do prawej,


otrzymując ciąg (p 1,p 2, ••• , Pn>·W i-tej fazie wypukłą otoczkę CH({p 1, p 2, ... ,
p;_ 1}) zbioru i - 1 pierwszych punktów z lewej strony modyfikuje się tak, by
uwzględniała i-ty punkt z lewej, tworząc w ten sposób CH({p 1, p 2 , ••• , p;}).
Celem zad. 35.3-6 jest wykazanie, że metodę tę można zaimplementować
tak, by działała w łącznym czasie O(nlgn).

1003
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

• W metodzie „dziel i zwyciężaj" w czasie 0(n) dzieli się zbiór n punktów na


dwa podzbiory: jeden złożony z pierwszych fn/1]punktów z lewej, a drugi
z pozostałych Ln/2J punktów z prawej. Otoczki podzbiorów oblicza się re-
kurencyjnie, a następnie sprytnie łączy się otoczki w czasie O(n).

• Metoda szukania z obcinaniem jest podobna do liniowego algorytmu znaj-


dowania mediany, opisanego w podrozdz. 10.3. Znajdujemy górną część
(,,górny łańcuch") otoczki wypuklej, wielokrotnie odrzucając stały procent
elementów ze zbioru rozważanych punktów, dopóki nie pozostanie w nim
sam górny łańcuch otoczki. Następnie robimy to samo dla dolnego łań­
cucha. Ta metoda jest asymptotycznie najszybsza: jeśli wypukła otoczka
składa się z h wierzchołków, działa ona w czasie O(nlgh).

Obliczanie wypukłej otoczki zbioru punktów samo z siebie jest interesują­


cym problemem. Co więcej, algorytmy dla wielu innych problemów geometrii
obliczeniowej zaczynają od znalezienia wypuklej otoczki. Jako przykład roz-
ważmy dwuwymiarowy problem pary najbardziej odległych punktów: dany jest
zbiór n punktów na płaszczyźnie, a chcemy znaleźć dwa punkty, których wza-
jemna odległość jest maksymalna. Owe dwa punkty, co należy udowodnić
w zad. 35.3-3, muszą być wierzchołkami wypukłej otoczki. Chociaż nie będzie­
my tutaj tego dowod1ić, parę najbardziej odległych wierzchołków n-wier7.chol-
kowego wielokąta wypukłego można znaleźć w czasie O(n). Obliczając zatem
wypukłą otoczkę zbioru n wejściowych punktów w czasie O(n lgn), a następnie
znajdując parę najbardziej odległych wierzchołków w otrzymanym wielokącie
wypukłym, możemy wyznaczyć parę najbardziej odległych punktów w dowol-
nym zbiorze n punktów w czasie O(nlgn).

Algorytm Grahama
W algorytmie Grahama problem wypukłej otoczki jest rozwiązywany z użyciem
stosu S, który zawiera kandydatów na wierzchołki otoczki. Każdy punkt
z wejściowego zbioru Q jest raz wkładany na stos, a punkty nie będące wierz-
chołkami CH(Q) są w końcu ze stosu zdejmowane. Po zakończeniu działania
algorytmu stos S zawiera wyłącznie wierzchołki Clł(Q), w przeciwnej do ruchu
wskazówek zegara kolejności ich występowania na brzegu.
Dane wejściowe dla procedury GRAHAM~SCAN stanowi zbiór punktów Q,
gdzie IQI~ 3. Procedura korzysta z funkcji TOP(S), zwracającej element na
szczycie stosu S bez zmiany S, oraz NEXT~1'o~TOP(S), zwracającej element
położony o jedno miejsce poniżej szczytu stosu, bez zmiany stosu S. Jak zaraz
wykażemy, stos S zwracany przez procedurę GRAHAM-SCAN zawiera, patrząc
od dołu do góry, wszystkie wierzchołki CH(Q) w kolejności przeciwnej do
ruchu wskazówek zegara.

1004
35.3. ZNAJDOWANIE WYPUKŁEJ OTOCZKI

GRAHAM-SCAN(Q)
1 niech p 0 będzie punktem w Q o minimalnej współrzędnej y, lub,
w przypadku remisu, pierwszym takim punktem z lewej
2 niech (pi, p 2, •.• , Pm) będą pozostałymi punktami Q, posortowanymi
ze względu na wsp. kątową w biegunowym układzie współ­
rzędnych o środku w Po w kierunku przeciwnym do ruchu
wskazówek zegara Geśli więcej niż jeden punkt ma taką samą
wsp. kątową, usuń wszystkie oprócz położonego najdalej od p 0 )
3 top(S] +- O
4 PUSH(p0 , S)
5 PUSH(p,, S)
6 Pus,1(p,, S)
7 fori+-3tom
8 do wbile kąt utworzony przez punkty NEXT-TO-TOP(S),TOP(S) i P;
nie oznacza skrętu w lewo
9 do POP(S)
IO PUSH(S, p;)
11 return S

Działanie algorytmu GRAHAM-SCAN ilustruje rys. 35.7. W wierszu I znaj-


dujemy p 0 jak.o punkt o najmniejszej współrzędnej y: w przypadku remisu wy-
bierając pierwszy taki punkt z lewej. Ponieważ nie ma żadnego punktu w Q le-
żącego poniżej p 0 , a wszystkie inne punkty o tej samej współrzędnej y są na
prawo od niego, punkt Po jest wierzchołkiem CH(Q). W wierszu 2 sortujemy
pozostałe punkty w Q ze względu na współrzędną kątową w biegunowym
układzie współrzędnych o środku w p 0, stosując tę samą metodę -porównywa-
nie iloczynów wektorowych - co w zad. 35.1-2. Jeśli dwa lub więcej punktów
ma tę samą współrzędną kątową względem p 0, wszystkie oprócz najdalszego
z nich są wypukłymi kombinacjami p 0 i najdalszego punktu, możemy więc
wyeliminować je całkowicie z dalszych rozważań. Przez m oznaczamy liczbę
pozostałych punktów różnych od p 0 • Mierzona w radianach współrzędna kąto­
wa każdego punktu w Q względem Po mieści się w prawostronnie otwartym
przedziale [O, n/2). Ponieważ współrzędne kątowe rosną w kierunku przeciw-
nym do ruchu wskazówek zegara, punkty są posortowane w takim właśnie
porządku w stosunku do p 0 • Ten posortowany ciąg punktów oznaczamy przez
(pp p 2, ••• , Pm>·Zauważmy, Ze punkty p 1 i Pm należą do CH(Q) (patrz zad.
35.3~1). Na rysunku 35.7a jest przedstawiony zbiór punktów z rys. 35.6
z uwidocznieniem uporządkowania współrzędnych kątowych w ciągu (p 1, p 2 ,
..., p 12) względem Po·
W dalszej części procedury jest wykorzystywany stos S. W wierszach 3-6
na stos jest wkładana początkowa zawartość - patrząc od spodu, pierwsze trzy
punkty p 0 , p 1 i p 2 . Na rysunku 35.7a widać początkową zawartość stosu S.
----------"-""""""'~------------
1005
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

-
-
-
-

-
P„

'
'
'
:p
...
9
- '- p R ' -
- ' '' ' ' '
p
7

'
P,
'

~ P„

.. .
-
' ,'
- ,
- -
- •P4 P1
' ' '' ''
,,'' '' ,,,
' '' ' ' ' p
'::/>' _, .· ,- l Pi~)
.,':,~~',:~1::.,-<i~
-~:---~··-~·-:f---:.-
-~--~-:- -:-~-:..--lp, ___ P,
Po (,) (b)

P, P, Po P, P, Po
P„
• • P, • • • P„
• • P, • • P,
P,

P;
• ·-,;:,_____ P,
Pn• P, P12• P,
p,• P,•
P, P,
Po (c) Po (d)

P„ P, P, P, P„ P, P, Po
• • Po • • •
Po
• P, • P,

P,
P, • P;
Pn• P1-i • P,
Pi• P,•
P, P,
P, (c) Po (0
Rys. 35.7. Działanie algorytmu GRAHAM-&ANna zbiorze punktów Q z rys. 35.6. Bieżąca wypukła
otoczka majdująca się na stos.ie S w każdym kroku jest zaznaczona na szaro. (a) Punkty (pt, Pi,
..., p 12) posortowane ze względu na współrz.ędne kątowe w biegunowym układzie współrz.ędnych
o początku w p 0 i stos S zawierający początkowo punkty p 0 , p 1 i pl. (b)-(k) Stos S po każdym
przebiegu pętli forw wierszach 7-10. Linie przerywane obrazują skręty inne niż: w lewo, powodują­
ce usuwanie punktów ze stosu. Na przykład w części (h) skręt w prawo w kącie ł'..p,1¼[)9 powoduje
usunięcie ze stosu p 1, a następnie skręt w prawo w kącie ł'.,p,JJ1p9 powoduje usunięcie p 7• O) Ob-
liczona przez procedurę wypukła otoczka, ta sama co na rys. 3S.6

1006
35.3. ZNAJDOWANIE WYPUKŁEJ OTOCZKI

P, Po P, Po
P„ • P„
• P, • P,
Po • P, Po • P,
'12• P, P12 • P,
p,• P,•
P, P,
Po (g) Po (h)

Pw, Pw
'

P„
• •
P„ P,
P, • P,
'r,• P,
P,•

--- P, ,...---- P,
P, (i) Po Ul

P,

• •
P, P,

P,
P, •r '
'" P,•

(k)
,,___--p·
Po (I)

tys. 35.7 (cd.)

Pętla for w wierszach 7-10 wykonuje po jednym obrocie na każdy punkt pod-
ciągu (p 3, p 4, ••• , Pm>·Naszą intencją jest, żeby po przetworzeniu punktu pj
stos S zawierał, patrząc od spodu, wierzchołki CH({p0 , p 1, ••• , pj}) w kolejności
przeciwnej do ruchu wskazówek zegara. W pętli while w wierszach 8-9 punkty
usuwane są ze stosu, kiedy okazuje się, że nie należą do otoczk.L Kiedy prze-

1007
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

chodzimy otoczkę w kierunku przeciwnym do ruchu wskazówek 7,egara,


w każdym wierzchołku powinniśmy skręcać w lewo. Dlatego za każdym ra-
zem, kiedy w pętli while znajdujemy wierzchołek, w którym nie skręcamy
w lewo, zdejmujemy go ze stosu. (Badając czy skręcamy inaczej niż w lewo,
a nie tylko czy skręcamy w prawo, eliminujemy możliwość wystąpienia trzech
punktów współliniowych na otoczce. Tak właśnie ma być, ponieważ żaden
wierzchołek wielokąta wypukłego nie może być wypukłą kombinacją innych
wierzchołków tego wielokąta). Po zdjęciu ze stosu wszystkich wierzchołków,
w których-zdążając do punktu pj- nie skręcamy w lewo, wkładamy pj na stos.
Na rysunku 35.'lb-k jest pokazana zawartość stosu S po każdym przebiegu
pętli for. Na koniec w wierszu 11 procedura GRAHAM-SCAN zwraca stos S.
Na rysunku 35.71 widać znalezioną wypukłą otoczkę.
Poniżej zamieszczamy formalny dowód poprawności algorytmu GRA-
1-łAM-SCAN.

TwIERDZENIE35.2. (Poprawność algorytmu Grahama)


Jeśli uruchomimy procedurę GRAHAM-SCAN dla zbioru punktów Q, gdzie
IQI;?; 3, to punkt z Q pozostaje na stosie S po jej zakończeniu wtedy i tylko
wtedy, gdy jest wierzchołkiem CH(Q).

DOWÓD
Jak wspomnieliśmy wyżej, wierzchołek będący wypukłą kombinacją p 0 i pew-
nego innego punktu ze zbioru Q nie należy do CH(Q). Takiego wierzchołka nie
będzie w ciągu (p 1, p 2 , ... , Pm), więc na pewno nigdy nie pojawi się na stosie S.

P;

Po
(o) (b)

Rys. 35.8. Dwie podstawowe sytuacje w dowodzie poprawności algorytmu GRAHAM-ScAN.(a)


Ilustracja faktu, że punkt usuwany ze stosu w procedurze GRAHAM-SCAN nie jest wierzcholk ~m
CH(Q). Jei!i punkt p1 zostaje zdjęty ze stosu, ponieważ kąt i:.Pll'J!'Jnie oznacza skrętu w lewo, to
zacieniowany trójkąt L':,.poPJJ, zawiera punkt p1 w swoim wnętrzu. Punkt p1 nie jest zatem
wierzchołkiem Clł(Q). (b) Jeśli punkt p 1 zostaje włożony na stos, to kąt ł,:.pJ)1p1 musi oznaczać skręt
w lewo. Ponieważp1 następuje po p1 w porządku współrzędnych kątowych i z uwagi na sposób wyboru
p„ punktp 1musi znajdować s.ię w zacieniowanym obszarze. Jeśli punkty na stosie tworzyły wielokąt
wypukły przed wstawieniem p 1, muszą tworzyć wielokąt wypukły także po tej operacji

1008
35.3. ZNAJDOWANIE WYPUKŁEJ OTOCZKI

W dowodzie są dwie sytuacje pokazane na rys. 35.8. Część (a) dotyczy


sytuacji, kiedy nie skręcamy w lewo, a część (b) ilustruje przypadek skrętu
w lewo.
Najpierw pokażemy, że żaden punkt zdjęty ze stosu S nie należy do
CH(Q). Przypuśćmy, że punkt p1 zostaje zdjęty ze stosu, gdyż kąt JJ:.pkp1p 1nie
oznacza skrętu w lewo, tak jak na rys. 35.8a. Ponieważ przeglądamy punkty
w kolejności rosnących współrzędnych kątowych względem punktu p 0, istnieje
trójkąt !'::,p0pJJk zawierający punkt p albo w środku, albo na odcinku jijj 1,..
1
W obydwu przypadkach punkt p1 nie może być wierzchołkiem CH(Q).
Teraz pokażemy, że każdy punkt znajdujący się na stosie S w chwili za~
kończenia działania procedury jest wierzchołkiem CH(Q), Zaczniemy od udo-
wodnienia następującego stwierdzenia: niezmiennikiem w procedurze GRA-
HAM-SCANjest to, że punkty na stosie S zawsze stanowią ciąg wierzchołków
wielokąta wypukłego w kolejności przeciwnej do ruchu wskazówek zegara.
Stwierdzenie to jest prawdziwe zaraz po wykonaniu instrukcji w wierszu 6,
ponieważ punkty Po, p 1 i p 2 tworzą wielokąt wypukły. Zbadajmy teraz zmiany
na stosie S w trakcie działania procedury GRAHAM-SCAN. Punkty są albo
wstawiane, albo usuwane ze stosu. W pierwszym przypadku opieramy się na
prostej własności geometrycznej: jeśli usuwamy wierzchołek z wielokąta wypu-
kłego, to otrzymany wielokąt pozostaje wypukły. Zatem zdjęcie punktu ze
stosu S zachowuje niezmiennik.
Zanim rozważymy przypadek, w którym punkt zostaje włożony na stos,
przeanalizujmy inną geometryczną własność, zilustrowaną na rys. 35.9a i b.
Niech P będzie wielokątem wypukłym, a p,p 1jego dowolnym ustalonym bo-
kiem. Rozważmy obszar ograniczony przezft,p 1 i przedłużenia dwóch sąsiadu­
jących z nim boków. 0N zależności od kątów, pod.jakimi są położone sąsiednie
boki, obszar ten może być albo ograniczony, jak zacieniowany obszar w części
(a), albo nieograniczony, jak zacieniowany obszar w części (b)). Jeśli dodamy

p
p

(,) (b)

Rys. 35.9. Dodanie punktu z obszaru za.cieniowanego do wielokąta wypukłego P daje znowu wielo-
kąt wypukły. z.acielllowany obszar jest ograniczony przez bok p,p~i przedłużenia dwóch sąsiednich
boków. (a) Zacieniowany obszar jest ograniczony. (b) Zacieniowany obszar jest nieograniczony

1009
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

dowolny punkt Ps z tego obszaru do P jako nowy wierzchołek, zastępując bok


P,/1
1 bokami P,P 8 i p;pl' otrzymany wielokąt pozostanie wypukły.
Rozwaz:my teraz punkt p 1 wkładany na stos S. Zgodnie z rys. 35.8b oz-
naczmy przez p1 wierzchołek znajdujący się na szczycie stosu S tuż przed wsta-
wieniem tam p 1, a przez Pk wierzchołek poprzedzający pi na stosie S. Twier-
dzimy, że p 1 musi leżeć w zacieniowanym obszarze na rys. 35.8b, odpowiadają­
cym zacieniowanym obszarom na rys. 35.9. Ponieważ kąt .Jf.pkp1p 1 oznacza
skręt w lewo, p 1 musi znajdować się po zacieniowanej stronie przedłużenia
odcinka pJ)j. Ponieważ p 1 następuje po p1 w porządku współrzędnych kąto­
wych, musi znajdować się po zacieniowanej stronie odcinka PoPrDalej, z uwa-
gi na to, jak wybraliśmy p 0, punkt P; musi leżeć po zacieniowanej stronie prze-
dłużenia odcinka j) 0p 1• Zatem p, znajduje się w obszarze zacieniowanym i dlate-
go po wstawieniu go na stos S punkty ze stosu tworzą wielokąt wypukły. To
kończy dowód naszego stwierdzenia.
Kiedy więc procedura GRAHAM-SCAN kończy działanie, punkty zbioru
Q znajdujące się na stosie S stanowią wierzchołki wielokąta wypukłego. Po-
kazaliśmy, że żaden punkt spoza S nie jest wierzchołkiem CH(Q) lub, co
równoważne, że wszystkie wierzchołki CH(Q) są na stosie S. Ponieważ S za-
wiera jedynie wierzchołki z Q, a punkty te tworzą wielokąt wypukły, musi
to być CH(Q).

Pokażemy teraz, że czas działania procedury GRAHAM-SCAN wynosi



O(nlgn), gdzie n= IQI.Wykonanie operacji w wierszu 1 zajmuje czas @(n).
Operacja w wierszu 2 zajmuje czas O(nlgn), jeśli do sortowania współrzędnych
kątowych użyjemy algorytmu mergesort lub heapsort, a kąty będziemy porów-
nywać metodą iloczynu wektorowego opisaną w podrozdz. 35.l. (Usunięcie
wszystkich, oprócz najdalszego, punktów o tej samej współrzędnej kątowej
można zrealizować w łącznym czasie O(n)). Instrukcje w wierszach 3-6 zajmują
czas 0(1). Ponieważ m ~ n - l, pętla for w wierszach 7-10 jest wykonywana co
najwyżej n - 3 razy. Ponieważ wykonanie PUSH zajmuje czas 0(1), każdy
przebieg jest wykonywany w czasie stałym, z wyjątkiem czasu spędzonego
w pętli while w wierszach 8-9, a zatem całkowity czas wykonywania pętli for to
O(n), przy pominięciu zagnieżdżonej pętli white.
W celu wykazania, że łączny czas wykonywania pętli while wynosi O(n),
skorzystamy z metody kosztu sumarycznego do analizy kosztu zamortyzowa~
nego. Dla i= O, 1, ... , m każdy punkt p 1 jest wkładany na stos S dokładnie raz.
Tak jak w analizie procedury MULTIPOP, podanej w podrozdz. 18.1, należy
7.auważyć, że na każdą operację PUSH przypada co najwyżej jedna operacja
Por. Co najmniej trzy punkty - p 0 , p 1 i Pm- nigdy nie zostają zdjęte ze stosu,
zatem faktycznie w sumie jest wykonanych co najwyżej m - 2 operacji POP.
W każdym przebiegu pętli while wykonuje się jedna operacja Por, zatem prze~
biegów tych może być łącznie co najwyżej m - 2. Ponieważ każdy test w wier-

1010
35.3. ZNAJDOWANIE WYPUKŁEJ OTOCZKI

szu 8 i każde wywołanie POP zajmuje czas 0(1), am.:::;;;n - 1, całkowity czas
spędzony w pętli while to O(n). Czas działania algorytmu GRAHAM-SCAN wy-
nosi zatem O(n lg n).

Algorytm Jarvisa
W algorytmie Jarvisa wypukła otoczka zbioru punktów Q jest obliczana meto-
dą znaną jako owijanie. Algorytm działa w czasie O(nh), gdzie h jest liczbą
wierzchołków CH(Q). Jeśli h wynosi O(lgn), algorytm Jarvisa jest asympto-
tycznie szybszy od algorytmu Grahama.
Ujmując rzecz intuicyjnie, algorytm Jarvisa naśladuje owijanie ciasno wokół
zbioru Q kawałka papieru. Zaczynamy od zamocowania końca papierowej
taśmy do najniżej położonego punktu w zbiorze, tzn. do tego samego punktu p 0,
od którego zaczynaliśmy algorytm Grahama. Punkt ten jest wierzchołkiem
wypuklej otoczki. Napinamy taśmę, ciągnąc ją w prawo, a następnie podnosimy
ją do góry, dopóki nie natrafimy na jakiś punkt. Punkt ten także musi należeć
do otoczki. Trzymając taśmę napiętą, wędrujemy w ten sposób naokoło zbioru
wierzchołków, dopóki nie trafimy z powrotem do początkowego punktu p 0 •
Bardziej formalnie rzecz biorąc, algorytm Jarvisa konstruuje ciąg
H = <Po, Pi, ... , Ph-i> wierzchołków CH(Q). Zaczynamy od punktu p 0 • Jak
widać z rys. 35.10, następny wierzchołek p 1 wypukłej otoczki ma najmniejszą
współrzędną kątową względem p 0 • (W przypadku remisów wybieramy punkt
leżący najdalej od p 0). Podobnie, p 2 ma najmniejszą współrzędną kątową
względem Pi itd. Kiedy osiągamy wierzchołek położony najwyżej, powiedzmy
Pk (rozstrzygając remisy na korzyść wierzchołka leżącego najdalej), mamy
skonstruowany, pokazany na rys. 35.10, prawy łańcuch otoczki CH(Q). Żeby
skonstruować lewy łańcuch, zaczynamy od Pk i wybieramy Pk+I jako punkt
o najmniejszej współrzędnej kątowej w biegunowym układzie współrzędnych
o środku Pk, ale z ujemnejpółosi x. Kontynuujemy ten proces tworzenia lewego
łańcucha, wybierając współrzędne kątowe z ujemnej części osi x, dopóki nie
powrócimy do naszego początkowego wierzchołka p 0 •
Moglibyśmy opisać algorytm Jarvisa jako pojedyncze obiegnięcie wokół
wypuklej otoczki, to znaczy bez oddzielnego konstruowania prawego i lewe-
go łańcucha. Implementacje takie zazwyczaj przechowują wartość kąta wy-
branego ostatnio boku otoczki z osią x i wymagają, żeby ciąg kątów związa­
nych z bokami otoc7.k:i był ściśle rosnący (w zakresie od O do 2n: radianów).
Zaletą konstruowania osobnych łańcuchów jest to, że nie musimy obliczać
kątów w sposób jawny; do porównywania kątów wystarczają metody opisane
w podrozdz. 35.I.
Jeśli algorytm Jarvisa został za.implementowany właściwie, to działa on
w czasie O(nh). Dla każdego spośród h wierzchołków otoczki CH(Q) znaj-
dujemy wierzchołek o minimalnej współrzędnej kątowej. Każde porównanie
-""----
1011
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

Lewy łańcuch ,: Prawy łańcuch


'
'
__
'
'
'
'
'
'''

• '
'
'
'' . • • •
''' •
'
' •
'''
'
'
' •
''
'

--
Lewy łańcuch Prawy łańcuch
Rys. 35.10. Działanie algorytmu Jarvisa Pierwszy wybrany wierzchołek to najniżej położony punkt
p0• Kolejny wierzchołek:, Pi, ma najmniejszą ze wszystkich punktów współrzędną kątową względem
p 0• Z kolei p 2 ma najmniejszą współrzędną kątową względem PP Prawy łańcuch kończy się na
najwyżej położonym punk.cie pl. Następnie jest konstruowany lewy łańcuch przez majdowanie
najmniejszych współrzędnych kątowych względem ujemnej półosi x

współrzędnych kątowych za pomocą metod podanych w podrozdz. 35.1 zaj-


muje czas stały. Jak wiadomo z podrozdz. 10.1, minimum spośród n wartości
możemy obliczyć w czasie O(n), jeśli każde porównanie zajmuje czas 0(1).
Algorytm Jarvisa działa zatem w czasie O(nh).

ZADANIA

35.3-1. Udowodnij, że w procedurze GRAHAM-SCAN punkty p 1 i Pmmuszą być


wierzchołkami CH(Q).
35.3-2. Rozważmy model obliczeń dopuszczający dodawanie, porównywanie
i mnożenie, w którym problem sortowania n liczb ma dolną granicę
Q(nlgn). Udowodnij, że w takim modelu O(nlgn) jest dolną granicą dla
problemu obliczenia ciągu kolejnych wierzchołków wypukłej otoczki zbio-
ru n punktów.
35.3-3. Udowodnij, że para najbardziej odległych punktów w zbiorze punktów
Q musi należeć do CH(Q).
35.3-4. Dla danego wielokąta P i punktu q na jego brzegu, cieniem q nazywa-
my zbiór punktów r takich, że odcinek ąr mieści się całkowicie na brzegu
lub we wnętrzu P. Wielokąt P jest gwiazdą, jeśli istnieje punkt p wewnątrz

1012
35.4. ZNAJDOWANIE PARY NAJMNIEJ ODLEGŁYCH PUNKTÓW

P znajdujący się w cieniu każdego punktu z brzegu P. Zbiór wszystkich


tak.ich punktów p nosi nazwę jądra P. (Patrz rys. 35.11). Pokaż, jak ma-
jąc daną n-wierzchołkową gwiazdę P zadaną przez ciąg swoich wierzchoł­
ków w kolejności przeciwnej do ruchu wskazówek zegara, obliczyć CH(P)
w czasie O(n) .

p

(,) (b)

Rys. 35,l l. Definicja gwiazdy na ui:ylek zad. 35.3-4. (a) Gwiazda. Odcinek od punktu p do dowolnego
punktu q na brzegu przecina brzeg tylko w q. (b) Wielokąt nie będą.cy gwiazdą. Zacieniowany obszar
po lewej stronie to cień punktu q, a po prawej - cień q'. Ponieważ obszary te są rozłączne, jądro
wielokąta jest puste

35.3-S. W problemie wypuklej otoczki „on-line" informację o n punktach zbio-


ru Q dostajemy po jednym punkcie na raz. Po otrzymaniu każdego punk.tu
mamy obliczyć wypukłą otoc7.k.ę wszystkich podanych dotychczas punk-
tów. Można oczywiście dla każdego punk.tu wykonać algorytm Grahama,
co daje łączny czas O(n 2 lgn). Pokaż, jak rozwiązać problem wypukłej
otoczki „on-line" w łącznym C'lasie O(n2 ).
* 35.3-6. Pokaż, jak zaimplementować przyrostową metodę obliczania wypukłej
otoczki n, aby działała ona w czasie O(nlgn).

35.4. Znajdowaniepary najmniejodległych punktów


Zajmiemy się teraz problemem znajdowania pary najmniej odległych punktów
w zbiorze n~ 2 punktów Q. Określenie „najmniej odległe" odnosi się do zwy-
kłej odległości euklidesowej: odległość między punktami p 1 = (x 1, y 1) i p 2 =
.J
= (x 2, y 2) to (x 1 - x 2) 2 ~-61 - y 2) • Dwa punkty w zbiorze Q mogą się
2

pokrywać; wtedy odległość między nimi jest równa O. Problem ten znajduje
zastosowania na przykład w systemach kontroli ruchu. W systemie kontroli
ruchu powietrznego lub morskiego informacja o tym, które dwa obiekty znaj-
dują się najbliżej siebie, może się przydać do wykrywania potencjalnych kolizji.
„Siłowy" algorytm znajdowania pary najmniej odległych punktów

sprawdza po prostu wszystkie (;) = 0(n 2


) pary punktów. W tym pod-

1013
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

rozdziale przedstawimy algorytm dla tego problemu działający na podstawie


zasady „dziel i zwyciężaj", którego czas działania opisuje znane już nam rów-
nanie rekurencyjne T(n) = 2T(n/2) + O(n). Algorytm ten działa zatem w cza-
~e O(nlgn).

Algorytm oparty na zasadzie „dziel i zwyciężaj"


Każde rekurencyjne wywołanie algorytmu otrzymuje jako dane wejściowe pod-
zbiór P c Q oraz tablice X i Y, z których każda zawiera wszystkie punkty
z wejściowego podzbioru P. Punkty w tablicy X są uporządkowane rosnąco
względem współrzędnej x, a w tablicy Y-względem współrzędnej y. Zwróćmy
uwagę, że jeśli chcemy osiągnąć czas O(n lgn), nie możemy sobie pozwolić na
sortowanie na każdym poziomie rekursji; gdybyśmy tak. zrobili, równaniem
rekurencyjnym na czas działania algorytmu byłoby T(n) = 2T(n/2) + O(nlg n),
którego rozwiązaniem jest T(n) = O(nlg 2 n), Nieco później pokażemy, jak. za
pomocą „sortowania wstępnego" uzyskać powyższą własność uporządkowania
danych, nie sortując ich w każdym wywołaniu rekurencyjnym.
W konkretnym wywołaniu rekurencyjnym dla danych P, X i Y spraw-
dzamy najpierw, czy IPI ~ 3. Jeśli tak, to stosujemy po prostu opisaną powyżej
metodę „siłową": sprawdzamy wszystkie (1~1) pary punktów i jak.o wynik
zwracamy parę najmniej odległych punktów. Jeśli !Pl> 3, to realizujemy zasa-
dę „dziel i zwyciężaj" w następujący sposób.

Dziel: Znajdujemy pionową prostą /, dzielącą zbiór punktów P na dwa zbiory


P, i P, tak, że IP,1- nPl/1],IP,1- LJPl/2J; wszystkie punkty zbioru P,
leżą na lewo od prostej /, a wszystkie punkty PR leżą na prawo od /.
Tablica X zostaje podzielona na tablice XL i XR, zawierające odpowiednio
punkty PL i PR•posortowane rosnąco względem współrzędnej x. Podob-
nie, tablicę Y dzielimy na tablice YL i YR, składające się odpowiednio
z punktów PL i PR, posortowanych rosnąco względem współrzędnej y.

Zwyciężaj: Po podzieleniu P na Pr, i PR wykonujemy dwa wywołania rekuren-


cyjne -jedno w celu znalezienia pary najmniej odległych punktów w P1-,
a drugie w PR·Dane wejściowe dla pierwszego wywołania to podzbiór
PL oraz tablice XL i Yr,;drugie wywołanie otrzymuje na wejściu PR, XR
oraz YR, Oznaczmy odległości par najbliższych siebie punktów obliczo-
ne dla PL i PR odpowiednio przez óL i óR i niech ó = min(óL, óR).

Połącz: Para najmniej odległych punktów jest albo parą o odległości ó znale-
zioną przez jedno z wywołań rekurencyjnych, albo parą, w której jeden
punkt należy do PL• a drugi do PR· Algorytm sprawdza, c::z;yistnieje

1014
35A. ZNAJDOWANIE PARY NAJMNIEJ ODLEGŁYCH PUNKTÓW

tak.a para o odległości mniejszej niż ó. Zauważmy, że jeśli istnieje para


punktów o odległości mniejszej niż ó, obydwa punkty nie mogą być
dalej niż {Jod prostej/. Jak zatem widać na rys. 35.12a, obydwa punkty
muszą się mieścić wewnątrz pionowego pasa szerokości 2ó wokół pros-
tej /. W celu znalezienia takiej pary, o ile istnieje, algorytm wykonuje
następujące operacje.

f->-P,

• ''
P, ~
.
.'
''
' .''
' •
• 2/J Para punktów
• pokrywających się:
jeden z P,.,
• drugi z P11.


'.
'
' .' '
'
'
Para punktów
pokrywających się:
jeden z Pi,
• I •' • drugi z P11.
(•) (b)

Rys. 35.12. Kluczowe fakty w dowodzie, że algorytm znajdowania najmniej odJeglej pary punktów
musi sprawdzać tylko 7 punktów następujących po każ.dym punkcie w tablicy Y'. (a) Jeśli Pi E PL
i PREPR są od siebie odległe o mnitj niż ó, muszą się mieścić wewnątrz prostokąta ó x 2ó, przez
którego środek przechodzi prosta/. (b) Przykład, że cztery punkty, z których każde dwa są od siebie
odlegle przynajmniej o ó, mogą pomieścić się w kwadracie ó x ó. Po lewej stronie znajdują się
4 punkty z PL•a po prawej 4 punkty z PR·W prostokącie ó x 2ó może pomieścić się 8 punktów,jeśli
punkty narysowane na prostej/ są w rzeczywistości parami pokrywających się punktów: jeden z PL•
a drugi z PR

1. Tworzy tablicę Y', uzyskaną z tablicy Yprzez usunięcie z niej wszystkich


punktów spoza pionowego pasa szerokości 2ó. Tablica Y' jest posortowana
względem współrzędnej y, tak jak Y.
2. Dla każdego punktu p z tablicy Y' algorytm próbuje znaleźć punkty w Y'
leżące w promieniu {J od p. Jak się wkrótce przekonamy, wystarczy roz-
ważyć tylko 7 punktów w tablicy Y' następujących pop. Algorytm oblicza
odległość od p do każdego z tych 7 punktów i przechowuje najmniejszą
znalezioną dotychczas odległość {J' między parami punktów w Y'.
3. Jeśli b' < ó, to pionowy pas rzeczywiście zawiera parę punktów położonych
bliżej niż te znalezione w wywołaniu rekurencyjnym. Jako wynik jest zwra-
cana owa para i jej odległość ó'. W przeciwnym razie jest zwracana para
najmniej odległych punktów znaleziona w wywołaniu rekurencyjnym i jej
odległość ó.

1015
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

W powyższym opisie pomijamy pewne szczegóły implementacyjne, nie-


zbędne do osiągnięcia czasu działania O(n lgn). Po udowodnieniu poprawności
algorytmu pokażemy, jak go zaimplementować, żeby taki czas uzyskać.

Poprawność algorytmu
Poprawność opisanego powyżej algorytmu znajdowania pary najmniej odleg-
łych punktów jest oczywista, z wyjątkiem dwóch kwestii. Po pierwsze, kończąc
rekursję kiedy IPI :::;;3, zapewniamy sobie to, że nigdy nie będziemy dzielić
zbioru składającego się tylko z jednego punktu. Drugą kwestią jest to, że musi-
my sprawdzać tylko 7 punktów następujących po każdym punkcie p w tablicy
Y'; teraz zajmiemy się dowodem tej własności.
Przypuśćmy, że na pewnym poziomie rekursji parę najmniej odległych
punktów stanowią pLePL i PRE PR. Zatem odległość ó' między PL a PR jest
ostro mniejsza niż ó. Punkt PL musi leżeć na prostej / lub na lewo od niej,
ale bliżej niż ó. Podobnie, PR leży na I lub na prawo od niej i bliżej niż
ó. Co więcej, odległość w poziomie PL i PR jest mniejsza niż ó. Zatem, jak
widać na rys. 35.12a, PL i PR mieszczą się w prostokącie ó x 2ó położonym
symetrycznie względem prostej l. (W prostokącie tym mogą również być i in-
ne punkty).
Pokażemy teraz, że w owym prostokącie ó x 2ó może znajdować się co
najwyżej 8 punktów ze zbioru P. Rozważmy kwadrat ó x ó stanowiący lewą
połowę tego prostokąta. Ponieważ wszystkie punkty zbioru PL są odlegle od
siebie przynajmniej o ó, wewnątrz tego kwadratu mogą się znajdować co naj-
wyżej cztery punkty; na rys. 35.12b widać, w jaki sposób. Podobnie, co naj-
wyżej cztery punkty ze zbioru PR mogą się znajdować w kwadracie ó x ó sta-
nowiącym prawą połowę prostokąta. Zatem w sumie w prostokącie ó x 2ó
może się zmieścić co najwyżej 8 punktów ze zbioru P. (Zauważmy, że ponieważ
punkty na prostej l mogą należeć zarówno do PL, jak i PR• na I mogą leżeć
nawet 4 punkty. Liczba ta zostaje osiągnięta, jeśli istnieją dwie pary pokrywa-
jących się punktów, z których każda składa się z jednego p11nktu z PL i jednego
z PR• jedna para znajduje się na przecięciu l z górnym, a druga - z dolnym
bokiem prostokąta).
Wiedząc, że wewnątrz prostokąta może się znajdować co najwyżej 8 punk-
tów ze zbioru P, łatwo stwierdzić, że wystarczy sprawdzać po 7 punktów na-
stępujących po każdym punkcie w tablicy Y'. Trzymając się założenia, że para
najmniej odległych punktów to PL i PR,możemy bez straty ogólności przyjąć, że
PL poprzedza PR w tablicy Y'. Wówczas, nawet jeśli PL występuje najwcześniej,
a PR najpóźniej jak można w tablicy Y', punkt PR jest na jednej z 7 pozycji
następujących po PL· Wykazaliśmy zatem poprawność algorytmu znajdowania
pary najmniej odległych punktów.

1016
35.4. ZNAJDOWANIE PARY NAJMNIEJ ODLEGŁYCH PUNKTÓW

Implementacja i czas działania algorytmu

Jak już wspomnieliśmy, chcielibyśmy, żeby równaniem rekurencyjnym opi-


sującym czas działania algorytmu było T(n) = 2T(n/2) + O(n), gdzie T(n)
to oczywiście czas działania dla n punktów. Główna trudność tkwi w za-
pewnieniu, żeby tablice XL, XR, YL i YR, przekazywane jak.o parametry
wywołań rekurencyjnych, były posortowane względem odpowiednich współ­
rzędnych oraz żeby tablica Y' była posortowana względem współrzędnej y.
(Zauwaimy, że jeśli otrzymana w wywołaniu rekurencyjnym tablica X jest
już posortowana, to podział zbioru P na PL i PR łatwo zrealizować w czasie
liniowym).
Podstawową obserwacją jest to, że w każdym wywołaniu chcemy utworzyć
posortowany podzbiór tablicy już posortowanej. Na przykład w pewnym wy-
wołaniu mamy dany podzbiór P i tablicę Y, posortowaną względem współ­
rzędnej y. Podzieliwszy P na PL i PR• chcemy utworzyć tablice YL i YR, posor-
towane względem współrzędnej y. Co więcej, tablice te muszą być utworzone
w czasie liniowym. Na naszą metodę można spojrzeć jak na odwrotność proce-
dury MERGE w algorytmie mergesort z podrozdz. 1.3.1: rozdzielamy posor-
towaną tablicę na dwie posortowane części. Poniższy pseudokod prezentuje tę
ideę. Zapis length[ł] oznacza tu liczbę elementów w tablicy Y.

l length[YL] - length[YR] +- O
2 for i +- 1 to length[Y]
3 doifY{i]EPL
4 tben length[YL] - length[YL]+ 1
5 Y[length[YL]] - Y[;J
6 else length[YR] - length[YR]+ 1
7 Y[length[Y,]] - Y[;J

Badamy po prostu po kolei punk.ty z tablicy Y. Jeśli punkt Y[i] nalezy do PL,
dodajemy go na koniec tablicy YL; w przeciwnym razie dołączamy go na ko-
niec tablicy YR. Podobnie wygląda pseudokod tworzenia tablic XL, XR i Y'.
Pozostaje jedynie pytanie, jak uzyskać początkowe uporządkowanie punk-
tów. Robimy to, po prostu poddając je sortowaniuwstępnemu; tzn. sortujemy
je tylko raz, przed pierwszym wywołaniem rekurencyjnym. Posortowane tabli-
ce zostają przekazane jako parametry pierwszego wywołania rekurencyjnego,
a stąd w miarę potrzeby rozdziela się je w dalszych wywołaniach rekurencyj-
nych. Sortowanie wstępne zwiększa czas działania o dodatkowy składnik
O(nlgn), ale teraz każdy krok rekursji zajmuje czas liniowy, jeśli pominiemy
wywołania rekurencyjne. Jeśli zatem przez T(n) oznaczymy czas działania al-
gorytmu na jednym poziomie rekursji, a przez T'(n) czas działania całego al-
gorytmu, to mamy T'(n) = T(n) + O(n lg n) oraz

1017
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

_ {27(n/2) + O(n), jeśli n > 3


T(n) - 0(1) , . ·1·
Jes1n::s:; 3

Zatem T(n)- O(nlgn) i T'(n) - O(nlgn).


ZADANIA

3S.4-l. Profesor Smothers proponuje ulepszenie pozwalające w algorytmie


znajdowania pary najmniej odległych punktów sprawdzać tylko 5 punktów
następujących po każdym punkcie w tablicy Y'. Pomysł polega na tym,
żeby zawsze umieszczać punkty leżące na prostej / w zbiorze PL. Nie może
wówczas istnieć para pokrywających się punktów na prostej /, z których
jeden należy do PL, a drugi do P 1?: W prostokącie t, x 2{) może się zatem
znajdować co najwyżej 6 punktów. Jaki błąd tkwi w propozycji profesora?
35.4-2. Pokaż, jak - nie zwiększając asymptotycznej złożoności czasowej al-
gorytmu - zapewnić, żeby zbiór przekazywany w pierwszym wywołaniu
rekurencyjnym nie zawierał pokrywających się punktów. Udowodnij, że
wystarczy wówczas sprawdzać 6 (a nie 7) pozycji w tablicy Y' następują­
cych po każdym punkcie. Dlaczego nie wystarczy sprawdzać tylko 5 pozy-
cji w tablicy następujących po każdym punkcie?
35.4-3. Odległość między dwoma punktami można zdefiniować na inne sposo-
by niż odległość euklidesową. Na płaszczyźnie odległość Lm między punk-
tami P 1 a P2 jest dana wzorem ((x 1 - x 2Y"+ U'1 - y2)' 11) 11m.Odległość eukli-
desowa jest zatem odległością L 2 • Zmodyfikuj algorytm znajdowania pary
najmniej odległych punktów tak, by działał dla odległości L 1, zwanej także
odległością miejską.
3S.4-4. Odległość L 00 między punktami p 1 a p 1 na płaszczyźnie to max(lx 1
-

- x 2I, lY1 - y 2 1). Zmodyfikuj algorytm znajdowania pary najmniej odleg-


łych punktów tak, by działał dla odległości L 00 •

Problemy
35-1. Wypukle warstwy
Dla danego zbioru punktów Q na płaszczyźnie indukcyjnie definiujemy wypuk-
le warstwy Q. Pierwsza wypukła warstwa Q składa się z punktów Q będących
wierzchołkami CH(Q). Dla i> 1 zdefiniujmy Q; jako zbiór powstały przez
usunięcie z Q wszystkich punktów z wypukłych warstw 1, 2, ... ,i-I. Wów-
czas i-ta wypukła warstwa Q to CH(Q;), jeśli Q, 'F 0, a w przeciwnym razie jest
nie zdefiniowana.

(a) Podaj działający w czasie O(n2) algorytm majdowania wypukłych warstw


zbioru n punktów.
----------- -----~--·-----~
PROBLEMY

(b) Udowodnij, że w każdym modelu obliczeń, w którym na posortowanie


n liczb rzeczywistych potrzeba czasu .Q(nlgn), obliczenie wypukłych
warstw zbioru n punktów wymaga czasu .Q(nlgn).

35-2. Warstwy maksimów


Niech Q będzie zbiorem n punktów na płaszczyźnie. Mówimy, że punkt (x, y)
dominuje punkt (x', y'), jeśli x ~ x' i y ~ y'. Punkt zbioru Q, który nie jest
dominowany przez żadne inne punkty z Q, nazywamy maksymalnym. Zbiór Q
może zawierać wiele punktów maksymalnych, które można uszeregować w hie-
rarchii warstw maksimów w następujący sposób. Pierwszą warstwą maksimów
L 1 jest zbiór punktów maksymalnych w Q. Dla i> 1 definiujemy i-tą warstwę
1-1
maksimów L 1 jako zbiór punktów maksymalnych w Q- U Lj.
j"' l
Załóżmy, że Q składa się
z k niepustych warstw maksimów i niech yi
będzie współrzędną y pierwszego z lewej strony punktu w L 1 dla i = 1, 2,
..., k. Załóżmy na razie, że żadne dwa punkty w Q nie mają tej samej współ­
rzędnej x ani y.

(a) Wykaż, że y 1 > Y2> ... > Yk·

Rozważmy punkt (x, y) leżący


na lewo od wszystkich punktów w Q, które-
go współrzędna y jest różna od współrzędnych y wszystkich punktów w Q.
Niech Q' - Qu {(x, y)).

(b) Niech j będzie najmniejszym indeksem takim, że y1 < y, chyba że y < yk;
wówczas przyjmujemy j = k + 1. Wykaż następujące własności warstw
maksimów zbioru Q'.

• Jeśli j ~ k, to warstwy maksimów Q' są takie same jak warstwy maksi-


mów Q, z tą różnicą, że L1 dodatkowo zawiera (x, y) jako swój pierwszy
punkt z lewej strony.
• Jeśli j = k + 1, to pierwszych k warstw maksimów Q' jest takich sa-
mych jak dla Q, ale oprócz tego Q' ma niepustą (k + 1)-szą warstwę
maksimów: Lk+i = {(x, y)}.

(c) Opisz działający w czasie O(nlgn) algorytm obliczania warstw maksimów


zbioru n punktów Q. (Wskazówka: Przesuwaj prostą zamiatającą od strony
prawej do lewej).
(d) Czy pojawiają się jakieś kłopoty, jeśli dopuścimy istnienie w wejściowym
zbiorze punktów o jednakowych współrzędnych x luby? Zaproponuj spo-
sób przezwyciężenia tak.ich trudności.

1019
ROZDZIAŁ 35. GEOMETRIA OBLICZENIOWA

35-3. Pogromcy duchów


Oddział n pogromców duchów walczy przeciwko n duchom. Każdy pogromca
jest uzbrojony w ładunek protonów, których strumień wystrzelony w ducha
unieszkodliwia go. Strumień porusza się po linii prostej i urywa się, kiedy trafi
w ducha. Pogromcy decydują się na następującą strategię. Każdy z nich dobie-
r.te sobie do pary jednego ducha, tworząc w ten sposób n par pogromca-duch,
a następnie wszyscy jednocześnie wystr1.elą stn1mienie protonów, każdy w wy-
branego przez siebie ducha. Jak powszechnie wiadomo, krzyżowanie strumieni
jest bardzo niebezpieczne, więc pogromcy muszą wybrać pary tak, żeby żadne
strumienie się nie krzyżowały.
Załóżmy, 7..epołożenie każdego pogromcy i każdego ducha jest ustalonym
punktem na płaszczyźnie oraz że żadne trzy z tych punktów nie są współ­
liniowe.

(a) Uzasadnij, Ze istnieje prosta przechodząca przez jednego pogromcę i jed-


nego ducha taka, Ze liczba pogromców po jednej stronie tej prostej jest
równa liczbie duchów po tej samej stronie, Opisz, jak znaleźć taką prostą
w czasie O(n lg n).
(b) Przedstaw działający w czasie O(n 2 lg n) algorytm łączenia w pary pogrom-
ców i duchów tak, żeby żadne strumienie się nie przecinały.

354. Rozkłady
skoncentrowane
Rozważmy problem obliczania wypukłej otoczki zbioru punktów na płasz­
czyźnie, które wylosowano zgodnie z pewnym znanym rozkładem prawdo-
podobieństwa. Czasami oczekiwany rozmiar wypukłej otoczki n punktów
wylosowanych zgodnie z takim rozkładem wynosi O(n 1-•) dla pewnej stałej
e > O. Rozkład tak.i nazywamy skoncentrowanym,Do rozkładów skoncent-
rowanych należą:

• Rozkład
jednostajny na kole o promieniu jednostkowym. Oczekiwany roz-
miar otoczki to 0(n 1 13 ).
• Rozkład jednostajny wewnątrz wielokąta wypukłego o k bokach, dla do-
wolnego ustalonego k. Oczekiwany rozmiar otoczki to E>(lgn).
• Dwuwymiarowy rozkład nonnalny, Oczekiwany rozmiar otoczki to E>Ogn),

(a) Dla dwóch danych wielokątów wypukłych, mających odpowiednio n1 i 'li


wierzchołków, opisz, jak obliczyć wypukłą otoczkę wszystkich n 1 + n2
wierzchołków w czasie O(n 1 + n 2). (Wielokąty mogą się przecinać).
(b) Wykaż, że wypukłą otoczkę zbioru n punktów wylosowanych niezależnie
zgodnie z rozkładem skoncentrowanym można obliczyć w oczekiwanym
czasie O(n), (Wskazówka: Rekurencyjnie oblicz wypukłe otoczki pierw-
szych n/2 i drugich n/2 punktów, a następnie połącz je).

1020
UWAGI DO ROZDZIAŁU

Uwagido rozdziału

W rozdziale tym zaledwie dotykamy problematyki algorytmów i metod geome-


trii obliczeniowej. Wśród książek z geometrii obliczeniowej należy wymienić
prace Preparaty i Shamosa [160] oraz Edelsbrunnera [60].
Chociaż geometrią zajmowano się od czasów antycznych, rozwój algoryt-
mów dla problemów geometrycznych następuje stosunkowo od niedawna.
Preparata i Shamos podają, że jako pierwszy pojęcie złożoności takiego prob-
lemu sformułował E. Lemoine w 1902 r. Zajmował się on konstrukcjami geo-
metrycznymi na płaszczyźnie euklidesowej - z użyciem cyrkla i linijki - i okreś­
lił zbiór pięciu operacji pierwotnych: umieszczenie jednego końca cyrkla w da-
nym punkcie, umieszczenie jednego końca cyrkla na danej prostej, narysowa-
nie okręgu, przyłożenie linijki do danego punktu i narysowanie prostej. Lemoi-
ne interesował się liczbą operacji pierwotnych potrzebnych do wykonania da-
nej konstrukcji; wielkość tę nazywał „prostotą" konstrukcji.
Algorytm opisany w podrozdz. 35.2, sprawdzający, czy którekolwiek od-
cinki się przecinają, pochodzi od Shamosa i Hoeya [176].
Oryginalną wersję algorytmu Grahama podał Graham [91J. Algorytm owi-
jania zaproponował Jarvis [112]. Yao [205] udowodnił, że w modelu drzew
decyzyjnych !l{nlgn) jest dolną granicą na czas działania dowolnego algoryt-
mu znajdowania wypuklej otoczki. Jeśli weźmiemy pod uwagę liczbę h wierz-
chołków na wypukłej otoczce, to podany przez Kirkpatricka i Seidla [120]
algorytm szukania z obcinaniem, działający w czasie O(nlgh), jest asympto-
tycznie optymalny.
Działający w czasie O(nlgn), oparty na zasadzie „dziel i zwyciężaj" al-
gorytm znajdowania pary najmniej odległych punktów jest autorstwa Shamosa
i pojawia się u Preparaty i Sbamosa [160]. Dowodzą oni też, że algorytm ten
jest asymptotycznie optymalny w modelu drzew decyzyjnych.
Rozdział 36

NP-zupełność

Wszystkie algorytmy, którymi się dotychczas zajmowaliśmy, były algorytmami


wielomianowymi:dla danych wejściowych rozmiaru n ich czas działania w naj-
gorszym przypadku wynosił O(nk) dla pewnej stałej k, Naturalne jest pytanie,
czy wszystkie problemy można rozwiązywać w czasie wielomianowym. Odpo-
wiedź brzmi: nie. Istnieją na przykład problemy, jak słynny „problem stopu"
Turinga, których nie może rozwiązać żaden komputer, niezależnie od tego, ile
będzie miał na to czasu. Istnieją także problemy, które można rozwiązać, ale
nie w czasie O(n1) dla jakiejkolwiek stałej k. Ogólnie rzecz biorąc, o prob-
lemach rozwiązywalnych za pomocą algorytmów wielomianowych można my-
śleć jako o łatwo rozwiązywalnych, a o problemach wymagających czasu więk­
szego niż wielomianowy - jako o trudno rozwiązywalnych.
Tematem niniejszego rozdziału jest interesująca klasa problemów zwanych
,,NP-zupełnymi'', których status nie jest znany. Nie znaleziono dotychczas algo-
rytmu wielomianowego dla problemu NP-zupełnego ani nie udowodniono istnie-
nia większej niż wielomianowa dolnej granicy dla żadnego z nich. Pytanie „Czy
P '# NP?" stanowi jeden z najgłębszych, najbardziej kłopotliwych otwartych
problemów w informatyce teoretycznej od czasu jego sformułowania w 1971 r.
Większość informatyków sądzi, że problemy NP-zupełne należą do trudno
rozwiązywalnych. Powodem jest to, że gdyby jakikolwiek problem NP-zupełny
można było rozwiązywać w czasie wielomianowym, to każdy problem NP-zu-
pełny miałby rozwiązanie wielomianowe. Jeśli weźmiemy pod uwagę całą gamę
rozważanych dotychczas problemów NP-zupełnych i brak postępów w poszu-
kiwaniach rozwiązania wielomianowego, byłoby naprawdę zadziwiające, gdy-
by wszystkie je można było rozwiązać w czasie wielomianowym.
Aby móc projektować dobre algorytmy, trzeba zrozumieć podstawy teorii
NP-zupełności. Jeśli umiemy pokazać, że problem jest NP-zupełny, stanowi to
mocny argument za tezą, że jest on trudno rozwiązywalny. W takiej sytuacji

1022
36.1. CZAS WIELOMIANOWY

projektant lepiej spożytkuje czas, pracując nad algorytmem aproksymacyjnym


(patrz rozdz. 37) niż szukając szybkiego algorytmu rozwiązującego dany prob-
lem dokładnie. Co więcej, wiele naturalnych i interesujących problemów, które
z pozoru wydają się nie trudniejsze niż sortowanie, przeszukiwanie grafu czy
znajdowanie przepływu w sieci, jest w rzeczywistości NP-zupełnych. Warto
zatem zapoznać się z tą ważną klasą problemów.
W rozdziale tym zajmiemy się tymi aspektami NP-zupełności, które w spo-
sób najbardziej bezpośredni są związane z analizą algorytmów. W podrozdziale
36.1 sformalizujemy używane przez nas pojęcie „problemu" i zdefmiujemy klasę
złożoności, obejmującą problemy decyzyjne rozwiązywalne w czasie wielomiano-
wym. Zaprezentujemy także podejście do tych zagadnień na gruncie teorii języ­
ków formalnych. W podrozdziale 36.2 zdefmiujemy klasę NP problemów decy-
zyjnych, których rozwiązania daje się weryfikować w czasie wielomianowym.
Postawimy tam również w sposób formalny pytanie „Czy P '::/-NP?".
W podrozdziale 36.3 pokażemy, jak badać zależności między różnymi pro-
blemami za pomocą „wielomianowej redukcji". Zdefiniujemy pojęcie NP-zu-
pełności i przedstawimy szk.ie dowodu faktu, że pewien problem, zwany „speł­
nialnością układów logicznych", jest NP-zupełny. Dysponując jednym prob-
lemem NP-zupełnym, w pod.rozdz. 36.4 wyjaśnimy, jak dowodzić NP-zupełno­
ści innych problemów znacznie prościej metodą redukcji. Metodę tę zilustruje-
my dowodami NP-zupełności dwóch problemów spełnialności formuł. NP-zu-
pełność wielu innych problemów udowodnimy w podrozdz. 36.5.

36.1. Czaswielomianowy
Nasze rozważ.ania dotyczące NP-zupełności rozpoczynamy od sformalizowa-
nia pojęcia problemów rozwiązywalnych w czasie wielomianowym. Problemy
takie trak.tuje się powszechnie jako łatwo rozwiązywalne. Powód, dlaczego tak
jest, stanowi kwestię filozoficzną, a nie matematyczną. Wymieńmy trzy moty-
wujące go argumenty.
Po pierwsze, chociaż rozsądnie jest potraktować problem, którego rozwią­
zanie wymaga czasu 0(n 100 ) jak.o trudno rozwiązywalny, bardzo niewiele pra-
ktycznych problemów wymaga czasu rzędu wielomianu tak wysokiego stopnia.
Napotykane w praktyce problemy rozwiązywalne w czasie wielomianowym
mają zazwyczaj znacznie mniejszą złożoność.
Po drugie, dla wielu rozsądnych modeli obliczeń problem dający się roz-
wiązać w czasie wielomianowym w jednym z nich można również rozwiązać
w czasie wielomianowym w innym modelu. Na przykład klasa problemów
rozwiązywalnych w czasie wielomianowym na sekwencyjnej maszynie o do-
stępie swobodnym, używanej w większej części tej książki, jest identyczna
z klasą problemów rozwiązywalnych w czasie wielomianowym na abstrakcyj-

1023
ROZDZIAŁ 36. NP-ZUPEŁNOSC

nych maszynach Turinga 11. Pokrywa się ona również z klasą problemów roz-
wiązywalnych w czasie wielomianowym na komputerze równoległym, nawet
jeśli liczba procesorów rośnie wielomianowa ze względu na rozmiar danych
wejściowych.
Po trzecie, klasa problemów rozwiązywalnych w czasie wielomianowym
ma dobre własności domykania, ponieważ rodzina wielomianów jest zamknię­
ta ze względu na operacje dodawania, mnożenia i składania. Jeśli na przykład
dane wyjściowe jednego algorytmu wielomianowego są danymi wejściowymi
dla innego algorytmu, to tak otrzymany złożony algorytm jest wielomianowy.
Jeśli algorytm, który jest wielomianowy, o ile pominiemy koszt wywoływanych
podprogramów, wywołuje stalą liczbę razy podprogramy o złożoności wielo-
mianowej, to czas działania całości jest wielomianowy.

Problemy abstrakcyjne
Żeby móc mówić o klasie problemów rozwiązywalnych w czasie wielomiano-
wym, musimy najpierw formalnie sprecyzować pojęcie „problemu". Definiuje-
my problem abstrakcyjny Q jako relację dwuargumentową na zbiorze I egzemp-
lany problemu i zbiorze S rozwiązań problemu. Jako przykład rozważmy pro-
blem SHORTEST-PATH znalezienia najkrótszej ścieżki między dwoma da-
nymi wierzchołkami w grafie nieskierowanym G = (V, E), bez wag na krawę­
dziach. Egzemplarzem problemu SHORTEST-PATH jest trójka uporządko­
wana, składająca się z grafu i dwóch jego wierzchołków. Rozwiązanie to ciąg
wierzchołków grafu, być może pusty (co oznacza, że ścieżka nie istnieje). Sam
problem SHORTEST-PATH to relacja wiążąca każdy egzemplarz grafu i parę
wierzchołków z najkrótszą ścieżką w tym grafie, łączącą te dwa wierzchołki.
Ponieważ najkrótsze ścieżki nie muszą być wyznaczone jednoznacznie, dany
egzemplarz problemu może mieć więcej niż jedno rozwiązanie.
Takie sformułowanie problemu abstrakcyjnego jest zbyt ogólne jak na
nasze potrzeby. Dla uproszczenia w teorii NP-zupełności ograniczamy się do
rozważania problemów decyzyjnych: tak.ich, których rozwiązanie stanowi odpo-
wiedź tak/nie. W tym wypadku możemy patrzeć na abstrakcyjny problem de-
cyzyjny jak na funkcję odwzorowującą zbiór egzemplarzy problemu I w zbiór
rozwiązań {O,I}. Na przykład problem decyzyjny PATH, związany z proble-
mem najkrótszej ścieżki, można sformułować tak: ,,Dany jest graf G = ( V, E),
dwa wierzchołki u, vE V i nieujemna liczba całkowita k. Czy istnieje ścieżka
w G łącząca u i v, o długości co najwyżej k?" Jeśli i= (G, u, v, k) jest egzemp-
larzem tego problemu, to PATH(i) = 1 (tak), jeżeli najkrótsza ścieżka od u do
v ma długość co najwyżej k, w przeciwnym zaś wypadku PATH(z) = O (nie).

•l Wyczerpujące omówienie modelu maszyn Turinga można znaleźć u Hopcrofta i Ullmana


[104] albo Lewisa i Papadimitriou [139].

1024
36.1. CZAS WIELOMIANOWY

Wiele problemów abstrakcyjnych to nie problemy decyzyjne, ale raczej


optymalizacyjne, w których pewną wielkość trzeba zminimalizować albo zmak-
symalizować, Żeby zastosować teorię NP-zupełności do problemów optymali-
zacyjnych, musimy przerobić je na problemy decyzyjne. Zazwyczaj taka prze-
róbka polega na narzuceniu ograniczenia na optymalizowaną wielkość. Przera-
biając na przykład problem najkrótszej ścieżki na problem decyzyjny, do da-
nych wejściowych dla problemu dołożyliśmy ograniczenie k.
Chociaż teoria NP-zupełności zmusza nas do przerabiania problemów op-
tymalizacyjnych na decyzyjne, wymaganie to nie ogranicza zakresu jej stoso-
walności. Ogólnie rzecz ujmując, jeśli potrafnny szybko rozwiązywać problem
optymalizacyjny, umiemy także szybko rozwiązać odpowiadający mu problem
decyzyjny. Porównujemy po prostu wartość otrzymaną jak.o rozwiązanie prob-
lemu optymalizacyjnego z ograniczeniem stanowiącym jedną z danych wejścio­
wych dla problemu decyzyjnego. Jeśli zatem problem optymalizacyjny jest łat­
wy, to łatwy jest także związany z nim problem decyzyjny. Formułując tę myśl
w nawiązaniu do NP-zupełności, możemy powiedzieć, że każdy argument za
tym, że dany problem decyzyjny jest trudny, jest także argumentem za tym, że
trudny jest odpowiadający mu problem optymalizacyjny. Chociaż więc ograni-
czona do problemów decyzyjnych, teoria NP-zupełności znajduje znacznie
szersze zastosowania.

Kodowanie
Jeśliprogram komputerowy ma rozwiązywać pewien problem abstrakcyjny,
egzemplarze problemu muszą być reprezentowane w sposób zrozumiały dla
programu. Kodowanie zbioru S abstrakcyjnych obiektów to odwzorowanie
ez S w zbiór ciągów złożonych z zer i jedynek 1l. Wszyscy na przykład znamy
sposób kodowania liczb naturalnych N= {O,1, 2, 3, 4, ... } jak.o ciągów binar-
nych {O, I, 10, li, 100, ...}. W kodowaniu tym e(l7) = 10001. Każdy, kto
zainteresował się komputerową reprezentacją znaków na klawiaturze, spotkał
się z kodami ASCII lub EBCDIC. W kodzie ASCII mamy e(A) = 1000001.
Również złożone obiekty można zakodować jako ciągi
bitów, łącząc reprezen-
tacje ich części składowych. Wielomiany, grafy, funkcje, pary uporządkowane
- wszystko to można zakodować w postaci ciągów binarnych.
Dane wejściowe dla algorytmu komputerowego, który „rozwiązuje" pe-
wien abstrakcyjny problem decyzyjny, stanowi zatem tak naprawdę zakodo-
wana postać egzemplarza problemu. Problem, którego zbiór egzemplarzy jest
zbiorem ciągów binarnych, nazywamy problemem konkretnym. Mówimy, że
algorytm rozwiązuje konkretny problem w czasie O(T(n)), jeśli otrzymawszy

tł Pri.eciwdziedziną
funkcji e nie muszą być ciągi binarne;może to być równie dobrze zbiór
słów nad dowolnym skończonym alfabetem o przynajmniej dwóch symbolach.

1025
ROZDZIAŁ 36, NP-ZUPEŁNQ$Ć

egzemplarz problemu i długości n = )il, potrafi obliczyć rozwiązanie w czasie co


najwyżej O(T(n}}. Konkretny problem jest więc rozwiązywalny w czasie wielomia-
nowym,jeśli istnieje algorytm rozwiązujący go w czasie O(n1}dla pewnej stałej k.
Możemy już teraz zdefiniować formalnie klasę złoźoności P jako zbiór kon-
kretnych problemów decyzyjnych rozwiązywalnych w czasie wielomianowym.
W celu przekształcenia problemów abstrakcyjnych na konkretne używamy
kodowania. Dla danego abstrakcyjnego problemu decyzyjnego Q, odwzoro-
wującego zbiór egzemplarzy I w {O,I}, kodowania e: 1-+ {O,I}• można użyć
do skonstruowania odpowiadającego problemowi Q konkretnego problemu
decyzyjnego, oznaczanego przez e(Q}. Jeśli rozwiązaniem egzemplarza prob-
lemu abstrakcyjnego i El jest Q(i)E{O, 1}, to rozwiązaniem egzemplarza kon-
kretnego problemu e(1)E{O, 1}• jest również Q(i). Należy wziąć pod uwagę
szczegół techniczny, że mogą istnieć ciągi binarne nie reprezentujące żadnego
sensownego egzemplarza problemu abstrakcyjnego. Dla wygody możemy zało­
żyć, że wszystkie takie ciągi są odwzorowywane na O. Problem konkretny ma
zatem takie same rozwiązania jak problem abstrakcyjny dla wszystkich swoich
egzemplarzy, będących kodowaniami egzemplarzy problemu abstrakcyjnego.
Chcielibyśmy rozszerzyć definicję rozwiązywalności w czasie wielomiano-
wym z problemów konkretnych na abstrakcyjne, używając kodowań jako po-
mostu między nimi; defmicja ta powinna być jednak niezależna od ustalonego
sposobu kodowania. Oznacza to, że efektywność rozwiązywania problemu nie
powinna zależeć od tego, jak problem jest zakodowany. Niestety, zależy i to
dość mocno. Przypuśćmy na przykład, że jedyną daną wejściową dla algoryt-
mu jest liczba całkowita k i że czas działania algorytmu to 0(k}. Jeśli liczba
k jest reprezentowana unarnie -jako ciąg k jedynek - to czas działania algoryt-
mu wynosi O(n} dla danych rożmiaru n, a więc jest wielomianowy. Jeśli jednak
użyjemy bardziej naturalnej reprezentacji binarnej liczby k, to rozmiar danych
wejściowych wyniesie n= [lgkl. W tym wypadku czas działania algorytmu
0(k} = 0(2"} jest wykładniczy ze względu na rozmiar danych wejściowych.
Tak więc w zależności od sposobu kodowania algorytm działa w czasie wielo-
mianowym albo większym niż wielomianowy.
Sposób kodowania ma zatem wpływ na to, co rozumiemy pod pojęciem
czasu wielomianowego. Nie możemy właściwie mówić o rozwiązywaniu proble-
mu abstrakcyjnego, nie określiwszy najpierw jego kodowania. W praktyce jed-
nak, jeśli odrzucimy „kosztowne" sposoby kodowania, w rodzaju unamego,
użyte kodowanie nie wpływa na to, czy problem można rozwiązać w czasie
wielomianowym. Na przykład reprezentacja liczb całkowitych w systemie pozy-
cyjnym o podstawie 3 zamiast w binarnym nie ma wpływu na to, czy problem jest
rozwiązywalny w czasie wielomianowym, ponieważ reprezentację liczby w syste-
mie trójkowym można przekształcić do binarnej w czasie wielomianowym.
Powiemy, że funkcja f {O, 1}• -+ {O, I}• jest obliczalna w czasie wielomiano-
wym, jeśli istnieje algorytm wielomianowy A, który dla dowolnego danego na

1026
36.1. CZAS WIELOMIANOWY

wejściu xe {O,I}• oblicza jako wynikf(x). Dla pewnego zbioru I egzemplarzy


problemu mówimy, że dwa kodowania e 1 i e2 są wielomianowo równoważne,
jeśli istnieją dwie obliczalne w czasie wielomianowym funkcje / 12 i/ 21 tak.ie, że
dla każdego ie/mamy f 12 (e 1(z)) = e 2(1) i/ 21 (e 2 (r)) = e 1(1). Oznacza to, że ko-
dowanie e2(i) można obliczyć z kodowania e1(1) za pomocą algorytmu wielo-
mianowego, i odwrotnie. Jeśli dwa kodowania e 1(z) i e 2(1) problemu abstrak-
cyjnego są wielomianowo równoważne, nie ma znaczenia, którego z nich uży­
jemy do sprawdzenia, czy problem jest rozwiązywalny w czasie wielomiano-
wym, czego dowodzi poniższy lemat.

LEMAT 36.1.
Niech Q będzie abstrakcyjnym problemem decyzyjnym na zbiorze egzemplarzy
I i niech e 1 i e 2 będą wielomianowo równoważnymi kodowaniami na!. Wów-
czas e 1(Q)EP wtedy i tylko wtedy, gdy e 2(Q)EP.

DOWÓD
Wystarczy, że udowodnimy tylko jedną z implikacji, ponieważ druga jest syme-
tryczna. Załóżmy zatem, że e 1 (Q) można rozwiązać w czasie O(nt) dla pewnej
stałej k. Dalej, załóżmy, że dla każdego egzemplarza problemu i kodowanie
e 1(1)można obliczyć z kodowania e2(1) w czasie O(nc) dla pewnej stałej c, gdzie
n = ]e2 (z)I.Aby rozwiązać problem e 2 (Q) dla danych e 2 (z), obliczamy najpierw
e1 (i), a następnie wykonujemy algorytm dla e 1(Q) na danych e 1 (z). Ile czasu to
zajmie? Zamiana kodowania zajmuje czas O(nc), a zatem le1(1)!= O(n~, ponie-
waż rozmiar danych wyjściowych komputera sekwencyjnego nie może być
większy niż jego czas działania. Czas rozwiązania problemu dla danych e 1 (i)
wynosi O(le1 (i)lt) = O(nct), jest więc wielomianowy, bo ci k są stałymi.

A zatem to, czy egzemplarze problemu abstrakcyjnego są kodowane binar-
nie czy przy podstawie 3, nie wpływa na jego „złożoność", czyli na to, czy jest
on rozwiązywalny w czasie wielomianowym czy nie. Jeśli natomiast będą one
kodowane unarnie, złożoność problemu może się zmienić. Żeby można było
przechodzić od problemu abstrakcyjnego do konkretnego w sposób niezależny
od kodowania, będziemy zazwyczaj zakładali, że egzemplarze problemu są
zakodowane w jakiejkolwiek zwartej postaci, o ile wyraźnie nie powiemy ina-
czej. Dokładniej, będziemy zakładać, że kodowanie liczby całkowitej jest wielo-
mianowa równoważne jej reprezentacji binarnej i że kodowanie zbioru skoń­
czonego jest wielomianowo równoważne przedstawieniu go jako otoczonej na-
wiasami listy jego elementów rozdzielonych przecinkami. (Jednym z takich
schematów kodowania jest kod ASCII). Dysponując tak.im „standardowym"
kodowaniem, możemy konstruować rozsądne kodowania innych matematycz-
nych obiektów, jak krotki, grafy i formuły. Standardowe kodowanie obiektu

1027
ROZDZIAŁ 36. NP-ZUPEŁNO$C

będziemy oznaczać, ujmując go w nawiasy ostre. Zapis (G) oznacza zatem


standardowe kodowanie grafu G.
O ile implicite korzystamy z kodowania wielomianowa równoważnego
standardowemu, możemy mówić bezpośrednio o problemach abstrakcyjnych,
nie odwołując się do żadnego ustalonego kodowania, skoro wiemy, że wybór
kodowania nie ma wpływu na to, czy problem abstrakcyjny jest rozwiązywalny
w czasie wielomianowym. W związku z tym będziemy z reguły zakładać, że
wszystkie egzemplarze problemów są ciągami binarnymi utworzonymi za po-
mocą standardowego kodowania, chyba że jawnie określimy je inaczej. Nie
będziemy też zazwyczaj rozróżniać problemów abstrakcyjnych i konkretnych.
Czytelnik powinien jednak zwracać uwagę na pojawiające się w praktyce prob-
lemy, w których kodowanie standardowe nie jest oczywiste, a sposób kodowa-
nia nie jest obojętny.

Podejście oparte na teorii języków formalnych


Jedną z zalet skupienia się na problemach decyzyjnych jest łatwość skorzysta-
nia z aparatu teorii języków formalnych. Warto w tym miejscu przypomnieć
garść definicji z tej teorii. Alfabet 1: to skończony zbiór symboli. Język L nad
t: to dowolny zbiór napisów (słów) złożonych z symboli alfabetu t:. Jeśli na
przykład i:- {O, I}, to zbiór L- {IO, Il, 101, Ili, 1011, 1101, 10001, ... } jest
językiem binarnych reprezentacji liczb pierwszych. Słowo puste będziemy ozna-
czać jako s, a język pusty jako 0. Język złożony z wszystkich słów nad alfa-
betem t: oznacza się przez t:".Na przykład,jeśli I= {O,I}, tot:·= {s, O, I, 00,
Ol, 10, 11, OOO,... } jest zbiorem wszystkich ciągów binarnych. Każdy język L
nad t: jest podzbiorem i:·.
Definiuje się wiele rozmaitych operacji na językach. Operacje teoriomno-
gościowe, jak suma i przecięcie, wynikają wprost z definicji dla zbiorów. Dopeł­
nienie języka L definiujemy jako L = i:• - L. Konkatenacja dwóch języków L 1
i L 2 to język
L={X1X2:X1EL1 j X2EL2}

Domknięcie albo inaczej gwiazdka Kleene'a języka L to język


L·={i:}uLuL 2 uL 3 u ...
gdzie L" to język otrzymany przez k-krotną konkatenację L ze sobą.
Z punktu widzenia teorii języków zbiór egzemplarzy dowolnego problemu
decyzyjnego Q to po prostu zbiór t:·, gdzie J; = {O, 1}. Ponieważ problem
Q jest w pełni określony przez te jego egzemplarze, dla których odpowiedzią
jest I (tak), możemy traktować Q jako język L nad E - {O, I}, gdzie

L- {xeE': Q(x)- I}
,~0~2~8---------------------~
36.1. CZAS WIELOMIANOWY

Na przykład problemowi decyzyjnemu PATH odpowiada język

PATH = {(G, u, v, k): G = (V, E) jest grafem nieskierowanym,


u, VE V,
k ~ O jest liczbą całkowitą oraz
istnieje ścieżka od u do v w G
o długości co najwyżej k}.

(fam, gdzie wygodniej, będziemy czasem używać tej samej nazwy PATH za-
równo w odniesieniu do problemu decyzyjnego, jak i do odpowiadającego
mu języka).
Skorzystanie z terminologii teorii języków formalnych pozwala nam wyra-
zić związek między problemami decyzyjnymi a rozwiązującymi je algorytmami
w zwarty sposób. Mówimy, że algorytm A akceptuje słowo xe{O, t}•, jeśli dla
danych wejściowych x algorytm oblicza A(x) = 1. Język akceptowany przez
algorytm A to zbiór L = {xe{O, 1}•: A(x) = l}, czyli zbiór tych słów, które
algorytm akceptuje. Algorytm A odrzuca słowo x, jeśli A(x) = O.
Nawet jeśli język L jest akceptowany przez algorytm A, algorytm nie musi
koniecznie odrzucać danego mu na wejściu słowa x f L. Algorytm może się na
przykład zapętlić. Język L jest rozstrzygalny przez algorytm A, jeśli każdy ciąg
binarny jest albo akceptowany, albo odrzucany przez A. Język L jest akcep-
towany w czasie wielomianowym przez algorytm A, jeśli dla dowolnego słowa
xe L długości n algorytm akceptuje x w czasie O(rł) dla pewnej stałej k.
Język L jest rozstrzygalny w czasie wielomianowym za pomocą algorytmu A,
jeśli dla dowolnego słowa xe{O, 1} długości n algorytm rozstrzyga przynależ­
0

ność x do L w czasie O(nk) dla pewnej stałej k. Zatem, aby akceptować język,
algorytm musi troszczyć się tylko o słowa z L, aby zaś rozstrzygać o języku,
musi akceptować bądź odrzucać każde słowo z {O, 1}'.
Język PATH na przykład można akceptować w czasie wielomianowym.
Jeden z wielomianowych, akceptujących go algorytmów oblicza najkrótszą
ścieżkę od u do v w G za pomocą przeszukiwania wszerz, a następnie porów-
nuje otrzymaną długość ścieżki z k. Jeśli długość nie przekrac-za k, algorytm
wypisuje odpowiedź I i się zatrzymuje. W przeciwnym razie algorytm wchodzi
w nieskończoną pętlę. Algorytm ten nie rozstrzyga o PATH, ponieważ nie
udziela wyraźnej odpowiedzi O w przypadkach, w których długość najkrótszej
ścieżki przekrac-za k. Algorytm rozstrzygający o PATH musi explicite odrzucać
ciągi binarne nie należące do PATH. Dla problemów decyzyjnych w rodzaju
PATH nietrudno taki algorytm znaleźć. Dla innych problemów, jak problem
stopu Turinga, istnieje algorytm akceptujący, ale nie ma rozstrzygającego.
Możemy nieformalnie zdefmiować klasę złożoności jako zbiór języków, do
którego przynależność jest określana pewną miarą złożoności Gak na przy-
kład czas działania) algorytmu rozstrzygającego, czy dane słowo x należy do

1029
ROZDZIAŁ 36. NP-ZUPEŁNQ$C

języka L. Ścisła definicja klasy złożoności jest bardziej techniczna - zaintereso-


wanych czytelników odsyłamy do pracy Hartmanisa i Stearnsa [95].
Korzystając z terminologii teorii języków formalnych, możemy sformuło­
wać alternatywną definicję klasy złożoności P:

P= {Le {O,!}.:istnieje algorytm A


rozstrzygający o L w czasie wielomianowym}

Jak się okazuje, P jest tak.że klasą języków akceptowalnych w czasie wielo-
.
m1anowym.

TwIERDZENIE 36.2.
P = {L: L jest akceptowany przez algorytm wielomianowy}

DOWÓD
Ponieważ klasa języków rozstrzygalnych za pomocą algorytmów wielomiano-
wych jest podzbiorem klasy języków akceptowanych przez algorytmy wielo-
mianowe, musimy tylko pokazać, że jeśli L jest akceptowany przez algorytm
wielomianowy, to jest także rozstrzygalny za pomocą algorytmu wielomiano-
wego. Niech L będzie językiem akceptowanym przez pewien algorytm wielo-
mianowy A. Użyjemy klasycznej metody „symulacji" w celu skonstruowania
innego algorytmu wielomianowego A', który rozstrzyga o L. Ponieważ A ak-
ceptuje L w czasie O(,ł) dla pewnej stałej k, istnieje także stała c taka, że
A akceptuje L w co najwyżej T = cnk krokach. Dla dowolnego wejściowego
słowa x algorytm A' symuluje działanie algorytmu A przez czas T. Po upływie
czasu T algorytm A' sprawdza zachowanie A. Jeśli A zaakceptował x, to A'
akceptuje x, wypisując 1. Jeśli A nie zaakceptował x, to A' odrzuca x, wypisu-
jąc O. Narzut na symulację A przez A' nie zwiększa czasu działania więcej niż
o czynnik wielomianowy, A' jest zatem wielomianowym algorytmem rozstrzy-
gającym o L.


Zauważmy, że dowód twierdzenia 36.2 jest niekonstruktywny. Dla danego
języka LEP być może nie znamy ograniczenia czasu działania algorytmu
A akceptującego L. Wiemy natomiast, że takie ograniczenie istnieje, czyli
istnieje wykorzystujący je algorytm. A', chociaż być może nie potrafuny go
łatwo znaleźć.

ZADANIA
36.1-1. Zdefiniujmy problem optymalizacyjny LONGEST-PATH-LENGTH
jak.o relację wiążącą każdy egzemplarz grafu nieskierowanego i parę jego
wierzchołków z długością najdłuższej ścieżki prostej między tymi dwoma

1030
36.2. WERYFIKACJA W CZASIE WIELOMIANOWYM

wierzchołkami. Zdefiniujmy problem decyzyjny LONGEST-PATH =


= { (G, u, v, k): G = (V, E) jest grafem nieskierowanym, u, ve V, k ~ O
jest liczbą całkowitą oraz istnieje ścieżka prosta od u do v w G o długości
przynajmniej k}. Pokaż, że problem optymalizacyjny LONGEST-PATH-
-LENGTH można rozwiązać w czasie wielomianowym wtedy i tylko wtedy,
gdy LONGEST-PATHeP.
36.1-2. Podaj formalną def10icję problemu znajdowania najdłuższego cyklu
prostego w grafie nieskierowanym. Podaj związany z nim problem decy-
zyjny. Podaj język odpowiadający problemowi decyzyjnemu.
36.1-3. Opisz formalnie kodowanie grafów skierowanych jak.o ciągów binar-
nych za pomocą reprezentacji w postaci macierzy sąsiedztwa. Zrób to sa-
mo przy użyciu reprezentacji w postaci list sąsiedztwa. Uzasadnij, że obie
reprezentacje są wielomianowo równoważne.
36.1-4. Czy algorytm programowania dynamicznego dla zero-jedynkowego
problemu plecak.owego, którego skonstruowanie jest celem zad. 17.2-2,
jest algorytmem wielomianowym? Odpowiedź uzasadnij.
36.1-5. Przypuśćmy, że pewien algorytm akceptuje każde słowo xeL w czasie
wielomianowym, ale działa w czasie większym niż wielomianowy, jeśli
xf/:L. Uzasadnij, że L jest rozstrzygalny w czasie wielomianowym.
36.1-6. Pokaż, że algorytm wykonujący co najwyżej stałą liczbę wywołań pod-
programów o wielomianowym czasie działania działa w czasie wielomia-
nowym, ale wielomianowa liczba wywołań podprogramów o złożoności
wielomianowej może prowadzić do algorytmu wykładniczego.
36.1-7. Pokaż, że klasa P, traktowana jak.o zbiór języków, jest zamknięta ze
względu na operacje sumy, przecięcia, konkatenacji, dopełnienia i do-
mknięcia, tzn. jeśli L 1 , L 2 EP, to L 1 u L 2 EP itd.

36.2. Weryfikacjaw czasiewielomianowym


Przyjrzymy się
teraz algorytmom „weryfikującym" przynależność do języków.
Przypuśćmy na przykład, że dla danego egzemplarza (G, u, v, k) problemu
decyzyjnego PATH mamy także daną ścieżkę p od u do v. Możemy łatwo
sprawdzić, czy długość pnie przekracza k, a skoro tak, to możemy traktować
p jak.o „świadectwo", że dany egzemplarz problemu rzeczywiście należy do
PATH. W przypadku problemu decyzyjnego PATH takie świadectwo wiele nie
wnosi. W końcu PATH należy do P - tak naprawdę problem PATH można
rozwiązać w czasie liniowym - a więc sprawdzenie przynależności za pomocą
posiadanego świadectwa zajmuje tyle samo czasu co rozwiązanie problemu od
początku. Zajmiemy się teraz problemem, dla którego nie znaleziono dotych-
czas żadnego rozstrzygającego go algorytmu wielomianowego, ale jeśli dane
jest świadectwo, weryfikacja jest łatwa.

1031
ROZDZIAŁ 36. NP-ZUPEŁNOSC

Cykle Hamiltona

Problem znalezienia cyklu Hamiltona w grafie nieskierowanym badano od


przeszło stu lat. Formalnie rzecz biorąc, cykl Hamiltona w grafie nieskierowa-
nym G = (V, E) to cykl prosty zawierający wszystkie wierzchołki zbioru V.
Graf, który ma cykl Hamiltona, nazywamy bamiltonowskim; w przeciwnym
razie jest niebamiltonowski. Bondy i Murty [31] przytaczają tekst autorstwa
W .R. Hamiltona opisujący matematyczną grę toczącą się na dwunastościanie
(rys. 36.la), na którym jeden gracz oznacza pięć kolejnych wierzchołków,
a drugi ma za zadanie uzupełnić tę ścieżkę do cyklu zawierającego wszystkie
wierzchołki. Dwunastościan jest hamiltonowski, a na rys. 36.la widać jeden
z jego cykli Hamiltona. Nie wszystkie jednak grafy są hamiltonowskie. Na
przykład na rys. 36. l b jest przedstawiony graf dwudzielny o nieparzystej licz-
bie wierzchołków. (Celem zad. 36.2-2 jest wykazanie, że wszystkie takie grafy
są niehamiltonowskie).
Możemy zdefiniować problem cyklu Hamiltona „Czy graf G ma cykl Ha-
miltona?" jako język formalny:
HAM-CYCLE - {(G): G jest grafem hamiltonowskim}
Jak mógłby działać algorytm rozstrzygania o przynależności do języka HAM-
-CYCLE? Dla danego egzemplarza problemu (G) jeden z możliwych algoryt-

(•) (b)

Rys. 36.1. (a) Graf reprezentujący wierzchołki, krawędrie i ściany dwunastościanu


z zaznaczonymi
szarym kolorem .krawędziami cyklu Hamiltona. (b) Graf dwudzielny o nieparzysttj liczbie wierz-
chołków. Żaden taki graf nie jest bamiltonowski

1032
36.2. WERYFIKACJA W CZASIE WIELOMIANOWYM

mów przegląda wszystkie permutacje wierzchołków G i sprawdza każdą z nich,


czy nie jest ona cyklem Hamiltona. Jaki jest czas działania tego algorytmu?
Jeśli użyjemy „rozsądnego" kodowania grafu biorąc jego macierz sąsiedztwa,
liczba m wierzchołków grafu jest O(.jtl,), gdzie n= l(G)I jest długością kodo-
wania G. Jest m! możliwych permutacji wierzchołków, a zatem czas działania
wynosi O(m!) = O(.jtl,!) = 0(2Jn), co nie daje się zapisać jako O(rł) dla żadnej
stałej k. Powyższy „naiwny" algorytm nie działa zatem w czasie wielomiano-
wym. W istocie problem cyklu Hamiltona jest NP-zupełny, co udowodnimy
w podrozdz. 36.5.

Algorytmy weryfikacji

Rozważmy nieco prostszy problem. Przypuśćmy, że ktoś mówi nam, iż dany


graf G jest hamiltonowski, a następnie jako dowód podaje ciąg wierzchołków
w kolejności ich występowania na cyklu Hamiltona. Nietrudno byłoby zweryfi-
kować taki dowód: wystarczy przekonać się, że podany cykl jest cyklem Hami-
ltona, sprawdzając, czy stanowi on permutację wierzchołków V i czy każda
z kolejnych krawędzi cyklu rzeczywiście jest w grafie. Taki algorytm weryfika-
cji na pewno da się zaimplementować tak, by działał w czasie O(n2 ), gdzie
n jest długością kodowania G. Świadectwo tego, że w grafie istnieje cykl Hami-
ltona, można zatem zweryfikować w czasie wielomianowym.
Algorytm weryfikacji definiujemy jako algorytm A o dwóch parametrach,
z których jeden jest zwykłym wejściowym ciągiem x, a drugi to ciąg binarny y,
zwany świadectwem. Dwuparametrowy algorytm A weryfikuje ciąg wejściowy
x, jeśli istnieje świadectwo y takie, że A(x, y) = 1. Język weryfikowany przez
algorytm A to

L = {xc {O,I}': istnieje yc {O,!}' takie, że A(x, y) = I)


Intuicyjnie, algorytm A. weryfikuje język L, jeśli dla każdego słowa x e L
istnieje świadectwo y, którego A może użyć w celu wykazania, że xeL. Co
więcej, dla żadnego słowa xfL nie może istnieć świadectwo tego, że xeL. Na
przykład w problemie cyklu Hamiltona świadectwem jest lista wierz-
chołków na cyk.lu Hamiltona. Jeśli graf jest hamiltonowski, sam cykl Hamil-
tona wnosi wystarczającą do sprawdzenia tego faktu informację. Jeśli nato-
miast graf nie jest hamiltonowski, nie istnieje lista wierzchołków, która mogła­
by oszukać algorytm weryfikacji, przekonując go o istnieniu cyklu łlamiltona
w grafie, ponieważ algorytm weryfikacji starannie sprawdza podsunięty
mu „cy kl" .

1033
ROZDZIAŁ 36. NP-ZUPEŁNOŚĆ

Klasazłożoności NP
Klasa złożoności
NP to klasa języków, które można weryfikować za pomocą
algorytmu wielomianowego 1l. Dokładniej, język L należy do klasy NP wtedy
i tylko wtedy, gdy istnieją dwuparametrowy wielomianowy algorytm A i stała
c takie, że
L = {xE {O, l} ·: istnieje takie świadectwo y, gdzie IYI= O(]xl'),
że A(x, y) ~ I}

Mówimy, że algorytm A weryfikuje język L w czasie wielomianowym,


Z naszych wcześniejszych rozważań nad problemem cyklu Hamiltona wy-
nika, że HAM-CYCLE E NP. (Zawsze dobrze jest wiedzieć, że ważny zbiór,
którym się zajmujemy, jest niepusty). Co więcej, jeśli LEP, to LENP, ponie-
waż jeśli istnieje wielomianowy algorytm rozstrzygający o L, algorytm ten
można łatwo przerobić na dwuparametrowy algorytm weryftk.acji, który po
prostu ignoruje dostarczane mu świadectwo i akceptuje wyłącznie te słowa
wejściowe, o których stwierdzi, że należą do L. Zatem P c NP.
Nie wiadomo, czy P = NP, ale większość badaczy uważa, że Pi NP nie są
tą samą klasą. Intuicyjnie, klasa P składa się z tych problemów, które można
szybko rozwiązywać. Klasa NP składa się z problemów, których rozwiązania
można szybko weryftk.ować. Doświadczenie uczy, że często trudniej jest roz-
wiązać problem od początku, niż sprawdzić jasno przedstawione rozwiązanie,
zwłaszcza przy narzuconych ograniczeniach czasowych. Większość informaty-
ków sądzi, że analogia ta rozciąga się na klasy P i NP, a więc że NP zawiera
języki nie należące do P.
Można podać również bardziej przekonujący argument za tym, że P # NP
-istnienie języków „NP-zupełnych". Klasą tą zajmiemy się w podrozdz. 36.3.
Wiele innych podstawowych pytań, oprócz tego czy P c:ftNP, pozostaje bez
odpowiedzi. Pomimo wysiłku wielu badaczy dotychczas nie wiadomo nawet,
czy klasa NP jest zamknięta ze względu na operację dopełnienia, tzn. cz.y z te-
go, że Le NP wynika, że LENP. Możemy zdefiniować klasę złożoności co-NP
jako zbiór języków L tak.ich, że LE NP. Pytanie: czy klasa NP jest zamknięta
ze względu na branie dopełnienia, można przeformułować na: czy NP = co-
-NP? Z tego, że klasa P jest zamknięta ze względu na operację dopełnienia
(zad. 36.1 ~ 7), wynika, że P c NP n co~NP. Znowu jednak nie wiadomo, czy
P = NP n co-NP, czy też istnieje jakiś język należący do NP nco-NP - P. Na
rysunku 36.2 są przedstawione cztery możliwe scenariusze.
-------·
>
1
Nazwa „NP" pochodzi. od słów „niedeterministycznie w czasie wielomianowym"
(ang. nondeterministic polynomial time). Klasa NP była pierwotnie ba.dana w kontekście niedeter-
minizmu, ale w niniejszej ksiąi.ce korzystamy z nieco prostszego, choć równoważnego pojęcia
weryfikacji. Dobre przedstawienie zagadnienia NP-zupełności na podstawie niedeterministycznych
modeli obliczeń podają Hopcroft i Ullman [104].

1034
p

,o '\P ..·· ',f'


,·I'" r-;p 1"1 c,)-Nl'.

Rys. 36.2. Cztery możliwości związków między klasami złożoności. Na każd)m diagramie ot.acz.anie
jednego obszaru przez drugi oznacza relację ścisłego zawierania zbiorów. (11.)P =NP= co-NP.
Większość badaczy uważa tę możliwość za najmniej prawdopodobną. (b) Jeśli NP jest zamknięta
ze względu na dopełnienia, to NP= CO·NP, ale nie musi przy l}m zachodzić P = NP. (c)
P = NP n co-NP, ale NP nie jest zamknięta ze względu na dopełnienia. (d) NP ,f. co-NP
i P #- NP n co-NP. Większość badaczy uwaza tę możliwość za najbardziej prawdopodobną

Nasze rozumienie dokładnej zależności między P a NP jest więc przygnę­


biająco niekompletne. Mimo to, poznając teorię NP-zupełności, przekonamy
się, iż nasze kłopoty związane z dowodzeniem, że pewne problemy są trudno
rozwiązywalne, z praktycznego punktu widzenia nie są aż tak wielkie, jak moż­
na by przypuszczać.

ZADANIA

36.2-1. Rozważmy język GRAPH-ISOMORP!ł!SM ~ {(G 1, G 2 ): G1 i G, są


grafami izomorficznymi}. Udowodnij, że GRAPH-ISOMORPHISM E
ENP, opisując wielomianowy algorytm weryfikacji tego języka.
36.2-2. Udowodnij, ie jeśli G jest dwudzielnym grafem nieskierowanym o nie-
parzystej liczbie wierzchołków, to Gnie jest bamiltonowski.
36.2-3. Wykaż, że jeśli HAM-CYCLE EP, to problem wypisania po kolei wie-
rzchołków cyklu Hamiltona jest rozwiązywalny w czasie wielomianowym.
36.2-4. Udowodnij, że klasa języków NP jest zamknięta ze względu na opera-
cje sumy, przecięcia, konkatenacji i domknięcia. Omów zagadnienie za-
mknięcia klasy NP -zewzględu na branie dopełnienia.
36.2-5. Wykaż, że każdy język z klasy NP jest rozstrzygalny za pomocą al-
gorytmu działającego w czasie 2°(n'l dla pewnej stałej k.
36.2-6. Ścieżka Hamiltona w grafie to ścieżka prosta, odwiedzająca każdy wie-
rzchołek dokładnie raz. Wykaż, że język HAM-PATH = {(G, u, v): ist-
nieje ścieżka Hamiltona od u do v w grafie G} należy do NP.
36.2-7. Wykaż, U ograniczając się do acyklicznych grafów skierowanych, pro-
blem ścieżki Hamiltona można rozwiązać w czasie wielomianowym. Podaj
efektywny algorytm dla tego problemu.
ROZDZIAŁ 36. NP"ZUPEŁNOSC

36.2-8. Niech q>będżie formułą logiczną zbudowaną ze zmiennych logicznych


x 1 , Xz, ... , xt, operatorów negacji ', koniunkcji A i alternatywy v oraz
nawiasów. Formuła q>jest tautologią, jeśli przy każdym przypisaniu warto-
ści 1 i O występującym w niej zmiennym ma ona wartość 1. Zdefiniujmy
TAUTOLOGY jako język formuł logicznych, które są tautologiami. Wy-
każ, że TAUTOLOGYeco-NP.
36.2-9. Udowodnij, że P c co-NP.
36.2-10. Udowodnij, że jeśli NP of. co-NP, to P of. NP.
36.2-11. Niech G będzie spójnym grafem nieskierowanym o przynajmniej
3 wierzchołkach i niech G3 będzie grafem otrzymanym przez połączenie
wszystkich par wierzchołków połączonych w G ścieżką długości co naj-
wyżej 3. Udowodnij, że G3 jest hamiltonowski. (Wskazówka: Skonstruuj
drzewo rozpinające dla G i zastosuj dowód indukcyjny).

36.3. NP-zupełność i redukowalność


Zapewne jednym z najistotniejszych powodów, dla których informatycy są
przekonani, że P =f. NP, jest istnienie klasy problemów „NP-zupełnych". Za-
dziwiającą własnością owej klasy jest to, że jeśli jakikolwiek problem NP-zupeł­
ny można rozwiązać w czasie wielomianowym, to wszystkie problemy klasy
NP mają wielomianowe rozwiązanie, to znaczy P =NP.Pomimo wieloletnich
badań nie znaleziono jednak dotychczas algorytmu wielomianowego dla żad­
nego problemu NP-zupełnego.
Jednym z problemów NP-zupełnych jest język HAM-CYCLE. Gdybyśmy
potrafili rozstrzygać o HAM-CYCLE w czasie wielomianowym, umielibyśmy
także rozwiązać każdy problem z NP w czasie wielomianowym. Gdyby nato-
miast zbiór NP - P okazał się niepusty, wiedzielibyśmy, że HAM-CYCLE e
eNP - P.
Języki NP-zupełne są w pewnym sensie „najtrudniejszymi" językami
w NP. W podrozdziale tym pokażemy, jak porównywać „trudność" języków
za pomocą precyzyjnego narzędzia zwanego „redukowalnością w czasie wielo-
mianowym". Najpierw zdefiniujemy formalnie języki NP-zupełne, a następnie
naszkicujemy dowód NP-zupełności pewnego języka, zwanego CIRCUIT-
-SAT. W podrozdziale 36.5 wykorzystamy pojęcie redukowalności do udowo-
dnienia, że wiele innych problemów jest NP-zupełnych.

Redukowalność

Intuicyjnie, problem Q można zredukować do innego problemu Q', jeśli każdy


egzemplarz Q można „łatwo przeformułować" na egzemplarz Q', z którego
rozwiązania można odczytać szukane rozwiązanie egzemplarza problemu Q.

1036
36.3. NP-ZUPEŁNO$ć I REDUKOWALNO$C

Na przykład problem rozwiązywania równań liniowych ze 2lllienną x redukuje


się do problemu rozwiązywania równań kwadratowych. Dany egzemplarz pro-
blemu ax + b = O przekształcamy w Ox2 + ax + b = O, którego rozwiązanie
daje nam rozwiązanie ax + b = O. Jeśli zatem problem Q redukuje się do in-
nego problemu Q', to Q jest, w pewnym sensie, ,,nie trudniejszy do rozwiąza­
nia" niż Q'.
Powracając do tetminologii teorii języków formalnych, powiemy, że ję­
zyk L 1 jest redukowalnyw czasie wielomianowymdo języka L 2 , co zapisujemy
jako L 1 ~ p L 2 , jeśli istnieje obliczalna w czasie wielomianowym funkcja
f: {O,I}' -{O,!}' taka, że dla każdego xe{O, I}'

xEL 1 wtedy i tylko wtedy, gdy /(x)EL 2 (36. I)

Funkcję/nazywamy funkcją redukcji,a obliczający ją wielomianowy algorytm


F - algorytmemredukcji.
Rysunek 36.3 ilustruje ideę redukcji w czasie wielomianowym języka L 1 do
innego języka L 2 • Obydwa języki są podzbiorami {O, t}·. Funkcja redukcji
J stanowi odwzorowanie możliwe do obliczenia w czasie wielomianowym i ta-
kie, że jeśli xEL 1 , to f(x)EL 2 . Co więcej, jeśli x(JL 1 , to J(x)f/L 2 • Funkcja
redukcji przekształca zatem dowolny egremplarz x problemu decyzyjnego re-
prezentowanego przez język L 1 na egzemplarz f(x) problemu reprezentowa-
nego przez L 2 . Stwierdzenie, czy f(x)EL 2 , rozstrzyga także, czy xEL 1 .
Redukcje w czasie wielomianowym stanowią silne narzędzie służące do
dowodzenia, że ro2lllaite języki należą do klasy P.

LEMAT 36.3.
Jeśli L 1 , L 2 c {O, t}• są językami takimi, że L 1 ~pL 2, to z tego, że L 2 EP,
wynika, że L 1 EP.

Rys. 36.3. Uustracja redukcji w czasie wieJom.ianowymjęzyka L 1 do języka L 2 za pomocą funkcji


redukcji/ Dla dowolnego słowa xe{O, l}" pytanie, czy xeL 1, ma taką samą odpowiedź jak
pytanie, czy /(x)eL 2

1037
ROZDZIAŁ 36. NP-ZUPEŁNOŚĆ

DOWÓD
Niech A 2 będzie algorytmem wielomianowym rozstrzygającym o L 2 , a F -wie-
lomianowym algorytmem redukcji, obliczającym funkcję redukcji/ Skonstru-
ujemy wielomianowy algorytm A 1 , rozstrzygający o L 1 .
Rysunek 36.4 ilustruje tę konstrukcję. Dla danego na wejściu słowa
xE {O, 1}• algorytm A 1 korzysta z F, żeby przekształcić x w J (x), a następnie
korzysta z A 2 , żeby sprawdzić, czy /(x)EL 2 • Odpowiedzią udzielaną przez A 1
jest wartość obliczona przez A 2 •

//;,) e L 1 L l .,.
X /(x) X E
. F A,

A,
Rys. 36.4. Dowód lematu 36.3. Algorytm F jesl algorytmem redukcji, obliczającym funkcję redukcji
f z 1 1 do L 2 w czasie wielomianowym, a A 1 jest wielomianowym algorytmem rozslrzygającym o Ll.
Algorytm A I rozstrzyga, czy x E L 1 , stosując F do przeksztak:enia dowolnego wejściowego słowa x na
f(x), a polem za pomocą Al rozstrzygając, C!.lY f(x)EL 2

Poprawność algorytmu A 1 wynika z warunku (36.1). Algorytm działa


w czasie wielomianowym, ponieważ zarówno F, jak i A 2 działają w czasie
wielomianowym (patrz zad. 36.1-6).

NP-zupełność

Redukcje w czasie wielomianowym dają formalną metodę dowodzenia, że je-


den problem jest przynajmniej tak samo trudny jak inny, z dokładnością do
czynnika wielomianowego. Znaczy to, że jeśli L 1 ~pL 2 , to L 1 jest nie więcej
niż o wielomianowy czynnik trudniejszy od L 2 , co tłumaczy użycie w oznacze·
niu symbolu „mniejsze bądź równe''. Możemy teraz z.definiować zbiór języków
NP-zupełnych, czyli najtrudniejszych problemów w klasie NP.
Język L c {O,!}' jest NP-zupełny, jeśli

(1) LENP oraz


(2) L' ~rLdla każdego L'ENP.

Jeśli język L spełnia własność


(2), ale niekoniecznie własność (1), mówimy,
że L jest NP-trudny. Zdefmiujmy także NPC jako klasę języków NP-zu-
pełnych.
Jak wynika z poniższego twierdzenia, pojęcie NP-zupełności jest zasad-
nicze dla rozstrzygnięcia, czy P jest równe NP.

1038
36.3. NP·ZUPEŁNOŚĆ I AEDUKOWALNOŚĆ

TwIERDZENIE 36.4.
Jeślijakikolwiek problem NP-zupełny jest rozwiązywalny w czasie wielomia-
nowym, to P = NP. Jeśli jakikolwiek problem w NP nie jest rozwiązywalny
w czasie wielomianowym, to żaden problem NP-zupełny nie jest rozwiązywal­
ny w czasie wielomianowym.

DOWÓD
Przypuśćmy, że LEP, a także LENPC. Dla każdego L' ENP zachodzi L' ~PL
na mocy własności (2) z definicji NP-zupełności. Z lematu 36.3 wynika zatem,
że L' EP, co dowodzi pierwszej części twierdzenia.
Dla dowodu drugiej części załóżmy, że istnieje LENP taki, że Lf: P. Niech
L' E NPC będzie dowolnym językiem NP-zupełnym. W celu doprowadzenia do
sprzeczności przypuśćmy, że L'eP. Wówczas jednak, skoro L l!{.pL', to na
mocy lematu 36.3 zachodzi LEP.


To właśnie jest powód, dla którego próby odpowiedzi na pytanie, czy
P ef:.NP, koncentrują się wokół problemów NP-zupełnych. Większość infor-
matyków sądzi, że P '# NP, czego konsekwencją jest układ zależności między
P, NP i NPC pokazany na rys. 36.5. Być może któregoś dnia ktoś znajdzie
algorytm wielomianowy dla jakiegoś problemu NP-zupełnego, dowodząc
w ten sposób, że P = NP. Ponieważ jednak dotychczas nie jest znany algorytm
wielomianowy dla żadnego problemu NP-zupełnego, więc dowód, że dany pro-
blem jest NP-zupełny, jest silnym argumentem za tezą, że problem ten jest
trudno rozwiązywalny.

Rys. 36.5. Oto jak większość informatyków wyobraża sobie układ zależności między P, NP i NPC.
Zarówno P, jak i NPC są całkowicie zawarte w NP, a Pr, NPC =0

Spełnialność układów logicznych


Zdefiniowaliśmy pojęcie problemu NP-zupełnego, ale dotychczas nie udowodni-
liśmy, że jakikolwiek problem jest NP-zupełny. Kiedy udowodnimy, że przynaj-
mniej jeden problem jest NP-zupełny, będziemy mogli używać reduk.owalności

1039
ROZDZIAŁ 36. NP·ZUPEŁNOSC

w czasie wielomianowym jak.o narzędzia do dowodzenia NP-zupełności innych


problemów. Skoncentrujemy się więc teraz na wykazaniu, że istnieje problem
NP-zupełny: problem spełnialności układów logicznych.
Niestety, szczegóły techniczne formalnego dowodu, że problem spełnial­
ności układów logicznych jest NP-zupełny, wykraczają poza ramy tej książ­
ki. Przedstawimy zatem jedynie nieformalny dowód oparty na podstawo-
wych własnościach układów logicznych, o których mówiliśmy na początku
rozdz. 29.
Na rysunku 36.6 widać dwa układy logiczne; obydwa o trzech wejściach
i jednym wyjściu. Wartościowanie dla układu logicznego to zbiór wejściowych
wartości logicznych. Mówimy, że układ logiczny o jednym wyjściu jest spełnial­
ny, jeśli ma wartościowanie spełniające: wartościowanie, które powoduje, że na
wyjściu układu jest 1. Na przykład układ na rys. 36.6a ma spełniające go
wartościowanie (x 1 = 1, x 2 = 1, x 3 = O), jest więc spełnialny. Żaden sposób
przypisania wartości do wejścia x 1 , x 2 i x 3 nie powoduje pojawienia się I na

,, I I
" ., .,,,.
}''' .
I I ,f ·'Sc•'
'2 I
o
I
o I
I
,, o
l•J

,,------.---


;.·,,,J;'
.------c '

(b)

Rys. 36.6. Dwa egzemplarze problemu spełnialności układów logicmych. (a) Przypisanie wartości
(x 1 = I, x 1 = l, x 3 = O) wejściom tego układu powOOuje, że wartością na wyjściu układu jest I.
Układ ten jest zatem spełniałny. (b) Żadne wartościowanie wejść tego układu nie powoduje poja-
wienia się na wyjściu obwodu wartości 1. Układ nie jest zatem spelniałny

1040
36.3. NP-ZUPEŁNOŚĆ I REDUKOWALNOSC

wyjściu układu z rys. 36.6b; wartością wyjściową jest zawsze O, a więc układ nie
jest spełni al ny.
Problem spełoialności układów logicznych to „Czy dany układ logicmy,
zbudowany z bramek AND, OR i NOT ,jest spełnialny?" żeby móc postawić to
pytanie w sposób formalny, musimy ustalić standardowe kodowanie układów.
Można skonstruować kodowanie podobne do stosowanego w przypadku gra-
fów, które przekształca dowolny układ Cna ciąg binarny ( C) długości niewiele
większej niż ro:zmiar samego układu. Możemy zatem zdefmiować język formalny

CIRCUIT-SAT- {(C): C jest spełnialnym układem logicznym}


Problem spełnialności układów logicznych jest ważnym zagadnieniem
w dziedzinie wspomaganej komputerowo optymalizacji sprzętowej. Jeśli war-
tością wyjściową układu jest zawsze O, można go zastąpić prostszym układem,
nie zawierającym żadnych bramek logicmych i przekazującym na swoje wyj-
ście stalą wartość O. Wielomianowy algorytm dla tego problemu miałby spore
praktyczne zastosowanie.
Mając dany układ C, moglibyśmy próbować stwierdzić, czy jest on speł­
nialny, sprawdzając po prostu wszystkie możliwe wartościowania jego wejść.
Niestety, jeśli układ ma k wejść, to istnieje 2" możliwych wartościowań. Jeśli
rozmiar C jest wielomianem ze względu na k, sprawdzanie wszystkich wartoś­
ciowań daje większy niż wielomianowy czas działania algorytmu. W istocie
rzeczy, jak.już wspominaliśmy, mamy silny argument za tym, że w ogóle nie ma
wielomianowego algorytmu rozwiązującego problem spełnialności układów lo-
gicznych, ponieważ problem ten jest NP-zupełny. Dowód tego faktu rozbijemy
na dwie części, odpowiadające dwóm częściom definicji NP-zupełności.

LEMAT36.5.
Problem spełnialności układów logicznych należy do klasy NP.

DOWÓD
Skonstruujemy dwuparametrowy, wielomianowy algorytm A, weryfikujący ję­
zyk CIRCUIT-SAT. Jednym z parametrów wejściowych dla A jest układ lo-
gicmy C (a raczej jego standardowe kodowanie). Drugim parametrem jest
świadectwo odpowiadające wartościowaniu wejść układu C.
Algorytm A jest skonstruowany następująco. Dla każdej bramki logicmej
należącej do układu sprawdza on, czy wartość wyjścia z bramki podana
w świadectwie jest poprawnie obliczona jako funkcja wartości z wejść bramki.
Następnie, jeśli wartością wyjściową całego układu jest I, algorytm odpowiada
I, ponieważ wartości przypisane wejściom układu C tworzą wartościowanie
spełniające. W przeciwnym razie odpowiedzią algorytmu jest O.
Jeśli układ C sprawdzany za pomocą algorytmu A jest spełnialny, to ist-
nieje świadectwo o długości wielomianowej względem ro:zmiaru C, dla którego

1041
ROZDZIAŁ 36. NP-ZUPEŁNOŚC

A zwróci wartość l. Jeśli układ nie jest spełnialny, żadne świadectwo nie prze-
kona A, że jest inaczej. Algorytm A działa w czasie wielomianowym: przy
dobrej implementacji - w liniowym. Język CIRCUIT-SAT można zatem wery-
fikować w czasie wielomianowym, czyli QRCUIT-SAT E NP.


Druga część dowodu NP-zupełności CIRCUIT-SAT to wykazanie, że
język ten jest NP-trudny. Oznacza to, iż musimy wykazać, że każdy język
w klasie NP jest redukowalny w czasie wielomianowym do CIRCUIT-SAT.
Ścisły dowód tego faktu pełen jest technicznych zawiłości, poprzestaniemy
więc na jego szkicu, opierając się na pewnej znajomości zasad funkcjonowania
komputerów,
Program jest przechowywany w pamięci komputera jako ciąg instrukcji.
1"ypowa instrukcja składa się z kodu operacji, którą należy wykonać, adresów
argumentów oraz adresu, pod którym należy umieścić wynik. Specjalna ko-
mórka pamięci, zwana licznikiem rozkazów, przechowuje numer instrukcji,
która ma być wykonana jako następna. Licznik ten jest automatycznie zwięk­
szany po pobraniu kolejnej instrukcji, wskutek czego komputer wykonuje in-
strukcje sekwencyjnie. Wykonanie instrukcji może jednak powodować zapisa-
nie jakiejś wartości w liczniku rozkazów, co prowadzi do zaburzenia zwykłej
sekwencyjnej kolejności operacji, umożliwiając tworzenie pętli i rozgałęzień
w programie.
W każdej chwili działania programu cały stan obliczeń jest reprezentowa-
ny w pamięci komputera. (Przyjmujemy, że w pamięci jest przechowywany sam
program, licznik rozkazów, obszar roboczy programu i wszelkie .zmienne sys-
temowe zawierające infonnacje o stanie komputera). Każdy konkretny układ
zawartości pamięci komputera nazywamy konfiguracją. Wykonanie instrukcji
można traktować jako przekształcenie jednej konfiguracji w drugą. Co istotne,
maszynę dokonującą tego przekształcenia można zaimplementować jako układ
logiczny, który w dowodzie poniższego lematu oznaczamy symbolem M.

LEMAT36.6.
Problem spelnialności układów logicznych jest NP-trudny.

DOWÓD
Niech L będzie dowolnym językiem należącym do klasy NP. Opiszemy wielo-
mianowy algorytm obliczania funkcji redukcji!, która każdemu ciągowi binar-
nemu x przyporządkowuje układ C = f(x) taki, że xEL wtedy i tylko wtedy,
gdy CeCIRCUIT-SAT.
Ponieważ LE NP, musi istnieć algorytm A weryfikujący L w czasie wielo-
mianowym. Konstruowany przez nas algorytm F będzie korzystał z dwupara-
metrowego algorytmu A do obliczania funkcji redukcji/

1042
36.3. NP-ZUPEŁNOSC I REDUK0WALN0$C

Oznacvny przez T{n) czas działania algorytmu A dla wejściowego słowa


długości n w najgorszym przypadku i niech k ;,::1 będzie taką stałą, że zarówno
T(n), jak i długość świadectwa wynosi O(n"'). (Czas działania algorytmu A jest
wprawdzie wielomianem ze względu na łączny rozmiar danych wejściowych,
na co składa się nie tylko słowo wejściowe, ale i świadectwo, ponieważ jednak
rozmiar świadectwa jest wielomianowy ze względu na długość n słowa wej-
ściowego, czas ten jest wielomianowy względem n).
Podstawową ideą dowodu jest reprezentowanie obliczeń wykonywanych
przez A jak.o ciągu konfiguracji. Jak widać na rys. 36.7, każdą konfigurację
można rozbić na kilka części: program algorytmu A, licznik rozkaz.ów i dodatko-
wą informację o stanie maszyny, słowo wejściowe x, świadectwo y oraz obszar
roboczy. Poczynając od startowej konfiguracji c0 , każda konfiguracja c1 jest
przekształcana w kolejną konfigurację c;+ 1 za pomocą układu M implementują­
cego logiczną strukturę komputera. Wyjście algorytmu A-wartość Olub I -jest
zapisywane w pewnym ustalonym miejscu w obszarze roboczym, kiedy A kończy
działanie, a jeśli Ważymy, że następnie A się zatrzymuje, wartość ta nie ulega już
później zmianie. Jeśli zatem algorytm działa w co najwyżej T{n) krokach, obli-
czoną przez niego wartość zawiera jeden z bitów w konfiguracji cT(,r)·
Algorytm redukcji F konstruuje jeden układ obliczający wszystkie kon-
figuracje wytworzone z danej konfiguracji startowej. Idea konstrukcji polega
na sklejeniu ze sobą T{n) kopii układu M. Wyjście i-tego układu, tworzącego
konfigurację c1, jest bezpośrednio wykorzystane jak.o wejście dla (i+ 1)-go
układu. Tak więc, konfiguracje, zamiast wędrować do rejestru stanu, pozostają
po prostu jako wartości zapisane na przewodach łączących kopie układu M.
Przypomnijmy, jak.ie zadanie ma wielomianowy algorytm redukcji F. Dla
danego wejściowego słowa x musi on znaleźć układ C = f(x), który jest speł­
nialny wtedy i tylko wtedy, gdy istnieje świadectwo y tak.ie, że A(x, y) = 1. Po
otrzymaniu słowa x algorytm F oblicza najpierw n = lxl i konstruuje układ C'
składający się z T(n) kopii układu M. Wejściem dla układu C' jest startowa
konfiguracja obliczenia A(x, y), a wyjściem jest konfiguracja cT(,r)·
Układ C = f(x) obliczany przez algorytm F otrzymuje się, modyfikując
nieco C'. Po pierwsz.e, na wejścia układu C' odpowiadające programowi al-
gorytmu A, początkowej wartości licznika rozkazów, słowu wejściowemu
x oraz początkowemu stanowi pamięci są od razu wpisywane te znane za-
wczasu wartości. Pozostają zatem jedynie wejścia układu odpowiadające świa·
dectwu y. Po drugie, ignorowane są wszystkie wyjścia z układu, z wyjątkiem
jednego bitu konfiguracji cT(,r) odpowiadającego wyjściowej wartości algoryt-
mu A. Skonstruowany w ten sposób układ C oblicza C(y) = A(x, y) dla dowol-
nego wejściowego ciągu y długości O(n"'). Algorytm redukcji F dla danego mu
słowa wejściowego x oblicza tak.i właśnie układ Ci zwraca go jako swój wynik.
Do udowodnienia pozostają dwie własności algorytmu F. Po pierwsze,
musimy wykazać, że F poprawnie oblicza funkcję redukcji f, tzn. że układ

1043
ROZDZIAŁ 36. NP-ZUPEŁNOSć

Dane wejściowe

PC

PC

PC

PC

Wyjście 0/l

Rys. 36.7. Ciąg konfiguracji wytwarzanych przez algorytm A działający na słowie wejściowym
x i świadectwie y. Każda konfiguracja reprezentuje stan komputera w jednym kroku obliczeń
i oprócz A, x oraz y zawiera licznik rozkazów (PC, od ang. Program Counter), pomocnicze dane
o stanie maszyny oraz obszar roboczy. Z wyjątkiem świadectwa y startowa konfiguracja c0 jest
ustalona. Każda konfiguracja jest przekształcana w następną 1.apomocą układu logicznego M.
Wyjście algorytmu to wyróżniony bit w obsmrze roboczym

(,' jest spełnialny wtedy i tylko wtedy, gdy istnieje świadectwo y takie, że
A(x, y) = 1. Po drugie, trzeba dowieść, że Fdziała w czasie wielomianowym.
żeby wykazać, że F poprawnie oblicza funkcję redukcji, załóżmy, że ist-
nieje świadectwo y długości O(nk) takie, że A(x, y) = 1. Jeśli wówczas użyje­
my y jako wejścia dla C, wyjściem C będzie C(y) = A(x, y) = 1. Jeśli więc
istnieje świadectwo, to C jest spełnialny. W celu udowodnienia odwrotnej im-

1044
36.3. NP-ZUPEŁNO$ć I REOUKOWALNO$C

plikacji załóżmy, że C jest spelnialny. Istnieje zatem wejście y dla układu C ta-
kie, że C(y) = I, skąd wnioskujemy, że A(x, y) = 1. Algorytm F oblicza więc
funkcję redukcji poprawnie.
Żeby zakończyć dowód, musimy jedynie wykazać, że F działa w czasie
wielomianowym względem n= lxl.Pierwszą poczynioną przez nas obserwacją
jest to, że liczba bitów potrzebnych do reprezentowania konfiguracji jest wielo-
mianowa ze względu na n. Sam program algorytmu A ma rozmiar stały, nieza-
leżny od rozmiaru jego danych wejściowych x i y. Długość wejściowego słowa
x jest równa n, a długość świadectwa y to O(tf'). Ponieważ algorytm wykonuje
co najwyżej O(rł) kroków, rozmiar potrzebnego mu obszaru roboczego taicie
jest wielomianem względem n. (Zakładamy, że obszar ten jest spójny; celem
zad. 36.3-4 jest rozszerzenie układu na przypadek, w którym pamięć wykorzys-
tywana przez A jest rozproszona na dużo większym obszarze i to w różny
sposób dla różnych słów wejściowych x).
Układ M implementujący strukturę komputera ma rozmiar wielomianowy
względem długości konfiguracji, która z kolei jest wielomianowa względem
O(nt), a więc także względem n. (Większa część tego układu implementuje
logiczną strukturę pamięci). Układ C składa się z co najwyżej t = O(n") kopii
układu M, jego rozmiar jest więc wielomianowy ze względu na n. Konstrukcję
układu C dla wejściowego słowa x algorytm redukcji F wykonuje w czasie
wielomianowym, ponieważ czas realizacji każdego kroku konstrukcji jest wie-
lomianowy.

Język CIRCUIT-SAT jest zatem przynajmniej tak samo trudny jak: każdy

język w klasie NP, a ponieważ należy on do NP, jest NP-zupełny.

TwlERDZENIE 36.7.
Problem spełnialności układów logicznych jest NP-zupełny.

DOWÓD
Natychmiastowy na mocy lematów 36.5 i 36.6 oraz definicji NP-zupełności .


ZADANIA
36.3-1. Wykaż, że ~ P jest relacją przechodnią na zbiorze języków. To znaczy,
wykaż, że jeśli L 1 ~pL 2 i L 2 ~pL 3 , to L 1 ~pL 3 .
36.3-2. Udowodnij, że L ~PL wtedy i tylko wtedy, gdy L ~pL,
36.3-3. Wykaż, że w alternatywnym dowodzie lematu 36.5 jako świadectwa
można użyć wartościowania spełniającego. Dla którego świadectwa do-
wód jest łatwiejszy?
36.3-4. W dowodzie lematu 36.6 :zakładamy, że obszar roboczy algorytmu A
zajmuje ciągły fragment pamięci rozmiaru wielomianowego. Gdzie w do-

1045
ROZDZIAŁ 36. NP-ZUPEŁNO$ć

wodzie korzystamy z tego założenia? Uzasadnij, że można je przyjąć bez


straty ogólności.
36.~S. Język L jest zupełny w klasie języków Cze względu na redukcję w cza-
sie wielomianowym, jeśli LEC oraz L' ~PL dla dowolnego L' EC. Wykaż,
że 0 i {O, t}• są jedynymi językami w klasie P, które nie są zupełne w P ze
względu na redukcję w czasie wielomianowym.
36.3-6. Wykaż, że język L jest zupełny w NP wtedy i tylko wtedy, gdy 1, jest
zupełny w co-NP.
36.3-7. Algorytm redukcji F w dowodzie lematu 36.6 konstruuje układ
C = f(x) na podstawie znajomości x, A oraz k. Profesor Sartre zauważył,
że wprawdzie słowo x jest dane algorytmowi F, ale jeśli chodzi o A i k, to F
wie tylko, że istnieją (ponieważ język L należy do NP), i nie zna ich fak-
tycznych wartości. Profesor konkluduje zatem, że algorytm F nie potrafi
skonstruować układu Ci że język CIRCUIT-SAT nie musi być wcale
NP-trudny. Wskaż błąd w rozumowaniu profesora.

36.4. DowodzenieNP-zupe/ności
NP-zupełność problemu spełnialności układów wykazaliśmy, dowodząc bezpo-
średnio, że L ~P CIRCUIT-SAT dla każdego języka Le NP. W tym podroz-
dziale pokażemy, w jaki sposób dowodzić NP-zupełności języka bez bezpo-
średniego redukowania do niego kaidego języka w klasie NP. Zilustrujemy tę
metodę dowodząc, że rozmaite problemy spełnialności formuł są NP-zupełne.
Podrozdział 36.5 zawiera o wiele więcej przykładów zastosowania tej metody.
Następujący lemat stanowi podstawę naszej metody dowodzenia NP-zu-
pełności języków.

LEMAT 36.8.
JeśliL jest językiem takim, że L' ~PL dla pewnego L'eNPC, to L jest NP-
-trudny. Co więcej,jeśli Le NP, to LeNPC.

DOWÓD
Ponieważ L' jest NP-zupełny, dla wszystkich L" E NP zachodzi L' 1 ~pL'. Z za-
łożenia L' ~pL, a zatem na mocy przechodniości relacji ~P (zad. 36.3-1) ma-
my L" ~pL, co dowodzi, że L jest NP-trudny. Jeśli przy tym Le NP, to rów-
nież LeNPC.

Innymi słowy, redukując
do L jeden język L', o którym wiadomo, że jest
NP-zupełny, implicite redukujemy do L każdy język w klasie NP. Lemat 36.8
daje nam zatem metodę dowodzenia, że język L jest NP-zupełny:

1046
36.4. DOWODZENIE NP-ZUPEŁNOSCI

I. Udowodnij, że LENP.
2. Wybierz język L', o którym wiadomo, że jest NP-zupełny.
3. Opisz algorytm obliczania funkcji/, przekształcającej każdy egzemplarz L'
w egzemplarz L.
4. Udowodnij, że funkcja/ma tę własność, że xEL' wtedy i tylko wtedy, gdy
f(x)cL dla dowolnego xc{O, l}'.
5. Udowodnij, że algorytm obliczania/działa w czasie wielomianowym.

Tak.a metoda redukowania jednego znanego nam języka NP-zupełnego jest


o wiele prostsza niż bardziej skomplikowany proces konstruowania redukcji
każdego języka z klasy NP. Dowód, że CIRCUIT-SATENPC, dal nam moż­
liwość jej stosowania. Wiedząc, że problem spełnialności układów jest NP-zu-
pełny, możemy teraz znacznie łatwiej dowodzić NP-zupełności innych prob-
lemów. Co więcej, w miarę jak nasza lista problemów NP-zupełnych będzie
rosnąć, stosowanie owej metody będzie się stawało coraz łatwiejsze.

Spelnialność formul
Zilustrujemy metodę redukcji, podając dowód NP-zupełności problemu stwier-
dzania, czy spełnialna jest dana formuła logiczna, a nie układ. Jest to histo-
rycznie pierwszy problem, którego NP-zupełności dowiedziono.
Problem spclnialności (formul) zdefiniujemy jako język SAT w sposób na-
stępujący. Egzemplarz problemu SAT stanowi formula logiczna cf,złożona z

(1) zmiennych logicznych: x 1 , x 2 , ... ;


(2) spójników logicznych: spójnikiem jest każda funkcja logiczna o jednym lub
dwóch argumentach i jednej wartości wyjściowej, jak A (AND), v (OR),
-,(NOT),-+ (implikacja), +-1-(wtedyi tylko wtedy); oraz
(3) nawiasów.
Tak jak w układach logicznych, wartościowaniem formuły logicznej cf,jest zbiór
wartości zmiennych cf,,a wartościowanie spełniające to takie, dla którego for-
muła przybiera wartość I. Formulę, dla której istnieje wartościowanie speł­
niające, nazywamy formułą spełnialną. W problemie spelnialności pytamy, czy
dana formuła logiczna jest spełnialna; w terminologii języków formalnych

SAT- {(,t,): ,t,jest spelnialną formulą logiczną)

Na przykład formula

ma wartościowanie spełniające (x 1 = O, x 2 = O, x 3 = 1, x 4 = 1), ponieważ

1047
ROZDZIAŁ 36. NP-ZUPEŁNOSC

~~((o~o)v ~((~O-I)vl))A ~o (36.2)

~ (I V ~(I V I)) A I

~(lvO)Al

~ I

a zatem formuła q,należy do języka SAT.


Algorytm „naiwny" sprawdzania, czy dowolna formula logiczna jest speł­
nialna, nie działa w czasie wielomianowym. Dla formuły (j; o n zmiennych
istnieje 2" możliwych wartościowań. Jeśli długość formuły (<P) jest wielomia-
nowa względem n, to sprawdzenie wszystkich wartościowań wymaga czasu
większego niż wielomianowy. Jak wynika z poniższego twierdzenia, algorytm
wielomianowy zapewne nie istnieje.

TWlERDZENIE36.9.
Problem spełnialności formuł logicznych jest NP-zupełny.

DOWÓD
Wykażemy najpierw, że SATeNP. Następnie udowodnimy, że CIRCUIT-
-SAT ~rSAT; na mocy lematu 36.8 zakończy to dowód twierdzenia.
żeby udowodnić, że język SAT należy do klasy NP, wykażemy, iż świadec­
two składające się z wartościowania spełniającego dla wejściowej formuły q,
można weryfikować w czasie wielomianowym. Algorytm weryfikacji zastępuje
po prostu każdą zmienną w formule odpowiadającą jej wartością, a następnie
oblicza otrzymane wyrażenie, tak jak robiliśmy to w równaniu (36.2). Czynno-
ści te można bez trudu wykonać w czasie wielomianowym. Jeśli wartością
wyrażenia jest 1, to formuła jest spełnialna. Wykazaliśmy zatem prawdziwość
pierwszego warunku NP-zupełności.
W celu udowodnienia, że język SAT jest NP-trudny, wykażemy, że CIR-
CUIT-SAT ~pSAT. Innymi słowy, każdy egzemplarz problemu spełnialności
obwodów można w czasie wielomianowym zredukować do egzemplarza prob-
lemu spełoialności formuł. Każdy obwód logiczny można metodą indukcji
przedstawić w postaci formuły logicznej. Dla bramki, wyjście z której jest zara-
zem wyjściem z całego układu, konstruujemy indukcyjnie formuły odpowiada-
jące każdemu z jej wejść. Formułę dla całego układu otrzymujemy następnie,
zapisując wyrażenie stosujące funkcję realizowaną przez bramkę do formuł
reprezentujących wejścia bramki.
Niestety, ta naturalna metoda nie daje redukcji w czasie wielomianowym.
Występowanie wspólnych podformuł może spowodować wykładniczy wzrost
rozmiaru tak utworzonej formuły (patrz zad. 36.4~1). Algorytm redukcji musi
więc być nieco sprytniejszy.

···----------------------
1048
------
36.4. DOWODZENIE NP-ZUPEŁNO$CI

Rysunek 36.8 ilustruje podstawową ideę redukcji problemu CIRCUIT-


-SAT do SAT na przykładzie układu z rys. 36.6a. Każdemu przewodowi X;
układu C odpowiada zmienna x 1 formuły tj,. Operację realizowaną przez jedną
bramkę można wyrazić jako formułę dotyczącą zmiennych odpowiadających
dochodzącym do bramki przewodom, Na przykład działanie wyjściowej bram-
ki AND opisuje formuła X 10 .-+(x 7 AX 8 AX 9 ).

x, x,
X,
x,
x,
x, x,,
x, x,

Rys. 36.8. Redukcja problemu spełnialności układów do problemu spełnialności formuł. Formuła
konstruowana przez algorytm redukcji zawiera zmienną. odpowiadają.cą ka.i.demu przewodowi
układu

Tworzona przez algorytm redukcji formuła r/) to koniunkcja zmiennej od-


powiadającej wyjściu układu i klauzul opisujących działanie wszystkich bra-
mek. Dla układu z rysunku jest to

I\ (x 5 .-+(X 1 V x 2 ))

Dla danego układu C łatwo skonstruować taką formulę tj, w czasie wielo-

mtanowym.
Dlaczego spełnialność układu C jest równoważna ze spelnialnością for-
muły tj,?Jeśli C ma wartościowanie spełniające, wartość na każdym pruwodzie
jest dobrze zdefmiowana, a na wyjściu układu jest 1. Przypisanie wartości na

1049
ROZDZIAŁ 36, NP-ZUPEŁNOSC

przewodach związanym z nimi .zmiennym powoduje zatem, że wartością


każdej klauzuli formuły tpjest I, a więc ich koniunkcja to także 1. Odwrotnie,
jeśli istnieje wartościowanie, przy którym tp ma wartość I, podobny argu-
ment dowodzi, że układ C jest spełnialny. Pokazaliśmy zatem, że CIRCUlT-
-SAT ~pSAT, co kończy dowód.


Spełnialność formuł 3-CNF
NP-zupełność wielu problemów można wykazać przez redukcję problemu spel-
nialności formuł. Algorytm redukcji musi jednak radzić sobie z dowolną for-
mulą wejściową, a to może się wiązać z olbrzymią liczbą przypadków do roz-
ważenia. W związku z tym często wolelibyśmy dokonywać redukcji ograniczo-
nego języka formul logicznych, żeby owych przypadków było mniej. Oczywi-
ście nie możemy ograniczyć języka do tego stopnia, żeby stal się rozwiązywalny
w czasie wielomianowym. Wygodnym do rozważania językiem jest spelnial-
ność formul 3-CNF<',czyli język 3-CNF-SAT.
Spełnialność formuł 3-CNF defmiujemy za pomocą następujących pojęć.
literał w formule logicznej to wystąpienie zmiennej lub jej negacji. Formuła
logiczna jest w postaci koniunkcyjnej normalnej albo CNF (od ang. conjunctive
norma!form), jeśli jest zapisana jako koniunkcja klauzul, z których każda jest
alternatywą jednego lub więcej literałów. Formuła logiczna jest w postaci
3-koniunkcyjnej normalnej albo 3-CNF, jeśli każda klauzula zawiera przy tym
dokładnie trzy różne literały.
Na przykład formuła

jest 3-CNF'. Pierwszą z jej trzech klauzul jest (x 1 v •x 1 v •x 2), zawierająca


trzy literały x 1 , •x 1 oraz •x 2 •
W problemie 3-CNF-SAT pytamy, czy dana formuła logiczna cpw postaci
3-koniunkcyjnej normalnej jest spełnialna. Z poniższego twierdzenia wynika, że
wielomianowy algorytm rozstrzygania spełnialności formuł logicznych zapewne
nie istnieje, nawet jeżeli formuły są wyrażone w tej prostej postaci normalnej.

TwlERDZENIE 36.10.
Spełnialność fonnul logicznych w postaci 3-koniunkcyjnej nonnalnej jest prob-
lemem NP-zupełnym.

DOWÓD
Argument, którego użyliśmy w dowodzie twierdzenia 36.9 do wykazania, że
SATeNP, można równie dobrze zastosować tutaj, żeby wykazać, że 3-CNF-

1050
~SA1"eNP. Pozostaje więc tylko wykazać, że problem 3-CNF-SAT jest NP-
-trudny. Udowodnimy to wykazując, że SAT ~p3-CNF-SAT, i korzystając
z lematu 36.8.
Algorytm redukcji można rozbić na trzy podstawowe kroki. W każdym
z nich przekształcamy stopniowo wejściową formułę ej,do postaci coraz bliższej
docelowej 3-koniunkcyjnej postaci normalnej.
Pierwszy krok jest podobny do użytego przy dowodzeniu, że CIRCUI'f-
-SAT ~pSAl' w twierdzeniu 36.9. Najpierw budujemy binarne „drzewo roz-
kładu" wejściowej formuły ej,,którego liśćmi są literały, a węzłami wewnętrz­
nymi~ spójniki. Na rysunku 36.9 widać takie dr7.ewo rozkładu dla formuły

(36.3)

Jeśli wejściowa formula zawiera takie klauzule, jak alternatywa większej liczby
literałów, to korzystając z łączności, można tak rozstawić nawiasy, żeby każdy
węzeł wewnętrzny w powstałym drzewie miał jednego lub dwóch synów. Binar-
ne drzewo rozkładu można teraz traktować jak układ logiczny, obliczający
pewną funkcję.
Naśladując redukcję z dowodu twierdzenia 36.9 z każdym wejściem z węz­
ła wewnętrznego związujemy zmienną y 1• Następnie przepisujemy pierwotną
formułę ej,jako koniunkcję zmiennej z korzenia i klauzul opisujących operacje
realizowane przez wszystkie węzły. Dla formuły (36.3) otrzymujemy wyrażenie

cj,'=Y1 A(y1+-+(y2A ....,X2))

i\ CY2+-+(y3V y4))

V
' '

' ·'
'
r~·6,

________ .,,-,,,,,,, __________ _


1051
HU.lLJLłAŁ ::ltl. NP-.lUPE:ŁNOSC

A (y 3 +-+(X1 -+Xi))
A (y4 +-+ •y,)
A (y 5 +-+ (y 6 V x 4 ))

A (y6 +-+ ( •x1 +-+X3))

Zauważmy, że tak otrzymana formuła tp'jest koniunkcją klauzul r/Ji,z których


każda zawiera co najwyżej 3 literały. Jedynym dodatkowym. wymaganiem jest
to, że każda klauzula ma być alternatywą literałów.
W drugim kroku redukcji przekształcamy każdą klauzulę do koniunkcyj-
nej postaci normalnej, Tworzymy tablicę wartości klauzuli t/JJdla wszystkich
możliwych wartościowań jej zmiennych. Każdy wiersz tej tablicy składa się
z jednego z wartościowań zmiennych klauzuli oraz wartości logicznej klauzuli
przy tym wartościowaniu. Korzystając z tych elementów w tablicy wartości,
dla których wartością klauzuli jest O, budujemy formułę w dysjunkcyjnej po-
staci normalnej albo DNF (od ang. disjunctive norma! form) - alternatywy
koniunkcji - równoważną z •tpj. Następnie przekształcamy ją w formułę
CNF rjJ;'za pomocą praw De Morgana (5.2), negując wszystkie literały i za-
mieniając spójniki OR na AND oraz AND na OR.

------ ..
Y, Y,
----
,, (y1-(y2A -U:2))
I I I o
I I o I
I o I o
I o o o
o I I -- I
o I o, o
o o I -
I
o o o I

Rys. 36.JO. Tablica wartości klauzuli (y 1 .... (y2 A •x 2))

W naszym przykładzie przekształcamy klauzulę t/Jl= (y 1 +-+(yiA 'Xi))


do postaci koniunkcyjnej w następujący sposób. Tablica wartości t/Jljest
przedstawiona na rys. 36.10. Formulą DNF równoważną z •r/Jl.jest

Ó'1 A Yi A Xi) V (yl A -,Yi A Xi) v(yl A -,Yi A 'Xi)v( 'Y1 A Yi A 'Xi)
Stosując prawa De Morgana, dostajemy formulę CNF
= ( 'Y1
r/JJ_ V -,Yi V 'Xi) A(-,Y1 V Yi V -,Xi)
A(-iy 1 V Yi V Xi)A(y 1 V -iy 2 V Xi)
równoważną z klauzulą tpJ_.
--~----------------------
1052
36.4. DOWODZENIE NP-ZUPEŁNOŚCI

Każda klauzula <Plformuły r/>'została przekształcona w formułę CNF <Pi,


a zatem tp' jest równoważna z formulą CNF cJ,",stanowiącą koniunkcję klau-
zul cJ,'f.Co więcej, każda klauzula formuły <P" zawiera co najwyżej 3 literały.
W trzecim i ostatnim kroku redukcji przekształcamy formułę w taki spo-
sób, żeby każda klauzula zawierała dokładnie 3 różne literały. Ostateczną for-
mułę 3-CNF <P"' skonstruujemy z klauzul formuły CNF cJ,".Użyjemy także
dwóch dodatkowych zmiennych, które nazwiemy pi ą. Dla każdej klauzuli Ci
formuły cJ,"do tp"'dołączymy następujące klauzule:

• Jeśli C1 zawiera 3 różne literały, to po prostu dołączamy C1 jak.o klauzu-


lę tł>'".
• JeśliC1 zawiera2różneliterały,tzn.jeśliCi = (/1 v /2),gdzie/1 i/2 sąliterałami,
jak.oklauzulerJ>"'dołączamy(/ 1 v / 2 v p)A(/ 1 v / 2 v •p).Literałypi -ipslu-
żą jedynie do wypełnienia syntaktycznego wymagania, żeby każda klauzu-
la składała się z dokładnie 3 literalów: formuła (/ 1 v / 2 v p) I\ (/ 1 v / 2 v •p)
jest równoważna z (/ 1 v 12 ) niezależnie od tego, czy p = O czy p = 1.
• Jeśli C 1 zawiera tylko jeden literał /, to jak.o klauzule cJ,"'dołączamy
(/ v p v q)A(l v pv •q)A(lv •p v q)A(lv •pv •q). Zauważmy, że
przy każdym wartościowaniu pi q wartość koniunkcji tych czterech klauzul
jest równa /.
Analizując każdy z tych trzech kroków, widzimy, że formula 3-CNF cJ,"'
jest spełnialna wtedy i tylko wtedy, gdy jest spelnialna cp.Podobnie jak. przy
redukcji języka CIRCUIT-SAT do SAT, przejście od tJ>do cJ,'zachowuje speł­
nialność. W drugim kroku tworzymy formulę CNF cJ,"algebraicznie równo-
ważną z cJ,'.W trzecim kroku tworzymy formułę 3-CNF tj,"', której spełnial­
ność jest równoważna ze spełnialnością tj,", ponieważ nadając dowolne war-
tości zmiennym pi q, dostajemy formułę algebraicznie równoważną z tj,".
Musimy jeszcze wykazać, że powyższą redukcję można obliczyć w czasie
wielomianowym. Konstruując tp'z cJ,dla każdego spójnik.a formuły q,wprowa-
dzamy co najwyżej 1 zmienną i 1 klauzulę. Przy konstrukcji tj," z tł>' z każdej
klauzuli rj,'może powstać co najwyżej 8 klauzul tp",ponieważ każda klauzula
tp' zawiera co najwyżej 3 zmienne, więc jej tablica wartości ma co najwyżej
2 3 = 8 wierszy. Konstrukcja tp'" z tp" dla każdej klauzuli tp" wprowadza co
najwyżej 4 klauzule do tj,'". Rozmiar otrzymanej formuły tp"'jest zatem wielo-
mianowy względem długości początkowej formuły tp. Każdy z kroków kon-
strukcji można łatwo zrealizować w czasie wielomianowym.

ZADANIA
36.4-1. Rozważmy naturalną (gorszą niż wielomianowa) redukcję w dowodzie
twierdzenia 36.9. Opisz układ rozmiaru n, dla którego rozmiar otrzymanej
tą metodą formuły jest wykładniczy względem n.

1053
ROZDZIAŁ 36. NP-ZUPEŁNOSC

36.4-2. Napisz formułę 3-CNF, którą otrzymamy, jeśli zastosujemy metodę


z dowodu twierdzenia 36.10 do formuły (36.3).
36.4-3. Profesor Jagger proponuje dowód, że SAT ~p3-CNF-SAT, w którym
korzysta się jedynie z metody tablicy wartości z dowodu twierdzenia 36.10,
bez pozostałych kroków. Profesor proponuje więc wziąć formułę logiczną
rj,, utworzyć tablicę wartości dla jej zmiennych, zbudować na podstawie tej
tablicy formułę 3-DNF równoważną z -,q,,a następnie zanegować ją i za-
stosować prawa De Morgana w celu otrzymania formuły 3-CNF równo-
ważnej z rj,. Wykaż, że taka strategia nie prowadzi do redukcji w czasie
wielomianowym.
36.4-4. Wykaż, że problem rozstrzygania, czy dana formuła logiczna jest tau-
tologią, jest zupełny dla klasy co-NP. (Wskazówka: Patrz zad. 36.3-6).
36.4-5. Wykaż, że problem rozstrzygania spełnialności formuły logicznej w dys-
junkcyjnej postaci normalnej jest rozwiązywalny w czasie wielomianowym.
36.4-6. Przypuśćmy, że ktoś daje Ci wielomianowy algorytm rozstrzygania
spelnialności formuł. Opisz, jak użyć tego algorytmu do znajdowania
w czasie wielomianowym wartościowania spełniającego.
36.4-7. Niech 2-CNF-SA'f będzie zbiorem spełnialnych formuł CNF o dokład­
nie 2 literałach w każdej klauzuli. Wykaż, że 2-CNF-SAT EP. Znajdź moż­
liwie najefektywniejszy algorytm. (Wskazówka: Zauwaimy, że formuła
x v y jest równoważna z formułą •x-+ y. Zredukuj 2-CNF-SAT do pew-
nego problemu w grafie skierowanym, mającego efektywne rozwiązanie).

36.5. ProblemyNP-zupełne
Problemy NP-zupełne pojawiają się w najrozmaitszych dziedzinach, jak logika
matematyczna, teoria grafów, arytmetyka, projektowanie sieci, zbiory i ich
podziały, zapisywanie i odczytywanie informacji, szeregowanie zadań i układa­
nie harmonogramów, programowanie matematyczne, algebra i teoria liczb, gry
i łamigłówki, automaty i teoria języków formalnych, optymalizacja progra-
mów i wiele innych. W tym podrozdziale użyjemy metody redukcji w dowo-
dach NP-zupełności rozmaitych problemów zaczerpniętych z teorii grafów
i podziałów zbioru.
Na rysunku 36.11 jest przedstawiona struktura zależności dowodów NP-
-zupełności w podrozdz. 36.4 i niniejszym. NP-zupełności każdego języka wi-
docznego na tym rysunku dowodzi się przez redukcję języka, od którego pro-
wadzi do niego strzałka. W korzeniu znajduje się język CIRCUIT-SAT, które-
go NP-zupełność udowodniliśmy w twierdzeniu 36.7.

36.5.1. Problemkliki
Klika w grafie nieskierowanym G = (V, E) to podzbiór V' c V, w którym
każda para wierzchołków jest połączona krawędzią należącą do E. Inaczej
36.5. PROBLEMY NP-ZUPEŁNE

CIRCUIT-SAT

SAT

3-CNF-SAT

CL!QUE HAM-CYCLB

!VERTBX-COVER
-
TSP

SUBSET-SUM

Rys. 36.11. Struktura dowodów NP-zupełności w pod.rozdz. 36.4 i 36.5. Wszystkie dowody wynikają
ostatecznie z reduktji NP-zupełnego problemu CIRCUIT-SAT

mówiąc, klika to pełny pod.graf grafu G. Rozmiarkliki to liczba wierzchołków,


które zawiera. Problemkliki to optymalizacyjny problem znalezienia w grafie
kliki maksymalnego rozmiaru. W wersji decyzyjnej pytamy po prostu, czy ist-
nieje w grafie klika danego rozmiaru k. Formalna definicja to

CLIQUE = {(G, k): G jest grafem zawierającym klikę rozmiaru k}

Algorytm „naiwny'' stwierdzania, czy graf G = (V, E) o IV] wierzchołkach


zawiera klikę rozmiaru k polega na przejrzeniu wszystkich k-podzbiorów zbio-
ru V i sprawdzeniu każdego z nich, czy aby nie tworzy on kliki. Czas działania
tego algorytmu równy O ( k 1 ( l~I)) jest wielomianowy, jeśli k jest stałą. Ogól-
nie jednak k może być proporcjonalne do IV], a wówczas algorytm działa
w czasie większym niż wielomianowy. Jak można przypuszczać, efektywny
algorytm dla problemu kliki najprawdopodobniej nie istnieje.

TwlERDZENIE 36.11.
Problem klik.ijest NP-zupełny.

DOWÓD
Żeby wykazać, że CLIQUE E NP, dla danego grafu G E) jako świadec­
= (V,
twa użyjemy zbioru V' c V wierzchołków kliki. Stwierdzić, czy V' jest kliką,
można w czasie wielomianowym, sprawdzając, czy dla każdej pary u, v E V'
krawędź (u, v) należy do E.
Pokażemy teraz, że problem kliki jest NP-trudny, dowodząc, że 3-CNF-
-SAT ~pCLIQUE. Fakt, że można coś takiego udowodnić, jest nieco zaska-

1055
ROZDZIAŁ 36. NP-ZUPEŁNOSć

kujący, ponieważ na pierwszy rzut oka formuły logiczne wydają się mieć nie-
wiele wspólnego z grafami.
Redukcję zaczynamy od egzemplarza problemu 3-CNF-SAT. Niech
ej,= C1 A C 2 A .•• A C1 będzie formulą logiczną 3-CNF ok klauzulach. Każda
klauzula C, dla r = 1, 2, ..., k zawiera dok.ładnie trzy różne literały li, IZ i/).
Skonstruujemy graf G taki, że formuła ej,jest spełnialna wtedy i tylko wtedy,
gdy G zawiera klikę rozmiaru k.
Graf G = (V, E) konstruujemy w następujący sposób. Każdej klauzuli
C, = (/'i v IZ v 13) w cJ,odpowiada trójka wierzchołków v'i_,vZ i vl w zbio-
rze V. Wierzchołki vj i vj łączymy krawędzią, jeśli zachodzą obydwa poniższe
warunki:

• vf i vj są w różnych trójkach, tzn. r # s, oraz


• odpowiadające im literały są niesprzeczne,tzn. że l'i nie jest zaprzecze-
.
niem I'i·

Graf ten można łatwo obliczyć z formuły cJ,w czasie wielomianowym. Jeśli
na przykład

to G jest grafem pokazanym na rys. 36.12.

Rys.. 36.12. Graf G otrzymany z formuły 3-CNF 4>= C 1 /\ C 2 11 C 3 , gdzie C 1 = (x 1 v •x 1 v •x 3 ),


C1 = (•x 1 v x 2 v x 3 ), a C 3 = (x 1 v x 2 v x 3 ), w wyniku redukcji 3-CNF·SAT do CLIQUE.
Wartościowaniem spełniającym formuły tj, jest (x 1 = O, x 2 = O, x 3 = 1). Przy tym wartościowaniu
klauzula C 1 jesl spełniona dzięki •x 1 , a C 2 i C 3 dzięki x 3 , co odpowiada klice o jasnoszarych
wierzchołkach

1056
36.5. PROBLEMY NP-ZUPEŁNE

Musimy wykazać, że to przekształcenie q>w G jest redukcją. Załóżmy


najpierw, że q>ma wartościowanie spełniające. Wówczas każda klauzula C,
zawiera przynajmniej jeden literał /f, któremu jest przypisana wartość 1, a każ­
dy taki literał odpowiada wierzchołkowi v/. Wybierając po jednym takim
„prawdziwym" literale z każdej klauzuli, otrzymujemy k-elementowy zbiór
wierzchołków V'. Twierdzimy, że V' jest kliką. Dla dowolnych dwóch wierz-
chołków vj', vje V', gdzie r 'F s, wartościowanie spełniające przypisuje obydwu
odpowiadającym im literałom /j' i /j wartość 1, a więc jeden nie może być
negacją drugiego. Z konstrukcji G wynika zatem, że krawędź (v/, vj) nale-
ży do E.
Odwrotnie, załóżmy, że G zawiera klikę V' rozmiaru k. żadna krawędź
w G nie łączy wierzchołków jednej trójki, a więc V' zawiera po jednym wierz-
chołku z każdej trójki. Możemy przypisać wartość 1 każdemu literałowi /'j
takiemu, że vj' EV', bez obawy, że przypiszemy 1 zarówno literałowi, jak
i jego negacji, ponieważ G nie zawiera krawędzi łączących sprzeczne literały.
Każda klauzula jest spełniona, a więc cała formuła <J,również. (Zmiennym
nie odpowiadającym żadnemu wierzchołkowi z kliki możemy przypisać do-
wolne wartości).


W przykładzie na rys. 36.12 wartościowaniem spełniającym dla formuły
<I>jest (x 1 = O, x 2 = O, x 3 = 1). Odpowiadająca mu klika rozmiaru k = 3 skła­
da się z wierzchołków odpowiadających literałom: •x 2 z pierwszej klauzuli, x 3
z drugiej i x 3 z trzeciej.

36.5.2. Problem pokrycia wierzchołkowego


Pokryciewierzchołkowe grafu nieskierowanego G = (V, E) to podzbiór V' s;; V
taki, że jeśli (u, v)eE, to ue V' lub ve V'. Inaczej mówiąc, każdy wierzchołek
„pokrywa" incydentne z nim krawędzie, a pokryciem wierzchołkowym G jest
zbiór wierzchołków pokrywający wszystkie krawędzie zbioru E. Rozmiarpo-
krycia wierzchołkowego to liczba składających się na nie wierzchołków. Na
przykład graf na rys. 36.13b ma pokrycie wierzchołkowe {w, z} rozmiaru 2.
Problem pokrycia wierzchołkowego polega na znalezieniu w danym grafie
pokrycia wierzchołkowego minimalnego rozmiaru. Przeformułowując ten pro-
blem optymalizacyjny na decyzyjny, chcemy stwierdzić, czy graf ma pokrycie
wierzchołkowe danego rozmiaru k. Trzymając się terminologii języków for-
malnych, definiujemy

VERTEX-COVER = {(G, k): graf Gma pokrycie wierzchołkowe rozmiaru k}

Poniższe twierdzenie mówi, że problem ten jest NP-zupełny.

1057
ROZDZIAŁ 36. NP-ZUPEŁNO$ć

u~----(,;')

w
'
y

(,) (b)

Rys. 36.13. Redukcja problemu CLIQUE do VERTEX-COYER. (a) Graf nieskierowany G = (V, EJ
z kliką V'= {u, v, x, y}. (b) Utworzony przez algorytm redukcji graf G o pokryciu wierzchoł­
kowym V- V'= {w,z}

TwlERDZENIE 36.12.
Problem pokrycia wierzchołkowego jest NP-zupełny.

DOWÓD
Najpierw wykażemy, że VERTEX-COVEReNP. Załómly, że dany jest graf
G = (V, E) i liczba całkowita k. Naszym świadectwem będzie samo pokrycie
wierzchołkowe V' c: V. Działanie algorytmu weryftlc.acji polega na upewnieniu
się, że IV'J= k, a następnie dla każdej krawędzi (u, v)EE sprawdzeniu, czy
ue V' lub vE V'. Weryfikację taką można bez trudu wykonać w czasie wielo-

m1anowym.
Udowodnimy, że problem pok.rycia wierzchołkowego jest NP-trudny, po-
kazując, że CLIQUE ~P VERTEX-COVER. Redukcja ta jest oparta na poję­
ciu „dopełnienia" grafu. Dla danego grafu nieskierowanego G = (V, E) defi-
niujemy dopełnienie G jako graf G = (V, E), gdzie E = {(u, v): (u, v)łE).
Inaczej mówiąc, <).jest grafem zawierającym dokładnie te krawędzie, które nie
należą do G. Na rysunku 36.13 przedstawiono graf i jego dopełnienie jako
ilustrację redukcji problemu CLIQUE do VERTEX-COVER.
Wejście dla algorytmu redukcji stanowi egzemplarz (G, k) problemu
kliki. Algorytm oblicza dopełnienie G, co łatwo wykonać w czasie wielo-
mianowym. Wynikiem działania algorytmu redukcji jest egzemplarz (G,
lf-1- k) problemu pokrycia wierzchołkowego. żeby zakończyć dowód, wy-
starczy pokazać, że powyższe przekształcenie jest faktycznie redukcją: graf G
zawiera klikę rozmiaru k wtedy i tylko wtedy, gdy graf c· ma pok.rycie wie-
rzchołkowe rozmiaru IVI- k.
Załóżmy, że G zawiera klikę V' c V taką, że IV I = k. Twierdzimy, że
1

V - V' jest pokryciem wierzchołkowym w ·a.Niech (u, v) będzie dowolną


krawędzią należącą do E. Wówczas (u, v)f:E, skąd wynika, że pr.lynajmniej
jeden z wierzchołków u i v nie należy do V', ponieważ każda para wierz.choi-

1058
36.5. PROBLEMY NP-ZUPEŁNE

ków ze zbioru V' jest połączona krawędzią z E. Jest to równoważne ze stwier-


dzeniem, że przynajmniej jeden spośród wierzchołków u i v należy do V - V',
co oznacza, że zbiór V - V' pokrywa krawędź (u, v). Ponieważ (u, v) była
dowolnie wybraną krawędzią z E, każda krawędź ze zbioru E jest pokryta
przez pewien wierzchołek z V - V', a zatem zbiór V - V' rozmiaru !VI- k
stanowi pokrycie wierzchołkowe grafu G .
Odwrotnie, załóżmy, że G ma pokrycie wierzchołkowe V' c V, gdzie
IV'I = IV! - k. Wówczas dla dowolnych u, ve V,jeśli(u, v)eE, to przynajmniej
jeden z tych wierzchołków należy do V'. Równoważne z tą implikacją jest
stwierdzenie, że dla dowolnych u, ve V, jeśli ani uf V', ani vf V', to (u, v)e E.
Innymi słowy, V - V' jest kliką, a jej rozmiarem jest !VI- IV'I = k.

Ponieważ problem VERTEX-COVER jest NP-zupełny, nie spodziewamy
się znaleźć wielomianowego algorytmu znajdowania minimalnego pokrycia wie-
rzchołkowego. W podrozdziale 37.1 przedstawiamy jednak wielomianowy „al-
gorytm aproksymacyjny", który znajduje „przybliżone" rozwiązania problemu
pokrycia wierzchołkowego. Rozmiar obliczanego przezeń pokrycia co najwyżej
dwukrotnie przekracza minimalny rozmiar pokrycia wierzchołkowego.
Nie należy więc załamywać rąk tylko dlatego, że rozważany problem oka-
zał się NP-zupełny. Być może istnieje wielomianowy algorytm aproksymacyj-
ny, obliczający rozwiązania bliskie optymalnym, mimo że znalezienie rozwią­
:zania optymalnego jest trudne. W rozdziale 37 przedstawimy kilka algoryt-
mów aproksymacyjnych dla problemów NP-zupełnych.

36.5.3. Problemsumy podzbioru


Kolejny rozważany przez nas problem NP-zupełny jest natury arytmetycznej.
W problemie sumy podzbioru mamy dany zbiór skończony Sc N i wartość
docelową te N. Pytamy, czy istnieje podzbiór S' c S, którego suma elementów
wynosi 1. Jeśli na przykład S = {l, 4, 16, 64, 256, 1040, 1041, 1093, 1284,
1344}, a I= 3754, to podzbiór S' = {1, 16, 64, 256, 1040, 1093, 1284} jest
rozwiązaniem problemu.
Jak zwykle, definiujemy problem jako język

SUBSET-SUM = {(S, 1): istnieje podzbiór S' c S taki, że I= L s)


,,s
Jak w każdym problemie arytmetycznym, należy przypomnieć, że w na-
szym standardowym kodowaniu wejściowe liczby całkowite są kodowane jako
ciągi binarne. Mając na uwadze to założenie, można pokazać, że szybki al-
gorytm dla problemu sumy podzbioru najprawdopodobniej nie istnieje.

1059
ROZDZIAŁ 36. NP-ZUPEŁNQ$C

TWIERDZENIE 36.13.
Problem sumy podzbioru jest NP-zupełny.

DOWÓD
Żeby wykazać, że SUBSET-SUM należy do NP,jak.o świadectwa dla egzemp-
larza problemu (S, t) użyjemy podzbioru S'. Za pomocą algorytmu weryftka-
cji można w czasie wielomianowym sprawdzić, czy t = L s.
,es'

Pokażemy teraz, że VERTEX-COVER ~pSUBSET-SUM. Dla danego


egzemplarza (G, k) problemu pokrycia wierzchołkowego algorytm redukcji
konstruuje egzemplarz (S, t) problemu sumy podzbioru tak.i, że G ma po-
krycie wierzchołkowe rozmiaru k wtedy i tylko wtedy, gdy istnieje podzbiór
zbioru S o sumie równej dokładnie t.
Klucz do redukcji stanowi reprezentacja grafu G w postaci macierzy sąsie­
dztwa. Niech G będzie grafem nieskierowanym, gdzie V= {v0 , v1 , ••. , v1vi- 1 },
a E = {e0 , e 1 , ... , e El_ 1 }. Macierz incydencji grafu G to macierz B = (b11) wy-
1

miaru IVIx !Eltaka, że

I, jeśli wierzchołek
v1 jest końcem krawędzi e1
bij= { o •
w przeciwnym •
razie

Na rysunku 36.14b widać macierz incydencji grafu nieskierowanego


z rys. 36.14a. Krawędzie o mniejszych indeksach są umieszczone z prawej stro-
ny zamiast Gak to się robi zazwyczaj) z lewej, w celu uproszczenia wzorów na
liczby stanowiące elementy zbioru S.
Dla danego grafu G i liczby całkowitej k algorytm redukcji oblicza zbiór
liczb S i liczbę t. W celu lepszego wyjaśnienia działania algorytmu redukcji
będziemy przedstawiali liczby w „zmodyfikowanym układzie czwórkowym".
I.Elmniej znaczących cyfr liczby będzie zapisanych w układzie czwórkowym,
natomiast bardziej znaczące cyfry mogą być równe nawet k. Zbiór liczb będzie
skonstruowany w tak.i sposób, żeby nie zdarzały się przeniesienia od mniej do
bardziej znaczących cyfr.
Zbiór S składa się z dwóch rodzajów liczb; jedne odpowiadają wierzchoł­
kom, a drugie krawędziom. Dla każdego wierzchołka v1EV tworzymy liczbę
naturalną xi, której reprezentacja w zmodyfikowanym układzie czwórkowym
to cyfra 1, po której następuje jeszcze !Elcyfr. Cyfry te pochodzą z wiersza V;
w macierzy incydencji B = (b11) grafu G, jak to widać z rys. 36.14c. Formalnie,
dla i = O, l, ..., IV] - 1 definiujemy

1060
rv /n1olil'/i/.:0K·unvrn
u/.:/a<i:rt 1·:'wórkow_rn1 J).:1ts1c111ic
('('('('('
., l C I <,

',,; - -

'' I o I I •

IaI ( b)
'
-
,.
' - oo oo o o oo o I - 16
Y;

''
-o
- I
I
() () ()
()
()
-

-
64
256

' .' ..' .' ' .' ' 7 \, \

I cI

Rys. 36.14. Redukcja problemu pokrycia wierzchołkowego do problemu sumy podzbioru. (a) Graf
nieskierowany G. Pokrycie wierzchołkowe {v1 , v 1, v4 } rozmiaru 3 jest oznaczone jaśniejszym kolo-
rem. (b) Macierz incydentji tego grafu. Cieniowanie wierszy odpowiada pokryciu wierz.chołkowe­
mu z punktu (a). Każda krawędź e1 ma l przynajmniej w jednym jasnoszarym wierszu. (c) Od-
powiadający egzemplarz problemu sumy p<Xlzbioru.Obramowany fragment to macierz incydencji.
Pokryciu wierzchołkowemu {v1, v 1 , v4 } rozmiaru k = 3 odpowiada tutaj oznaczony jamoszarym
kolorem podzbiór {I, 16, 64, 256, 1040, 1093, 1284} o sumie 3754

Dla każdej krawędzi e;E E tworzymy liczbę Y; odpowiadającą wierszowi z ,jed-


nostkowej" macierzy incydencji. (Jednostkowa macierz incydencji to macierz
I.Elx IE'lzawierająca jedynki tylko na przekątnej). Definiując formalnie, dla
i~ O, I, ..., IEl- I
Yi = 4i
Pierwszą cyfrą docelowej sumy t jest k, a wszystkie IE1mniej znaczące
cyfry są równe 2. f"ormalnie

IE!- I
t=k41EI+ L 2·4j
i"' o

Rozmiar tych wszystkich liczb będzie wielomianowy, jeśli przedstawimy je


w postaci binarnej. Redukcji można dokonać w czasie wielomianowym, mani-
pulując bitami macierzy incydencji.
Musimy teraz wykazać, że graf G ma pokrycie wierzchołkowe rozmiaru
k wtedy i tylko wtedy, gdy istnieje podzbiór S' c S o sumie równej t. Załóżmy
najpierw, że G ma pokrycie wierzchołkowe V' c V rozmiaru k, V'= (v;, V;,
... , vi }, i zdefiniujmy S' jako ' '

1061
ROZDZIAŁ 36. NP-ZUPEŁNOSC

{yi dokładnie jeden koniec krawędzi e1 należy do V'}

Żeby się przekonać, iż L s = t, muwaimy, że sumując k najbardziej zna-


,,,
czących jedynek liczb Xi,. e S', dostajemy najbardziej znaczącą cyfrę k liczby t
w zmodyfikowanym układzie czwórkowym. Żeby otrzymać pozostałe cyfry t,
wszystkie równe 2, rozważmy po kolei ich pozycje, z których każda odpowiada
pewnej krawędzi e1. Ponieważ V' jest pokryciem wierzchołkowym, przynaj-
mniej jeden z końców e1 należy do V'. Dla każdej krawędzi ej istnieje zatem
przynajmniej jeden X1.,e S', mający 1 na pozycji j. Jeśli oba końce ej należą do
V', obydwa te wierzchołki wnoszą po jedynce do sumy naj-tej pozycji, nato-
miast j-ta cyfra liczby y 1 nie wnosi nic, bo skoro krawędź jest pokryta przez
oba swoje końce, to yiffS'. W tym przypadku zatem, sumując liczby ze zbio-
ru S', naj-tej pozycji wt dostajemy 2. W przeciwnym razie - kiedy dokładnie
jeden koniec krawędzi e1 jest wierzchołkiem z pokrycia V' - y 1e S', a ten wie-
rzchołek i y wnoszą po jedynce do sumy na )-tej pozycji liczby t, zatem rów-
1
nież otrzymujemy 2. Zbiór S' jest więc rozwiązaniem egzemplarza S problemu
sumy podzbioru.
Załóżmy teraz, że istnieje podzbiór S' c S o sumie równej t. Niech
S' = {x 1,, x 1,, ... , xi..} u {Y1,, Yi,' ..., Yi,}. Twierdzimy, że m =ki że V'= {v1,, v1,,
... , v1 } jest pokryciem wierzchołkowym grafu G. Żeby to udowodnić, zacznie-

my od obserwacji, że dla każdej krawędzi e1 eE w elementach zbioru S na
pozycji odpowiadającej e1 są trzy jedynki: po jednej dla każdego z końców
krawędzi e eE i jedna w yi. Ponieważ posługujemy się reprezentacją w zmody-
1
fikowanym układzie czwórkowym, nie ma przeniesień z pozycji e; do ei+ 1 .
W związku z tym na każdej z I.El najmniej znaczących pozycji liczby t udział do
sumy wnosi co najmniej jedno, a co najwyżej dwa spośród x 1• Ponieważ dla
każdej krawędzi co najmniej jedno x 1 wnosi wkład do sumy, V' jest pokryciem
wierzchołkowym. Żeby uzasadnić, że m = k, a więc, że V' jest pokryciem wie-
rzchołkowym rozmiaru k, zauważmy, iż jedyną możliwością osiągnięcia pierw-
szej cyfry liczby t równej k jest wzięcie do sumy dokładnie k liczb spośród X; .

Na rysunku 36.14 pokrycie wierzchołkowe V'= {v1 , v 3 , v4 } odpowiada
podzbiorowi S' = {x1 , x 3 , x 4 , Yo, Y2 , y 3 , y 4 }. Do zbioru S' należą wszystkie YJ
z wyjątkiem y 1 , któremu odpowiada krawędź o obu końcach w V'.

36.5.4. Problemcyklu Hamiltona


Powrócimy teraz do problemu cyklu Hamiltona, zdefmiowanego w pod~
rozdz. 36.2.

1062
36.5. PROBLEMY NP-ZUPEŁNE

TwIERDZENIE 36.14.
Problem cyklu Hamiltona jest NP-zupełny.

DOWÓD
Pokażemy najpierw, że problem HAM-CYCLE należy do klasy NP. Dla da-
nego grafu G = (V, E) naszym świadectwem jest ciąg IVIwierzchołków tworzą­
cych cykl Hamiltona. Algorytm weryfikacji polega na sprawdzeniu, że ten ciąg
zawiera każdy wierzchołek ze zbioru V dokładnie raz i że dopisując pierwszy
wierzchołek jeszcze raz na końcu otrzymujemy cykl w G. Sprawdzenia tego
można dokonać w czasie wielomianowym.
Udowodnimy teraz, że problem HAM-CYCLE jest NP-zupełny, pokazu-
jąc, że 3-CNF-SAT ::s:;;pHAM-CYCLE. Dla danej formuły logicznej cppostaci
3-CNF, zawierającej zmienne x 1 , x 2 , ... , xn i zbudowanej z klauzul C 1 , C2 , ... ,
C1:,z których każda składa się z dokładnie trzech różnych literałów, konstruuje-
my w czasie wielomianowym graf G = (V, E) tak.i, że G zawiera cykl Hamiltona
wtedy i tylko wtedy, gdy formuła cpjest spełnialna. Nasza konstrukcja opiera
się na gadżetach, czyli fragmentach grafu wymuszających pewne jego własności.
Naszym pierwszym gadżetem jest podgraf A pokazany na rys. 36.15a.
Przypuśćmy, że A jest pod grafem pewnego grafu G i że jedynym połączeniem
A z resztą G są wierzchołki a, a', bib'. Załóżmy przy tym, że graf G ma cykl
Hamiltona. Ponieważ każdy cykl Hamiltona w G musi przechodzić przez

(,) (b)

-
'4
-"
A

b ..,
(c) (d)

Rys. 36.15. (a) Gadżet A używany przy redukcji problemu 3-CNF-SAT do HAM-CYCLE. (b)-(c)Jeśli
A jest pod graf em pewnego grafu G, który zawiera cykl Hamiltona i jedyne połączenie A zresztą grafu
G prowadzi przez wierzchołki a, a', bi b', to zamaczone krawędzie stanowią jedyne dwa możliwe
sposoby przechodzenia cyklu Hamiltona przez krawędzie podgrafu A. (d) Skrócone omaczenie
gadżetu A

1063
ROZDZIAŁ 36. NP-ZUPEŁNOŚĆ

wierzchołki z 1 ,
z 2 , z 3 i z4 na jeden ze sposobów pokazanych na rys. 6.15b i c,
możemy traktować podgraf A tak., jak gdyby był on tylko parą krawędzi (a, a')
i (b, b'), ale z ograniczeniem, że każdy cykl Hamiltona w G musi zawierać
dokładnie jedną z tych krawędzi. Wystąpienie gadżetu A będziemy zapisywać
w postaci przedstawionej na rys. 36.15d.
Drugim gadżetem jest podgraf B widoczny na rys. 36.16. Przypuśćmy, że
B jest pod grafem pewnego grafu G i że jedyne połączenie B z resztą G stanowią
wierzchołki b 1 , b 2 , b 3 i b 4 • Cykl Hamiltona w grafie Gnie może przechodzić
przez wszystkie trzy krawędzie (b 1 , b2 ), (b2 , b3 ) i (b3 , b4 ), bo wówczas musiałby
ominąć wszystkie wierzchołki gadżetu oprócz b 1 , b 2 , b 3 i b4 • Cykl Hamiltona
w G może jednak przechodzić przez każdy właściwy podzbiór tego zbioru
krawędzi. Rysunki 36.I6a-e zawierają pięć takich podzbiorów; pozostałe dwa
można otrzymać, odbijając symetrycznie części (b) i (e). Gadżet ten będziemy
przedstawiać jak na rys. 36.I6f; chodzi w nim o to, że do cyklu Hamiltona
trzeba wziąć przynajmniej jedną ze ścieżek wskazywanych przez strzałki.
Graf G, który skonstruujemy, składa się głównie z kopii tych dwóch ga-
dżetów. Konstrukcję ilustruje rys. 36.17. Dla każdej spośród k klauzul formuły
tJ,dołączamy do grafu kopię gadżetu B i łączymy je wszystkie w następujący
sposób. Jeśli przez bu oznaczymy kopię wierzchołka b1 w i-tej kopii gadżetu B,
to dla i= 1, 2, ... , k -1 łączymy b 1, 4 z b 1+ 1 , 1 .
Następnie dla każdej zmiennej x 111formuły q,do grafu dodajemy dwa wierz-
chołki x;,.i x;. Łączymy je ze sobą za pomocą dwóch kopii krawędzi (x;,.,x;),
które dla rozróżnienia oznaczymy jako e111ie,,,. Idea konstrukcji polega na tym,
że jeśli do cyklu Hamiltona wchodzi krawędź e111, to odpowiada to przypisaniu
zmiennej x,,,wartości I. Jeśli do cyklu wchodzi krawędź e,,,, zmiennej tej jest
przypisywana wartość O. Każda para takich krawędzi stanowi dwukrawędzio­
wy cykl; wszystkie temale cykle łączymy ze sobą, dodając krawędzie (x;,.,x::i+1 )
dla m = l, 2, ... , n - 1. Łączymy lewą (odpowiadającą klauzulom) część grafu
z prawą (odpowiadającą zmiennym) częścią za pomocą dwóch krawędzi (b1 , 1 ,
xJ.) i (b1 •4 , xZ) (na rys. 36.17 krawędzie najwyższa i najniższa) .
To nie koniec konstrukcji grafu G, bo musimy jeszcze powiązać zmienne
z klauzulami. Jeśli j-tym literałem klauzuli C 1 jest x,,,,to krawędź (b1i, bi,J+1)
z krawędzią e,., łączymy gadżetem A. Jeśli j-tym literałem klauzuli C; jest
......,x,,,,
to gadżet A umieszczamy między krawędzią (biJ, b1,J+1 ) a kra-
wędzią tf,,,. W przykładzie na rys. 36.17, ponieważ klauzula C2 jest równa
2 v x 3 ), trzy gadżety A umieszczamy następująco:
(x 1 v ......,x
• między (b 2 • 1 , b2 , 2 ) a e 1 ,
• między (b 2 , 2 , b 2 , 3) a e 2 , oraz
• między (b 2 ,3 , b 2 ,J a e3 .
Zauważmy, że połączenie dwóch krawędzi za pomocą gadżetu A oznacza
tak naprawdę zastąpienie każdej z nich pięcioma krawędziami odpowiednio

1064
36.5. PROBLEMY NP-ZUPEŁNE

(a) (b) (c)

(d) (e) lD
Rys. 36.16. Gadżet B używany przy redukcji problemu 3-CNF-SAT do HAM-CYCLE. żadna
ścieżka od wierzchołka h 1 do h„ zawierająca wszystkie wierzchołki gadżetu nie może przechodzić
przez wszystkie trzy krawędzie (h 1 , h2 ), (h2 , h 3 ) i (h 3 , h,.), może jednak przechodzić przez każ.dy
właściwy podzbiór tego zbioru krawędzi. (a}{e) Pięć spośród tych podzbiorów. (I) Skrócone oma-
czenie tego gadżetu; do cyklu Hamiltona musi wchodzić przynajmniej jedna ze wskazywanych
przez strzałki ścieżek

1065
ROZDZIAŁ 36. NP-ZUPEŁNQ$C

z górnej lub dolnej części


rys. 36.15a, jak również - oczywiście - dodanie
połączeń przechodzących przez wierzchołki z. Dany literał może się pojawiać
w kilku klauzulach Gak.np. •x 3 na rys. 36.17), a więc do krawędzi może
dochodzić kilka gadżetów A (np. do e 3 ). W takiej sytuacji dołączamy gadżety
A po kolei, jak to widać na rys. 36.18, zastępując w rzeczywistości krawędź em
lub e·mciągiem krawędzi.
Twierdzimy, że formuła ej,jest spełnialna wtedy i tylko wtedy, gdy graf
G zawiera cykl Hamiltona. Załóżmy najpierw, że G zawiera cykl Hamiltona h.
Udowodnimy, że wówczas formuła ej,jest spełnialna. Cykl h musi mieć okreś­
loną postać:

B -,,

,A

-----\A

Rys. 36.17. Graf G skonstruowany dla formuły ,j> =(•X1 V X2 V •X3)A (Xi V •X2 V X3)A (x1 V X2
v •x 3 ). Wartościowaniem spełniającym szmiennych formuły ,j>jests(x 1) = O,s(x 2 ) = I is(x 3 ) = I, co
odpowiada pokazanemu cyklowi Hamiltona. Zauważmy, że jeśli s(x.,) = l, to krawędź e„ należy do
cyklu Hamiltona, a jeśli s(x ..) = O, to do cyklu należy krawędź e.

1066
36.5. PROBLEMY NP-ZUPEŁNE

x'
'

bu

(b.,. A •'
'"
' ,,
-

(b„ A
•"'
b,.. ,.
(•) (b)
'
Rys. 36.18. Sposób postępowania, gdy do krawędzie. lub e„dochodzi wiele gadżetów A. (a) Frag-
ment rys. 36.17. (b) Faktycznie konstruowany podgraf

• Najpierw przechodzi przez krawędź (h 1 , 1, xl,), idąc od lewej do prawej.


• Następnie przebiega przez wszystkie wierzchołki x:ni x;:.od góry do dołu,
przechodząc albo przez krawędź em, albo przez em, ale nie przez obydwie.
• Następnie przechodzi przez krawędź (h1c,
4 , x:), wracając na lewą stronę grafu.
• Wreszcie przechodzi przez gadżety B z lewej strony, od dołu do góry.

(W rzeczywistości przechodzi także przez krawędzie gadżetów A, nam jednak


podgrafy te służą tylko do wymuszenia wyboru dokładnie jednej z łączonych
przez nie krawędzi}.
Dla danego cyklu Hamiltona h definiujemy następujące wartościowanie
formuły q>. Jeśli krawędź em należy do h, to kładziemy Xm= l. W przeciwnym
razie do h należy krawędź e,,.i kładziemy xm = O.
Twierdzimy, że powyższe wartościowanie spełnia formułę q>.Rozważmy
klauzulę C1 i odpowiadający jej gadżet Bw grafie G. Każda krawędź (b1,1b1,J+ 1 )
jest połączona gadżetem A albo z krawędzią em,albo z em,zależnie od tego czy
j~tym literałem klauzuli jest Xm czy -,xm. Cykl h przechodzi przez krawędź
(b;,1, h;,;+1 ) wtedy i tylko wtedy, gdy wartością odpowiadającego jej literału
jest O. Ponieważ krawędzie (h1, 1 , b1, 2}, (b 1, 2 , b1, 3 ), (b1, 3 , b1, 4 } należą do gadżetu B,
cykl Hamiltona h nie może przechodzić przez wszystkie trzy. Jednej z tych

1067
ROZDZIAŁ 36. NP-ZUPEŁNOSC

trzech krawędzi musi zatem odpowiadać literał, którego wartością jest 1, więc
klauzula Cf jest spełniona. To samo zachodzi dla każdej klauzuli C1, gdzie
i= l, 2, ... , k, a więc jest spełniona cała formula cf,.
W celu udowodnienia odwrotnej implikacji załóżmy, że formuła tp ma
wartościowanie spełniające s. Stosując poniższe reguły, możemy skonstruować
cykl Hamiltona w grafie G: bierzemy do cyklu krawędź em-jeśli xm = 1, a kra-
wędź em -jeśli Xm = O; krawędź (b 1,j, bi,i+ 1 ) bierzemy wtedy i tylko wtedy, gdy
)-ty literał klauzuli C; ma przy tym wartościowaniu wartość O. Reguły te da-
ją się zastosować, bo założyliśmy, że s jest wartościowaniem spełniającym
dla formuły ef,.
Nadmieńmy na koniec, że graf G można skonstruować w czasie wielo-
mianowym. Zawiera on po jednym gadżecie B dla każdej spośród k klauzul
formuły tp.Każdemu wystąpieniu literału w tpodpowiada jeden gadżet A, jest
ich więc w sumie 3k. Ponieważ gadżety A i B są stałego rozmiaru, graf G zawie-
ra O(k) wierzchołków i krawędzi i łatwo skonstruować go w czasie wielomia-
nowym. Przedstawiliśmy zatem redukcję w czasie wielomianowym problemu
3-CNF-SAT do HAM-CYCLE.

36.5.5. Problem komiwojażera
W problemiekomiwojażera, ściśle związanym z problemem cyklu Hamiltona,
komiwojażer musi odwiedzić n miast. Modelując problem za pomocą grafu
pełnego o n wierzchołkach, możemy powiedzieć, że komiwojażer chce znaleźć
marszrutę, czyli cykl Hamiltona, odwiedzając każde miasto dokładnie raz
i kończąc w mieście, z którego wystartował. Koszt podróży z miasta i do miasta
j to liczba całkowita c(i, 1), a komiwojażer chce przebyć marszrutę o minimal-
nym łącznym koszcie, gdzie łączny koszt jest sumą kosztów poszczególnych
krawędzi marszruty. Na rysunku 36.19 na przykład optymalną marszrutą jest
(u, w, v, x, u) o koszcie 7. Język formalny dla problemu komiwojażera to

TSP - {(G, c, k): G - (V, E) jest grafem pełnym,


c jest funkcją V x V-+ Z,
kEZ, oraz
w G istnieje marszruta komiwojażera o koszcie co naj-
wyżej k)

Z poniższego twierdzenia wynika, że zapewne nie istnieje szybki algorytm


dla problemu komiwojażera.

TwlERDZENIE 36.15.
Problem komiwojażera jest NP-zupełny.

1068
'36.5. PROBLEMY NP-ZUPEŁNE

Rys. 36.19. Egzemplarz problemu komiwojażera. Z.amaczone krawędzie stanowią optymalną marsz-
rutę o koszcie 7

DOWÓD
Wykażemy najpierw, re TSP należy do NP. Dla danego egzemplarza problemu
jako świadectwa użyjemy ciągu n wierzchołków marszruty. Algorytm weryfika-
cji polega na upewnieniu się, że ciąg zawiera każdy wierzchołek dokładnie raz,
zsumowaniu kosztów krawędzi i sprawdzeniu, czy otrzymana suma nie prze-
kracza k. Operacje te można z pewnością wykonać w czasie wielomianowym.
żeby udowodnić, że problem TSP jest NP-trudny, wykażemy, że HAM-
TSP. Niech G = (V, E) będzie egzemplarzem problemu HAM-
-CYCLE ,:;;;;p
-CYCLE. Egzemplarz problemu TSP konstruujemy w następujący sposób.
Tworzymy graf pełny G' = (V, E1, gdzie E' = {(i, j): i, je V), i definiujemy
funkcję kosztu c wzorem

jeśli (i, j)eE


c(i,j) = {~: jeśli (i, J)łE

Tak zdefiniowany egzemplarz problemu komiwojażera łatwo skonstruować


w czasie wielomianowym.
Pokażemy teraz, że graf G ma cykl Hamiltona wtedy i tylko wtedy, gdy
graf G' zawiera marszrutę o koszcie co najwyżej O. Załóżmy, że graf G zawiera
cykl Hamiltona h. K a:żrla krawędź cyklu h należy do E, a zatem w grafie G' ma
koszt O. Cykl h jest więc marszrutą w G' o koszcie O. Dla dowodu odwrotnej
implikacji załóżmy, że graf G' zawiera marszrutę h' o koszcie co najwyżej O.
Ponieważ koszty krawędzi z E' są równe O lub 1, koszt marszruty h' wynosi
dokładnie O. Marszruta h' zawiera zatem jedynie krawędzie z E. Wnioskujemy
stąd, że h' jest cyklem Hamiltona w grafie G.


ZADANIA
36.5-1. W problemie izomorfizmu podgrafu mamy dane dwa grafy G 1 i G2 i py-
tamy, czy G 1 jest podgrafem G2 . Wykaż, że problem izomorfizmu pod-
grafu jest NP-zupełny.
36.5-2. Dla danej całkowitoliczbowej macierzy A wymiaru m x n i całkowito­
liczbowego wektora b długości m w problemie zero-jedynkowego programo-

1069
ROZDZIAŁ 36. NP-ZUPEŁNOŚĆ

wania całkowitoliczbowego pytamy, czy istnieje całkowitoliczbowy wektor


x długości n elementów ze zbioru {O, 1} taki, że Ax ~ b. Udowodnij, że
problem zero-jedynkowego programowania całkowitoliczbowego jest
NP-zupełny. (Wskazówka: Redukcja problemu 3-CNF-SAT).
36.5-3. Wykaż, że problem sumy podzbioru jest rozwiązywalny w czasie wielo-
mianowym, jeśli wartość docelowa t jest reprezentowana unarnie.
36.5-4. Wejściem dla problemu podziału zbioru jest zbiór liczb S. Stawianym
pytaniem jest to, czy można te liczby podzielić na dwa zbiory A
i A = S - A tak, żeby Lx = L x. Wykaż, że problem podziału zbioru
-""A -""A
jest NP-zupełny.
36.5-5. Wykaż, że problem ścieżki Hamiltona jest NP-zupełny.
36.5-6. Problem najdłuższego cyklu prostego polega na wyznaczeniu cyklu
prostego (bez powtarzających się wierzchołków) o maksymalnej długości
w danym grafie. Wykaż, że problem ten jest NP-zupełny.
36.5-7. Profesor Marconi twierdzi, że pod graf użyty jako gadżet A w dowodzie
twierdzenia 36.14 jest bardziej skomplikowany niż to konieczne: wierz-
chołki z 3 i z 4 z rys. 36.15a oraz wierzchołki nad i pod nimi są niepotrzebne.
Czy profesor ma rację? To znaczy, czy redukcja z użyciem tak zmniejszo-
nej wersji gadżetu jest poprawna, czy też tracimy własność wymuszania
wyboru jednej z dwóch krawędzi?

Problemy
~1. Zbiór niezależny
Zbiór niezależny w grafie G = ( V, E) to podzbiór V' c V zbioru wierzchołków
taki, że co najwyżej jeden z końców każdej krawędzi z E należy do V'. Problem
zbioru niezależnego polega na znalezieniu zbioru niezależnego maksymalnego
rozmiaru w danym grafie G.

(a) Sformułuj problem decyzyjny związany z problemem zbioru niezależ­


nego i udowodnij, że jest on NP-zupełny. (Wskazówka: Redukcja pro-
blemu kliki).
(b) Przypuśćmy, że mamy daną procedurę - ,.czarną skrzynkę" rozwiązującą
problem decyzyjny z punktu (a). Podaj algorytm znajdowania zbioru nie-
zależnego maksymalnego rozmiaru. Czas działania Twojego algorytmu
powinien być wielomianowy ze względu na IV I i IE I, przy czym pytania
zadawane czarnej skrzynce liczymy jako pojedyncze kroki.

Chociaż decyzyjna wersja problemu zbioru niezależnego jest NP-zupełna, nie-


które szczególne przypadki są rozwiązywalne w czasie wielomianowym.

1070
PROBLEMY

(c) Podaj efektywny algorytm rozwiązujący problem zbioru niezależnego, jeśli


każdy wierzchołek grafu G ma stopień 2. Zanalizuj czas działania i udowo-
dnij poprawność swojego algorytmu.
(d) Podaj efektywny algorytm rozwiązujący problem zbioru niezależnego, jeśli
graf G jest dwudzielny. Zanalizuj czas działania i udowodnij poprawność
swojego algorytmu. (Wskazówka: Wykorzystaj wyniki z podrozdz. 27 .3).

Jft-2. Kolorowaniegrafu
k-kolorowaoiegrafu nieskierowanego G = ( V, E) to funkcja c: V-+ { 1, 2, ..., k}
taka, że c(u) =Fc(v) dla każdej krawędzi (u, v) EE. Inaczej mówiąc, liczby 1, 2,
..., k reprezentują k kolorów, a sąsiednie wierzchołki muszą mieć różne kolory.
Problemkolorowaniagrafupolega na wyznaczeniu minimalnej liczby kolorów
potrzebnych do pokolorowania danego grafu.

(a) Podaj efektywny algorytm wyznaczania 2-kolorowania grafu, o ile takie


kolorowanie istnieje.
(b) Przełóż problem kolorowania grafu na problem decyzyjny. Wykaż, że ów
problem decyzyjny daje się rozwiązać w czasie wielomianowym wtedy i tyl-
ko wtedy, gdy problem kolorowania grafu jest rozwiązywalny w czasie
wielomianowym.
(c) Niech język 3-COLOR będzie zbiorem grafów, dla których istnieje 3-kolo-
rowanie. Wykaż, że jeśli język 3-COLOR jest NP-zupełny, to problem de-
cyzyjny z punktu (b) również jest NP-zupełny.

żeby udowodnić, że język 3-COLOR jest NP-zupełny, dokonamy redukcji ję­


zyka 3-CNF-SAT. Dla danej formuły (p złożonej z m klauzul zawierających
w sumie n zmiennych x 1 , x 2 , ... , x„ skonstruujemy graf G = (V, E} w następują­
cy sposób. Zbiór V zawiera po jednym wier7.Chołk.u dla każdej zmiennej, po
jednym wierzchołku dla negacji każdej zmiennej, po 5 wierzchołków dla każdej
klauzuli oraz 3 wierzchołki specjalne: TRUE, FALSE i RED. Krawędzie grafu są
w dwóch rodzajach: krawędzie „literałowe", niezależne od klauzul, oraz kra-
wędzie „klauzulowe", zależne od klauzul. Krawędzie literalowe łączą w trójkąt
wierzchołki specjalne, a także x 1, -,x 1 i RED dla i= 1, 2, ... , n.

(d) Uzasadnij, żew dowolnym 3-kolorowaniu c grafu złożonego z krawędzi


literałowych dokładnie jeden z dwóch wierzchołków odpowiadających
zmiennej i jej negacji otrzymuje kolor c(TRUE), drugi zaś ma kolor c(FAL-
SE). Uzasadnij, że dla dowolnego wartościowania formuły <Pistnieje 3-ko-
lorowanie grafu złożonego z krawędzi literałowych.

Gadżetu pokazanego na rys. 36.20 używamy w celu wymuszenia spełnienia


warunku odpowiadającego klauzuli (x v y v z). Dla każdej klauzuli potrzebna
jest osobna kopia 5 wierzchołków zaznaczonych na rysunku ciemnym kolore1n;

1071
ROZDZIAŁ 36. NP-ZUPEŁNOSC

TRUE

,-------~
Rys.. 36.20. Gadżet odpowiadający klauzuli (x v y v z), wykorzystywany w problemie 36--2

na rysunku widać też sposób połączenia ich z wierzchołkami odpowiadającymi


literałom klauzuli i z wierzchołkiem specjalnym TRUE.

(e) Uzasadnij, że jeśli każdy spośród wierzchołków x, y i z ma kolor c(TRUE)


lub c(FALSE), to gadżet jest 3-kolorowalny wtedy i tylko wtedy, gdy przy-
najmniej jeden z wierzchołków x, y, z ma kolor c(TRUE).
(f) Dokończ dowód NP-zupełności języka 3-COLOR.

Uwagi do rozdziału
Książka Gareya i Johnsona (79] stanowi doskonałe
wprowadzenie do zagad-
nienia NP-zupełności, zawierając szczegółowe omówienie teorii i katalog wielu
problemów znanych jako NP-zupełne w 1979 r. (Lista dziedzin, w których
występują problemy NP-zupełne, zamieszczona na początku podrozdz. 36.5
jest zaczerpnięta z jej spisu treści). U Hopcrofta i Ullmana [104] oraz Lewisa
i Papadimitriou (I 39] można znale-lć dobre omówienie NP-zupełności w kon-
tekście teorii złożoności. Aho, Hopcroft i Ullman [4] również omawiają tema-
tykę NP-zupełności i podają kilka przykładów redukcji, w tym redukcję prob-
lemu cyklu Hamiltona do problemu pokrycia wierzchołkowego.
Pojęcie klasy P wprowadził w 1964 r. Cobham [44] i, niezależnie, w 1965 r.
Edmonds [61], który wprowadził także pojęcie klasy NP i postawił hipotezę, że
P '#NP.Pojęcie NP-zupełności zaproponował w 1971 r. Cook [49], który po-
dał pierwsze dowody NP-zupełności problemów spelnialności formuł i speł­
nialności formuł 3-CNF. Levin [138] odkrył to pojęcie niezależnie, podając
dowód NP-zupełności problemu wypełniania płaszczyzny. Karp [116] w 1972 r.
wprowadził metodę redukcji i przedstawił szeroką gamę problemów NP~zupeł­
nych. Jego praca zawierała między innymi oryginalne dowody NP-zupełności
problemów kliki, pokrycia wierzchołkowego i cyk.lu Hamiltona. Od tamtych
czasów za sprawą wielu badaczy powstały setki dowodów NP-zupełności roz~
mai tych problemów.
Dowód twierdzenia 36.14 to adaptacja dowodu z pracy Papadimitriou
i Steiglitza [154].
Rozdział 37

Algorytmyaproksymacyjne

Wiele problemów o praktycznym znaczeniu jest NP-zupełnych, ale są one zbyt


ważne, żeby o nich zapomnieć tylko dlatego, że otrzymanie optymalnego
rozwiązania jest trudne. Jeśli problem jest NP-zupełny, nikłe są szanse znale-
zienia algorytmu o złożoności wielomianowej, zapewniającego jego dokładne
rozwiązanie, nie znaczy to jednak,ze wszystko jest stracone. Z NP-zupełnością
radzić sobie można dwojak.o. Po pierwsze, jeśli ro7rniar konkretnych danych
wejściowych jest niewielki, algorytm o wykładniczym czasie działania może
nas w zupełności satysfakcjonować. Po drugie, być może dają się znalei.ć roz-
wiązania prawie optymalne w czasie wielomianowym (w przypadku pesymis-
tycznym albo średnim). W praktyce rozwiązanie prawie optymalne jest często
wystarczające. Algorytm umożliwiający otrzymanie prawie optymalnego roz-
wiązania jest nazywany algorytmem aproksymacyjnym. W tym ro7.dziale przed-
stawimy wielomianowe algorytmy aproksymacyjne dla kilku problemów NP-
-zupełnych.

Oszacowania jakości algorytmów aproksymacyjnych


Załóżmy, że mamy do czynienia z problemem optymalizacyjnym, w którym
każde potencjalne rozwiązanie ma dodatni koszt, i że chcemy znaleźć rozwią­
zanie prawie optymalne. Zależnie od problemu rozwiązanie optymalne może
być 7.definiowane jako to o maksymalnym możliwym koszcie lub o minimal-
nym; zadanie może polegać na maksymalizacji albo na minimalizacji.
Mówimy, że algorytm aproksymacyjny dla danego problemu ma ograni-
czenie względne p(n), jeśli dla dowolnych danych wejściowych rozmiaru n koszt
C rozwiązania konstruowanego przez ów algorytm szacuje się z dokładnością
do czynnika p(n) przez koszt c· rozwiązania optymalnego:

max CC')
( :::;:
c·• C p(n) (37.1)
ROZDZIAŁ 37. ALGORYTMY APROKSYMACYJNE

Definicja ta stosuje się zarówno do problemów minimalizacji, jak i maksy-


malizacji. Dla problemu maksymalizacji O< C ~ c·, a współczynnik C'/C
określa, ile razy koszt rozwiązania optymalnego jest większy od kosztu rozwią­
zania przybliżonego. Podobnie, dla problemu minimalizacji O < c· ~ C,
a współczynnik C/c• określa, ile razy koszt rozwiązania przybliżonego jest
większy od kosztu rozwiązania optymalnego. Ponieważ zakładamy, że wszystkie
rozwiązania mają dodatni koszt, współczynniki te są zawsze dobrze określone.
Ograniczenie względne algorytmu aproksymacyjnego nigdy nie jest mniejsze
niż 1, ponieważ nierówność C/C"< 1 implikuje c·1c > 1. Ograniczeniem
względnym algorytmu optymalnego jest 1, a algorytm aproksymacyjny o dużym
ograniczeniu względnym może dać rozwiązanie znacznie gorsze niż optymalne.
Czasami wygodniej jest operować pojęciem błędu względnego. Dla dowol-
nych danych wejściowych błąd względny definiuje się jako

IC- c·1

gdzie, jak poprzednio, c· jest kosztem rozwiązania optymalnego, a C to koszt
rozwiązania uzyskanego za pomocą algorytmu aproksymacyjnego. Błąd
względny jest zawsze nieujemny. Dla algorytmu aproksymacyjnego i(n) jest
ograniczeniembłędu względnego, jeśli

IC- c·1
--c~----
~ E(n) (37.2)

Z powyższych definicji wynika, że ograniczenie błędu względnego można


oszacować przez funkcję ograniczenia względnego:

,(n) <; p(n) - I (37.3)

(Dla problemu minimalizacyjnego jest to równość, podczas gdy dla problemu


maksymalizacyjnego mamy e(n) = (p(n) - 1)/p(n); spełniona jest więc nierów-
ność (37.3), ponieważ p(n) ~ 1).
Dla wielu problemów skonstruowano algorytmy aproksymacyjne o sta-
łym, niezależnym od n ograniczeniu względnym. W tak.ich wypadkach będzie­
my po prostu pisać p lub E, wskazując w ten sposób na niezależność od n.
Dla innych problemów informatykom nie udało się zaprojektować żad­
nego wielomianowego algorytmu aproksymacyjnego o stałym ograniczeniu
względnym. Wszystko, co można wówczas zrobić, to potraktować ogranicze-
nie względne jako funkcję rosną.cą wraz z rozmiarem danych wejściowych n.
Przykładem takiego problemu jest problem pokrycia zbioru, który omówimy
w podrozdz. 37.3.

1074
ROZDZIAŁ 37. ALGORYTMY APROKSYMACYJNE

Dla niektórych problemów NP-zupełnych istnieją algorytmy aproksyma-


cyjne, za pomocą których można uzyskiwać coraz mniejsze ograniczenie
względne (lub, równoważnie, malejący błąd względny) kosztem dłuższego cza-
su obliczeń. Inaczej mówiąc, zachodzi odwrotnie proporcjonalna współzależ­
ność między czasem obliczeń a jakością aproksymacji. Przykładem może tu
być problem sumy podzbioru, którym zajmiemy się w podrozdz. 37.4. Sytuacja
taka jest na tyle ważna, że zasługuje na własną nazwę.
Schemat aproksymacji dla problemu optymalizacyjnego to algorytm ap-
roksymacyjny, otrzymujący na wejściu nie tylko komplet danych opisujących
problem, ale także wartość li > O taką, że dla każdego ustalonego li schemat
ten jest algorytmem aproksymacyjnym o ograniczeniu błędu względnego li.
Mówimy, że schemat aproksymacji jest wielomianowym schematem aproksy-
macji, jeśli dla dowolnego ustalonego li > Odziała on w czasie wielomianowym
ze względu na rozmiar n jego danych wejściowych.
Czas działania wielomianowego schematu aproksymacji nie powinien rów-
nież rosnąć zbyt gwałtownie, kiedy zmniejsza się li. Najlepiej, gdyby zm.niejsze-
nie li o stały czynnik nie powodowało wzrostu czasu obliczeń potrzebnych do
osiągnięcia dostatecznego przybliżenia o więcej niż stały czynnik. Innymi sło­
wy, chcielibyśmy, żeby czas obliczeń był wielomianem ze względu na n, ale
również i ze względu na 1/e.
Mówimy, że schemat aproksymacji jest w pełni wielomianowym schematem
aproksymacji, jeśli czas jego działania jest wielomianem zarówno ze względu na
1/e, jak i rozmiar n danych wejściowych, gdzie e jest ograniczeniem błędu
względnego schematu. Czas działania schematu mógłby na przykład wynosić
(1/li) 2 n 3 • Dla takiego schematu dowolne zmniejszenie o stały czynnik ograni-
czenia błędu względnego daje się osiągnąć za pomocą odpowiedniego zwięk­
szenia o stały czynnik czasu obliczeń.

Zawartość rozdziału

W trzech pierwszych podrozdziałach tego rozdziału przedstawimy kilka przy-


kładów wielomianowych algorytmów aproksymacyjnych dla problemów NP-
-zupełnych, a w ostatnim podrozdziale zaprezentujemy w pełni wielomianowy
schemat aproksymacji. W podrozdziale 37 .1 omówimy problem pokrycia wie-
rzchołkowego, NP-zupełny problem minimalizacji, dla którego istnieje algo-
rytm aproksymacyjny o ograniczeniu względnym 2. W podrozdziale 37.2
przedstawimy algorytm aproksymacyjny o ograniczeniu względnym 2 dla wer-
sji problemu komiwojażera, w której funkcja kosztu spełnia warunek trójkąta.
Udowodnimy też, że bez założenia o nierówności trójkąta nie może istnieć
algorytm aproksymacyjny o stałym ograniczeniu błędu względnego, o ile tylko
P =ft NP. W podrozdziale 37.3 pokażemy, jak można użyć metody zachłannej
jako efektywnego algorytmu aproksymacyjnego dla problemu pokrycia zbioru,

1075
ROZDZIAŁ 37. ALGORYTMY APROKSYMACYJNE

otrzymując pokrycie, którego koszt w najgorszym przypadku przewyższa koszt


optymalny o czynnik logarytmiczny. Wreszcie w podrozdziale 37.4 przedstawiH
my w pełni wielomianowy schemat aproksymacji dla problemu sumy podzbioru.

37.1. Problempokryciawierzchołkowego
Definicja i dowód NP-zupełności problemu pokrycia wierzchołkowego pojawi-
ły się w pod.rozdz. 36.5.2. Pokryciem wierzchołkowym grafu nieskierowanego
G = (V, E) jest podzbiór V' c V taki, że jeśli (u, v) jest krawędzią w grafie, to
albo ue V', albo ve V' (albo obydwa). Rozmiar pokrycia wierzchołkowego to
liczba należących do niego wierzchołków.
Problem pokrycia wierzchołkowego polega na malezieniu w danym grafie
nieskierowanym pokrycia wierzchołkowego minimalnego rozmiaru. Nazywa-
my je optymalnym pokryciem wierzchołkowym. Problem ten jest NP-trud.ny,
ponieważ odpowiadający mu problem decyzyjny jest NP-zupełny, na mocy
twierdzenia 36.12.
Chociaż znalezienie optymalnego pokrycia wierzchołkowego w grafie G mo-
że nie być łatwe, niezbyt trudno znalei.ć pokrycie wierzchołkowe bliskie optymal-
nemu. Poniższy algorytm aproksymacyjny otrzymuje jako dane wejściowe graf
nieskierowany G, a w wyniku daje pokrycie wierzchołkowe, którego ro7miar na
pewno nie przekracza rozmiaru pokrycia optymalnego więcej niż dwukrotnie.

APPROX-VERTEX-COVER(G)
1 C+-0
2 E'-E[G]
3 while E' ;< 0
4 do wybierz dowolną krawędź (u, v) z E'
5 c-cu{u,v)
6 usuń z E' wszystkie krawędzie incydentne z u lub v
7 return C

Rysunek 37.l ilustruje działanie procedury APPROX-VERTEX-COVER.


Zmienna C przechowuje konstruowane pokrycie wierrehołk.owe. W wierszu
1 jej wartością początkową staje się zbiór pusty. W wierszu 2 zbiór E' staje się
kopią zbioru krawędzi grafu E[G]. W pętli w wierszach 3-6 kolejno wybieramy
krawędź (u, v) z E', dodajemy jej końce u i v do C, a następnie usuwamy z E'
wszystkie krawędzie pokryte przez u lub v. Czas działania tego algorytmu wy-
nosi O(E), jeśli użyjemy odpowiedniej struktury danych do reprezentacji E'.

TwIERDZENIE 37.1.
Ograniczenie względne algorytmu APPROX-VERTEX-COVER wynosi 2.

1076
• • /."', •
/
,.,
..

'• /!
' .

),i..,:IRIJl&l.,Ę,Ą (

• • • • I ,I , • • • • 'b,

. ··-- •
'· h .I!:m:;;:;;~;; .' ', .'
' ','

.. ___ ,,.,

• •
,
' (; 'iii
/
i ll ••w(J
"_,,
)
!' I 'd'


'' . -- • I) '. ' d '
'
'," /
,·'. ~-

• ,,
(e)
(1·--
. ...
'
.
.
• ', i: )'
'
ID •
Rys. 37.1. Dzia/anie procedury APPROX-VERTEX-CoVER. (a) Wejściowy graf Go 7 wierzchołkach
i 8 krawędziach. (b) Krawędź (b, c), oznaczona pogrubioną linią,jest pierwszą krawędzią wybraną
przez procedurę APPROX-VERTEX-CoVER. Wierzchołki bi c, na rysunku jasnoszare, zostają dodane
do zbioru C zawierającego budowane pokrycie wierzchołkowe. Krawędzie (a, b), (c, e) i (c, d),
narysowane linią przerywaną, zostają usunięte, ponieważ są teraz pokryte przez pewien wierz-
chołek z C. (e) Końce krawędzi (e, j) zoslaj, dodane do C. (d) Końce krawędzi (d, g) zostają
dodane do_C. (e) Zbiór C, stanowiący pokrycie wierzchołkowe utworzone przez APPROX-VERTEX-
·COVER, składa się z 6 wierzchołków b, c, d, e, f, g. (I) Optymalne pokrycie wierzchołkowe tego
grafu zawiera tylko 3 wierzchołki: h, d j e

DOWÓD
Zbiór C skonstruowany przez procedurę APPROX-VERTEX-COVERjest pokry-
ciem wierzchołkowym, ponieważ pętla w algorytmie jest wykonywana tak dłu­
go, aż każda krawędź z E[G] zostanie pokryta przez jakiś wierzchołek z C.
Żeby się przekonać, że algorytm APPROX-VERTEX-COVERoblicza pokry-
cie wierzchołkowe co najwyżej dwukrotnie większe od optymalnego, oznaczmy
przez A zbiór krawędzi wybranych w wierszu 4 procedury APPROX-VERTEX-
-COVER. Żadne dwie krawędzie z A nie mają wspólnego wierzchołka, ponieważ
za każdym razem, kiedy w wierszu 4 jest wybierana krawędź, wszystkie inne
krawędzie incydentne z jej końcami zostają usunięte z E' w wierszu 6. Każde
wykonanie operacji w wierszu 5 dodaje dwa nowe wierzchołki do C, zatem
ICJ = 21AI.Aby jednak pokryć wszystkie krawędzie z A, każde pokrycie wierz-
chołkowe - w szczególności pokrycie optymalne C: - musi zawierać przynaj-
mniej jeden z końców każdej krawędzi z A. Ponieważ żadne dwie krawędzie

1077
ROZDZIAŁ 37. ALGORYTMY APROKSYMACYJNE

w A nie mają wspólnego końca, żaden wierzchołek pokrycia nie jest incydentny
z więcej niż jedną krawędzią z A. Mamy zatem IAI::;;:;ic"I i ICI~ 21c1,co
kończy dowód twierdzenia.

ZADANIA

37.1-1. Podaj przykład grafu, dla którego algorytm APPROX-VERTEX-COVER
zawsze znajduje rozwiązanie gorsze od optymalnego.
37.1-2. Profesor Nixon proponuje heurystykę rozwiązywania problemu pokry-
cia wierzchołkowego polegającą na wielokrotnym wybieraniu wierzchołka
o najwyższym stopniu i usuwaniu wszystkich incydentnych z nim krawę­
dzi. Podaj przykład dowodzący, że heurystyka profesora nie ma ogranicze-
nia względnego 2.
37.1-3. Podaj efektywny algorytm zachłanny znajdowania optymalnego po-
krycia wierzchołkowego dla drzewa, działający w czas.ie liniowym.
37.1-4. Z dowodu twierdzenia 36.12 wiemy, że problem pokrycia wierzchoł­
kowego i NP-zupełny problem kliki są dualne w tym sens.ie, że optymalne
pokrycie wierzchołkowe jest dopełnieniem kliki maksymalnego rozmiaru
w dopełnieniu grafu. Czy z tej współzależności wynik.a istnienie algorytmu
aproksymacyjnego o stałym ograniczeniu względnym dla problemu kliki?
Odpowiedź uzasadnij.

37.2. Problemkomiwojażera
W problemie komiwojażera, wprowadzonym w podrozdz. 36.5,5, mamy dany
pełny graf nieskierowany G = (V, E), z którego każdą krawędzią (u, v) EE jest
związany nieujemny całkowity koszt c(u, v), a musimy znaleźć cykl Hamiltona
(marszrutę) w Go minimalnym koszcie. Rozszerzając naszą notację, oznaczmy
przez c(A) łączny koszt krawędzi w podzbiorze A c E:

c(A) = L c(u, v)
(11,u)1o..t

W wielu praktycznych sytuacjach zawsze najtaniej jest iść bezpośrednio


z u do w; pójście przez jakikolwiek pośredni punkt v nie może być tańsze.
Inaczej mówiąc, usunięcie pośredniego punktu na drodze między dwoma węz­
łami nigdy nie zwiększa kosztu. Sytuację taką można opisać formalnie, mó-
wiąc, że funkcja kosztu c spełnia nierówność trójkąta, tzn. dla wszystkich wierz-
chołków u, v, w E V zachodzi zależność

c(u, w)::;;:;c(u, v) + c(v, w)

1078
37.2. PROBLEM KOMIWOJAŻERA

Nierówność trójkąta jest naturalna i w wielu zastosowaniach jest auto-


matycznie spełniona. Jeśli na przykład wierzchołki grafu są punktami na płasz­
czyźnie, a koszt krawędzi łączącej dwa wierzchołki to zwykła euklidesowa od-
ległość między nimi, nierówność trójkąta jest spełniona.
Zgodnie z zad. 3 7.2-1 mimo ograniczenia dopuszczalnych funkcji kosztu
do spełniających nierówność trójkąta problem komiwojażera pozostaje NP-zu-
pełny. Prawdopodobnie nie znajdziemy zatem wielomianowego algorytmu roz-
wiązującego ten problem dokładnie. Zamiast tego warto szukać dobrych al-
gorytmów aproksymacyjnych.
W podrozdziale 37.2-1 analizujemy algorytm aproksymacyjny o ograni-
czeniu względnym 2 dla problemu komiwojażera z nierównością trójkąta.
W podrozdziale 37.2.2 dowodzimy, że bez założenia o nierówności trójką­
ta nie istnieje algorytm aproksymacyjny o stałym ograniC"Zeniuwzględnym,
o ile P #NP.

37.2.1. Problem komiwojażera z nierównością trójkąta


Poniższy algorytm oblicza bliską optymalnej marszrutę w grafie nieskierowa-
nym G, wykorzystując do tego algorytm znajdowania minimalnego drzewa
rozpinającego MST-PRIM z podrozdz. 24.2. Przekonamy się, że jeśli funkcja
kosztu spełnia nierówność trójkąta, marszruta wyznaczana przez ten algorytm
jest co najwyżej dwa razy dłuższa niż optymalna.

APPROX-TSP-TOUR(G,c)
1 wybierz wierzchołek re V[G] na „korzeń"
2 zbuduj minimalne drzewo rozpinające T dla G o korzeniu r
za pomocą procedury MST-PRIM(G, c, r)
3 niech L będzie listą wierzchołków drzewa T w kolejności preorder
4 return cykl Hamiltona H odwiedzający wierzchołki w takiej kolejności
jak w L

Jak mówiliśmy w podrozdz. 13.1, przejście drzewa metodą preorder polega


na rekurencyjnym odwiedzaniu wszystkich wierzchołków drzewa, przy czym
wierzchołek jest wypisywany, kiedy napotykamy go po raz pierwszy, przed
odwiedzeniem któregokolwiek z jego synów.
Rysunek 37.2 ilustruje działanie procedury APPROX-TSP-TOUR.Część (a)
rysunku to dany zbiór wierzchołków, a część (b) - minimalne drzewo roz-
pinające T o korzeniu w wierzchołku a, utworzone za pomocą algorytmu
MST-PRIM. Część (c) obrazuje sposób odwiedzania wierzchołków drzewa T
metodą preorder, a część (d) - odpowiadającą mu marszrutę, wyznaczaną
przez algorytm A.PPROX-TSP-TOUR.W części (e) widać optymalną marszrutę,
około 23% krótszą.

1079
ROZDZIAŁ 37. ALGORYTMYAPROKSYMACYJNE

@-
t '~ e


---® - .
h
(>)
I (b)

(c)
1-1

(d) (cl

Rys. 37.l. Działanie procedury APPROX-TSP·TOUR.(a) Dany zbiór punktów leżących w węzłach
siatki całkowiloliczbowej. Na przy kl.ad j znajduje się jedną jednostkę na prawo i dwie jednostki
powyżej h. Funkcją kosztu pary punktów jest zwykła euklidesowa odległość między nimi. (b)
Minimalne drzewo rozpinające T dla tych punktów, wyznaczone przez procedurę MST-PRIM.
Wierzchołek a jest korzeniem. Wierzchołki są poetykietowane tak, jak były dodawane do drzewa
przez procedurę MST-PRIM, w porządku alfabetycznym. (e) Obejście drzewa T, zaczynając od a.
Wierzchołki są odwiedzane w kolejności a, b, c, b, h, b, a, d, e,j, e, g, e, d, a. Przechodz.ąc drzewo
T metodą preorder, wypisujemy wierzchołek tylko wtedy, kiedy napotykamy go po raz pierwszy,
co daje kolejność a, b, c, h, d, e,j, g. (d) Marszruta otrzymana przez odwiedzenie wierzchołków
w kolejności wyznaczonej przez przejście metodą preorder. Tę właśnie marszrutę H oblicza al-
gorytm APPROX·TSP-TouR.Jej łączny koszt wynosi w przybliżeniu 19,074. (e) Optymalna marsz-
ruta 1t dla danego zbioru wierzchołków. Jej łączny koszt wynosi około 14,715
1080
37.2. PROBLEM KOMIWOJA2ERA

Czas działania algorytmu APPROX-TSP-TOURwynosi 0(E) = 0(V 2 ), po-


nieważ wejściowy graf jest grafem pełnym (patrz W. 24.2-2). Pokai.emy teraz, że
jeśli funkcja kosztu dla konkretnych danych w problemie komiwojażera spełnia
nierówność trójkąta, to algorytm APPROX-TSP-TOUR znajduje marszrutę, której
koszt przewyższa koszt optymalnej marszruty nie więcej niż dwukrotnie.

TwlERDZENIE37.2.
Algorytm APPROX-TSP-TOURjestalgorytmem aproksymacyjnym z ogranicze-
niem względnym 2 dla problemu komiwojażera z nierównością trójkąta.

DOWÓD
Oznac11i1yprzez Jt optymalną marszrutę dla danego zbioru wierzchołków.
Warunkiem równoważnym treści twierdzenia jest c(H)::;;;;2c(d), gdzie H jest
marszrutą obliczoną przez algorytm APPROX-TSP-TOUR.Ponieważ przez
usunięcie dowolnej krawędzi z marszruty otrzymujemy drzewo rozpinające,
więc jeśli T jest minimalnym drzewem rozpinającym dla danego zbioru wierz-
chołków, to

c(n" c(H') (37.4)

Pełne przejściedrzewa T polega na wypisywaniu wierzchołków, kiedy są od-


wiedzane po raz pierwszy, ale również za każdym razem kiedy wracamy do
nich po odwiedzeniu poddrzewa. Oznaczmy tak otrzymany ciąg wier7.Cholków
przez W. Pełne przejście w naszym przykładzie daje kolejność

a, b, c, b, h, b, a, d, e,f, e, g, e, d, a

Ponieważ w trakcie pełnego przejścia przechodzimy każdą krawędź T dokład­


nie dwa razy, mamy

c(W) =2c(n (37.5)

Z równań (37.4) i (37.5) wynika, że

c(W).; 2c(H') (37.6)

a więc koszt W jest co najwyżej dwa razy większy niż koszt optymalnej
marszruty.
Niestety, W nie określa zwykle marszruty, gdyż niektóre wierzchołki są
odwiedzane więcej niż raz. Korzystając z nierówności trójkąta, możemy jednak
wyeliminować wizytę w dowolnym wierzchołku z W, nie powiększając kosztu.
(Usunięcie z W wierzchołka v odwiedzanego między u a w odpowiada przejściu

1081
ROZDZIAŁ 37. ALGORYTMY APROKSYMACYJNE

bezpośrednio z u do w). Stosując tę operację wielokrotnie, możemy usunąć


z W wszystkie, oprócz pierwszego, wystąpienia każdego wierzchołka. W na-
szym przykładzie dostaniemy w ten sposób kolejność

a, b, c, h, d, e,f, g
Jest to taka sama kolejność, jak otrzymana przez przejście metodą preorder
drzewa T. Niech H będzie cyklem, na którym wierzchołki występują w tej
właśnie kolejności. Jest to cykl Hamiltona, ponieważ każdy wierzchołek jest
odwiedzany dokładnie raz, i to jego właśnie oblicza algorytm APPROX-TSP-
-TOUR. Ponieważ cykl H otrzymaliśmy, usuwając wierzchołki z pełnego przejś­
cia W, zachodzi więc

c(H),:; c(W) (37.7)

Połączenie nierówności (37.6) i (37.7) kończy dowód twierdzenia.


Pomimo dobrego ograniczenia względnego, wynikającego z twierdzenia 37.2,
APPROX-TSP-TOUR nie jest zwykle najpraktyczniejszym algorytmem dla tego
problemu. Istnieją inne algorytmy aproksymacyjne w praktyce zachowujące się
zazwyczaj znaci.nie lepiej (patrz uwagi na końcu tego rozdziału).

37.2.2. Ogólny problem komiwojażera


Jeśli odrzucimy założenie, że funkcja kosztu c spełnia nierówność trójkąta,
to w wielomianowym czasie nie da się znaleźć dobrej przybliżonej marszruty,
o ile P # NP.

TWIERDZF..NIE 37 .3.
Jeśli P #- NP i p ~ I, to nie istnieje wielomianowy algorytm aproksymacyjny
o ograniczeniu względnym p dla ogólnego problemu komiwojażera.

DOWÓD
Dowód polega na doprowadzeniu do sprzeczności. Załóżmy przeciwnie, że dla
pewnej liczby p ~ 1 istnieje wielomianowy algorytm aproksymacyjny A
o ograniczeniu względnym p. Bez straty ogólności możemy założyć, że p jest
liczbą całkowitą, w razie potrzeby zaokrąglając je w górę. Pokażemy, jak uży­
wać algorytmu A do rozwiązywania problemu cyklu Hamiltona (zdefiniowa-
nego w podrozdz. 36.5.5) w czasie wielomianowym. Ponieważ problem cyklu
Hamiltona jest NP-zupełny, na mocy twierdzenia 36.14, z możliwości rozwią­
zania go w czasie wielomianowym wynika, że P = NP (tw. 36.4).

1082
37.2. PROBLEM KOMIWOJA2ERA

Niech G = (V. E) będzie grafem, dla którego mamy rozwiązać problem


cyklu Hamiltona. Chcemy efektywnie stwierdzić, czy G zawiera cykl Hamilto-
na, wykorzystując hipotetyczny algorytm aproksymacyjny A. Zamieniamy graf
G w dane wejściowe dla problemu komiwojażera w następujący sposób. Niech
G' = (V, E') będzie grafem pełnym na zbiorze V, to znaczy

E' - {(u, v):u, veVi u,' v}

Przypisujemy całkowitoliczbowy koszt każdej krawędzi z E' zgodnie z poniż­


szym wzorem:

l, jeśli (u, v)eE


c(u, v)- {PIVI + 1, w przeciwnym razie

Reprezentacje G' i c można skonstruować z reprezentacji G w czasie wielo-


mianowym ze względu na IVI i I.El.
Rozważmy teraz problem komiwojażera (G', c). Jeśli początkowy graf G
ma cykl Hamiltona H, to funkcja kosztu c przypisuje każdej krawędzi H
koszt 1, zatem ( G', c) zawiera marszrutę o koszcie IJ/1.
Jeśli natomiast G nie ma
cyklu Hamiltona, to każda marszruta w G' musi zawierać pewną krawędź nie
należącą do E. Każda marszruta przechodząca przez krawędź spoza E ma
jednak koszt równy przynajmniej

(plVI + 1) + (IVI - 1) > pl VI

Ponieważ krawędzie spoza grafu G są tak kosztowne, istnieje duża luk.a między
kosztem marszruty stanowiącej cykl Hamiltona w G (koszt IV]) a kosztem
dowolnej innej marszruty (koszt większy niż PlV]).
Co się dzieje, jeśli zastosujemy algorytm aproksymacyjny A do problem.u
komiwojażera (G', c)? Algorytm A zawsze znajduje marszrutę o koszcie nie
większym niż p razy koszt optymalnej marszruty, więc jeśli G zawiera cykl
Hamiltona, to A musi go znaleźć. Jeśli G nie ma cyklu Hamiltona, to A znaj-
duje marszrutę o koszcie większym niż plVj. Możemy zatem użyć algorytmu
A do rozwiązania problemu cyklu Hamiltona w czasie wielomianowym.


ZADANIA
37.2-1. Pokaż, jak w czasie wielomianowym można przekształcić jeden przy-
padek problemu komiwojażera w inny, którego funkcja kosztu spebtia
nierówność trójkąta. Obydwa problemy muszą mieć taki sam zbiór opty-
malnych marszrut. Wyjaśnij, dlaczego takie wielomianowe przekształcenie
nie przeczy twierdzeniu 37.3.

1083
ROZDZIAŁ 37. ALGORYTMY APROKSYMACYJNE

37.2-2. Rozważmy następującą heurystykę najblii.szego punktu służącą do bu-


dowania przybliżenia optymalnej marszruty komiwojażera. Zaczynamy od
trywialnego cyklu składającego się z jednego dowolnie wybranego wierz-
chołka. W każdym kroku znajdujemy wierzchołek u, nie należący do cy-
klu, ale taki, że jego odległość od cyklu (tzn. od najbliższego mu wierzchoł­
ka z cyklu) jest minimalna. Przyjmijmy, że v jest wierzchołkiem na cyklu
leżącym najbliżej u. Rozszerzamy cykl o wierzchołek u, wstawiając go za-
raz po v. Powtarzamy to dopóty, dopóki wszystkie wierzchołki nie znajdą
się na cyklu. Udowodnij, że powyższa heurystyka wnożliwia znalezienie
marszruty, której łączny koszt nie przewyższa kosztu marszruty optymal-
nej więcej niż dwukrotnie.
37.2-3. Problem komiwojażera-krótkodystansowca polega na znalezieniu cyklu
Hamiltona, w którym długość najdłuższej jego krawędzi jest minimalna.
Przyjmując, że funkcja kosztu spełnia warunek trójkąta, wykaż, że dla tego
problemu istnieje wielomianowy algorytm aproksymacyjny z ograniczeniem
względnym 3. (Wskazówka: Udowodnij przez indukcję, że możemy odwie-
dzić wszystkie wierzchołki minimalnego drzewa rozpinającego, każdy do-
kładnie jeden raz, wykonując pełne przejście drzewa i przeskakując niektóre
wierzchołki, ale nigdy więcej niż dwa kolejne wierzchołki drzewa naraz).
37 .2-4. Załóżmy, że wierzchołki w problemie komiwojażera są punktami na
płaszczyźnie i że koszt c(u, v) jest euklidesową odległością między punk-
tami u i v. Udowodnij, że w optymalnej marszrucie nie ma samoprzecięć.

37.3. Problempokryciazbioru
Problem pokrycia zbioru to problem optymalizacyjny stanowiący model dla
wielu zadań związanych z doborem zasobów. Jest on uogólnieniem NP-zupeł­
nego problemu pokrycia wierzchołkowego, a zatem jest również NP-trudny.
Algorytm aproksymacyjny dla problemu pokrycia wierzchołkowego nie daje
się tu jednak zastosować, musimy więc szukać innych rozwiązań. Przedstawi-
my prostą zachłanną heurystykę o logarytmicznym ograniczeniu względnym.
Oznacza to, że wraz ze wzrostem rozmiaru problemu rozmiar rozwiązania
przybliżonego może rosnąć w stosunku do rozmiaru optymalnego rozwiąza~
nia. Ponieważ jednak funkcja logarytmiczna rośnie dość wolno, taki algorytm
aproksymacyjny może mimo wszystko dawać użyteczne wyniki.
Dane dla problemu pokrycia zbioru to para (X, !F), składająca się ze zbioru
skończonego X i rodziny !F podzbiorów X takiej, że każdy element zbioru
X należy do przynajmniej jednego podzbioru z rodziny §':

us
x- s.,

1084
37.3. PROBLEM POKRYCIA ZBIORU

Mówimy, że podzbiór Se:F pokrywa swoje elementy. Problem polega na zna-


lezieniu podrodziny rt c :F minimalnego rozmiaru, której elementy pokrywa-
ją cały zbiór X:

X= US (37.8)
s,.
O każdej rodzinie et, spełniającej warunek (37.8), będziemy mówić, że pokrywa
X. Rysunek 37.3 stanowi ilustrację problemu .

• s, • •
• • •
• • s,

•s, s, •s, •s,
Rys. 37.3. Przykładowe dane (X, ') dla problemu pokrycia zbioru, gdzie X sirłada się z 12 czarnych
s.,
punktów, a gr = {Sv S'/;>S 3, S4, Sj> S6 }. Minimalne pokrycie zbioru to I( = {S3, s,}. Algorytm
zachłanny znajduje pokrycie rozmiaru 4, wybierając kolejno zbiory S 1, s., S, i S 1

Do problemu pokrycia zbioru sprowadza się wiele często pojawiających


się problemów kombinatorycznych. Rozważmy następujący prosty przykład.
Przypuśćmy, że X reprezentuje zbiór umiejętności niezbędnych do rozwiązania
pewnego zadania i że mamy do dyspozycji pewną grupę ludzi, którzy mogą
pracować nad jego rozwiązaniem. Chcemy utworzyć komisję, składającą się
z możliwie najmniejszej liczby osób i taką, żeby dla każdej spośród umiejętno­
ści ze zbioru X pewien członek komisji ją posiadał. W decyzyjnej wersji prob-
lemu pokrycia zbioru pytamy, czy istnieje pokrycie rozmiaru co najwyżej k,
gdzie k jest dodatkowym parametrem wchodzącym w skład danych wejścio­
wych dla problemu. Decyzyjna wersja problemu jest NP-zupełna, czego wyka-
zanie jest celem zad. 37.3-2.

Zachłanny algorytm aproksymacyjny

Metoda zachłanna polega na wybieraniu, w każdej fazie, zbioru S pokrywają­


cego najwięcej spośród nie pokrytych dotychczas elementów.

GREEDY-SET-COVER(X, :F)
1 U+-X

1085
ROZDZIAŁ 37. ALGORYTMY APROKSYMACYJNE

2 re-0
3 while U i' 0
4 do wybierz SE ff, który maksymalizuje IS n Ul
5 U+-U-S
6 lf-lfu{S}
7 returnre

W przykładzie
na rys. 37.3 algorytm GREEDY-SET-COVERdodaje kolejno do
rezbiory fl'1, S4 , S5, S3 .
Algorytm działa w sposób następujący. W każdej fazie U oznacza zbiór nie
pokrytych dotychczas elementów. Zbiór qJ zawiera konstruowane pokrycie.
Wiersz 4 to krok, w którym jest podejmowana decyzja zachłanna. Wybierany
jest podzbiór S, pokrywający możliwie najwięcej spośród nie pokrytych ele-
mentów (remisy są rozstrzygane w dowolny sposób). Po wybraniu S jego ele-
menty są usuwane z U, a S zostaje dodany do qJ. Kiedy algorytm kończy
działanie, zbiór qJ stanowi podrodzinę !F pokrywającą X.
Algorytm GREEDY-SET-COVERłatwo zaimplementować tak, by działał
w czasie wielomianowym ze względu na IXI i l!FI.Ponieważ liczba przebiegów
pętli w wierszach 3-6 wynosi co najwyżej min(]Xl,IFI), a wnętrze pętli można
zaimplementować tak, żeby wykonywało się w czasie O(IXI l!FI), istnieje im-
plementacja działająca w czasie O(IXI JF!min(JXI, 1§1)). Celem zadania 37.3-3
jest uzyskanie złożoności liniowej.

Analiza
Wykażemy teraz, żepokrycie zbioru znajdowane przez algorytm zachłanny nie
jest dużo większe od optymalnego. Dla wygody w tym ro:zdziale d-tą liczbę
harmoniczną lid= L' 1/i (patrz podrozdz. 3.1) będziemy oznaczać przez H(d).
i= 1

fwIERDZENIE 37.4.
Ograniczenie względne algorytmu GREEDY-SET-COVERwynosi

J/(max{l.>1:
Sc9'})

DOWÓD
Dowód przeprowadzimy, związując z każdym zbiorem wybieranym przez al-
gorytm pewien koszt, ro:zdzielając ten koszt między elementy pokrywane po
raz pierwszy i wykorzystując owe koszty do wyprowadzenia zapowiedzianej
zależności między rozmiarem optymalnego pokrycia q/• a rozmiarem pokrycia
q/ znajdowanego przez algorytm. Niech S; oznacza i-ty podzbiór wybierany
przez procedurę GREEDY-SET-COVER;dodanie przez algorytm S; do ma re
1086
37.3. PROBLEM POKRYCIA ZBIORU

koszt jednostkowy. Koszt wybrania Si rozdzielamy równo między elementy


pokrywane przez S 1 po raz pierwszy. Dla każdego xeX oznaczmy koszt zwią­
zany z elementem x jak.o c"'.Każdemu elementowi przypisujemy koszt tylko
jeden raz, kiedy zostaje pokryty po raz pierwszy. Jeśli x jest pokryty po raz
pierwszy przez S1, to

C = ·----------- I
"' IS; - (S1 u S2 u ... u S1_ 1)I
Algorytm znajduje pokrycie CCo całkowitym koszcie l<tl,a koszt ten zostaje
rozdzielony między elementy zbioru X. Ponieważ optymalne pokrycie <t • także
pokrywa X, mamy

(37.9)

Dalsza część dowodu opiera się


na następującej istotnej nierówności, któ-
rej prawdziwość wykażemy poniżej. Dla dowolnego zbioru S należącego do
rodziny :F mamy

L
,.,c,.; H(ISJ) (37.10)

Z nierówności (37.9) i (37.10) wynika, że

l~I .; L H(ISJ)
Se'#•

.; l~·l·H(max{ISl:Seji,})
. ' ''
co dowodzi tezy twierdzenia. Pozostaje więc jedynie wykazać n1erownosc
(37.10). Dla dowolnego zbioru Se:F oraz i= 1, 2, ... , 1'1Pfl,
niech

U; - IS - (S, uS,u ... uS;)I

będzie liczbą elementów S nadal nie pokrytych po wybraniu przez algorytm


zbiorów S 1, S 2 , •.• , S;. Zdefiniujmy dodatkowo l4J= !SIjako liczbę elementów S
nie pokrytych na samym początku. Niech k będzie najmniejszym takim indek-
sem, że uk = O, a więc każdy element Sjest pokryty przynajmniej przez jeden
spośród zbiorów S 1, S 2, ••• , Sk. Wówczas dla i= 1, 2, ... , k zachodzi u1_ 1 ~ u1,
a zbiór S 1 pokrywa po raz pierwszy u1_ 1 - u, elementów S. Zatem

1087
ROZDZIAŁ 37. ALGORYTMY APROKSYMACYJNE

Zauważmy, że

1s,- (s, us, u ...u s,_,)I;,1s- (s,us, u ...u s,_,)I

ponieważ zachłanny wybór S1 zapewnia, że S nie pokrywa większej liczby no-


wych elementów niż S; (w przeciwnym. razie zamiast S1 zostałby wybrany S).
Mamy zatem

Dla liczb naturalnych a i b, gdzie a < b, mamy

H(b) - H(a) -
•L 1/i
1=11+ 1

I
;, (b - a) b
Po zastosowaniu tej nierówności otrzymujemy sumę „teleskopową"


L c, <: L (H(u,_,) - H(uJ)
XES /"' 1

- H(u,,) - H(u,)
- H(u,,) - H(O)
- H(u,,)
- H(ISI)

ponieważ H(O) =O.Kończy to dowód nierówności (37.10).


WNIOSEK37,5.
Algorytm GREEDY-SET-COVERma ograniczenie względne (lnlX] + 1).

DOWÓD
Wynika z nierówności {3.12) i twierdzenia 37.4.

-------------------------

1088
37.4. PROBLEM SUMY PODZBIORU

W niektórych zastosowaniach max{ISJ:SE.F} jest niewielką stałą, więc


rozwiązanie znajdowane przez algorytm GREEDY-SET-COVERjest co najwyżej
niewielką stałą liczbę razy większe od optymalnego. Jednym z takich zastoso-
wań jest wykorzystanie powyższej heurystyki do obliczenia aproksymacji op-
tymalnego pokrycia wierzchołkowego w grafie o wierzchołkach stopnia co naj-
wyżej 3. W tym wypadku rozwiązanie znajdowane przez GRBBDY-SET-COVER
jest co najwyżej H(3) = 11/6 raza większe od optymalnego, co stanowi oszaco-
wanie nieco lepsze niż zapewniane przez APPROX-VERTEX-COVER.

ZADANIA
37.3-1. Potraktujmy każde z poniższych słów jak.o zbiór liter: {arid, dash, drain,
heard, lost, nosa, shun, slate, snare, thread}. Wskaż pokrycie obliczone
przez algorytm GREEDY-SET-COVER,jeśli remisy są rozstrzygane na ko-
rzyść słowa znajdującego się wcześniej w słowniku.
37.3-2. Udowodnij, stosując redukcję problemu pokrycia wierzchołkowego, że
wersja decyzyjna problemu pokrycia zbioru jest NP-zupełna.
37.3-3. Pokaż, jak zaimplementować algorytm GREEDY-SET-COVBR, żeby

działał w czasie O( L
s,, ISJ).
37.3-4. Znajdź prosty dowód poniższej słabszej wersji twierdzenia 37.4:

l~I,; J~'Jmax{JSJ:SeF}

37.3-5. Przedstaw konstrukcję


rodziny podzbiorów demonstrującej, że liczba
różnych rozwiązań obliczanych przez algorytm GREEDY-SET-COVER
może być wykładnicza ze względu na rozmiar problemu. (Różne rozwią­
zania biorą się z różnych sposobów rozstrzygania remisów przy wyborze S
w wierszu 4).

37.4. Problemsumypodzbioru
Dane wejściowe dla problemu sumy podzbioru stanowi para (S,t), gdzie Sjest
zbiorem {Xi, x 2, ••• , xn} dodatnich liczb całkowitych, a t jest dodatnią liczbą
całkowitą. Nasz problem decyzyjny polega na rozstrzygnięciu, czy istnieje pod-
zbiór zbioru S, którego suma równa jest dokładnie docelowej wartości t. Prob-
lem ten jest NP-zupełny (patrz podrozdz. 36.5.3).
Związany z powyższą wersją decyzyjną problem optymalizacyjny pojawia
się w praktycznych zastosowaniach. W problemie optymalizacyjnym chcemy
znaleźć podzbiór {x 1, x 2, •••, xn}, którego suma jest możliwie największa, ale nie
przewyższa t. Przypuśćmy na przykład, że mamy ciężarówkę, na którą można
załadować nie więcej niż t kilogramów towaru, oraz n różnych skrzynek do

1089
ROZDZIAŁ 37. ALGORYTMY APROKSYMACYJNE

przewiezienia, przy czym i-ta skrzynka waży x 1 kilogramów. Chcemy załado­


wać na ciężarówkę jak najwięcej, nie przekraczając jej nośności.
W tym rozdziale przedstawimy algorytm wykładniczy dla tego problemu
optymalizacyjnego, a następnie pokażemy, jak przerobić go na w pełni wielo-
mianowy schemat aproksymacji. (Przypomnijmy, że w pełni wielomianowy
schemat aproksymacji działa w czasie wielomianowym zarówno ze względu na
!/,,jak i n).

Algorytm wykładniczy

Jeśli L jest ciągiem a x - jeszcze jedną liczbą naturalną, to


liczb naturalnych,
przez L + x będziemy oznaczać ciąg liczb otrzymany z L przez zwiększenie
każdego jego elementu o x. Jeśli na przykład L = (1, 2, 3, 5, 9), to
L + 2 = (3, 4, 5, 7, 11). Będziemy używać tego oznaczenia również dla zbio-
• •
row, a więc

S+x = {s + x:seS}
Będziemy wykorzystywać pomocniczą procedurę MERGE-LISTS(L, L'), zwra-
cającą posortowany ciąg stanowiący efekt scalenia dwóch posortowanych cią­
gów wejściowych Li L'. Podobnie jak procedura MERGE, używana przy sor-
towaniu przez scalanie (podrozdz. 1.3.1), MERGE-LISTS działa w czasie
O(ILI + ]T...'I). (Pseudokodu procedury MERGE-LISTS nie zamieszczamy). Dane
wejściowe dla procedury EXACT-SUBSET-SUM stanowi zbiór S = {x 1, x 1 , ••• , xn}
i docelowa wartość t.

EXACf-SUBSET-SUM(S,t)
I n~ISI
2 Lo~<o>
3 fori-1 ton
4 do LJ - MERGE-LISTS(L1_i, L 1_ 1 + xJ
5 usuń z L, wszystkie elementy większe niż t
6 return największy element listy L~

Niech P 1 oznacza zbiór wszystkich możliwych wartości, jakie można otrzy-


mać wybierając (być może pusty) podzbiór zbioru {x1, x 2, ••• , x 1} i sumując jego
elementy. Jeśli na przykład S = {!, 4, 5}, to

P,={0, I}
P,= {O,1, 4, 5}
P, - {O, I, 4, 5, 6, 9, 10}

1090
37.4. PROBLEM SUMY PODZBIORU

Opierając się na równości

(37.11)

możemy udowodnić przez indukcję względem


i (patrz zad. 37.4-1), że lista L 1
jest posortowanym ciągiem wszystkich elementów zbioru P;, których wartość
nie przekracza t. Ponieważ długość ciągu L; może sięgać 2 1, algorytm EXACT-
-SUBSET-SUMjest w ogólności wykładniczy, chociaż w szczególnych przypad-
kach, kiedy t szacuje się przez wielomian ze względu na IS] albo wszystkie
liczby ze zbioru S są ograniczone przez wielomian ze względu na ISI, jest on
algorytmem wielomianowym.

W pełni wielomianowy schemataproksymacji


W pełni
wielomianowy schemat aproksymacji dla problemu sumy podzbioru
możemy otrzymać, skracając każdą listę L 1 po jej utworzeniu. Przy skracaniu
będziemy używać parametru ó, gdzie O< ó < 1. Skrócenie listy L przez ó ozna-
cza usunięcie z L możliwie największej liczby elementów tak, żeby dla każdego
elementu y usuniętego z listy L na liście L', będącej wynikiem skrócenia L,
istniał element z ~ y taki, że

y-z
~-,; ó
y
lub równoważnie

(I - ó)y,; z,; y

Możemy myśleć o takim z jako o „reprezentancie" y na nowej liście L'. Kai;dy


element y jest reprezentowany przez takie z, że błąd względny z wobec y nie
przekracza ó. Jeśli na przykład ó = 0,1, a

L- (IO, 11, 12, 15, 20, 21, 22, 23, 24, 29)

to możemy skrócić L, otrzymując

L' - (10, 12, 15, 20, 23, 29)

gdzie usunięta wartość 11 jest reprezentowana przez 10, usunięte wartości 21


i 22 są reprezentowane przez 20, a usunięta wartość 24 jest reprezentowana
przez 23. Trzeba pamiętać, że każdy element skróconej wersji listy jest także
elementem jej pierwotnej wersji. Skrócenie listy może zdecydowanie zreduko-
wać liczbę jej elementów, przy zachowaniu na liście bliskiej oryginałowi (ale
nieco mniejszej) wartości reprezentującej każdy usunięty element.

1091
ROZDZIAŁ 37. ALGORYTMY APROKSYMACYJNE

Poniższaprocedura skraca wejściową listę L = (y 1, y2, ••• , Ym>w cza-


sie E>(m),przy założeniu, że L jest posortowana niemalejąco. Wynikiem działa­
nia procedury jest lista skrócona i posortowana.

TRIM(L, ó)
I m~ ILI
2 L'~<Y,)
3 last +- y 1
4 fori+-2tom
5 do if last < (I - ó)y,
6 then dołącz y 1 na koniec listy L'
7 last+- Y 1
8 return L'
Elementy L są przeglądane w porządku rosnącym, a liczba jest umieszczana na
wynikowej liście L I tylko wówczas, gdy jest pierwszym elementem L, albo nie
może być reprezentowana przez liczbę ostatnio dołączoną do L'.
Wykorzystując procedurę TRIM, możemy skonstruować nasz schemat ap-
roksymacji w sposób następujący. Dane wejściowe dla procedury to zbiór
S = {x1, x 2, ••• , xn} zawierający n liczb całkowitych (w dowolnej kolejności),
docelowa wartość t oraz parametr e opisujący ,,jak.ość aproksymacji", przy
czymO<e<l.

APPROX-SUBSET-SUM(S, t, e)
I •~ISI
2 L,,~ (O)
3 fori+-1 ton
4 do L 1 +-MERGE-LISTS(L;_ 1, L,_ 1 + x)
5 L; +-TRIM(L 1, e/n)
6 usuń z L 1 wszystkie elementy większe niż t
7 niech z będzie największą wartością w Ln
8 return z
W wierszu 2 tworzymy [.,0 - listę zawierającą tylko jeden element O. Celem
pętli w wierszach 3-6 jest wyznaczenie L 1 - posortowanej listy stanowiącej od-
powiednio skróconą wersję zbioru P1, pozbawioną wszystkich elementów więk­
szych niż t. Ponieważ lista L 1jest tworzona z L,_ 1, musimy zapewnić, że wielo-
krotne skracanie nie powoduje zbyt wielkiej niedokładności. Wkrótce przeko-
namy się, że algorytm APPROX-SUBSRT-SUM znajduje poprawne przybliżenie,
o ile takie istnieje.
Jak.o przykład rozpat.tzmy zbiór

L- (104,102,201, 101)

1092
37.4. PROBLEM SUMY PODZBIORU

oraz t = 308 i e = 0,20. Parametr skracania ó wynosi e/4 = 0,05. Algorytm


APPROX-SUBSET-SUM oblicza w poszczególnychwierszach następujące wartości:

wiersz 2: L, = (O),
wiersz 4: L 1 = (O, 104),
wiersz 5: L 1 = (O, 104),
wiersz 6: L, = (O, 104),
wiersz 4: L, = (O, 102, 104,206),
wiersz 5: L, = (O, 102,206),
wiersz 6: L, = (O, 102, 206),
wiersz 4: L, = (O, 102,201, 206,303,407),
wiersz 5: L 3 = (O, 102,201,303,407),
wiersz 6: L, = (O, 102,201, 303),
wiersz 4: L 4 = (O, 101,102,201,203, 302,303,404),
wiersz 5: L 4 = (O, 101,201, 302,404),
wiersz 6: L, = (O, 101,201,302).

Odpowiedzią udzielaną przez algorytm jest z = 302, co z powodzeniem mieści


się w zakresie e = 20% od optymalnego rozwiązania 307 = 104 + 102 + 101;
w istocie różni się od niego o mniej niż 2%.

TwlERDZENIE37.6.
APPROX-SUBSET-SUM jest w pełni wielomianowym schematem aproksymacji
dla problemu sumy podzbioru.

DOWÓD
Operacje skracania listy L 1 w wierszu 5 i usuwania z L 1 wszystkich elementów
większych niż t nie zmieniają faktu, że każdy element L 1 należy także do Pi"
Wartość z zwracana w wierszu 8 jest zatem rzeczywiście sumą pewnego pod-
zbioru S. Pozostaje wykazać, że jest ona nie mniejsza niż 1 - e razy wartość
rozwiązania optymalnego. (Zauważmy, że ponieważ problem sumy podzbioru
jest problemem maksymali7.3.Cji, nierówność (37.2) jest równoważna z nierów-
nością C'(l - e)::;; C). Musimy także udowodnić, że algorytm działa w czasie
wielomianowym.
W celu wykazania, że błąd względny udzielanej odpowiedzi jest mały, za-
uważmy, że skracając listę L 1, wprowadzamy między pozostające na liście war-
tości reprezentantów a wartości przed jej skróceniem błąd względny nie prze-
kraczający e/n. Przez indukcję względem i można pokazać, że dla każdego
elementu y zbioru P1 nie większego niż t istnieje ze L 1 takie, że

(37.12)

1093
ROZDZIAŁ 37. ALGORYTMY APROKSYMACYJNE

Jeśli y • e
P 11 oznacza optymalne rozwiązanie problemu sumy podzbioru, to ist-
nieje ze L 11 takie, że

(37.13)

Największe takie z jest wartością zwracaną przez procedurę APPROX-SUBSET-


-SUM. Ponieważ można pokazać, że

d(
dni-~ ')" >0

funkcja (I - e/n)" jest rosnąca ze względu na n, a więc dla n > 1 zachodzi

I- t < (1 - t/n)"
skąd

(1-t)y"~z

Wartość z zwracana przez algorytm APPROX-SUBSET-SUM jest więc nie mniej-


sza niż 1 - e razy optymalne rozwiązanie y •.
Aby wykazać, Ze APPROX-SUBSET-SUM jest w pełni wielomianowym
schematem aproksymacji, musimy wyprowadzić ograniczenie na długość Lr
Po skróceniu kolejne elementy z i z' listy L; muszą spełniać zalei.ność z/z' >
> 1/(1 - e/n). Znaczy to, ze muszą się różnić przynajmniej o czynnik
1/(1 - t/n). Liczba elementów na każdej liście L 1 wynosi zatem co najwy:żej
!n I
Iog 11 t =
0-11/ 11) -ln(l-t/n)
nln t

'
na mocy równania (2.1 O). Oszacowanie to jest wielomianowe ze względu na
liczbę n danych wejściowych, liczbę bitów lg t potrzebnych do reprezentacji t
i 1/s. Ponieważ czas działania procedury APPROX-SUBSET-SUM jest wielomia-
nem ze względu na długość L 1, jest ona w pełni wielomianowym schematem
aproksymacji.

ZADANIA
37.4-1. Udowodnij równość (37.11).
37.4-2. Udowodnij nierówności (37.12) i (37.13).
37.4-3. Jak 7Jllodyfikowalbyś przedstawiony w tym podrozdziale schemat
aproksymacji, aby umożliwiał on znajdowanie dobrego przybli:Zenia mini-

1094
PROBLEMY

malnej wartości nie mniejszej niż t, będącej sumą pewnego podzbioru da-
nej na wejściu listy?

Problemy
37-1. Problem pakowania
Załóżmy, że mamy dany zbiór n obiektów, a rozmiar s, i-tego obiektu spełnia
warunek O< s1 < l. Chcemy zapakować wszystkie obiekty do minimalnej licz-
by skrzyń rozmiaru jednostkowego. Każda skrzynia może pomieścić dowolny
zbiór obiektów, których łącz.ny rozmiar nie przekracza 1.

(a) Udowodnij, że problem wyznaczenia minimalnej liczby potrzebnych skrzyń


jest NP-trudny. (Wskazówka: Redukcja problemu sumy podzbioru).

Heurystyka „pierwszy-pasujący" polega na przeglądaniu obiektów kolejno


i mnieszczaniu każdego w pierwszej skrzyni, która może go pomieścić. Niech
"
s- [s,.
i= 1

(h) Uzasadnij, że optymalna liczba potrzebnych skrzyń wynosi przynaj-


mnitj rs1.
(c) Uzasadnij, że heurystyka „pierwszy-pasujący" pozostawi co najwyżej jedną
skrzynię wypełnioną mniej niż w połowie.
(d) Udowodnij, że liczba skrzyń w rozwiązaniu znalezionym za pomocą heury-
styk.i „pierwszy-pasujący" nigdy nie przekracza r2s1.
(e) Udowodnij, że heurystyka „pierwszy-pasujący" ma ograniczenie względne 2.
(f) Podaj efektywną implementację heurystyki „pierwszy-pasujący" i przeana-
lizuj czas jej działania.

37-2. Aproksymacja rozmiaru maksymalnej kliki


Niech G = (V, E) będzie grafem nieskierowanym. Dla dowolnego k ;,=l defi-
niujemy (j.kl jako graf nieskierowany (JXkl, /jj,k>),gdzie Jl(kljest zbiorem wszyst-
kich uporządkowanych k-tek wierzchołków z V, a zbiór krawędzi Jfkl definiu-
jemy tak, że (v1, v1, ... , v.J jest połączony z (w1, w2, ••• , wk) wtedy i tylko wtedy,
gdy dla pewnego i wierzchołek v,jest połączony z w, w G.

(a) Udowodnij, że rozmiar maksymalnej kliki w ot1t-Jjest równy k-tej potędze


rozmiaru maksymalnej klik.i w G.
(b) Wykaż, ze jeśli istnieje algorytm aproksymacyjny o stałym ograniczeniu
względnym, znajdujący maksymalną klikę, to istnieje także w pełni wielo-
mianowy schemat aproksymacji dla tego problemu.

1095
ROZDZIAŁ 37. ALGORYTMY APROKSYMACYJNE

37-3. Problem waionego pokrycia zbioru


Możemy uogólnić problem pokrycia zbioru, przypisując każdemu zbiorowi S;

z rodziny /F wagę w1 i definiując wagę pokrycia ~ jak.o sumę L w;. Chcemy


s,"-"'
wyznaczyć pokrycie o minimalnej wadze. (W podrozdziale 37.3 zajmujemy się
przypadkiem, w którym w;= 1 dla -każdego 1).
Wykaż, że zachłanną heurystykę pokrywania zbioru można w naturalny
sposób uogólnić, by dawała przybliżone rozwiązanie problemu ważonego po-
krycia zbioru. Udowodnij, że Twoja heurystyka ma ograniczenie względne
H(d), gdzie d jest równe maksimum spośród rozmiarów zbiorów S 1•

Uwagi do rozdziału
Istnieje bogata literatura dotycząca algorytmów aproksymacyjnych. Dobrą
lekturą na początek jest praca Gareya i Johnsona [79]. Znakomite przedstawie-
nie algorytmów aproksymacyjnych można również znaleźć u Papadimitriou
i Steiglitza [154). Lawler, Lenstra, Rinnooy Kan i Shmoys [133] wyczerpująco
omawiają problem komiwojażera.
Papadimitriou i Steiglitz przypisują algorytm APPROX-VERTEX-COVER
F. Gavrilowi i M. Yannakakisowi. Algorytm APPROX-TSP-TOUR pojawił się
w znakomitej pracy Rosenkrantza, Steamsa i Lewisa [170]. Twierdzenie 37.3
pochodzi od Sahniego i Gonzalesa [41]. Algorytm APPROX-SUBSET-SUMi jego
analiza są lużno oparte na podobnych algorytmach aproksymacyjnych dla
problemu plecakowego i sumy podzbioru autorstwa Ibarry i Kima [111].
Literatura
(I] Milton Abramowitz and Irene A. Stegun, editon. Handbook of Mathemat·
ical Functions. Dover, 1965.
[2] G. M. Adel'son-Vel'skil and E. M. Landis. An algorithm for the organiza-
tioh of information. Soviet Mathematics Doklady, 3: 1259-1263, 1962.
[31 Leonard M. AdJeman, Carl Pomerance, and Robert S. Rumely. On distin-
guishing prime num bers from composite num bers. Annals of Mathematics,
117:173-206, 1983.
(4] Alfred V. Abo, Jolin E. Hopcroft, Jeffrey D. Ullman. Projektowanie i analiza
algorytmów komputerowych. PWN, Warszawa 1983.
[5] Alfred V. Aho, John E. Hopcroft, and Jeffrey D. Ullman. Data Structures
and Algorithms. Addison-Wesley, I 983.
[6] Ravindra K. Ahuja, Kurt Mehlhom, James B. Orlin, and Robert E. Tarjan.
Faster algorithms for the shortest path problem. Technical Report 193,
MIT Operations Research Center, 1988.
[7) Howard H. Aiken and Grace M. Hopper. The automatic sequence con-
trolled calculator. In Brian Randell, editor, The Origins of Digital Com-
puters, pages 203-222. Springer-Verlag, third edition, l 982.
(8] M. Ajtai, J. Komlós, and E. Szemerćdi. An O(nlogn) sorting network. In
Proceedingsof the Fifteenth Annual ACM Symposium on Theory of Com-
puting, pages 1-9, 1983.
(9] Selim G. Ald. The Design and Analysis of Parallel Algorithms. Prentice-
Hall, 1989.
[IO) Richard J. Anderson and Gary L. Miller. Detenninistic parallel list rank-
ing. In John H. Reif, editor, 1988 Aegean Workshop on Computing, volume
319 of Lecture Notes in Computer Science, J)ages 81-90. Springer-Yerlag,
1988.
[11] Richard J. Anderson and Gary L. Miller. A simple randomized parallel
algorithm for list-ranking. Unpublished manuscript, 1988.
[12] Tom M. Apostoł. Calcu/us, volume I. Blaisdell Publishing Company,
second edition, 1967.
[13] A. J. Atrubin. A one-dimensional real-time iterative multiplier. JEEE
Transactions on E/ectronic Computers, EC-14(1):394-399, 1965.
[14) Sara Baase. Computer Algorithms: lntroduction to Design and Analysis.
Addison-Wesley, second edition, 1988.
[ 15) Eric Bach. Private communication, 1989.
[16) Eric Bach. Number-theoretic algorithms. In Annual Review ofComputer
Science, volume 4, pages 119-172. Annual Reviews, Inc., 1990.

1097
[ I 7] R. Bayer. Symmetric bi nary B-trees: Data structure and maintenance al-
gorithms. Acta lnformalica, 1:290-306, 1972.
{18] R. Bayer and E. M. McCreight. Organization and maintenance of large
ordered index es. Acta Jnformatica, I ( 3): I 73-189, I 972.
[19] Paul W. Beame, Stephen A. Cook, and H. James Hoover. Log depth cir-
cuits for division and related problems. SIAM Journal on ('omputing,
15(4):994-1003, 1986.
[20] Pierre Beauchemin, Gilles Brassard, Claude Crćpeau, Claude Gautier, and
Carl Pomerance. The generation of random numbers that are probably
prime. Journal ofCryptofogy, 1:53-64, 1988.
[21] Richard Bellman. Dynamie Programming. Princeton University Press,
l 957.
[22] Richard Bellman. On a routing problem. Quarter!y of Applied Mathemal-
ics, 16(1):87-90, 1958.
[23] Michael Ben-Or. Lower bounds for algebraic computation trees. In Pro-
ceedings of the Fifteenth Annual ACM Symposium on Theory of Computing,
pages 80-86, 1983.
[24] Jon L. Bentley. Writing Efficient Programs. Prentice-Hall, 1982.
{25}Jon L. Bentley. Perełki oprogramowania.WNT, Warszawa 1992.
[26] Jon L. Bentley, Dorothea Haken, and James B. Saxe. A generał method
for solving divide-and-conquer recurrences. SIGACT News. 12(3):36-44,
1980.
(27] William H. Beyer, editor. CRC Standard Mathematica/ Tab/es. The Chem-
ical Rubber Company, 1984.
[28] Patrick Billingsley. Probability and Measure. John Wiley & Sons, second
edition, 1986.
[29] Manuel Blum, Robert W. Floyd, Vaughan Pratt, Ronald L. Rivest, and
Robert E. Tarjan. Time bounds for selection. Journal of Computer and
System Science:;,7(4):448-461, 1973.
[30] Bćla Bollob.is. Random Graphs. Academic Press, 1985.
[31 J J. A. Bondy and U. S. R. Murty. Graph Theory with Applications. American
Elsevier, 1976.
[321 Robert S. Boyer and J. Strother Moore. A fast string-searching algorithm.
Communications of the ACM, 20( 10):762-772, 1977.
[33] Gilles Brassard and Paul Bratley. Algorithmics: 1'heoryand Practice. Pren-
tice-Hall, 1988.
[34] Richard P. Brent. The parallel evaluation of generał arithmetic expressions.
Journal of the ACM, 21 (2):201-206, 1974.
[35] Richard P. Brent. An improved Monte Carlo factorization algorithm. B/1",
20(2):176-184, 1980.
[36] Mark R. Brown. The Ana/ysis of a Practical and Nearly Optima/ Priority
Queue. PhD thesis, Computer Science Department, Stanford University,
1977. Technical Report STAN-CS-77-600.
[37] Mark R. Brown. lmplementation and analysis of binomial queue algo-
rithms. SIAM Journal on Computing, 7(3):298-319, 1978.
[38] Arthur W. Burks, editor. Theory of Se[f-ReproducingAutomata. University
of Illinois Press, 1966.
[39] Joseph J. F. Cavanagh. Digital Computer Arithmetic. McGraw-Hill, 1984.
[40) H. Chemoff. A measure of asymptotic efficiency for tests of a hypothe-
sis based on the sum of observations. Annals of Mathematical Statistics,
23:493-507, 1952.
[41] Kai Lai Chung. Elementary Probability Theory with Stochastic Processes.
Springer-Verlag, 1974.
[42] V. Chvital. A greedy heuristic for the set-covering problem. Mathematics
ofOperations Research, 4(3):233-235, 1979.
[43) V. Chvital, O. A. Klamer, and O. E. Knuth. Selected combinatorial re-
search problems. Technical Report STAN-CS-72-292, Computer Science
Department, Stanford University, 1972.
[44] Alan Cobham. The intrinsic computational difficulty of functions. In Pro-
ceedings of the 1964 Congress for Logic, Methodology, and the Philosophy
of Science, pages 24-30. North-Holland, 1964.
[45] H. Cohen and H. W. Lenstra, Jr. Primality testing andjacobi sums. Math-
ematics ofComputation, 42(165):297-330, 1984.
[46] Richard Cole. Parallel merge sort. In Proceedings of the 27th Annual Sym-
posium on Foundations of Computer Science, pages 511-516. IEEE Com-
puter Society, 1986.
[47] Richard Cole and Uzi Vishkin. Deterministic coin tossing with applica-
tions to optima! parallel list ranking. lnformation and Control, 10( I ):32-
53, 1986.
[48] O. Corner. The ubiquitous 8-tree. ACM Computing Surveys, 11(2):121-
137, 1979.
[49] Stephen Cook. The complexity of theorem proving procedures. In Pro-
ceedings of the Third Annua! ACM Symposium on Theory of Computing,
pages 151-158, 1971.
[50] Stephen Cook, Cynthia Dwork, and Ri.idiger Reischuk. Upper and !ower
time bounds for parallel random access machines without simultaneous
writes. SIAM Journal on Computing, 15(1):87-97, 1986.
[51) James W. Cooley and John W. Tukey. An algorithm for the machine cal-
culation of complex Fourier series. Mathematics of Computation, 19(90):
297-301, April 1965.
[52] Don Coppersmith and Shmuel Winograd. Matrix multiplication via arith-
metic progressions. In Proceedings of the Nineteenth Annual ACM Sympo-
sium on Theory of Computing, pages 1-6, 1987.
(53) George B. Dantzig. Linear Programming and Extensions. Princeton Uni-
versity Press, 1963.
[54] Whitfield Diffie and Martin E. Hellman. New directions in cryptography.
IEEE Transactions on lnformation Theory, IT-22(6):644-654, 1976.
[55] E. W. Dijkstra. A note on two problems in connexion with graphs. Nu-
merische Mathematik, 1:269-271, 1959.
[56) John D. Dixon. Factorization and primality tests. The American Mathe-
matical Monthly, 91(6):333-352, 1984.
[57] Alvin W. Drake. Fundamenta/s of Applied Probability Theory. McGraw-
Hill, 1967.
(58] James R. Driscoll, Harold N. Gabow, Ruth Shrairman, and Robert E. Tar~
jan. Relaxed heaps: An alternative to Fibonacci heaps with applications
to parali el computation. Communications of the ACM, 31 ( 11): 1343-1354,
1988.
[59] James R. Driscoll, Neil Sarnak, Daniel D. Sieator, and Robert E. Tarjan.
Making data structures persistent. In Proceedings of the Eighteenth Annual
ACM Symposium on Theory ofComputing, pages 109-121, 1986.
160] Herbert Edelsbrunner. Algorithms in Combinatorial Geometry, volume IO
of EATCS Monographs on Theoreticaf Computer Science. Springer-Verlag,
1987,
[61] Jack Edmonds. Paths, trees, and flowers. Canadian Journal of Mathemat-
ics, 17:449-467, I 965.
[62] Jack Edmonds. Matroids and the greedy algorithm. Mathematical Pro-
gramming, 1:126-136, 1971.
[63] Jack Edmonds and Richard M. Karp. Theoretical improvements in the
algorithmic effi.ciency for network flow problems. Journal of the ACM,
19:248-264, 1972.
[64] G. Estrin, B. Gilchrist, and J. H. Pomerene. A note on high-speed digital
multiplication. /RE Transactions on Electronic Computers, 5(3): 140, 1956.
[65] Shimon Even. Graph Algorithms. Computer Science Press, 1979.
[66] William Feller. An Introduction to Probabi/ity Theory and lts Applications.
John Wiley & Sons, third edition, 1968.
[67] M. J. Fischer and A. R. Meyer. Boolean matrix multiplication and transi-
tive closure. In Proceedings of the Twe/fthAnnual Symposium on Switching
and Automata Theory, pages 129-131. IEEE Computer Society, 1971.
[68] Robert W. Aoyd. Algorithm 97 (SHORTEST PATH). Communications of
theACM, 5(6):345, 1962.
[69] Robert W. Floyd. Algorithm 245 (TREESORT). Communications o/the
ACM, 7:701, 1964.
[70] Robert W. Floyd and Ronald L. Rivest. Expected time bounds for selec-
tion. CommunicatiorlS of the ACM, 18(3):165-172, 1975.
[71] Lestor R. Ford, Jr., and D. R. Fulkerson. Flows in Networks. Princeton
University Press, 1962.
[72] Lestor R. Ford, Jr., and Selmer M. Johnson. A tournament problem. The
American Mathematical Monthly, 66:387-389, I 959.
(73) Steven Fortune and James Wyllie. Parallelism in random access machines.
In Proceedings of the Tenth Annual ACM Symposium on Theory of Com-
puting, pages 114-118, 1978.
[74] Michael L. Fredman and Michael E. Saks. The cell probe complexity of
dynamie data structures. In Proceedings of the Twenty First Annual ACM
Symposium on Theory of Computing, 1989.
[75] Michael L. Fredman and Robert E. Tarjan. Fibonacci heaps and their
uses in improved network optimization algorithms. Journal of the ACM,
34(3):596-615, 1987.
[76} Harold N. Gabow and Robert E. Tarjan. A linear-time algorithm for a
special case of disjoint set union. Journal of Computer and System Sciences,
30(2),209-221, 1985.
[77] Harold N. Gabow and Robert E. Tarjan. Faster scaling algorithms for
network problems. SIAM Journal on Computing, 18(5):1013-1036, 1989.
[78] Zvi Galii and Joel Seiferas. Time-space-optima! string matching. Journal
ofComputer and System Sciences, 26(3):280-294, 1983.
[79] Michael R. Garey and David S. Johnson. Computers and Jntractability: A
G_uideto the Theory of NP-Completeness. W. H. Freeman, 1979.
[80) Fa.nica Gavril. Algorithms for minimum coloring, maximum clique, min-
imum covering by cliques, and maximum independent set of a chordal
graph. SIAM Journal on Computing, 1(2):180-187, 1972.
[81] Alan George and Joseph W-H Liu. Computer Solution of Large Sparse
Positive Definite Systems. Prentice-Hall, I 981.
[82] Andrew V. Goldberg. Efficient Graph Algorithms for Sequentia/ and Par-
a/le/ Computers. PhD thesis, Department of Electrical Engineering and
Computer Science, MIT, 1987.
[83] Andrew V. Goldberg, Eva Tardos, and Robert E. Tarjan. Network flow
algorithms. Technical Report STAN..CS-89-1252, Computer Science De-
partment, Stanford University, I 989.
[84] Andrew V. Goldberg and Serge A. Plotkin. Parallel (ó + I) coloring of
constant-degree graphs. Information Processing Letters, 25(4):241-245,
1987.
[85] Andrew V. Goldberg and Robert E. Tarjan. A new approach to the max-
imum flow problem. In Proceedingsof the Eighteenth Annua/ ACM Sym-
posium on Theory ofComputing, pages 136-146, 1986.
[86J Shafi Goldwasser and Silvio Micali. Probabilistic encryption. Journal of
Computer and System Sciences, 28(2):270-299, 1984.
[87] Shafi Goldwasser, Silvio Micali, and Charles Rackoff. The knowledge
complexity of interactive proof systems. SIAM Journal on Computing,
I 8( I )c186-208, 1989.
[88] Shafi Goldwasser, Silvio Micali, and Ronald L. Rivest. A digital signature
scheme secure against adaptive chosen-message attacks. SIAM Journal on
Compu'ting, 17(2):281-308, 1988.
[89] Gene H. Golub and Charles F. Van Loan. Matrix Computations. The
Johns Hopkins University Press, 1983.
[90] G. H. Gonnet. Handbook of Algorithms and Data Structures. Addison-
Wesley, 1984.
[91] R. L. Graham. An efficient algorithm for determining the convex bull of a
finite planar set. Information ProcessingLetters, 1: 132-133, 1972.
[92] R. L. Graham and Pavol Heli. On the bistory of the minimum spanning
tree problem. Anna/sof the History of Computing, 7(1):43-57, 1985.
(93] Leo J. Guibas and Robert Sedgewick. A diochromatic framework for bal~
anced trees. In Proceedingsof the 19th Annual Symposium on Foundations
ofComputer Science, pages 8-21. IEEE Computer Society, 1978.
{94] Frank Harary. Graph Theory. Addison-Wesley, 1969.
[95] J. Hartmanis and R. E. Steams. On the computationa1 complexity of algo-
rithms. Transactions of the American Mathematica/ Society, l I 7:285-306,
1965.
[96] Frederick J. Hill and Gerald R. Peterson. lntroduction to Switching Theory
and Logical Design. John Wiley & Sons, second edition, 1974.
[97] C. A. R. Hoare. Algorithm 63 (partition) and algorithm 65 (find). Com-
munications of the ACM, 4(7):321-322, 1961.
[98] C. A. R. Hoare. Quicksort. Computer Journal, 5( 1): 10-15, 1962.
[99] W. Hoeffding. On the distribution of the number of successes in indepen-
dent trials. Anna/s of Mathematical Statistics, 27:713- 721, 1956.
[I 00] Micha Hofri. ProbabilisticAnalysis of Algorithms. Springer-Verlag, 1987.
[101) John E. Hopcroft and Richard M. Karp. An n512 algorithm for maximum
matchings in bipartite graphs. SIAM Journal on Computing, 2(4):225-231,
1973.
[102) John E. Hopcroft and Robert E. Tarjan. Efficient algorithms for graph
manipulation. Communications of the ACM, 16(6):372-378, 1973.
[103] John E. Hopcroft and Jeffrey D. Ullman. Set merging algorithms. SIAM
Journal on Computing, 2(4):294-303, 1973.
[104] John E. Hopcroft and Jeffrey D. Ullman. lntroduction toAutomata Theory,
Languages, and Computation. Addison-Wesley, 1979.
(105] Ellis Horowitz and Sartaj Sahni. Fundamentals ofComputer Algorithms.
Computer Science Press, 1978.
[106] T. C. Hu and M. T. Shing. Some theorems about matrix multiplication,
In Proceedingso/the 21st Annua/ Symposium on Foundations ofComputer
Science, pages 28-35. IEEE Computer Society, 1980.
(107] David A. Huffman. A method for the construction of minimum-redun-
dancy codes. Proceedingsof the !RE, 40(9):1098-1101, 1952,
(108] Kai Hwang. Computer Arithmetic: Principles, Architecture, and Design.
John Wiley & Sons, 1979.
[109] Kai Hwang and Faye A. Briggs. Computer Architecture and Para/lei Prt.r
cessing. McGraw-Hill, 1984.
[ 11OJ Kai Hwang and Doug DeGroot. Paraf/el Processingfor Supercomputers
and Artificial Intelligence. McGraw-Hill, 1989.
[ 111) Oscar H. lbarra and Chul E. Kim. Fast approximation algorithms for the
knapsack and sum of subset problems. Journal of the ACM, 22( 4):463-468,
1975.
[112] R. A. Jarvis. On the identification of the convex bull of a finite set of
points in the plane. Information ProcessingLetters, 2: 18-21, 1973.
[113] D. S. Johnson. Approximation algorithms for combinatorial problems.
Journal ofComputer and System Sciences, 9:256-278, 1974.
[114] Donald 8. Johnson. Efficient algorithms for shortest paths in sparse net-
works. Journal o/the ACM, 24(1):1-13, 1977.
[ 115] N. Kannar kar. A new polynomial-time algorithm for linear programming.
Combinatorica, 4(4):373-395, 1984.
(116] Richard M. Karp. Reducibility among combinatorial problems. In Ray-
mond E. Miller and James W. Thatcher, editors, Complexity ofComputer
Computations, pages 85-103. Plenum Press, 1972.
( 117] Richard M. Karp and Michael O. Rabin. Efficient randomized pattem-
matching algorithms. Tecbnical Report TR-31-81, Aiken Computation
Laboratory, Harvard University, 1981.
[118] Richard M. Karp and Vijaya Ramachandran. A survey of parallel algo-
rithms for shared-memory machines. Technical Report UCB/CSD 88/408,
Computer Science Division (EECS), University of Califomia, Berkeley,
1988.
(119) A. V. K.arzanov. Determining the maxirnal Oowin a network by the method
of preffows. Soviet Mathematics Doklady, 15:434-437, 1974.
{120) D. G. Kirkpatrick and R, Seidel. The ultimate planar convex hull algo-
rithm? SIAM Journal on Computing, 15(2):287-299, 1986.
{121] Donald E. Knuth. Fundamental Algorithms, volume I of The Art ofCom-
puter Programming. Addison-Wesley, 1968. Second edition, 1973.
[122) Donald E. Knuth. Seminumerical Algorithms, volume 2 of The Art of
Computer Programming. Addison-Wesley, 1969. Second edition, 1981.
[123] Donald E. Knuth. Sorting and Searching, volume 3 of The Art ofComputer
Programming. Addison-Wesley, 1973.
[124) Donald E. Knuth. Big omicron and big omega and big theta. ACM SJGACT
News, 8{2):18-23, 1976.
{125] Donald E. K.nuth, James H. Morris, Jr., and Vaughan R. Pratt. Fast pattem
matching in strings. SIAM Journal on Computing, 6(2):323-350, 1977.
[ 126] Zvi Kohavi. Switching and Finite Automata Theory. McGraw-Hill, 1970.
[127] Bernhard Korte and Llszlo Lovisz. Mathematical structures underlying
greedy algorithms. In F. Gecseg, editor, Fundamentals of Computation
Theory, number 117 in Lecture Notes in Computer Science, pages 205-
209. Springer-Verlag, 198 I.
[ 128] Bernhard Korte and Llszlo Lovisz. Structural properties of greedoids.
Combinatorica, 3:359-374, 1983.
( 129] Bernhard Korte and Llszlo Lovśsz. Greedoids-a structural framework
for the greedy algorithm. In W. Pulleybank, editor, Progressin Combina-
torial Optimization, pages 221-243. Academic Press, I 984.
[ 130) Bernhard Korte and Li.szlo Lovasz. Greedoids and linear objective func-
tions. SIAM Journal on Algebraic and Discrete Methods, 5(2):229-238,
1984.
[131] J. B. K.ruskal. On the shortest spanning subtree of a graph and the travel-
ing salesman problem. Proceedingsof the American Mathematical Society,
7:48-50, 1956.
[132] Eugene L. Lawler. Combinatorial Optimization: Networks and Matroids.
Holt, Rinehart, and Winston, 1976.
[133] Eugene L. Lawler, J. K. Lenstra, A. H. G. Rinnooy Kan, and D. B. Shmoys,
editoi's. The TravelingSalesman Problem. John Wiley & Sons, 1985.
[134] C. Y. Lee. An algorithm for path connection and its applications. /RE
Transactions on Electronic Computers, EC-10(3):346-365, 1961.
[135] F. Thomson Leighton. lntroduction to Parallel Algorilhms and Ar:chitec-
tures: Networks and Algorithms. Morgan-Kaufmann, in preparation.
[136] Debra A. Lelewer and Daniel S. Hirschberg. Data compression. ACM
Computing Surveys, I 9(3):261-296, I 987.
[137) H. W. Lenstra, Jr. Factoring integers with elliptic curves. Annals of Math-
ematics, 126:649-673, 1987.
[138] L. A. Levin. Universal sorting problems. Problemy PeredachiInformatsii,
9{3):265-266, 1973. In Russian.
[ 139] Harry R. Lewis and Christos H. Papadimitriou. Elements of the Theory of
Computation. Prentice-Hall, I 981.
{140] C. L. Liu. Introduction to Combinatoria/ Mathematics. McGraw-Hill,
I 968.
[141] Li.szlo Lovśsz. On the ratio of optima! integral and fractional covers.
DiscreteMathematics, 13:383-390, 1975.
[142] Udi Manber. Introduction to Algorithms: A Creative Approach. Addison-
Wesley, 1989.
[143] William J. Masek and Michael S. Paterson. A faster algorithm computing
string edit di stan ces. Journal of Computer and System &iences, 20( I): I 8-
31, 1980.
[144] Kurt Mehlhom. Sorting and Searching, volume I of Data Structures and
Algorithms. Springer-Verlag, 1984.
[145] Kurt Mehlhom. Graph Algorithms and NP-Completeness, volume 2 of Data
Structures and Algorithms. Springer-Verlag, I 984.
[ 146) Kurt Mehlhom. Multidimensiona/ Searching and Computationaf Geome-
try, volume 3 of Data Structures and Algorithms. Springer-Verlag, 1984.
[147] Gary L. Miller. Riemann's hypothesis and tests for primality. Journal of
Computer and System Sciences, 13(3):300-317, 1976.
(148] Louis Monier. Algorithmes de Factorisation D'Entiers. PhD thesis, L'Uni-
versite Paris-Sud, Centre D'Orsay, 1980.
[149] Louis Monier. Evaluation and comparison of two efficient probabilistic
primality testing algorithms. Theoretical Computer Science, 12(1):97-108,
1980.
[ISO] Edward F. Moore. The shortest path through a maze. In Proceedings of
the International Symposium on the Theory of Switching, pages 285-292.
Harvard University Press, 1959.
[ 15 I J Ivan Niven and Herbert S. Zuckerman. An lntroduction to the Theory of
Numbers. John Wiley & Sons, fourth edition, 1980.
[152] Yu. Ofman. On the algorithmic complexity of discrete functions. Soviet
Physics Doklady, 7(7):589-591, I 963. English translation.
[153] Alan V, Oppenheim and Alan S. Willsky, with Ian T. Young. Signals and
Systems. Prentice-Hall, 1983.
[154] Christos H. Papadimitriou and Kenneth Steiglitz. Combinatorial Opti-
mization: Algorithms and Complexity. Prentice-Hall, 1982.
[ISS] Michael S. Paterson, 1974. Unpublished lecture, Ile de Berder, France.
[156] J. M. Pollard. A Monte Carlo method for factorization. BIT, 15:331-334,
I 975.
[157] Carl Pomerance. On the distribution of pseudoprirµes. Mathematics of
Computation, 37(156):587-593, 1981.
[158] Carl Pomerance. The quadratic sieve factoring algorithm. In T. Beth,
N. Cot, and I. Ingemarrson, editors, Advances in Cryptology, volume 209
of Lecture Notes in Computer Science, pages 169-182. Springer-Verlag,
1984.
[159] Carl Pomerance, editor. Proceedings of the AMS Symposia in Applied
Mathematics: Computational Number Theory and Cryptography. Ameri-
can Mathematical Society, to appear.
[ 160] Franco P. Pre para ta and Micheal Ian Shamos. Computational Geometry:
An lntroduction. Springer-Verlag, 1985.
[ I 6 1J William H. Press, Brian P. Plannery, Saul A. Teukolsky, and William T.
Vetterling. Numerical Recipes: The Art ofScientific Computing. Cambridge
University Press, 1986.
[162] William H. Press, Brian P. Plannery, Saul A. Teukolsky, and William T.
Vetterling. Numerical Recipes in C. Cambridge University Press, 1988.
{163] R. C. Prim. Shortest connection networks and some generalizations. Bell
System Technical Journal, 36:1389-1401, 1957.
[164] Paul W. Purdom, Jr., and Cynthia A. Brown. The Analysis of Algorithms.
Holt, Rinehart, and Winston, 1985.
{165] Michael O. Rabin. Probabilistic algorithms. In J. F. Traub, editor, Algo--
rithms and Complexity: New Directions and Recent Results, pages 21-39.
Academic Press, 1976.
[ 1661 Michael O. Rabin. Probabilistic algorithm for testing primality. Journal of
Number Theory, 12: I 28- I 38, 1980.
[167] Edward M. Reingold, Jiirg Nievergelt, and Narsingh Deo. Combinatorial
Algorithms: Theory and Practice. Prentice-Hall, 1977.
[ 168] Hans Riesel. Prime Nurnbers and Cornputer Methods for Factorization.
Progress in Mathematics. Birkhiiuser, 1985.
[ 169] Ronald L. Rivest, Adi Shamir, and Leonard M. Adleman. A method for ob-
taining digital signatures and public-key cryptosystems. Comrnunications
of the ACM, 21(2):120-126, 1978. See also U.S. Patent 4,405,829.
[170] D. J. Rosenkrantz, R. E. Steams, and P. M. Lewis. An analysis of severa!
heuristics for the traveling salesman problem. SIAM Journal on Comput-
ing, 6:563-581, 1977.
(171] Y. A. Rozanov. Probability Theory: A Concise Course. Dover, 1969.
[172] S. Sahni and T. Gonzalez. P-complete approximation problems. Journal
of the ACM, 23:555-565, 1976.
[173] John E. Savage. The Cornplexity of Computing. John Wiley & Sans, 1976.
[ I 74] Robert Sedgewick. lmplementing quicksort programs. Cornrnunicationsof
theACM, 21(10):847-857, 1978.
[175] Robert Sedgewick. Algorithrns. Addison-Wesley, second edition, 1988.
[176] Michael I. Shamos and Dan Hoey. Geometrie intersection problems. In
Proceedingsof the 16th Annual Syrnposiurn on Foundations of Cornputer
Science, pages 208-215. IEEE Computer Society, 1975.
[177] Daniel D. Sleator and Robert E. Tarjan. A data structure for dynamie
trees. Journal ofCornputer and System Sciences, 26(3):362-391, 1983.
[ I 78] Daniel D. Sleator and Robert E. Tarjan. Self-adjusting binary search trees.
Journal of the ACM, 32(3):652-686, 1985.
(179) Joel Spencer. Ten Lectures on the Probabi/isticMethod. Regional Confer-
ence Series on Applied Mathematics (No. 52). SIAM, 1987.
[180] Staff of the Computation Laboratory. Description of a Relay Calculator,
volume XXIV of The Annals of the Computation Laboratory of Harvard
University. Harvard University Press, 1949.
[181] Gilbert Strang. Introduction to Applied Mathernatics. Wellesley-Cambridge
Press, 1986.
(182) Gilbert Strang. Linear Algebra and Its Applications. Harcourt Brace Jo-
vanovich, third edition, 1988.
[183] Volker Strassen. Gaussian elimination is not optima!. NurnerischeMathe-
matik, 14(3):354-356, 1969.
[184] T. G. Szymanski. A special case of the maxima! common subsequence
problem. Technical Report TR-170, Computer Science Laboratory, Prince-
ton University, 1975.
[ 185] Robert E. Tarjan. Depth first search and linear graph algorithms. SIAM
Journal on Computing, l (2): 146-160, 1972.
( 186] Robert E. Tarjan. Effieien cy of a good but not linear set union algorithm.
Journal of the ACM, 22(2):215-225, 1975.
[187) Robert E. Tarjan. A class of algorithms which require nonlinear time to
maintain disjoint sets. Journal ofComputer and System Sciences, 18(2):
110-127, 1979.
[ 188] Robert E. Tarjan. Data Structures and Network Algorithms. Society for
Industrial and Applied Mathematics, 1983.
{189] Robert E. Tarjan. Amortized computational complexity. SIAM Journal on
Algebraicand DiscreteMethods, 6(2):306-3 I 8, I 985.
[190) Robert E. Tarjan and Jan van Leeuwen. Wont-case analysis of set union
algorithms. Journal of the ACM, 31(2):245-281, 1984.
(191] Robert E. Tarjan and Uzi Vishkin. An efficient parallel biconnectivity
algorithm. SIAM Journal on Computing, 14(4):862-874, 1985.
[192] George B. Thomas, Jr., and Ross L. Finney. Calcu/us and Analytic Geom-
etry. Addison.Wesley, seventh edition, 1988.
[193] Leslie G. Valiant. Parallelism in comparison problems. SIAM Journal on
Computing, 4(3):348-355, 1975.
(194) P. van Emde Boas. Preserving order in a forest in less than logarithmic
time. In Proceedingsof the I6th Annual Symposium on Foundations of
Computer Science, pages 75-84. IEEE Computer Society, 1975.
[195] Uzi Vishkin. lmplementation of simultaneous memory address access in
models that forbid it. Journal of Algorithms, 4( l ):45-50, 1983.
[196] Jean Vuillemin. A data structure for manipulating priority queues. Com-
munications of the ACM, 21(4):309-315, 1978.
[197] C. S. Wallace. A suggestion for a fast multiplier. IEEE Transactions on
Electronic Computers, EC.13( 1}:14-17, 1964.
[ 198) Stephen Wanhalt A theorem on boolean matrices. Journal of the ACM,
9(1):11-12, 1962.
[199] A. Weinberger and J. L. Smith. A one·microsecond adder using one·
megacycle circuitry. !RE Transactions on Electronic Computers, EC·5(2),
1956.
(200] Hassler Whitney. On the abstract properties of linear dependenc~. Ameri-
can Journal of Mathematics, 57:509-533, 1935.
(201] Herbert S. Wilf. Algorithms and Complexity. Prentice·Hall, 1986.
[202] J. W. J. Williams. Algorithm 232 (heapsort). Communications of the ACM,
7:347-348, I 964.
[203] S. Winograd. On the a1gebraic complexity of functions. In Actes du
Congri!sInternational des Mathematiciens, volume 3, pages 283-288, 1970.
[204] James C. Wyllie. The Complexity of Parallel Computations. PhD thesis,
Department of Computer Science, Cornell Univenity, I 979.
[205] Andrew C.-C. Yao. A !ower bound to finding convex hulls. Journal of the
ACM, 28(4):780-787, 1981.
Skorowidz

lJ (podłoga) 54 algorytm Euklidesa, rozszerzony 909


fl (sufit) 54 - Floyda-Warshalla 627
2·3-4-drzewo 438 - Forda-Fulkersona 666
-, rozbijanie 452 - Grahama 1004
-, sklejanie 452 - Huffmana 384, 386
2-3-4-kopiec 472 - Jarvisa 1011
- Johnsona 634
A - Karpa wyznaczania cyklu o minimal-
nej średniej wadze 615
adresowanie bezpośrednie 257 - Knutha-Morrisa-Pratta 972
- kwadratowe 274 - Kruskala 568
- liniowe 273 -, poprawność 22
- otwarte 271 - ,,podnieś i przesuń na początek" 691,
aksjomaty prawdopodobieństwa 133 695
alfabet 1028 - Prima 570
algorytm 21 - probabilistyczny 194
- aproksymacyjny 1073 - Rabina-Karpa 960
- Bellmana-Forda 598 - redukcji 1037
- BFS 531 - rekurencyjny 32
- Boyera-Moore'a 980 - rosyjskich wieśniaków 761
- CRCW 771 - równoległy, sekwencyjnie efektywny
- CREW 771 777
-, czas działania 27 - Shamira 866
-, - -, przypadek ocz.ckiwany 30 - skalujący 614
-, - -, - pesymistyczny 30 - Strassena 826
-, - -, - średni 30 - sympleks 606
- DFS 540 - weryfikacji 1033
- Dijkstry 593 - wielomianowy 898
- -, zmodyfikowany 597 algorytmy równolegle 771
- Edmondsa-Karpa 670 analiza algorytm u 26
- ERCW 771 argument funkcji 111
- BREW 771 arytmetyka modularna 911
- Euklidesa 906 asymptotyczna granica dolna 49

1107
SKOROWIDZ

asymptotycma granica górna 47 cykl 114


- złożoność algorytmu 44 - Eulera 561, 781
automat, funkcja przejść 966 - Hamiltona 1032
- skończony 966 - o minimalnej średniej wadze 615
-, stan 966 - prosty 114
- wyszukiwania wzorca 967 czas dostępu do dysku 434
częściowy porządek 109

B
B-drzewo 437 D
-, rozbijanie węzła 442 dag 116
-, tworzenie pustego 441 -, najkrótsza ścieżka 603
-, usuwanie klucza 447 dane wejściowe 21
-, wstawianie klucza 443 - wyjściowe 21
-, wyszukiwanie 440 DFf 876,882
bijekcja 112 diagram Venna 105
bit przeniesienia 740 digraf 113
- sumy 740 długość ścieżki wewnętrmej 123
błąd niedomiaru 237 - - zewnętrznej 124
- przepełnienia 237 DNF 1051
- przybliżenia 862 dodatni przepływ netto 652
- względny 1074 domknięcie przechodnie grafu 631
bracia węzła w drzewie 121 dopełnienie grafu 1058
bramka logicma 734 - zbioru 105
- -AND 734 - zdarzenia 133
- -, głębokość 738 drzewa 249, 250
- - NAND 734 - dwumianowe 456
- - NOR 734 - dynamiczne 431
- - NOT 734 - Sleatora-Tarjana 432
--OR734 - zrównoważone, zamortyzowane 426
- -, stopień wejściowy 737 drzewo a-zrównoważone 426
- - XOR 734 - binarne 121, 250
- -, regularne 122
- BST 285
C - -, losowo skonstruowane 295
certyfikat 937 - -, usuwanie węzła 292
chińskie twierdzenie o resztach 923 - -, wstawianie węzła 291
ciało 837 - czerwono-czarne 305
ciąg bitoniczny 721 - -, usuwanie węzła 315
- nieskończony 111 - -, wstawianie węzła 310
- skończony 111 - -, wzbogacanie 332
CNF 1050 - -, złączanie 322
CRCW PRAM, dowolny 772 - -, zrównoważone 305
- -, jednolity 772 - decyzyjne 207
- -, mieszany 772 - dwumianowe, nieuporządkowane 479
- -, priorytetowy 772 - najkrótszych ścieżek 582

1108
SKOROWIDZ

drzewo pozycyjne 122, 301 funkcja asymptotycznie nieujemna 45


-, przechodzenie metodą inonier 286 - dobrego sufiksu 1)85
-,- - postorder 286 - entropii 130
-,- - preonier 286 - Eulera 915
- przedziałowe 335 - gęstości prawdopodobieństwa 140
- przeszukiwania w głąb 539 - haszująca 259, 264, 936
- - wszerz 537 - kwadratowa 29
- puste 121 - liniowa 29
- rekursji 85, 357 - logarytmiczna 56
-, reprezentacja „na lewo syn, na prawo - logicma 131
brat" 251 - monotonicmie malejąca 54
- rozpinające 393 - - rosnąca 54
- -, minimalne 473, 562, 647 - na" 112
- rzędu k 122 "
- niemalejąca 54
- -, pełne 122 - nierosnąca 54
- struktury wyraienia 367 - oblicmlna w czasie wielomianowym
- ukorzenione 120 1026
- uporządkowane 121 - ograniczona polilogarytmicmie 57
- Wallace'a 755 - - wielomianowa 55
- wolne 117 - ostatniego wystąpienia 983
- z korzeniem 120 - prefiksowa 972, 974
dyskretna transformata Fouriera 876, - przejść automatu 966
882 - redukcji 1037
dyskretny problem plecakowy 381 - rozmieszczenia liczb pierwszych 938
- rozkład prawdopodobieństwa 134 - różnowartościowa 112
dystrybuanta 218 - ściśle malejąca 54
dziedzina funkcji 110 - - rosnąca 54
dzielnik 899 - tworząca 100
- trywialny 899 - wykładnicza 55
- wzajemnie jednoznaczna 112
E funkcje bazowe 861

egzemplarz problemu 1024


element maksymalny 110 G
- osiowy 847 generator 917
- zbioru 103 - liczb losowych 194
eliminacja Gaussa 845 - z: 927
ewaluacja wielomianu 895 głębokość stosu 204
- węzła w drewie 121
głowa kolejki 238, 240
F
graf e--gęsty 647
FFT 876,882 - acykliczny 115
FIFO 236 - częściowo spójny 559
funkcja 110 -, domknięcie przechodnie 631
- Ackermanna 510 - dwudzielny 116
- -, odwrotność 511 - gęsty 527

1109
SKOROWIDZ

graf hamiltonowski 1032 haszowanie uniwersalne 268


-, kolorowanie 805, 1071 heapsort 180
-, krawędź bezpieczna 564 heurystyka „ro" 947
-, listy sąsiedztwa 527 - dobrego sufiksu 985
-, most 560 - najbliższego punktu 1084
- nieskierowany 113 - niezgodności 983
- -, stopień wierzchołka 114 hiperkrawędi 116
-, odległość 533 hipergraf 116
- ograniczeń 608, 609
- pełny 116
- pojedynczo spójny 548 I
- poprzedników 581 iloczyn wektorowy 992
- prosty 115 iloraz 900
- przedziałów, kolorowanie 379 incydencja 114
-, przeszukiwanie w głąb 539 indeks elementu 927
- -, wszerz 530 indukcja matematyczna 69
-, punkt artykulacji 560 interpolacja 873
- ,zadki 526 inwersja 38
- skierowany 113 izomorfizm grafów 11S
- -, stopień wierzchołka 114
-, składowa dwuspójna 560
- skład.owych 559 J
-, skojarzenie 674 jednoczesny odczyt 771
-, spójna składowa 811 - zapis 771
-, spójność krawędziowa 673
jednokierunkowa funkcja skrótu 936
- spójny 115
jednostajny rozkład prawdopodobień-
- z wagami 528 stwa 134
grupa 911
jednoznaczność rozkładu 904
- addytywna modulo n 912 język 1028
- cykliczna 927
- akceptowany przez algorytm 1029
- multiplikatywna mod.uto n 912
- - w czasie wielomianowym przez al-
- przemienna 911, 912
gorytm 1029
- skończona 911, 912 -, domknięcie 1028
grupowanie 273
-, dopełnienie 1028
- wtórne 274 -, konkatenacja 1028
gwiazda 1012
- NP·trudny 1038
- NP-zupełny 1038
H -, prrec:ięcie 1028
haszowanie 256 - pusty 1028
- dwukrotne 274 - rozstrzygalny przez algorytm 1029
- k-uniwersalne 283 - - w czasie wielomianowym przez al·
- modularne 265 gorytm 1029
- proste, równomierne 261 -, suma 1028
- przez mnożenie 266 - weryfikowany przez algorytm 1033
- równomierne 273 - zupełny 1046

111 O
SKOROWIDZ

K kopiec Fibonacciego, usuwanie 492


- -, - węzła minimalnego 482
k-kolorowanie 1071 - -, wstawianie 480
k-kombinacja 128 - -, zmniejszanie wartości klucza i usu-
klasa abstrakcji 108 wanie węzła 488
- równoważności modulo 900 - -, znajdowanie węzła minimalnego
- złożoności 1029 481
- - co-NP 1034 - rzędu d 184
- - NP 1034 - złączalny 253, 454
- - P 1026, 1030 korzeń drzewa 120
klika 1054 koszt zamortyzowany 403
klucz 170,181,232 - -, analiza 404, 408, 411
- jawny 931 - -, metoda kosztu sumarycznego 404
- tajny 931 - -, - księgowania 408
kod Huffmana 384, 386 - - , - potencjału 411
- prefiksowy 384 k-permutacja 128
kodowania wielomianowo równoważne k-podsłowo 127
1027 k-podzbiór 106
kodowanie 1025 krańce rozkładu dwumianowego 150
kolejka 236, 238 krawędzie drzewowe 545
- dwustronna 239 - poprzeczne 545
- priorytetowa 181 - powrotne 545
kolizje 259 - w przód 545
kolorowanie grafu 124, 805 krawędź dopuszczalna 691
kombinacja wypukła dwóch punktów - grafu 113
991 - lekka 564
kombinacje 128 - residualna 660
komparator 714 kredyt 408
kongruencja 900 kryptosystem 931
konkatenacja słów 957 - z kluczem jawnym 932
kopiec 173 - - - RSA934
- dwumianowy 459 krzywe sklejane 867
- -, łączenie 461 k-słowo 127
- -, reprezentacja 459 kwadrat grafu skierowanego 529
- -, usuwanie minimalnego klucza 468 kwantyle 228
- -, usuwanie węzła 471
- -, wstawianie węzła 467
- -, zmniejszanie wartości klucza 468 L
- -, tworzenie nowego kopca 461 las 116, 118
- -, własności 459 - przeszukiwania w głąb 539
- -, znajdowanie minimalnego klucza - zbiorów rozłącznych 505
461 lemat o podawaniu rąk 117
- Fibonacciego 476 - o redukcji 880
- -, łączenie 480 - o skracaniu 880
- -, potencjał 478 - o sumowani u 881
- -, tworzenie nowego kopca 480 liczba Calatana 304, 349

1111
SKOROWIDZ

liczba Cannichaela 940 macierz trójdiagonalna 817


- harmoniczna 66 - trójkątna dolna 818
- pierwsza 899 - - -, jednostkowa 818
- pseudopierwsza 939 - - górna 818
-· złożona 899 - - -, jednostkowa 818
liczby Fibonacciego 59, 100 - Vandennonde'a 825, 874
- parami względnie pierwsze 903 -, wyznacznik 822
- względnie pierwsze 903 - zerowa 816
licznik binarny 406 macierze boolowskie, mnożenie 836
LIFO 236 maksymalne skojarzenie 674
lista 240 maksymalny, niezależny zbiór wierz·
- cykliczna 241 chołków 805
- dwukierunkowa 240 - przepływ, skalowanie 705
- jednokierunkowa 241 marszruta 1068
- nieposortowana 241 matroid 391
liść 121 - grafowy 392
logarytm dyskretny 927 - macierzowy 392
- iterowany 58, 509 -, podzbiory niezaleine 392
- ważony 393
M -, własność wymiany 392
mediana 220
macierz 816 - ważona 229
- diagonalna 817 metoda cyklu Eulera 780
- dodatnio określona 823 - ,.dziel i zwyciężaj" 32, 186
-, dodawanie 819 - Forda-Fulkersona 659
-, iloczyn skalamy 821 - Homera 31
-, - zewnętrzny 821 - iteracyjna Newtona 765
·- incydencji 401, 529,1060 - łańcuchowa 260
- kwadratowa 817 - najmniejszych kwadratów 861
-, mnożenie 819 - przedprzeplywowa 678, 681
-, - przez skalar 819 - -, operacja podnosz.enia LIFf 682
- nieodwracalna (osobliwa) 821 - -, - operacja przesyłania PUSH 681
-, odejmowanie 819 -, poprawność 684, 686
- odwracalna (nieosobliwa) 821 - przyrostowa 32
-, odwracanie 853 - relaksacji 585
- odwrotna 821 - wielokrotnego podnoszenia do kwad-
- permutacyjna 818 ratu 929
- poprzedników 619 - zamiatania 997
- przeciwna 819 - - obrotowego 1003
- pseudoodwrotna 863 metryka miejska 230
-, rozkład LU 845 minimalne drzewo rozpinające 473, 562,
-, rząd 822 647
- sąsiedztwa 528 - - -, algorybn z użyciem kopców złą­
- symetryczna 818 czalnych 473
- Toeplitza 894 - - -, drugie w kolejności 575
- transponowana 816 minimalny stopień B-drzewa 438

1112
SKOROWIDZ

minor 822 o
mnożenie macierzy 348
obliczanie prefiksów 742
moc zbioru 106 - rozkładu LUP 849
moneta symetryczna 134 obliczenia prefiksowe 778
monoid 834 - -, odcinkowe 810
most 560 - -, równolegle 778
multigraf 116 - -, -, rekurencyjne 798
obraz 111
N odchylenie standardowe 143
odcinek 991
najkrótsza ścieżka 533, 578 - skierowany 991
- - w dagu 603 odległość L ....1018
najkrótsze ścieżki, metoda zmieniają­ - redakcyjna (edycyjna) 372
cych się wag 634 odśmiccacz 247
- -, wielokrotne podnoszenie do kwad- odwrotność funkcji 112
ratu 625 - multiplikatywna 921
najmniejsza wspólna wielokrotność 911 ogon kolejki 238, 240
największy wspólny dzielnik 901 ograniczenia różnicowe 607
następnik lewy 121 ogranicz.enie błędu względnego 1074
- prawy 121 - prostokątne 994
- Wyzła w drzewie 121 - względne 1073
ojciec węzła w drzewie 121
nawiasowanie 347, 367
operacja motylkowa 888
niejawna notacja sumowania 655
operacje modyfikujące 233
nierówność Boole'a 138
- na drzewach rozłącznych 499
- Krafta 124
oszacowanie asymptotycmie dokładne
- Markowa 143
45
- trójkąta I 078 - wagi najkrótszej ścieżki 585
niezależny zbiór wierzchołków 805
otoczka wypukła 1003
notacja asymptotycma 45 owijanie 1011
- O 47
-
- O 62 p
- O' 62
- o 51 para uporządkowana 107
..- 0 45 paradoks dnia urodzin 157
-
- 0 62 permutacja 112, 127
- O 49 - Józefa 340
-
- O 62
- odwracająca bity 424

- O 62
pętla w grafie 113
pierścień 835
- w 52 pierwiastek pierwotny 927
NP-zupełność 1046 - z jedności, główny 879
numerycma niestabilność 840 - -, zespolony 879
NWD901 podciąg 361
n-zbiór 106 poddrzewo 121

1113
SKOROWIDZ

poddrzewo lewe 121 problem 3-CNF-SAT 1050


- prawe 121 - abstrakcyjny 1024
podgraf 116 - cyklu Hamiltona 1032
- poprzedników 537 - decyzyjny 1024
podgrupa 915 - istnienia rozwiązań dopuszczalnych
- generowana 916 607
podmacierz główna 859 - izomorfizmu podgrafu 1069
podpis cyfrowy 931,933 - Józefa 340
podsłowo 127 - kliki 1055
podstruktura optymalna 381 - kolorowania grafu 1071
podścieżka 114 - komiwojażera 1068
podwymacznik 823 - -, bitonicmy 371
podzbiór 104 - -, euklidesowy 371
- właściwy 104 - komiwojażera-krótkodystansowca
podział zbioru 106 1084
podzielność 899 - konkretny 1025
pokrycie ścieżkowe 703 - łamania symetrii 804
- -, minimalne 704 - maksymalnego przepływu 651
- wierzchołkowe 1057, 1076 - minimalnego drzewa rozpinającego
poprawność algorytmu 22 394, 562
poprzednik węzła w drzewie 121 - minimum „off-line" 518
porażka 144 - najdłuższego wspólnego podciągu 361
porządek kopcowy 459 - najkrótszych ścieżek 578
- leksykograficzny 301 - - - z jednym źródłem 579
- liniowy 11O - oblici:eniowy 21
postać 3-koniunkcyjna normalna 1050 - optymalizacyjny 346, 1025
- dysjunkcyjna nonnalna 1051 - optymalnego mnożenia ciągu macie-
- koniunkcyjna normalna 1050 rzy 347, 348
potencjał 411 - optymalnej triangulacji wielokąta 367
potęgowanie modularne 929 - pakowania 1095
potomek węzła w drzewie 121 - pary najbardziej odległych punktów
półpierścień domknięty 639 1004
praca algorytmu równoległego 777 - plecakowy, ciągły 381
prawa De Morgana 105 - podziału zbioru 1070
- idempotentności 104 - pokrycia wierzchołkowego 1057, 1076
- łączności 105 - - zbioru 1084
- pochłaniania 105 - sortowania 170
- przemienności 104 - spcłnialności formuł 1047
- zbiorów pustych 104 - - układów logicmych 1041
- rozdzielności 105 - sumy podzbioru 1059
prawdopodobieństwo 133 - szeregowania zadań 398
- warunkowe 135 - ważonego pokrycia zbioru 1096
prawo iloczynu 127 - wyboru 220
- sumy 127 - - zajęć 376
prefiks 361 - wyszukiwania wzorca 956
- słowa 957 - wyznaczania głębokości 520

1114
SKOROWIDZ

problem zbioru niezależnego 1070 relacja antysymetryczna 109


- :zero-jedynkowego programowania - binarna 108
całkowitoliczbowego 1070 - ~owego porządku 109
- znajdowania najniższych wspólnych - przechodnia 108
przodków off-line 521 - równoważności 108
prosta zamiatająca 997 - symetryczna 108
próby Bemoulliego 144 relaksacja krawędzi 585
przeciwdziedzina funkcji 110 reprezentacja wielomianu przez wartości
przedział domknięty 334 w punktach 873
- jednostronnie otwarty 334 - - - współczynniki 872
- otwarty 334 reprezentacja zbiorów rozłącznych, lis-
przekrój grafu nieskierowanego 564 towa 501
- w sieci 663 - - -, -, łączenie z wyważaniem 503
przepływ 679 - - -, kompresja ścieżki 506
- całkowitoliczbowy 676 - - -, łączenie wg rangi 506
- netto 651 - - -, las zbiorów rozłącznych 505
- - przez przekrój 663 reszta 900
przepustowość krawędzi. 650 - kwadratowa 953
- przekroju 663 - Schura 846, 856, 860
- rcsidualna 659, 662 rodzina funkcji haszujących, k-uniwer-
przeskok 776 salna 283
przestrzeń 7.darzeń 132 rotacja 308
przeszukiwanie grafu w głąb 539 rozkład jednostajny, ciągły 134
- - wszerz 530 - liczby na czynniki 946
przodek węzła w drzewie 121 - LU 845
przystawanie liczb modulo 900 - LUP 841
punkt artykulacji 560 - prawdopodobieństwa 133
- -, dwumianowy 146
o - -, geometryczny 144
rozładowywanie nadmiarowego wterz-
quasi-pierścień
834 cholka 693
- boolowski 834 rozmiar danych wejściowych 27
quicksort 186 rozwiązanie dopuszczalne 607
rozwinięcie Taylora 304
równanie normalne 863
R
równość funkcji 111
ranga liczby w zbiorze 198 - zbiorów 103
- węzła 327, 506 RSA 934
redukowalność w czasie wielomiano- rząd elementu w grupie 917
wym 1037 - wielkości funkcji 31
rekord 170
rekurencja 34, 77
-, rozwiązywanie metodą iteracyjną 82 s
-, - - podstawiania 78 scalanie dwóch posortowanych ciągów
-, - - rekurencji uniwersalnej 86 33
rekursja końcowa 203 schemat aproksymacji 1075

1115
SKOROWIDZ

schemat aproksymacji, w pełni wielo- stan automatu 966


mianowy 1075 statystyki pozycyjne 172, 220, 326
- -, wielomianowy 1075 stopień wejściowy wierzchołka 114
- Hornera 872 - węzła w drzewie 121
sieć dopuszczalna 691 - wielomianu 870
- permutacyjna 730 - wyjściowy wierzchołka 114
- PERT, ścieżka krytyczna 605 stos 204, 236
- porównująca 714 - pusty 237
- -, głębokość 716 strona na dysku 434
- półczyszcz.ąca 721 struktura danych dla zbiorów rozłącz-
- przepływowa 650 nych 498
- residualna 660 sufiks słowa 957
- scalająca 725 sukces 144
- - Batchera 729 suma przepływów 658
- sortująca 716, 727 sumator pełny 735
··· - typu odd-even 729 - równoległy 741, 746
- -, bitoniczna 722 - szeregowy 740
- transpozycyjna 729 - -, bitowy 759
- z wieloma źródłami i wieloma ujścia- - z zapamiętywaniem przeniesień 747
mi 655 surjekcja 111
silnia 58 symbol Legendre'a 953
silnie spójne składowe 115, 552 syn węzła w drzewie 121
singleton 106 szereg arytmetyczny 66
składowa dwuspójna 560 - geometryczny 66
skojarzenie doskonałe 678 - teleskopowy 67
słowa, konkatenacja 957 szybkie przekształcenie Fouriera 876,
słownik 232 882
słowo 127,956
- puste 957, 1028
-, prefiks 957
$
-, sufiks 957 ścieżka 114
sortowanie 22 - Hamiltona 1035
- kubełkowe 215 - krytyczna w sieci PERT 605
- pozycyjne 212 - na dysku 434
- przez kopcowanie 180 - prosta 114
- - scalanie 32 ścieżki bitoniczne 371
- - selekcję 31 średnica drzewa 538
- - wstawianie 23, 27 świadectwo 1033
- - zliczanie 210
- - -, stabilność 21 l
T
- szybkie 186
- topologiczne 548 tablica z haszowaniem 259
- w miejscu 23, 171 tablice dynamiczne 415
spamiętywanie 358 tablicowy układ mnożący 751
spójność krawędziowa 673 test Millera-Rabina 940
stała Eulera 280 transpozycja grafu 552

1116
SKOROWIDZ

transpozycja grafu skierowanego 529


- macierzy 528
w
triangulacja wielokąta 366 wielokąt 366
trójkąt Pascala 131 waga minimaksowa 648
trwale struktury danych 432 - najkrótsz.ej ścieżki 578
twierdzenie Brenta 793 - ścieżki 578
- chińskie o resztach 923 wariancja 142
- Eulera 926 warstwy maksimów zbioru punktów
- Fermata 927 1019
- Halla 678 - wypukłe zbioru punktów 1018
- Lagrange'a 916 wartościowanie dla układu logicmego
- Lamego 908 1040
- o dzieleniu z resztą 900 wartościowanie spełniające 1040
- o liczbach pierwszych 938 wartość funkcji 111
- o logarytmie dyskretnym 927 - oczekiwana 141
- o maksymalnym przepływie I. mmt• .. wartownik 242
malnym przekroju 665 warunek przepustowości 650
- o splocie 886 - skośnej symetrycmości 650
- z.achowania przepływu 650
wektor 816, 991
u - bitowy 258
ujście529, 650 - jednostkowy 816
układ kombinacyjny 735, 793 - kolumnowy 816
- -, elementarny 734 -, norma Euklidesowa 821
- -, głębokość 738, 793 - splotu 873
- -, rozmiar 738, 793 - wierszowy 816
- -, stopień rozgałęzienia 735 wektorowe układy mnożące 761
- -, ścieżka krytycma 749 wektory liniowo niezależne 822
układ logiczny spełnialny 1040 - - zależne 821
- -, wartościowanie 1040 weryfikacja w czasie wielomianowym
- równań liniowych, nadokreślony 840 1034
- - -, podokreślony 840 węzeł drzewa 120
- - -, rozwiązywanie 839 - wewnętrm y 121
- - -, - przez podstawianie do przcxiu - z.ewnętrzny 121
842 wielokrotność 899
- - -, - przez podstawianie do tyłu 842 wielomaterialowa sieć przepływowa 658
- - -, trójdiagonalny 867 wielomian 55, 870
układy dzielące 765 -, ewaluacja 872, 895
- mnożące 750 -, pochodna 894
- sumujące 739 wielomiany, dodawanie 870
- z taktowaną pamięcią 758 -, mnożenie 871
uniwersalna rodzina funkcji haszują.cych wierzchołek grafu 113
268 - osiągalny 114
uniwersum 105 własność drzewa BST 285
ustalanie porządku obiektów na liście - kopca 174
775 - optymalnej podstruktury 355, 396

1117
SKOROWIDZ

własność wspólnych podproblemów 356 zbiory, przecięcie 104


- wyboru zachłannego 380 -, rozłączne 106
wspólny dzielnik 901 -, różnica 104
- podciąg 361 -, suma 104
współczynnik dwumienny 129 -, zasada włączania i wyłączania 107
- zapełnienia 261, 415 zbiór 103
współczynniki wielomianu 870 - częściowo uporządkowany 109
- wielomianu 55 - dynamiczny 232
wyłączny odczyt 771 - liczb całkowitych Z 103
- zapis 771 - liczb naturalnych N 103
wysokość drzewa 174 - liczb neczywistych R 103
wysokość węzła w drzewie 174 - nieprzeliczalny 106
wyszukiwanie 26 - nieskończony 106
- binarne 36 - niezależny 1070
- -, dynamiczne 425 - potęgowy 106
- liniowe 26 - przeliczalny 106
- w B-drzewie 440 - pusty 103
wyznacznik, własność 823 - skończony 106
wzór Bayesa 137 - statyczny 281
- Lagrange'a 874 zdarzenia niezależne 136
- Stirlinga 58 - parami niezależne 136
- warunkowo niezależne 139
z - wzajemnie jednoznaczne 133
- - niezależne 136
zadania programowania liniowego 606 zdarzenie 132
zakres funkcji 111 - elementarne 132
zależność rekurencyjna 34 - niemożliwe 133
zamiatanie, harmonogram zdarzeń 997 - pewne 133
-, struktura stanu prostej zamiatającej zliczanie probabilistyczne 166
998 złożoność algorytmu, asymptotyczna 44
zapytania 233 zmienna losowa 139
zasada zero~jedynkowa 718, 720 zmienne losowe, niezależne 140
zawieranie się zbiorów 104
zbiory dynamiczne, trwałe 320
ź
-, iloczyn kartezjański 107
-, parami rozłączne 106 źródło 650

WNT. Warsz.a.wa 2001


Wyd. IV. Ark. wyd. 70,0. Ark. druk. 70,0.
Symbol Et/83655/WNT
Drukarnia Wydawnictw Naukowych SA
Łódź, ul. Żwirki 2
MYDAWNICTWA NAUKQWQ.TECHNICZNE
:W-048
Warszawa,Mazowiecka
2/4
TEL/FAX626-62-93___________________________ _

Zamawiam za zaliczeniem pocztowym następujące ksią1ki:

• Arabas J.: Wykłady z algorytmów ewolucyjnych 45,00 zł ... egz.


• Amold K., Gosling J.: Java TM 42,00 zł egz
• Banachowski L .. , Diks K„ Rytter W.: Algorytmy i struktury danych 38,00 zł egz.
• Barker R., Longman C.: CASE· MethodSM_Modelowanie funkcji i procesów 58,00 zł egz.
• Ben-Ań M.: Podstawy programowania współbieżnego i rozproszonego 18,00 zł egz
• Beynon-Davies P.: Inżynieria systemów info1macyjnych 27,50 zł egz.
• Beynon-Davies P.: Systemy baz danych 35,00 zł egz.
• Bialasiewicz J. T.: Falki i aproksymacje 36,00 zł egz.
• Boone B .. Java™ dla programistów Ci C++ 38,00 zł egz.
• Bowman J.S., Emerson S.L., Damovsky M.: Podręcznik języka SQL 84,00 z! egz.
• Cichosz P.: Systemy uczące się 77,00 zł egz.
• Cou/ouńs G., Dol/imore J,, Kindberg T.: Systemy rozproszone.
Podstawy i projektowanie 79,00 zł egz.
• Dale C.J., Darwen H.: SQL. Omówienie standardu języka 78,00 zł egz.
• Drozdek A.: Wprowadzenie do kompresji danych 21,50zł egz.
• Drozdek A., Simon O.L.: Struktury danych w języku C 34,00 zł egz
• Goodheart B., Cox J.: Sekrety magicznego ogrodu. UNIXR System V Wersja 4
od środka. Podręcznik 75,00 z! egz
• Goodheart B., Cox J.: Sekrety magicznego ogrodu. UN1XRSystem V Wersja 4
25,00 zł egz.
od środka. Klucz do zadań
45,00 zł egz.
• Jajszczyk A ..: Wstęp do telekomutacji
• Johnson M.K .. Troan E. W.: Oprogramowanie użytkowe w systemie Linux 86.00 zł egz.
• Kiciak P.: Podstawy modelowania krzywych i powierzchni.
Zastosowania w grafice komputerowej 31,50zl egz.
• Koblitz N.: Algebraiczne aspekty kryptografii 38.00 zł egz.
• Lausen G., Vos.sen G.: Obiektowe bazy danych 40,00 zł egz.
• Ledgard H.F.: Mała księga programowania obiektowego 20,00 z/ egz
• Lippman S.B.: Model obiektu w C++ 28,00 zł egz.
• Lippman S.B., Lajoie J.: Podstawy języka C++ 110,00 zł egz
19,50zł egz.
• MagielL.J.: Mała księga komputerów PC
44,00 zł egz
• Majidimehr A.H.: Optymalizacja systemu UNIX
• Meyers S.: Język C++ bardziej efekty,vny 28,00 zł egz
• Osowski S.: Sieci neuronowe w ujęciu algorytmicznym (+ dyskietka) 33.00 zł egz.
• Plauger P.J.: Biblioteka standardowa C++ 65,00 zł egz.
• Poe V.. Klauer P., Brobst S.: Tworzenie hurtowni danych 39,00 zł egz.
• Pugh K.: Un!)t dla u2:ytkownika DOS-u 19,00 zł egz.
• Skahill K.: Język VHOL. Projektowanie programowalnych układów logicznych 68,00 z! egz.
• Southerton A., Perkins E.C., Jr.: Słownik poleceń systemów Unix i X 43,00 zł egz.
• Sta//ings W.: Ochrona danych w sieci i intersieci 38,00 zł egz.
• Stallings W.: Organizacja i architektura systemu komputerowego.
Projektowanie systemu a jego wydajność 60,00 zł egz.
• Stevens WR.: Programowanie zastosowań sieciowych
w systemie Unix 42,00 zł egz
• Stevens W.R.: UNIX. Programowanie usług sieciowych.
T. 1 -API: gniazda i XTI 75,50 zł ... egz
• Stevens W.R.: UNIX. Programowanie usług sieciowych.

T. 2 - Komunikacja międzyprocesowa
• Stroustrup B.: Projektowanie i rozwój języka C++
108,00
35,00
45,00


'"
egz.
egz.
• Vandevoorde D.: Język C++. Ćwiczenia i rozwiązania
• Yourdon E., Argila C.: Analiza obiektowa i projektowanie. Przykłady zastosowań 43,00 zł egz.
Seria: KLASYKA INFORMATYKI
• Bentley J.: Perełki
oprogramowania
• Dale C.J.: Wprowadzenie do systemów baz danych
65,00 z/
92,00 zl
43,00 zł
""
egz.
• Kemighan B. W., Ritchie O.M.: Język ANSI C
• StroustrupB.: Język C1-+ 132,00 zł
55,00 zł
'"
,,,
egz.
• Ul/man J.D., Widom J.: Podstawowy wykład z systemów baz danych
62.00 zł ..
• Wirth N.: Algorytmy+ struktury danych"' programy

Seria: LUDZIE, KOMPUTERY, INFORMACJA


'"'
• Brooks F.P. Jr.: Mityczny osobomiesiąc. Ese}e o inżynieńi oprogramowania 45,00 zł ... egz.
• Cooper A.: Wanaa rządzą domem wariatów. Dlaczego produkty wysokich technologii
doprowadza}ą nas do szaleństwa i co zrobić, żeby tego uniknąć 55,00 zł _ egz.
• Young R., Goldman Rohm W.: Pod kontrolą radarową 45,00 zł egz
• Yourdon E.: Marsz ku klęsce. Przewodnik dla projektanta systemów 35,00 zł __egz.

W PRZYGOTOWANIU
• Knuth D.E.: Sztuka programowania
T, 1-Algorytmy podstawowe
T. 2 -Algorytmy seminumeryczne
T. 3 - Sortowanie i wyszukiwanie
Ukaże się w czwartym kwartale 2001 roku

dam podpiszamawiaJące{Jo

Zamówienie nawybraneksiążki proszę wysyłać pod adresem:


Dział Marketingu
i Sprzedaży Wydawnictw Naukowo-Technicznych
Skrytkapocztowa 359,00-950Warszawa

Zamówienia również za pośrednictwem poczty


przyjmujemy elel<lronicznej,
Naszadres:marketir19@wntcom.pl

Zamawiający:

Imię i nazwisko. ,, .... , ·········-············--·········


Adres......................................................................... .
. . . . . .. . " " .... " ......... " ............ ..
NIP......................... . ,,,,,, ................... , ............ ,, .......... .
~--- --------------------------
Przyzakupi€ksią±ek o wartoSdprzekraczającej 200,00zł udzielamy do naszejksięgami
10%rabatu.Zapraszamy
internetowej-www.wntcom.pl

Powyższe cenyobowiązują do wyczerpania danegotytułu


nakradu

Wyrażam zgodę nawykorzystanie do celówmarke~ngowych


przezWNTmOichdanychosobowych
(głównie wysyłanie ofertreklamowych)

..... ,,.................
, ..............
..
dam podpis

Wprowadzenie
do algorytmow

You might also like