Sie sind auf Seite 1von 34

Team Contest Reference

University of Karlsruhe

23. Oktober 2008


INHALTSVERZEICHNIS 1

Inhaltsverzeichnis
1 Suchen 1
1.1 Binäre und ternäre Suche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 N-tes Element (Select) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.3 Teilstringsuche (Knuth-Morris-Pratt) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

2 Parsen 2
2.1 Rekursiver Parser für arithmetische Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.2 Umwandlung von Infix- nach Postfix-Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.3 Bottom-up-Parser nach Cocke, Younger und Kasami . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

3 Arithmetik und Algebra 4


3.1 Bigints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3.2 Schnelles Potenzieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.3 Endliche Summation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.4 Matrixmultiplikation (ikj, Strassen) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.5 Lineare Gleichungssysteme (LGS) und Determinanten . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.6 Polynome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

4 Rekurrenzen, Kombinatorik und DP 10


4.1 Lineare Rekurrenzen (z.B. Fibonacci) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4.2 Urnenmodelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.3 Binomialkoeffizienten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.4 Häufige Rekurrenzen in der Kombinatorik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.5 Längste Teilfolge (LCS, LIS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.6 SUBSET-SUM (KNAPSACK nur mit Gewichten) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4.7 Nim (bisschen Spieltheorie) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

5 Zahlentheorie 12
5.1 GGT und Kongruenzen (Euklid) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
5.2 Chinesischer Restsatz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5.3 Eulersche Phi-Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5.4 Primzahlen (Erathostenes, Miller-Rabin) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

6 Graphen 14
6.1 Topologische Sortierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
6.2 Artikulationspunkte, Brücken und Bikonnektivität (Tarjan) . . . . . . . . . . . . . . . . . . . . . . . . . 15
6.3 Starke Zusammenhangskomponenten (Tarjan) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
6.4 Eulerscher Kreis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
6.5 Kürzeste Pfade (Dijkstra, Floyd-Warshall, Bellman-Ford) . . . . . . . . . . . . . . . . . . . . . . . . . 16
6.6 Minimaler Spannbaum (Kruskal, Prim) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
6.7 Bipartites Matching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
6.8 Maximaler Fluss (Ford-Fulkerson) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
6.9 Min-Cost-Max-Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

7 Geometrie 22
7.1 Geraden und Punkte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
7.2 Dreiecke und Liniensegmente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
7.3 Kreise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
7.4 Polygone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
7.5 Rasterung von Linien/Kreisen (Bresenham) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

8 Datenstrukturen 29
8.1 Disjunkte Mengen (Union-Find) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
8.2 Heap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
8.3 Fenwick-Baum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
8.4 Trie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
8.5 Balancierter binärer Suchbaum (AVL) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1 SUCHEN 2

1 Suchen
1.1 Binäre und ternäre Suche
Wenn möglich, lower bound oder upper bound verwenden.
Wenn nicht, geht der generelle Algorithmus folgendermaßen: Man braucht ein Prädikat (z.B. x < 42, das irgendwo
in dieser Liste von true auf false springt. Man setzt seine beiden Anfangsindizes (z.B. lo und hi ) auf Werte,
von denen man sicher weiß, dass das Prädikat an dieses Stellen den jeweiligen Wert annimmt. Achtung: Bei
Suche in einem Array kann das heißen, die beiden Startindizes außerhalb des Arrays zu setzen, z.B. lo = −1 und
hi = N. Dann wertet man immer das Prädikat beim arithmetischen Mittel der beiden Indizes aus und setzt je nach
Wert entweder lo oder hi auf das Mittel. Solange wiederholen, bis sich diese beiden Indizes nur noch um eins
unterscheiden, dann zeigt lo auf den höchsten Wert, wo das Prädikat noch true ergibt und hi auf das niedrigste
false.
Die ternäre Suche eignet sich für bitonische (auf einem Abschnitt monoton steigende, auf dem anderen monoton
fallende) Funktionen. Immer bei einem und zwei Dritteln des aktuellen Intervalls auswerten und dann nur einen
der beiden aktuellen Indizes anpassen.

1.2 N-tes Element (Select)


 
1 # include <a l g o r i t h m >
2 # include <f u n c t i o n a l >
3
4 / / o r d n e t [ a , b ) so um, dass a [ n ] das g l e i c h e Element e n t h a e l t ,
5 / / wie wenn [ a , b ) s o r t i e r t waere , und g i b t a [ n ] zurueck
6 / / L a u f z e i t i n O( b − a ) g a r a n t i e r t
7 int select ( int ∗ a , int ∗ b , int n) {
8 i f ( b − a < 10000) {
9 nth element ( a , a + n , b ) ;
10 return a [ n ] ;
11 }
12
13 int ∗ q = a;
14 f o r ( i n t ∗p = a ; b − p >= 5 ; p += 5 ) {
15 nth element ( p , p + 2 , p + 5 ) ;
16 swap ( ∗ q++ , p [ 2 ] ) ;
17 }
18
19 q = p a r t i t i o n ( a , b , bind2nd ( l e s s <i n t > ( ) , s e l e c t ( a , q , ( q − a ) / 2 ) ) ) ;
20 return n < q − a ? s e l e c t ( a , q , n ) : s e l e c t ( q , b , n − ( q − a ) ) ;
21 }
 

1.3 Teilstringsuche (Knuth-Morris-Pratt)


 
1 void KMP( char ∗x , i n t m, char ∗y , i n t n ) {
2 i n t i , j , kmpNext [m+ 1 ] ;
3
4 / ∗ P r e p r o ce s si n g ∗ /
5 i = 0;
6 j = kmpNext [ 0 ] = −1;
7 while ( i < m) {
8 while ( j > −1 && x [ i ] ! = x [ j ] )
9 j = kmpNext [ j ] ;
10 i ++;
11 j ++;
12 i f ( x [ i ] == x [ j ] )
13 kmpNext [ i ] = kmpNext [ j ] ;
14 else
15 kmpNext [ i ] = j ;
16 }
17
18 / ∗ Searching ∗ /
19 i = j = 0;
2 PARSEN 3

20 while ( j < n ) {
21 while ( i > −1 && x [ i ] ! = y [ j ] )
22 i = kmpNext [ i ] ;
23 i ++;
24 j ++;
25 i f ( i >= m) {
26 p r i n t f ( ”%d\n ” , j − i ) ;
27 i = kmpNext [ i ] ;
28 }
29 }
30 }
 

2 Parsen
2.1 Rekursiver Parser für arithmetische Ausdrücke
 
1 # include <c s t d l i b >
2
3 / / e r s t p t r setzen , dann A u f r u f von parse ( )
4 char ∗ p t r ;
5
6 double atom ( ) ;
7 double prod ( ) ;
8 double parse ( ) ;
9
10 double atom ( ) {
11 double r e s ;
12 i f ( ∗ p t r == ’ ( ’ ) {
13 ++ p t r ;
14 r e s = parse ( ) ;
15 ++ p t r ;
16 } else r e s = s t r t o d ( p t r , & p t r ) ;
17 return res ;
18 }
19
20 double prod ( ) {
21 double r e s = atom ( ) ;
22 while ( ∗ p t r == ’ ∗ ’ | | ∗ p t r == ’ / ’ )
23 r e s = ∗ p t r ++ == ’ ∗ ’ ? r e s ∗ atom ( ) : r e s / atom ( ) ;
24 return res ;
25 }
26
27 double parse ( ) {
28 double r e s = prod ( ) ;
29 while ( ∗ p t r == ’ + ’ | | ∗ p t r == ’− ’ )
30 r e s = ∗ p t r ++ == ’ + ’ ? r e s + prod ( ) : r e s − prod ( ) ;
31 return res ;
32 }
 

2.2 Umwandlung von Infix- nach Postfix-Notation


 
1 # include <stack>
2
3 i n t p r e c v a l ( char c ) {
4 i f ( c == ’ + ’ | | c == ’− ’ ) r e t u r n 1 ;
5 else r e t u r n 2 ;
6 }
7
8 bool p r e c I s S m a l l e r ( char op1 , char op2 ) {
9 r e t u r n p r e c v a l ( op1 ) < p r e c v a l ( op2 ) ;
10 }
2 PARSEN 4

11
12 void parse ( char ∗ i n f i x , char ∗ p o s t f i x ) {
13 stack<char> s ;
14 char c ;
15
16 while ( ∗ i n f i x ! = 0 ) {
17 switch ( ∗ i n f i x ) {
18 case ’ ( ’ :
19 s . push ( ’ ( ’ ) ;
20 break ;
21 case ’ ) ’ :
22 while ( ! s . empty ( ) ) {
23 c = s . top ( ) ;
24 s . pop ( ) ;
25 i f ( c == ’ ( ’ ) break ;
26 ∗ p o s t f i x ++ = c ;
27 }
28 break ;
29 case ’ + ’ : case ’− ’ : case ’ ∗ ’ : case ’ / ’ :
30 while ( ! s . empty ( ) ) {
31 c = s . top ( ) ;
32 i f ( c == ’ ( ’ ) break ;
33 else i f ( ! p r e c I s S m a l l e r ( c , ∗ i n f i x ) ) {
34 s . pop ( ) ;
35 ∗ p o s t f i x ++ = c ;
36 } else break ;
37 }
38 s . push ( ∗ i n f i x ) ;
39 break ;
40 default :
41 ∗ p o s t f i x ++ = ∗ i n f i x ;
42 break ;
43 }
44 ++ i n f i x ;
45 }
46
47 while ( ! s . empty ( ) ) {
48 ∗ p o s t f i x ++ = s . t o p ( ) ;
49 s . pop ( ) ;
50 }
51
52 ∗ p o s t f i x = 0;
53 }
 

2.3 Bottom-up-Parser nach Cocke, Younger und Kasami


Eine kontextfreie Grammatik ist in Chomsky-Normalform, wenn jede Produktion eine der folgenden Formen hat:

S → ε, A → a, A → BC

Um Grammatik in CNF zu bringen, folgende Schritte:


• Jedem Terminal ein Nichtterminal zuordnen, Produktion Xa → a einfügen.

• Wenn wo mehr als zwei Nichtterminale stehen, immer zwei zu einem neuen Symbol zusammenfassen und
entsprechende Produktion einfügen.
• ε-Produktionen entfernen.
• Kettenproduktionen (A → B entfernen, indem B nacheinander durch alle seine Folgeprodukte ersetzt wird.
 
1 # define MAX 1024
2
3 # define TERMINALS 7
4 # define NONTERMINALS 14
3 ARITHMETIK UND ALGEBRA 5

5
6 / / # d e f i n e A 1 , # d e f i n e MOD 2 , # d e f i n e BA 4 , usw f u e r a l l e N i c h t t e r m i n a l e
7
8 i n t nonterminal map [ NONTERMINALS ] [ NONTERMINALS ] , words , symbol [MAX ] [ MAX ] ;
9
10 / / am Anfang i n symbol [ i ] [ i ] d i e Maske des N i c h t t e r m i n a l s des i −t e n Wortes e i n t r a g e n
11 bool cyk ( ) {
12 i n t i , j , k , m, n ;
13 f o r ( i = 1 ; i < words ; ++ i )
14 f o r ( j = 0 ; j + i < words ; ++ j ) {
15 symbol [ j ] [ j + i ] = 0 ;
16 f o r ( k = 0 ; k < i ; ++k )
17 f o r (m = 0 ; m < NONTERMINALS ; ++m)
18 f o r ( n = 0 ; n < NONTERMINALS ; ++n )
19 i f ( ( symbol [ j ] [ j + k ] & ( 1 << m) )
20 && ( symbol [ j + k + 1 ] [ j + i ] & ( 1 << n ) ) )
21 symbol [ j ] [ j + i ] | = nonterminal map [m] [ n ] ;
22 }
23 r e t u r n words > 0 && ( symbol [ 0 ] [ words − 1 ] & SENTENCE ) ;
24 }
 

3 Arithmetik und Algebra


3.1 Bigints
3.1.1 Bigints in C++
 
1 # include <iostream>
2 # include <c s t r i n g >
3
4 # define LEN 128
5 # define DPI 9
6 # define MOD 1000000000
7
8 typedef i n t bignum [ LEN ] ;
9
10 / ∗ alpha = i n t e g ; ∗ /
11 void s e t i n t ( bignum alpha , i n t i n t e g ) {
12 alpha [ 0 ] = 2 ;
13 alpha [ 1 ] = i n t e g ;
14 }
15
16 / ∗ alpha = a t o i ( s t r ) ; ∗ /
17 void s e t s t r ( bignum alpha , char ∗ s t r ) {
18 char ∗ p t r = s t r + s t r l e n ( s t r ) ;
19 i n t power10 , d i g i t s = DPI ;
20
21 alpha [ 0 ] = 1 ;
22 while ( p t r −− ! = s t r ) {
23 i f ( d i g i t s == DPI ) {
24 alpha [ alpha [ 0 ] + + ] = 0 ;
25 power10 = 1 ;
26 d i g i t s = 0;
27 }
28
29 alpha [ alpha [ 0 ] − 1 ] += ( ∗ p t r − ’ 0 ’ ) ∗ power10 ;
30 power10 ∗= 1 0 ;
31 ++ d i g i t s ;
32 }
33
34 while ( alpha [ 0 ] > 2 && alpha [ alpha [ 0 ] − 1 ] == 0 ) −−alpha [ 0 ] ;
35 }
36
37 / ∗ alpha = beta ; ∗ /
3 ARITHMETIK UND ALGEBRA 6

38 void s e t b i g ( bignum alpha , const bignum beta ) {


39 int i ;
40
41 f o r ( i = 0 ; i < beta [ 0 ] ; ++ i ) {
42 alpha [ i ] = beta [ i ] ;
43 }
44 }
45
46 / ∗ alpha += i n t e g ; ∗ /
47 void a d d i n t ( bignum alpha , i n t i n t e g ) {
48 int i = 1;
49
50 while ( i n t e g > 0 ) {
51 i f ( i < alpha [ 0 ] ) i n t e g += alpha [ i ] ;
52 alpha [ i ++] = i n t e g % MOD;
53 i n t e g / = MOD;
54 }
55
56 i f ( i > alpha [ 0 ] ) alpha [ 0 ] = i ;
57 }
58
59 / ∗ alpha += beta ; ∗ /
60 void a d d b i g ( bignum alpha , const bignum beta ) {
61 int carry = 0 , i = 1 , j = 1;
62
63 while ( c a r r y > 0 | | j < beta [ 0 ] ) {
64 i f ( i < alpha [ 0 ] ) c a r r y += alpha [ i ] ;
65 i f ( j < beta [ 0 ] ) c a r r y += beta [ j + + ] ;
66 alpha [ i ++] = c a r r y % MOD;
67 c a r r y / = MOD;
68 }
69
70 i f ( i > alpha [ 0 ] ) alpha [ 0 ] = i ;
71 }
72
73 / ∗ alpha −= i n t e g ; ∗ /
74 void s u b i n t ( bignum alpha , i n t i n t e g ) {
75 int i = 1;
76
77 i n t e g = −i n t e g ;
78 while ( i n t e g < 0 ) {
79 i n t e g += alpha [ i ] ;
80 i f ( i n t e g < 0 ) i n t e g += 2 ∗ MOD;
81 alpha [ i ++] = i n t e g % MOD;
82 i n t e g / = −MOD;
83 }
84
85 while ( alpha [ 0 ] > 2 && alpha [ alpha [ 0 ] − 1 ] == 0 ) −−alpha [ 0 ] ;
86 }
87
88 / ∗ alpha −= beta ; ∗ /
89 void s u b b i g ( bignum alpha , const bignum beta ) {
90 int carry = 0 , i = 1 , j = 1;
91
92 while ( c a r r y < 0 | | j < beta [ 0 ] ) {
93 c a r r y += alpha [ i ] ;
94 i f ( j < beta [ 0 ] ) c a r r y −= beta [ j + + ] ;
95 i f ( c a r r y < 0 ) c a r r y += 2 ∗ MOD;
96 alpha [ i ++] = c a r r y % MOD;
97 c a r r y / = −MOD;
98 }
99
100 while ( alpha [ 0 ] > 2 && alpha [ alpha [ 0 ] − 1 ] == 0 ) −−alpha [ 0 ] ;
101 }
102
103 / ∗ alpha ∗= i n t e g ; ∗ /
3 ARITHMETIK UND ALGEBRA 7

104 void m u l i n t ( bignum alpha , long long i n t e g ) {


105 long long c a r r y = 0 ;
106 int i = 1;
107
108 while ( c a r r y > 0 | | i < alpha [ 0 ] ) {
109 i f ( i < alpha [ 0 ] ) c a r r y += alpha [ i ] ∗ i n t e g ;
110 alpha [ i ++] = c a r r y % MOD;
111 c a r r y / = MOD;
112 }
113
114 i f ( i > alpha [ 0 ] ) alpha [ 0 ] = i ;
115 }
116
117 / ∗ alpha += beta ∗ gamma ; ∗ /
118 void mul add ( bignum alpha , const bignum beta , const bignum gamma) {
119 long long i n t e g , c a r r y ;
120 int i , j , k = 1;
121
122 while ( k < gamma [ 0 ] ) {
123 i n t e g = gamma [ k ] ;
124 carry = 0;
125 i = k ++;
126 j = 1;
127
128 while ( c a r r y > 0 | | j < beta [ 0 ] ) {
129 i f ( i < alpha [ 0 ] ) c a r r y += alpha [ i ] ;
130 i f ( j < beta [ 0 ] ) c a r r y += beta [ j ++] ∗ i n t e g ;
131 alpha [ i ++] = c a r r y % MOD;
132 c a r r y / = MOD;
133 }
134
135 i f ( i > alpha [ 0 ] ) alpha [ 0 ] = i ;
136 }
137
138 while ( alpha [ 0 ] > 2 && alpha [ alpha [ 0 ] − 1 ] == 0 ) −−alpha [ 0 ] ;
139 }
140
141 / ∗ alpha ∗= beta ; ∗ /
142 void m u l b i g ( bignum alpha , const bignum beta ) {
143 bignum gamma ;
144
145 s e t i n t (gamma, 0 ) ;
146 mul add (gamma, alpha , beta ) ;
147 s e t b i g ( alpha , gamma ) ;
148 }
149
150 / ∗ alpha / = i n t e g ; r e t u r n alpha % i n t e g ; ∗ /
151 i n t d i v i n t ( bignum alpha , i n t i n t e g ) {
152 long long c a r r y = 0 ;
153 i n t i = alpha [ 0 ] ;
154
155 while ( i > 1 ) {
156 c a r r y ∗= MOD;
157 c a r r y += alpha[−− i ] ;
158 alpha [ i ] = c a r r y / i n t e g ;
159 c a r r y %= i n t e g ;
160 }
161
162 while ( alpha [ 0 ] > 2 && alpha [ alpha [ 0 ] − 1 ] == 0 ) −−alpha [ 0 ] ;
163
164 return carry ;
165 }
166
167 / ∗ alpha = pow ( alpha , i n t e g ) ; ∗ /
168 void p o w i n t ( bignum alpha , i n t i n t e g ) {
169 bignum square [ 2 ] , answer [ 2 ] ;
3 ARITHMETIK UND ALGEBRA 8

170 i n t square idx = 0 , answer idx = 0;


171
172 s e t i n t ( answer [ a n s w e r i d x ] , 1 ) ;
173 s e t b i g ( square [ s q u a r e i d x ] , alpha ) ;
174
175 while ( i n t e g > 0 ) {
176 i f (( integ & 1)) {
177 s e t i n t ( answer [ a n s w e r i d x ˆ 1 ] , 0 ) ;
178 mul add ( answer [ a n s w e r i d x ˆ 1 ] , answer [ a n s w e r i d x ] , square [ s q u a r e i d x ] ) ;
179 a n s w e r i d x ˆ= 1 ;
180 }
181 i n t e g >>= 1 ;
182
183 s e t i n t ( square [ s q u a r e i d x ˆ 1 ] , 0 ) ;
184 mul add ( square [ s q u a r e i d x ˆ 1 ] , square [ s q u a r e i d x ] , square [ s q u a r e i d x ] ) ;
185 s q u a r e i d x ˆ= 1 ;
186 }
187
188 s e t b i g ( alpha , answer [ a n s w e r i d x ] ) ;
189 }
190
191 / ∗ c o u t << alpha ; ∗ /
192 void p r i n t b i g ( bignum alpha ) {
193 i n t i = alpha [ 0 ] − 1 ;
194
195 c o u t << alpha [ i ] ;
196 cout . f i l l ( ’ 0 ’ ) ;
197 while ( i −− > 1 ) {
198 c o u t . w i d t h ( DPI ) ;
199 c o u t << alpha [ i ] ;
200 }
201 cout . f i l l ( ) ;
202 }
 

3.1.2 Bigints in Java


 
1 import java . lang . ∗ ;
2 import java . u t i l . ∗ ;
3 import java . io . ∗ ;
4 import j a v a . math . ∗ ;
5
6 class Main {
7 f i n a l s t a t i c i n t MAX = 255;
8 static BigInteger [ ] fac ;
9 s t a t i c void i n i t F a c ( ) {
10 B i g I n t e g e r b i = B i g I n t e g e r .ONE;
11 f a c = new B i g I n t e g e r [MAX + 1 ] ;
12 f a c [ 0 ] = B i g I n t e g e r .ONE;
13 f o r ( i n t i = 1 ; i <= MAX; ++ i ) {
14 fac [ i ] = fac [ i − 1 ] . m u l t i p l y ( bi ) ;
15 b i = b i . add ( B i g I n t e g e r .ONE ) ;
16 }
17 }
18 public s t a t i c void main ( S t r i n g [ ] args ) {
19 Scanner sc = new Scanner (new BufferedReader (new InputStreamReader ( System . i n ) ) ) ;
20 while ( sc . h a s N e x t I n t ( ) ) {
21 i n t t o t a l = sc . n e x t I n t ( ) ;
22 B i g I n t e g e r rank = sc . n e x t B i g I n t e g e r ( ) ;
23 }
24 }
25 }
 

3 ARITHMETIK UND ALGEBRA 9

3.2 Schnelles Potenzieren


 
1 int fast exp ( int a , int b) {
2 int r = 1;
3
4 while ( b > 0 ) {
5 i f ( ( b & 1 ) ) r ∗= a ;
6 b >>= 1 ;
7 a ∗= a ;
8 }
9
10 return r ;
11 }
 

3.3 Endliche Summation


Def. Pochhammer-Symbol: nk = n · (n − 1) · . . . · (n − k + 1). Bei Summation über Polynome, drücke die normalen
Potenzen in dieser Schreibweise aus, z.B. 3n2 − n = 3n2 + 2n1 . Dann wie in der Analysis integrieren, ergibt eine
Art Stammfunktion: X
3n2 + 2n1 = n3 + n2
Wenn man das Polynom von 1, . . . , N summiert, muss man die Stammfunktion an der Stelle N + 1 und 1 aus-
werten:
XN
3n2 + 2n1 = n3 + n2 |N 1
+1
= (N + 1)3 + (N + 1)2 = (N + 1)N 2
n=1
P
Das Gegenteil vomP Summationsoperator ist der Differenzenoperator ∆f (x) = f (x + 1) − f (x). Der e-Funktion
entspricht 2n , also 2n = ∆2n = 2n .

3.4 Matrixmultiplikation (ikj, Strassen)


3.4.1 Cachefreundliche Matrixmultiplikation
 
1 f o r ( i = 0 ; i < SIZE ; i ++)
2 f o r ( k = 0 ; k < SIZE ; k ++)
3 f o r ( j = 0 ; j < SIZE ; j ++)
4 c [ i ] [ j ] += a [ i ] [ k ] ∗ b [ k ] [ j ] ;
 

3.4.2 Algorithmus von Strassen


    
r s a b e f
=
t u c d g h

rclp1 = a(f − h) (1)


p2 = (a + b)h (2)
p3 = (c + d)e (3)
p4 = d(g − e) (4)
p5 = (a + d)(e + h) (5)
p6 = (b − d)(g + h) (6)
p7 = (a − c)(e + f ) (7)

Dann:
r = p5 + p4 − p2 + p6 , s = p1 + p2 , t = p3 + p4 , u = p5 + p1 − p3 − p7
3 ARITHMETIK UND ALGEBRA 10

3.5 Lineare Gleichungssysteme (LGS) und Determinanten


3.5.1 Gauß-Algorithmus
 
1 # define EPSILON 0.0000001
2
3 bool LGS( double ∗∗ A , double∗ b , i n t m, i n t n , double∗ r e s ) {
4 i n t b l a [ n ] ; / / Werte von 0 . .m−1
5 memset ( bla , −1 ,n∗ s i z e o f ( i n t ) ) ;
6 i n t x , y , x2 , y2 ;
7 f o r ( y =0; y<m; y ++){
8 f o r ( x = 0 ; ( x<n ) & & ( !A [ x ] [ y ] ) ; x + + ) ; / / x i s t der e r s t e E i n t r a g der n i c h t 0 i s t
9 i f ( x==n ) {
10 i f ( b [ y]>EPSILON ) r e t u r n f a l s e ;
11 else continue ;
12 }
13 f o r ( x2=x +1; x2<n ; x2 ++){
14 A [ x2 ] [ y ] / = A [ x ] [ y ] ;
15 }
16 b [ y ]/=A[ x ] [ y ] ;
17 A[ x ] [ y ]=1;
18 f o r ( y2 =0; y2<m; y2 ++){
19 i f ( ! A [ x ] [ y2 ] ) continue ;
20 i f ( y==y2 ) continue ;
21 f o r ( x2 =0; x2<n ; x2 ++){
22 i f ( x==x2 ) continue ;
23 A [ x2 ] [ y2]−=A [ x2 ] [ y ] ∗ A [ x ] [ y2 ] ;
24 }
25 b [ y2]−=b [ y ] ∗ A [ x ] [ y2 ] ;
26 A [ x ] [ y2 ] = 0 ;
27 }
28 bla [ x ]= y ;
29 }
30
31 memset ( res , 0 , n∗ s i z e o f ( double ) ) ;
32 f o r ( x =0; x<n ; x ++){
33 i f ( b l a [ x ]== −1) continue ;
34 res [ x ]= b [ bla [ x ] ] ;
35 }
36 return true ;
37 }
 

3.5.2 LR-Zerlegung, Determinanten


 
1 const i n t MAX = 4 2 ;
2
3 void l r ( double a [MAX ] [ MAX] , i n t n ) {
4 int i , j , k ;
5
6 f o r ( i = 0 ; i < n ; ++ i ) {
7 f o r ( k = 0 ; k < i ; ++k ) a [ i ] [ i ] −= a [ i ] [ k ] ∗ a [ k ] [ i ] ;
8 f o r ( j = i + 1 ; j < n ; ++ j ) {
9 f o r ( k = 0 ; k < i ; ++k ) a [ j ] [ i ] −= a [ j ] [ k ] ∗ a [ k ] [ i ] ;
10 a [ j ] [ i ] /= a [ i ] [ i ] ;
11 f o r ( k = 0 ; k < i ; ++k ) a [ i ] [ j ] −= a [ i ] [ k ] ∗ a [ k ] [ j ] ;
12 }
13 }
14 }
15
16 double d e t ( double a [MAX ] [ MAX] , i n t n ) {
17 l r (a, n ) ;
18 double d = 1 ;
19 f o r ( i n t i = 0 ; i < n ; ++ i ) d ∗= a [ i ] [ i ] ;
20 return d ;
4 REKURRENZEN, KOMBINATORIK UND DP 11

21 }
22
23 void s o l v e ( double a [MAX ] [ MAX] , double ∗b , i n t n ) {
24 int i , j ;
25
26 f o r ( i = 1 ; i < n ; ++ i ) {
27 f o r ( j = 0 ; j < i ; ++ j ) b [ i ] −= a [ i ] [ j ] ∗ b [ j ] ;
28 }
29 f o r ( i = n − 1 ; i >= 0 ; −− i ) {
30 f o r ( j = i + 1 ; j < n ; ++ j ) b [ i ] −= a [ i ] [ j ] ∗ b [ j ] ;
31 b [ i ] /= a [ i ] [ i ] ;
32 }
33 }
 

3.6 Polynome
3.6.1 Newtonsche/Hermitsche Interpolation
Dividierte Differenzen:
[xi+1 , . . . , xj ] − [xi , . . . , xj−1 ]
[xi , . . . , xj ] =
xj − xi
[xi , . . . , xi ] = f (n−1) (xi )/n!
| {z }
nmal

Newton-Polynome:
i−1
Y
Pi = (x − xk )
k=1

Also immer ein Term weniger mulitplizieren als das neue xi ! Interpoliertes Polynom:
n
X
P = [x1 , . . . , xi ] · Pi
i=1

Wenn ein xi mehrmals auftaucht, als man auch die ersten paar Ableitungen interpolieren will, wird dieses xi dann
halt auch im Newton-Polynom mehrmals dranmultipliziert.

3.6.2 Hornerschema
Pn Pm
Seien f (T ) = i=0 αi T i und g(T ) = j=0 βj T j zwei Polynome. Setze für alle i = n, . . . , 0:

min(m,n−i)
X
γi = αi − βm−j γi+j
j=max(1,m−i)

Dann ist der Rest r(T ) und das Ergebnis s(T ) der Division von f durch g gegeben durch:
m−1
X n
X
r(T ) = γi T i , s(T ) = γj T j−m
i=0 j=m

4 Rekurrenzen, Kombinatorik und DP


4.1 Lineare Rekurrenzen (z.B. Fibonacci)
Lassen sich als Matrixgleichung schreiben, z.B. Fibonacci:
     
Fn 1 1 Fn−1
= ·
Fn−1 1 0 Fn−2

Für große n dann einfach die Matrix mittels schneller Potenzierung potenzieren, geht in O(log n).
4 REKURRENZEN, KOMBINATORIK UND DP 12

4.2 Urnenmodelle
k aus n ziehen mit Zurücklegen ohne Zur ücklegen
n
mit Beachtung der Reihenfolge nk k ·k!
n+k−1 n

ohne Beachtung der Reihenfolge k k

4.3 Binomialkoeffizienten
               
n n! n n r r r−1 r r−1 r−1
= , = , = , = +
k k!(n − k)! k n−k k k k−1 k k k−1
          r  
r k−r−1 r m r r−k X r
= (−1)k , = , (x + y)r = xk y r−k
k k m k k m−k k
k=0
X k  n + 1 X r + k  r + n + 1 X  r  s  r + s
= , = , =
m m+1 k n k n−k n
0≤k≤n k≤n k

4.4 Häufige Rekurrenzen in der Kombinatorik


4.4.1 Catalansche Zahlen
Anzahl der Sehnentriangulationen eines n + 2-Ecks, Anzahl der gültigen Klammerausdrücke mit n Klammern,
Anzahl der Pfade in einem Grid, wobei man nur eins nach rechts und eins nach unten gehen darf.
  n
1 2n X
Cn = , Cn+1 = Ck Cn−k
n+1 n
k=0

4.4.2 Stirlingsche Zahlen 1. Art


Anzahl der n-Permutationen mit genau k Zyklen.

sn+1,k = sn,k−1 ± n · sn,k

4.4.3 Stirlingsche Zahlen 2. Art


Anzahl der Partitionen von n Elementen in genau k Mengen.

Sn+1,k = Sn,k−1 + k · Sn,k

4.4.4 Eulersche Zahlen


Anzahl der n-Permutation, wo genau k Elemente größer als ihr vorhergehendes sind.

En,k = (n − k) · En−1,k−1 + (k + 1) · En−1,k

4.5 Längste Teilfolge (LCS, LIS)


 
1 # include <a l g o r i t h m >
2
3 i n t eingabe [ SIZE ] ;
4 i n t seq [ SIZE ] ;
5
6 int l i s () {
7 int m = 0;
8 f o r ( i n t i = 0 ; i < p ; ++ i ) {
9 i n t j = lower bound ( seq , seq + m, eingabe [ i ] ) − seq ;
10 i f ( j == m) seq [m++] = eingabe [ i ] ; else seq [ j ] = eingabe [ i ] ;
11 }
12 r e t u r n m;
13 }
 

5 ZAHLENTHEORIE 13

4.6 SUBSET-SUM (KNAPSACK nur mit Gewichten)


 
1 # include <iostream>
2 # include <v e c t o r >
3
4 / / l i e f e r t d i e g r o e s s t e Summe von Elementen aus v , d i e k l e i n e r oder g l e i c h l i m i t ist
5 i n t subset sum ( const v e c t o r <i n t >& v , i n t l i m i t ) {
6 v e c t o r <bool> poss ( l i m i t + 1 , f a l s e ) ;
7 int m = 0;
8
9 poss [ 0 ] = t r u e ;
10 f o r ( v e c t o r <i n t > : : c o n s t i t e r a t o r i t = v . begin ( ) ; i t ! = v . end ( ) ; ++ i t )
11 f o r ( i n t j = m; j >= 0 ; −− j )
12 i f ( poss [ j ] && j + ∗ i t <= l i m i t ) {
13 poss [ j + ∗ i t ] = t r u e ;
14 m = max (m, j + ∗ i t ) ;
15 }
16
17 r e t u r n m;
18 }
 

4.7 Nim (bisschen Spieltheorie)


Gegeben: n Haufen mit a1 , . . . , an Steinen, wer dran ist nimmt bis zu k Steine von einem Haufen (k = ∞ erlaubt).
1. Variante: Ziel ist es als letztes einen Stein aufzunehmen. Man gewinnt, wenn
(a[1] \% (k + 1)) XOR ... XOR (a[n] \% (k + 1)) == 0 vor dem eigenen Zug.

2. Variante: Ziel ist es, dass der Gegner den letztes Stein aufnimmt: To win at misère nim, play exactly as if you
were playing normal play nim, except if your winning move would lead to a position that consists of heaps
of size one only. In that case, leave exactly one more or one fewer heaps of size one than the normal play
strategy recommends.

3. Variante: Ziel ist es, den letzten Stein eines der Haufen aufzunehmen. Man gewinnt, wenn vor dem eige-
nem Zug ein Stapel maximal k Steine hat oder (a[1] \% (k + 1)) XOR ... XOR (a[n] \% (k + 1)) == 0, indem man
entweder den letzten Stein nimmt oder man genau diesen Zustand herstellt.

5 Zahlentheorie
5.1 GGT und Kongruenzen (Euklid)
 
1 # include <a l g o r i t h m >
2 # include <v a l a r r a y >
3 # include <v e c t o r >
4
5 using namespace s t d ;
6
7 typedef v a l a r r a y <i n t > a i ;
8 typedef v e c t o r <i n t > v i ;
9
10 // a % e u c l i d ( a , b ) [ 0 ] == 0
11 // b % e u c l i d ( a , b ) [ 0 ] == 0
12 // e u c l i d ( a , b ) [ 0 ] == a ∗ e u c l i d ( a , b ) [ 1 ] + b ∗ e u c l i d ( a , b ) [ 2 ]
13 ai euclid ( int a , int b) {
14 int R[ ] = { a , 1 , 0 } , S [ ] = { b , 0 , 1 };
15 a i r (R, 3 ) , s ( S , 3 ) ;
16
17 while ( s [ 0 ] ! = 0 ) {
18 r −= r [ 0 ] / s [ 0 ] ∗ s ;
19 swap ( r , s ) ;
20 }
21
5 ZAHLENTHEORIE 14

22 return r ;
23 }
24
25 / / a l l e Loesungen von ( a ∗ x ) % m == b m i t 0 <= x < m
26 v i c o n g s o l v ( i n t a , i n t b , i n t m) {
27 a i gcd = e u c l i d ( a , m) ;
28 v i res ;
29
30 i f ( b % gcd [ 0 ] == 0 ) {
31 m / = gcd [ 0 ] ;
32 i n t i n v = gcd [ 1 ] < 0 ? (m − (−gcd [ 1 ] % m) ) % m : gcd [ 1 ] % m,
33 s o l = ( b / gcd [ 0 ] ∗ i n v ) % m;
34 f o r ( i n t i = gcd [ 0 ] ; i > 0 ; −− i ) {
35 r e s . push back ( s o l ) ;
36 s o l += m;
37 }
38 }
39
40 return res ;
41 }
 

5.2 Chinesischer Restsatz


Zwei Kongruenzen der Art x ≡ a1 mod m1 , x ≡ a2 mod m2 lassen sich lösen, indem man jeweils geschickt
eine Eins dranmultipliziert und das dann aufaddiert. Die erste Kongruenz erweitern wir mit m−12 m2 (Inverses bzgl.
m1 ) und die zweite mit m−1
1 m1 (bzgl. m2 ). Die Summe der rechten Seiten liefert dann das Ergebnis. Die Inversen
lassen sich mit dem ggT-Algorithmus von Euklid berechnen.
Dies funktioniert nur, wenn m1 und m2 teilerfremd sind. Wenn nicht, muss a1 ≡ a2 mod ggT(m1 , m2 ) gelten.
Dann kann man die Kongruenzen durch diesen ggT teilen.

5.3 Eulersche Phi-Funktion


ϕ(n) = Anzahl teilerfremden Zahlen kleiner gleich n.
Y p−1
ϕ(n) = n · , m und n teilerfremd =⇒ ϕ(m · n) = ϕ(m) · ϕ(n) und mϕ(n) ≡ 1 mod n)
p|n
p
p prim

Wenn man nur die Werte bis ein paar Millionen braucht, dann mit Backtracking erzeugen:
 
1 unsigned prime [ NUM PRIMES ] , p h i [MAX ] ;
2 bool used [ NUM PRIMES ] ;
3 / / Primzahlen muessen i n prime stehen , A u f r u f m i t genphi ( 0 , 1 , 1 )
4 void genphi ( unsigned next , unsigned n , unsigned p ) {
5 phi [ n ] = p ;
6 while ( n e x t < primes && n <= MAX / prime [ n e x t ] ) {
7 i f ( ! used [ n e x t ] ) {
8 used [ n e x t ] = t r u e ;
9 genphi ( next , n ∗ prime [ n e x t ] , p ∗ ( prime [ n e x t ] − 1 ) ) ;
10 used [ n e x t ] = f a l s e ;
11 } else genphi ( next , n ∗ prime [ n e x t ] , p ∗ prime [ n e x t ] ) ;
12 ++ n e x t ;
13 }
14 }
 

5.4 Primzahlen (Erathostenes, Miller-Rabin)


5.4.1 Sieb des Erathostenes
 
1 # include <c s t r i n g >
2
3 unsigned ∗ s i e v e ( unsigned ∗ next , unsigned h i g h ) {
6 GRAPHEN 15

4 unsigned char i s p r i m e [ ( h i g h >> 4 ) + 1 ] ;


5 unsigned i , j ;
6
7 memset ( i s p r i m e , 0 , ( h i g h >> 4 ) + 1 ) ;
8 i f ( 2 <= h i g h ) {
9 ∗ n e x t ++ = 2 ;
10 }
11
12 f o r ( i = 3 ; i <= h i g h ; i += 2 ) {
13 i f ( ( i s p r i m e [ i >> 4 ] & ( 1 << ( ( i >> 1 ) & 7 ) ) ) == 0 ) {
14 ∗ n e x t ++ = j = i ;
15 while ( ( j += i << 1 ) <= h i g h ) {
16 i s p r i m e [ j >> 4 ] | = 1 << ( ( j >> 1 ) & 7 ) ;
17 }
18 }
19 }
20
21 return next ;
22 }
 

Fenstersieb?

5.4.2 Primzahltest nach Miller und Rabin


 
1 typedef unsigned long long u l l ;
2 const s t r u c t z e r o t {
3 i n t z [ 0 x10000 ] ;
4 zero t () {
5 f o r ( i n t i = 1 ; i < 0x10000 ; ++ i ) z [ i ] = ( i & 1 ) ? 0 : 1 + z [ i >> 1 ] ;
6 }
7 } trail ;
8 i n l i n e bool i s p r o b ( unsigned nr , unsigned base ) {
9 unsigned u = 1 , odd = n r − 1 , sh = ( odd & 0xFFFF )
10 ? t r a i l . z [ odd & 0xFFFF ] : 16 + t r a i l . z [ odd >> 1 6 ] ;
11 f o r ( odd >>= sh ; odd > 0 ; odd >>= 1 ) {
12 i f ( ( odd & 1 ) ) u = ( u l l ( u ) ∗ base ) % n r ;
13 base = ( u l l ( base ) ∗ base ) % n r ;
14 }
15 i f ( u == 1 ) r e t u r n t r u e ;
16 while ( sh−− > 0 ) {
17 i f ( u == n r − 1 ) r e t u r n t r u e ;
18 u = ( u l l ( u ) ∗ u ) % nr ;
19 }
20 return false ;
21 }
22 bool i s p r i m e ( unsigned n r ) {
23 s t a t i c const unsigned p [ ] = { 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 } ;
24 f o r ( i n t i = 0 ; i < 8 ; ++ i ) {
25 i f ( p [ i ] ∗ p [ i ] > nr ) return nr > 1;
26 i f ( n r % p [ i ] == 0 ) r e t u r n f a l s e ;
27 }
28 r e t u r n i s p r o b ( nr , 2 ) && i s p r o b ( nr , 7 ) && i s p r o b ( nr , 6 1 ) ;
29 }
 

6 Graphen
6.1 Topologische Sortierung
 
1 i n t t o p s o r t ( graph ∗g , i n t s o r t e d [ ] ) {
2 i n t i n d e g r e e [MAXV ] ; / ∗ i n d e g r e e o f each v e r t e x ∗ /
3 queue<i n t > z e r o i n ; / ∗ v e r t i c e s of indegree 0 ∗ /
4 int x , y ; / ∗ c u r r e n t and n e x t v e r t e x ∗ /
6 GRAPHEN 16

5 int i , c ;
6
7 compute indegrees ( g , i n d e g r e e ) ;
8 f o r ( i n t i = 0 ; i < g−>n v e r t i c e s ; i ++)
9 i f ( i n d e g r e e [ i ] == 0 )
10 z e r o i n . push ( i ) ;
11
12 c = 0;
13 while ( ! z e r o i n . empty ( ) ) {
14 c ++;
15 x = zeroin . f r o n t ( ) ;
16 z e r o i n . pop ( ) ;
17 sorted [ c ] = x ;
18 f o r ( i = 0 ; i < g−>degree [ x ] ; i ++) {
19 y = g−>edges [ x ] [ i ] ;
20 ( i n d e g r e e [ y ]) − −;
21 i f ( i n d e g r e e [ y ] == 0 )
22 z e r o i n . push ( y ) ;
23 }
24 }
25
26 i f ( c ! = g−>n v e r t i c e s )
27 return 0;
28 / / p r i n t f ( ” Not a DAG −− o n l y %d v e r t i c e s found \n ” , j ) ;
29 else
30 r e t u r n −1;
31 }
 

6.2 Artikulationspunkte, Brücken und Bikonnektivität (Tarjan)


 
1 # include <v e c t o r >
2
3 using namespace s t d ;
4
5 const i n t MAX = 1024;
6
7 v e c t o r <v e c t o r <i n t > > graph ;
8 i n t low [MAX] , depth [MAX ] ;
9 bool i s a r t i [MAX] , i s b r i d g e [MAX ] [ MAX ] ;
10
11 i n t v i s i t ( i n t nod , i n t par , i n t dep ) {
12 int children = 0;
13
14 low [ nod ] = depth [ nod ] = dep ;
15 f o r ( s i z e t i = 0 ; i < graph [ nod ] . s i z e ( ) ; ++ i ) {
16 i n t k = graph [ nod ] [ i ] ;
17
18 i f ( depth [ k ] < 0 ) {
19 ++ c h i l d r e n ;
20 v i s i t ( k , nod , dep + 1 ) ;
21 i f ( low [ nod ] > low [ k ] ) low [ nod ] = low [ k ] ;
22 i s a r t i [ nod ] = i s a r t i [ nod ] | | low [ k ] >= dep ;
23 i s b r i d g e [ nod ] [ i ] = low [ k ] > dep ;
24 } else i f ( k ! = par ) {
25 i f ( low [ nod ] > depth [ k ] ) low [ nod ] = depth [ k ] ;
26 i s b r i d g e [ nod ] [ i ] = f a l s e ;
27 }
28 }
29 return c h i l d r e n ;
30 }
31
32 void t a r j a n ( ) {
33 f i l l ( depth , depth + graph . s i z e ( ) , −1);
34 f i l l ( i s a r t i , i s a r t i + graph . s i z e ( ) , f a l s e ) ;
6 GRAPHEN 17

35 f o r ( s i z e t i = 0 ; i < graph . s i z e ( ) ; ++ i )
36 f i l l ( i s b r i d g e [ i ] , i s b r i d g e [ i ] + graph [ i ] . s i z e ( ) , t r u e ) ;
37 f o r ( s i z e t i = 0 ; i < graph . s i z e ( ) ; ++ i )
38 i f ( depth [ i ] < 0 ) i s a r t i [ i ] = v i s i t ( i , i , 0 ) > 1 ;
39 }
 

6.3 Starke Zusammenhangskomponenten (Tarjan)


 
1 v v i gr ;
2 v i dep , low ;
3 stack<i n t > S ;
4
5 void v i s i t ( i n t i , i n t d ) {
6 S . push ( i ) ;
7 dep [ i ] = low [ i ] = 0 ;
8 f o r ( v i : : i t e r a t o r i t = g r [ i ] . begin ( ) ; i t ! = g r [ i ] . end ( ) ; ++ i t ) {
9 i f ( dep [ ∗ i t ] < 0 ) {
10 v i s i t (∗ i t , d + 1 ) ;
11 low [ i ] = min ( low [ i ] , low [ ∗ i t ] ) ;
12 } else i f ( dep [ ∗ i t ] == 0 ) {
13 low [ i ] = min ( low [ i ] , d + 1 ) ;
14 }
15 }
16 dep [ i ] = d ;
17 i f ( dep [ i ] == low [ i ] ) {
18 / / a l l e s a u f Stack b i s h i n u n t e r zu i g e h o e r t i n e i n e SCC
19 }
20 }
 

6.4 Eulerscher Kreis


Bei ungerichteten Graphen existiert ein Eulerkreis genau dann, wenn alle Knoten geraden Grad haben. Bei ge-
richteten Graphen existiert ein Eulerkreis genau dann, wenn bei allen Knoten Eingangsgrad und Ausgangsgrad
gleich sind. Natürlich sollte der Graph zusammenhängend sein!!
 
1 l i s t < i n t > cyc ;
2 void e u l e r ( l i s t < i n t >:: i t e r a t o r i , i n t u ) {
3 f o r ( i n t v = 0 ; v < n ; v++ ) i f ( graph [ u ] [ v ] ) {
4 graph [ u ] [ v ] = graph [ v ] [ u ] = f a l s e ;
5 e u l e r ( cyc . i n s e r t ( i , u ) , v ) ;
6 }
7 }
8
9 i n t main ( ) {
10 / / read graph i n t o graph [ ] [ ] and s e t n t o t h e number o f v e r t i c e s
11 e u l e r ( cyc . begin ( ) , 0 ) ;
12 / / cyc c o n t a i n s an e u l e r c y c l e s t a r t i n g a t 0
13 }
 

6.5 Kürzeste Pfade (Dijkstra, Floyd-Warshall, Bellman-Ford)


6.5.1 Dijkstra
 
1 # include <v e c t o r >
2 # include <queue>
3 # include <f u n c t i o n a l >
4 # include <u t i l i t y >
5
6 const i n t INF = 12345678;
7
8 typedef p a i r <i n t , i n t > i i ;
6 GRAPHEN 18

9 typedef v e c t o r <i i > v i i ;


10 typedef v e c t o r <v i i > v v i i ;
11
12 / / Anzahl der Knoten = g r . s i z e ( )
13 / / Grad des Knotens i = g r [ i ] . s i z e ( )
14 / / j −t e r b e n a c hb ar t er Knoten des Knotens i = g r [ i ] [ j ] . f i r s t
15 / / Laenge d i e s e r Kante = g r [ i ] [ j ] . second
16 v e c t o r <i n t > d i j k s t r a ( v v i i & gr , i n t s r c ) {
17 v e c t o r <i n t > d i s t ( g r . s i z e ( ) , INF ) ;
18 p r i o r i t y q u e u e <i i , v i i , g r e a t e r <i i > > kew ;
19
20 d i s t [ src ] = 0;
21 f o r ( kew . push ( i i ( 0 , s r c ) ) ; ! kew . empty ( ) ; kew . pop ( ) ) {
22 i n t d = kew . t o p ( ) . f i r s t , f r = kew . t o p ( ) . second ;
23 i f ( d <= d i s t [ f r ] ) {
24 f o r ( v i i : : i t e r a t o r i t = g r [ f r ] . begin ( ) ; i t ! = g r [ f r ] . end ( ) ; ++ i t ) {
25 i n t t o = i t −>f i r s t , l e n = i t −>second ;
26 i f ( d i s t [ t o ] > d + l e n ) kew . push ( i i ( d i s t [ t o ] = d + len , t o ) ) ;
27 }
28 }
29 }
30
31 return d i s t ;
32 }
 

6.5.2 Floyd-Warshall
 
1 const i n t MAX = 100 , INF = 12345678;
2
3 / / N = Anzahl Knoten
4 / / g r [ i ] [ j ] = Kosten von Knoten i nach Knoten j
5 / / nach A u f r u f : v i a [ i ] [ j ] = n a e c h s t e r Knoten a u f dem k u e r z es t e n Pfad von i nach j
6 i n t N, v i a [MAX ] [ MAX] , g r [MAX ] [ MAX ] ;
7
8 / / wer nur d i e Distanzen braucht , n i c h t d i e t a t s a e c h l i c h e n Wege,
9 / / kann auch a l l e s m i t ” v i a ” weglassen
10 void f l o y d w a r s h ( ) {
11 f o r ( i n t i = 0 ; i < N; ++ i )
12 f o r ( i n t j = 0 ; j < N; ++ j )
13 via [ i ] [ j ] = j ;
14 f o r ( i n t k = 0 ; k < N; ++k )
15 f o r ( i n t i = 0 ; i < N; ++ i )
16 f o r ( i n t j = 0 ; j < N; ++ j )
17 i f ( gr [ i ] [ j ] > gr [ i ] [ k ] + gr [ k ] [ j ] ) {
18 gr [ i ] [ j ] = gr [ i ] [ k ] + gr [ k ] [ j ] ;
19 via [ i ] [ j ] = k ;
20 }
21 f o r ( i n t i = 0 ; i < N; ++ i )
22 f o r ( i n t j = 0 ; j < N; ++ j )
23 i f ( g r [ i ] [ j ] < INF )
24 while ( v i a [ i ] [ j ] ! = v i a [ i ] [ v i a [ i ] [ j ] ] )
25 via [ i ] [ j ] = via [ i ] [ via [ i ] [ j ] ] ;
26 }
 

6.5.3 Bellman-Ford
 
1 # define NODES 1000
2 # define EDGES 1000
3 # define INFTY 1000000000
4
5 struct {
6 s t r u c t { i n t to , l e n ; } edge [EDGES ] ;
6 GRAPHEN 19

7 i n t degree , d i s t ;
8 } node [NODES ] ;
9
10 i n t nodes ;
11
12 / / t r u e , wenn Graph keinen n e g a t i v e n K r e i s e n t h a e l t
13 bool b e l l m a n f o r d ( i n t source ) {
14 i n t i , j , from , to , d i s t ;
15
16 f o r ( i = 0 ; i < nodes ; ++ i ) node [ i ] . d i s t = INFTY ;
17 node [ source ] . d i s t = 0 ;
18 f o r ( j = 1 ; j < nodes ; ++ j )
19 f o r ( from = 0 ; from < nodes ; ++from )
20 f o r ( i = 0 ; i < node [ from ] . degree ; ++ i ) {
21 t o = node [ from ] . edge [ i ] . t o ;
22 d i s t = node [ from ] . d i s t + node [ from ] . edge [ i ] . l e n ;
23 i f ( d i s t < node [ t o ] . d i s t ) node [ t o ] . d i s t = d i s t ;
24 }
25 f o r ( from = 0 ; from < nodes ; ++from )
26 f o r ( i = 0 ; i < node [ from ] . degree ; ++ i ) {
27 t o = node [ from ] . edge [ i ] . t o ;
28 d i s t = node [ from ] . d i s t + node [ from ] . edge [ i ] . l e n ;
29 i f ( d i s t < node [ t o ] . d i s t ) r e t u r n f a l s e ;
30 }
31 return true ;
32 }
 

6.6 Minimaler Spannbaum (Kruskal, Prim)


6.6.1 Kruskal
 
1 # include <a l g o r i t h m >
2
3 / / e d g e t f e h l t , r o o t und j o i n i s t das u e b l i c h e union−f i n d
4 int kruskal ( ) {
5 v e c t o r <i n t > p a r e n t ( n r o f n o d e s , −1);
6 i n t rem = n r o f n o d e s − 1 , ans = 0 ;
7
8 s o r t ( edges . begin ( ) , edges . end ( ) ) ;
9 f o r ( v e c t o r <edge t > : : i t e r a t o r i t = edges . begin ( ) ; rem > 0 && i t ! = edges . end ( ) ; ++ i t ) {
10 i n t a = r o o t ( parent , i t −>from ) , b = r o o t ( parent , i t −>t o ) ;
11 i f ( a != b ) {
12 j o i n ( parent , a , b ) ;
13 ans += i t −>l e n ;
14 −−rem ;
15 }
16 }
17 r e t u r n ans ;
18 }
 

6.6.2 Prim
 
1 / / a l l e s wie b e i D i j k s t r a
2 i n t prim ( v v i i & g r ) {
3 v e c t o r <i n t > d i s t ( g r . s i z e ( ) , INF ) ;
4 p r i o r i t y q u e u e <i i , v i i , g r e a t e r <i i > > kew ;
5 i n t ans = 0 ;
6
7 d i s t [ 0 ] = 0;
8 f o r ( kew . push ( i i ( 0 , 0 ) ) ; ! kew . empty ( ) ; kew . pop ( ) ) {
9 i n t d = kew . t o p ( ) . f i r s t , f r = kew . t o p ( ) . second ;
10 i f ( d <= d i s t [ f r ] ) {
6 GRAPHEN 20

11 ans += d ;
12 d i s t [ f r ] = −1;
13 f o r ( v i i : : i t e r a t o r i t = g r [ f r ] . begin ( ) ; i t ! = g r [ f r ] . end ( ) ; ++ i t ) {
14 i n t t o = i t −>f i r s t , l e n = i t −>second ;
15 i f ( d i s t [ t o ] > l e n ) kew . push ( i i ( d i s t [ t o ] = len , t o ) ) ;
16 }
17 }
18 }
19 r e t u r n ans ;
20 }
 

6.7 Bipartites Matching


 
1 # include <a l g o r i t h m >
2
3 # define FROM N 1000
4 # define TO N 1000
5
6 i n t from nodes , to nodes ;
7
8 bool graph [ FROM N ] [ TO N ] , seen [ TO N ] ;
9
10 i n t match from [FROM N] , match to [ TO N ] ;
11
12 bool m a t c h v i s i t ( i n t from ) {
13 f o r ( i n t t o = 0 ; t o < to nodes ; ++ t o ) {
14 i f ( graph [ from ] [ t o ] && ! seen [ t o ] ) {
15 seen [ t o ] = t r u e ;
16
17 i f ( match to [ t o ] < 0 | | m a t c h v i s i t ( match to [ t o ] ) ) {
18 match from [ from ] = t o ;
19 match to [ t o ] = from ;
20 return true ;
21 }
22 }
23 }
24
25 return false ;
26 }
27
28 i n t match ( ) {
29 i n t res = 0;
30
31 f i l l ( match from , match from + from nodes , −1);
32 f i l l ( match to , match to + to nodes , −1);
33 f o r ( i n t i = 0 ; i < from nodes ; ++ i ) {
34 f i l l ( seen , seen + to nodes , f a l s e ) ;
35 i f ( match visit ( i )) {
36 ++ r e s ;
37 }
38 }
39
40 return res ;
41 }
 

6.8 Maximaler Fluss (Ford-Fulkerson)


 
1 # include <a l g o r i t h m >
2 # include <c s t r i n g >
3
4 # define NODES 100
5 # define INFTY 1000000000
6 GRAPHEN 21

6
7 i n t nodes , cap [NODES ] [ NODES] , f l o w [NODES ] [ NODES ] ;
8
9 bool s r c s i d e [NODES ] ;
10
11 struct {
12 i n t node , parent , mincap ;
13 } kew [NODES ] ;
14
15 i n t low , h i g h ;
16
17 i n t i n i t b f s ( i n t source , i n t t a r g e t ) {
18 memset ( s r c s i d e , 0 , s i z e o f s r c s i d e ) ;
19 s r c s i d e [ source ] = t r u e ;
20
21 kew [ 0 ] . node = source ;
22 kew [ 0 ] . p a r e n t = −1;
23 kew [ 0 ] . mincap = INFTY ;
24
25 low = 0 ;
26 high = 1;
27
28 return t a r g e t ;
29 }
30
31 bool b f s ( i n t t a r g e t ) {
32 i n t from , t o ;
33
34 while ( low < h i g h && ( from = kew [ low ] . node ) ! = t a r g e t ) {
35 f o r ( t o = 0 ; t o < nodes ; ++ t o ) {
36 i f ( ! s r c s i d e [ t o ] && cap [ from ] [ t o ] > f l o w [ from ] [ t o ] ) {
37 srcside [ to ] = true ;
38
39 kew [ h i g h ] . node = t o ;
40 kew [ h i g h ] . p a r e n t = low ;
41 kew [ h i g h ] . mincap = min ( kew [ low ] . mincap , cap [ from ] [ t o ] − f l o w [ from ] [ t o ] ) ;
42
43 ++ h i g h ;
44 }
45 }
46
47 ++low ;
48 }
49
50 r e t u r n low < h i g h ;
51 }
52
53 i n t maxflow ( i n t source , i n t t a r g e t ) {
54 i n t i , j , res = 0;
55
56 memset ( f l o w , 0 , s i z e o f f l o w ) ;
57 while ( b f s ( i n i t b f s ( source , t a r g e t ) ) ) {
58 r e s += kew [ low ] . mincap ;
59 f o r ( i = low ; i > 0 ; i = j ) {
60 j = kew [ i ] . p a r e n t ;
61 f l o w [ kew [ j ] . node ] [ kew [ i ] . node ] += kew [ low ] . mincap ;
62 f l o w [ kew [ i ] . node ] [ kew [ j ] . node ] −= kew [ low ] . mincap ;
63 }
64 }
65
66 return res ;
67 }
 

6.9 Min-Cost-Max-Flow
6 GRAPHEN 22

 
1 # include <a l g o r i t h m >
2 # include <c l i m i t s >
3 # include <c s t r i n g >
4 using namespace s t d ;
5
6 # define NN 110
7 i n t cap [NN ] [ NN ] ; / / adjacency m a t r i x ( f i l l t h i s up )
8 i n t c o s t [NN ] [ NN ] ; / / c o s t per u n i t o f f l o w m a t r i x ( f i l l t h i s up )
9 i n t f n e t [NN ] [ NN] , a d j [NN ] [ NN] , deg [NN ] ; / / f l o w network and adjacency l i s t
10 i n t par [NN] , d [NN ] ; / / par [ source ] = source ; / / D i j k s t r a ’ s successor and depth
11 i n t p i [NN ] ; / / L a b e l l i n g f u n c t i o n
12
13 # define CLR( a , x ) memset ( a , x , s i z e o f ( a ) )
14 # define I n f ( INT MAX / 2 )
15
16 / / D i j k s t r a ’ s u s i n g non−n e g a t i v e edge w e i g h t s ( c o s t + p o t e n t i a l )
17 # define Pot ( u , v ) ( d [ u ] + p i [ u ] − pi [ v ] )
18 bool d i j k s t r a ( i n t n , i n t s , i n t t )
19 {
20 f o r ( i n t i = 0 ; i < n ; i ++ ) d [ i ] = I n f , par [ i ] = −1;
21 d [ s ] = 0;
22 par [ s ] = −n − 1 ;
23
24 while ( 1 )
25 {
26 / / find u with smallest d [ u ]
27 i n t u = −1, bestD = I n f ;
28 f o r ( i n t i = 0 ; i < n ; i ++ ) i f ( par [ i ] < 0 && d [ i ] < bestD )
29 bestD = d [ u = i ] ;
30 i f ( bestD == I n f ) break ;
31
32 / / r e l a x edge ( u , i ) o r ( i , u ) f o r a l l i ;
33 par [ u ] = −par [ u ] − 1 ;
34 f o r ( i n t i = 0 ; i < deg [ u ] ; i ++ )
35 {
36 / / t r y undoing edge v−>u
37 int v = adj [ u ] [ i ] ;
38 i f ( par [ v ] >= 0 ) continue ;
39 i f ( f n e t [ v ] [ u ] && d [ v ] > Pot ( u , v ) − c o s t [ v ] [ u ] )
40 d [ v ] = Pot ( u , v ) − c o s t [ v ] [ u ] , par [ v ] = −u−1;
41
42 / / t r y edge u−>v
43 i f ( f n e t [ u ] [ v ] < cap [ u ] [ v ] && d [ v ] > Pot ( u , v ) + c o s t [ u ] [ v ] )
44 d [ v ] = Pot ( u , v ) + c o s t [ u ] [ v ] , par [ v ] = −u − 1 ;
45 }
46 }
47
48 f o r ( i n t i = 0 ; i < n ; i ++ ) i f ( p i [ i ] < I n f ) p i [ i ] += d [ i ] ;
49
50 r e t u r n par [ t ] >= 0 ;
51 }
52 #undef Pot
53
54 i n t mcmf3 ( i n t n , i n t s , i n t t , i n t & f c o s t )
55 {
56 / / b u i l d t h e adjacency l i s t
57 CLR( deg , 0 ) ;
58 f o r ( i n t i = 0 ; i < n ; i ++ )
59 f o r ( i n t j = 0 ; j < n ; j ++ )
60 i f ( cap [ i ] [ j ] | | cap [ j ] [ i ] ) a d j [ i ] [ deg [ i ] + + ] = j ;
61
62 CLR( f n e t , 0 ) ;
63 CLR( p i , 0 ) ;
64 int flow = 0;
65 fcost = 0;
7 GEOMETRIE 23

66
67 / / r e p e a t e d l y , f i n d a cheapest path from s t o t
68 while ( d i j k s t r a ( n , s , t ) )
69 {
70 / / get the bottleneck capacity
71 i n t b o t = INT MAX ;
72 f o r ( i n t v = t , u = par [ v ] ; v ! = s ; u = par [ v = u ] ) {
73 b o t = min ( bot , f n e t [ v ] [ u ] ? f n e t [ v ] [ u ] : ( cap [ u ] [ v ] − f n e t [ u ] [ v ] ) ) ;
74
75 / / update t h e f l o w network
76 f o r ( i n t v = t , u = par [ v ] ; v ! = s ; u = par [ v = u ] )
77 i f ( f n e t [ v ] [ u ] ) { f n e t [ v ] [ u ] −= b o t ; f c o s t −= b o t ∗ c o s t [ v ] [ u ] ; }
78 else { f n e t [ u ] [ v ] += b o t ; f c o s t += b o t ∗ c o s t [ u ] [ v ] ; }
79
80 f l o w += b o t ;
81 }
82
83 return flow ;
84 }
 

7 Geometrie
 
1 # include <a l g o r i t h m >
2 # include <cmath>
3 # include <v a l a r r a y >
4
5 using namespace s t d ;
6
7 const double PI = 2 ∗ acos ( 0 ) , EPS = 1e−9;
8
9 typedef v a l a r r a y <double> vec ;
10 typedef v a l a r r a y <vec> vecvec ;
 

7.1 Geraden und Punkte


 
1 # include <a l g o r i t h m >
2 # include <cmath>
3 # include <v a l a r r a y >
4
5 using namespace s t d ;
6
7 const double EPS = 1e−9;
8
9 typedef v a l a r r a y <double> p o i n t ;
10 typedef v a l a r r a y <p o i n t > p o i n t s ;
11
12 typedef v a l a r r a y <double> vec ;
13 typedef v a l a r r a y <vec> vecvec ;
14
15 / / Abstand des Punkts pos zum Ursprung
16 double norm ( const vec& a ) {
17 r e t u r n s q r t ( ( a ∗ a ) . sum ( ) ) ;
18 }
19
20 / / Abstand z w e i e r Punkte
21 double d i s t ( const vec& a , const vec& b ) {
22 r e t u r n norm ( a − b ) ;
23 }
24
25 / / Punkt a u f Gerade durch Punkt pos i n Richtung d i r
26 / / m i t k l e i n s t e m Abstand zu Ursprung ( o r t h o g o n a l e P r o j e k t i o n )
7 GEOMETRIE 24

27 vec p r o j ( const vec& pos , const vec& d i r ) {


28 r e t u r n pos − ( pos ∗ d i r ) . sum ( ) / ( d i r ∗ d i r ) . sum ( ) ∗ d i r ;
29 }
30
31 / / Abstand Punkt−Gerade
32 double d i s t ( const vec& pos , const vec& d i r , const vec& p t ) {
33 r e t u r n norm ( p r o j ( pos − pt , d i r ) ) ;
34 }
35
36 / / S c h n i t t p u n k t Gerade durch pos i n Richtung d i r
37 / / m i t Gerade / Ebene durch Ursprung m i t Normale norm
38 vec i s e c t ( const vec& pos , const vec& d i r , const vec& norm ) {
39 r e t u r n pos − ( pos ∗ norm ) . sum ( ) / ( d i r ∗ norm ) . sum ( ) ∗ d i r ;
40 }
41
42 / / 2D−S c h n i t t p u n k t der Geraden durch Punkte a1−a2 und b1−b2
43 vec i s e c t ( const vec& a1 , const vec& a2 , const vec& b1 , const vec& b2 ) {
44 double temp [ ] = { a1 [ 1 ] − a2 [ 1 ] , a2 [ 0 ] − a1 [ 0 ] } ;
45 vec norm ( temp , 2 ) ;
46 r e t u r n i s e c t ( b1 − a1 , b2 − b1 , norm ) + a1 ;
47 }
48
49 / / S c h n i t t p u n k t Gerade durch pos i n Richtung d i r
50 / / m i t K r e i s / Kugel um Ursprung m i t Radius rad
51 i n l i n e vecvec i s e c t ( const vec& pos , const vec& d i r , double rad ) {
52 double pp = ( pos ∗ pos ) . sum ( ) , dd = ( d i r ∗ d i r ) . sum ( ) ,
53 pd = ( pos ∗ d i r ) . sum ( ) , r r = rad ∗ rad ,
54 d i s = pd ∗ pd − dd ∗ ( pp − r r ) ;
55
56 i f ( d i s > EPS) {
57 vecvec r e s ( pos , 2 ) ;
58 dis = sqrt ( dis ) ;
59 r e s [ 0 ] −= ( pd + d i s ) / dd ∗ d i r ;
60 r e s [ 1 ] −= ( pd − d i s ) / dd ∗ d i r ;
61 return res ;
62 } else i f ( d i s > −EPS) {
63 vecvec r e s ( pos , 1 ) ;
64 r e s [ 0 ] −= pd / dd ∗ d i r ;
65 return res ;
66 }
67
68 r e t u r n vecvec ( ) ;
69 }
 

7.2 Dreiecke und Liniensegmente


 
1 # include <a l g o r i t h m >
2 # include <cmath>
3 # include <v a l a r r a y >
4
5 using namespace s t d ;
6
7 const double PI = 2 ∗ acos ( 0 ) , EPS = 1e−9;
8
9 typedef v a l a r r a y <double> vec ;
10
11 / / Flaeche des durch a und b aufgespannten Parallelogramms
12 / / p o s i t i v , wenn Winkel zwischen a und b p o s i t i v
13 double sgn area ( const vec& a , const vec& b ) {
14 return a [ 0 ] ∗ b [ 1 ] − a [ 1 ] ∗ b [ 0 ] ;
15 }
16
17 / / p o s i t i v , wenn a−b−c im Gegenuhrzeigersinn ( math . p o s i t i v ) l i e g e n
18 double sgn area ( const vec& a , const vec& b , const vec& c ) {
7 GEOMETRIE 25

19 r e t u r n sgn area ( b − a , c − a ) ;
20 }
21
22 / / Dreiecksflaeche
23 double area ( const vec& a , const vec& b , const vec& c ) {
24 r e t u r n 0 . 5 ∗ f a b s ( sgn area ( a , b , c ) ) ;
25 }
26
27 / / D r e i e c k s f l a e c h e aus Se it en la en ge n
28 double area ( double a , double b , double c ) {
29 i f ( a < b ) swap ( a , b ) ;
30 i f ( b < c ) swap ( b , c ) ;
31 i f ( a < b ) swap ( a , b ) ;
32 r e t u r n 0.25 ∗ s q r t ( ( a + ( b + c ) ) ∗ ( c − ( a − b ) ) ∗ ( c + ( a − b ) ) ∗ ( a + ( b − c ) ) ) ;
33 }
34
35 / / t r u e , wenn a und b verschiedene Vorzeichen haben
36 i n l i n e bool pos neg ( double a , double b ) {
37 r e t u r n ( a < 0 && 0 < b ) | | ( b < 0 && 0 < a ) ;
38 }
39
40 / / t r u e , wenn Punkt d i n D r e i e c k m i t Eckpunkten a−b−c l i e g t
41 bool i n s i d e ( const vec& a , const vec& b , const vec& c , const vec& d ) {
42 double x = sgn area ( c , b , a ) ;
43 r e t u r n pos neg ( x , sgn area ( a , b , d))
44 && pos neg ( x , sgn area ( b , c , d))
45 && pos neg ( x , sgn area ( c , a , d));
46 }
47
48 / / t r u e , wenn Punkt c i n a c h s e n p a r a l l e l e m Rechteck durch Punkt a und b l i e g t
49 bool i n s i d e ( const vec& a , const vec& b , const vec& c ) {
50 r e t u r n min ( a [ 0 ] , b [ 0 ] ) < c [ 0 ] + EPS && max ( a [ 0 ] , b [ 0 ] ) > c [ 0 ] − EPS
51 && min ( a [ 1 ] , b [ 1 ] ) < c [ 1 ] + EPS && max ( a [ 1 ] , b [ 1 ] ) > c [ 1 ] − EPS ;
52 }
53
54 / / t r u e , wenn c a u f Segment a−b l i e g t bzw . g l e i c h a oder b i s t
55 bool on seg ( const vec& a , const vec& b , const vec& c ) {
56 r e t u r n i n s i d e ( a , b , c ) && f a b s ( sgn area ( a , b , c ) ) < EPS ;
57 }
58
59 / / S c h n i t t der Liniensegmente a1−a2 und b1−b2
60 / / 0 = k e i n S c h n i t t , 1 = S c h n i t t , −1 = Beruehrung
61 i n t i s e c t ( const vec& a1 , const vec& a2 , const vec& b1 , const vec& b2 ) {
62 double da1 = sgn area ( b1 , b2 , a1 ) , da2 = sgn area ( b1 , b2 , a2 ) ,
63 db1 = sgn area ( a1 , a2 , b1 ) , db2 = sgn area ( a1 , a2 , b2 ) ;
64
65 i f ( pos neg ( da1 , da2 ) && pos neg ( db1 , db2 ) ) r e t u r n 1 ;
66 i f ( on seg ( a1 , a2 , b1 ) | | on seg ( a1 , a2 , b2 )
67 | | on seg ( b1 , b2 , a1 ) | | on seg ( b1 , b2 , a2 ) ) r e t u r n −1;
68 return 0;
69 }
 

Abstand eines Punktes, Abstand eines anderen Segments.

7.3 Kreise
 
1 / / S c h n i t t p u n k t e von K r e i s um 0 m i t Radius r 1 m i t K r e i s um Punkt pos m i t Radius r 2
2 vecvec i s e c t ( double r1 , vec pos , double r 2 ) {
3 double d2 = ( pos ∗ pos ) . sum ( ) , d = s q r t ( d2 ) ;
4 r 1 ∗= r 1 ; r 2 ∗= r 2 ;
5 double x = 0 . 5 ∗ ( d2 + r 1 − r 2 ) / d , y2 = r 1 − x ∗ x ;
6
7 i f ( y2 > EPS) {
8 double norma [ ] = { −pos [ 1 ] , pos [ 0 ] } ;
9 vec norm ( norma , 2 ) ;
7 GEOMETRIE 26

10 vecvec r ( x / d ∗ pos , 2 ) ;
11 y2 = s q r t ( y2 ) ;
12 r [ 0 ] += y2 / d ∗ norm ;
13 r [ 1 ] −= y2 / d ∗ norm ;
14 return r ;
15 } else i f ( y2 > −EPS) {
16 r e t u r n vecvec ( x / d ∗ pos , 1 ) ;
17 }
18 r e t u r n vecvec ( ) ;
19 }
 

Kreis durch drei Punkte, Kreis durch zwei Punkte mit geg. Radius.

7.4 Polygone
Die N Punkte eines Polygons werden mit (xi , yi ) für i = 1, . . . , N bezeichnet. Konvention: (x0 , y0 ) = (xN , yN ).
Die vorzeichenbehaftete Fläche A berechnet sich wie folgt:
N
1X
A= xi−1 yi − xi yi−1
2 i=1

Bei Polygonen mit ganzzahligen Koordinaten gilt für die Fläche A, die Anzahl der Gitterpunkte auf dem Rand B
und die derjenigen im Innern I:
B
I =A− +1
2

7.4.1 Punkt in Polygon


 
1 # include <cmath>
2
3 # define MAX 1024
4 # define EPS 1e−7
5
6 struct point {
7 double x , y ;
8 };
9
10 s t r u c t polygon {
11 int n;
12 p o i n t p [MAX ] ;
13 p o i n t &operator [ ] ( i n t i ) {
14 return p [ i ] ;
15 }
16 };
17
18 i n l i n e double d i s t ( const p o i n t &a , const p o i n t &b ) {
19 double dx = a . x − b . x , dy = a . y − b . y ;
20 r e t u r n s q r t ( dx ∗ dx + dy ∗ dy ) ;
21 }
22
23 bool c o n t a i n s ( polygon &P , p o i n t &p ) {
24 bool i n s i d e = f a l s e ;
25
26 f o r ( i n t j = P . n − 1 , i = 0 ; i < P . n ; j = i ++) {
27 i f ( f a b s ( d i s t ( p , P [ j ] ) + d i s t ( p , P [ i ] ) − d i s t (P [ j ] , P [ i ] ) ) < EPS) {
28 r e t u r n t r u e ; / / t r u e = Rand g e h o e r t m i t zum Polygon
29 }
30
31 i f ( min (P [ j ] . y , P [ i ] . y ) <= p . y && max (P [ j ] . y , P [ i ] . y ) > p . y &&
32 ( p . y − P [ j ] . y ) ∗ (P [ i ] . x − P [ j ] . x ) / (P [ i ] . y − P [ j ] . y ) > p . x − P [ j ] . x ) {
33 inside = ! inside ;
34 }
35 }
36 return i n s i d e ;
7 GEOMETRIE 27

37 }
 

7.4.2 Konvexe Hülle (Graham’s Scan)


 
1 # include <a l g o r i t h m >
2 # include <cmath>
3
4 using namespace s t d ;
5
6 const long double EPS = 1e−5;
7 const i n t MAXPOINTS = 1005;
8
9 struct point {
10 long double x , y ;
11 } p o i n t s [ MAXPOINTS ] , h u l l [ MAXPOINTS ] ;
12 i n t npoints , n h u l l ;
13
14 long double signedArea ( const p o i n t & a , const p o i n t & b , const p o i n t & c ) {
15 return a . x ∗ b . y − b . x ∗ a . y + b . x ∗ c . y − c . x ∗ b . y + c . x ∗ a . y − a . x ∗ c . y ;
16 }
17
18 long double s q r d i s t ( const p o i n t & a , const p o i n t & b ) {
19 return ( a . x − b . x ) ∗ ( a . x − b . x ) + ( a . y − b . y ) ∗ ( a . y − b . y ) ;
20 }
21
22 bool bySignedArea ( const p o i n t & a , const p o i n t & b ) {
23 long double sa = signedArea ( p o i n t s [ 0 ] , a , b ) ;
24
25 r e t u r n ( f a b s ( sa ) < EPS ) ?
26 ( sqrdist ( points [0] , a ) < sqrdist ( points [0] , b ) )
27 : ( sa > 0 ) ;
28 }
29
30 void f i n d m i n p o i n t ( ) {
31 long double minx = p o i n t s [ 0 ] . x , miny = p o i n t s [ 0 ] . y ;
32 int currentmin = 0;
33
34 f o r ( i n t i = 1 ; i < n p o i n t s ; ++ i ) {
35 i f ( p o i n t s [ i ] . y < miny | | ( p o i n t s [ i ] . y == miny && p o i n t s [ i ] . x < minx ) ) {
36 minx = p o i n t s [ i ] . x ;
37 miny = p o i n t s [ i ] . y ;
38 currentmin = i ;
39 }
40 }
41
42 / / exchange min p o i n t w i t h p o i n t [ 0 ]
43 swap ( p o i n t s [ c u r r e n t m i n ] , p o i n t s [ 0 ] ) ;
44 }
45
46 void c o n v e x h u l l ( )
47 {
48 findminpoint ( );
49 s o r t ( p o i n t s + 1 , p o i n t s + n p o i n t s , bySignedArea ) ;
50
51 hull [0] = points [ 0 ] ;
52 nhull = 1;
53
54 f o r ( i n t i = 1 ; i < n p o i n t s ; ++ i ) {
55 / / h i e r anpassen , wenn k o l l i n e a r e punkte m i t aufgenommen werden s o l l e n
56 while ( n h u l l > 1 && signedArea ( h u l l [ n h u l l − 2 ] , h u l l [ n h u l l − 1 ] , p o i n t s [ i ] ) < EPS ) {
57 −−n h u l l ;
58 }
59
60 h u l l [ n h u l l ++] = p o i n t s [ i ] ;
7 GEOMETRIE 28

61 }
62 }
 

7.4.3 Clipping an Halbebene bzw. Gerade


 
1 # include <c s t d i o >
2 # include <c a s s e r t >
3 # include <cmath>
4
5 struct point {
6 double x , y ;
7 };
8
9 const i n t MAX = 1510
10
11 s t r u c t polygon {
12 p o i n t p [MAX ] ;
13 int n;
14 p o i n t & operator [ ] ( i n t i ) {
15 return p [ i ] ;
16 }
17 } poly , c l i p p e d [ 2 ] ;
18
19 double n o r m a l i z e ;
20
21 double signedPolygonArea ( polygon &p ) {
22 double a = 0 ;
23 f o r ( i n t i = 1 ; i < p . n ; ++ i )
24 a += p [ i −1]. x ∗ p [ i ] . y − p [ i ] . x ∗ p [ i −1]. y ;
25
26 a += p [ p . n −1]. x ∗ p [ 0 ] . y − p [ 0 ] . x ∗ p [ p . n −1]. y ;
27
28 return a / 2 ;
29 }
30
31 void i n s e r t ( polygon &p , p o i n t &a ) {
32 i f ( p . n > 0) {
33 i f ( p [ p . n −1]. x == a . x && p [ p . n −1]. y == a . y )
34 return ;
35 }
36 p [ p . n ++] = a ;
37 }
38 double sa ( p o i n t & a , p o i n t & b , p o i n t & c ) {
39 return ( a . x ∗ b . y − a . y ∗ b . x + b . x ∗ c . y − b . y ∗ c . x + c . x ∗ a . y − a . x ∗ c . y ) ∗ normalize ;
40 }
41 p o i n t i n t e r s e c t ( p o i n t & p1 , p o i n t & p2 , p o i n t & p3 , p o i n t & p4 ) {
42 double a1 = p2 . y − p1 . y , b1 = p1 . x − p2 . x ;
43 double c1 = p1 . x∗p2 . y − p2 . x∗p1 . y ;
44 double a2 = p4 . y − p3 . y , b2 = p3 . x − p4 . x ;
45 double c2 = p3 . x∗p4 . y − p4 . x∗p3 . y ;
46
47 double d = a1∗b2 − a2∗b1 ;
48 point p ;
49 p . x = ( c1∗b2 − c2∗b1 ) / d ;
50 p . y = ( a1∗c2 − a2∗c1 ) / d ;
51
52 return p ;
53 }
54 void d o c l i p p i n g ( p o i n t & a , p o i n t & b , polygon& i n p u t , polygon& o u t p u t ) {
55 output . n = 0;
56 f o r ( i n t k = 0 ; k < i n p u t . n ; ++k ) {
57 i n t i = k , i p p = ( k +1) % i n p u t . n ;
58 double s a i = sa ( a , b , i n p u t [ i ] ) ;
59 double s a i p p = sa ( a , b , i n p u t [ i p p ] ) ;
7 GEOMETRIE 29

60
61 i f ( s a i >= 0 && s a i p p >= 0 )
62 i n s e r t ( output , i n p u t [ ipp ] ) ;
63 else i f ( s a i >= 0 && s a i p p < 0 ) {
64 point c = i n t e r s e c t (a , b , input [ i ] , input [ ipp ] ) ;
65 i n s e r t ( output , c ) ;
66 }
67 else i f ( s a i < 0 && s a i p p >= 0 ) {
68 point c = i n t e r s e c t (a , b , input [ i ] , input [ ipp ] ) ;
69 i n s e r t ( output , c ) ;
70 i n s e r t ( output , i n p u t [ ipp ] ) ;
71 }
72 else {
73 a s s e r t ( s a i < 0 && s a i p p < 0 ) ;
74 }
75 }
76 }
77 i n t main ( ) {
78 int currentclipped = 0;
79 / / TODO here :
80 / / i n p u t polygon i n t o both p o l y and c l i p p e d [ 0 ] ! !
81
82 / / n o r m a l i z e t h e d i r e c t i o n o f t h e p o i n t s o f t h e polygon
83 n o r m a l i z e = signedPolygonArea ( p o l y ) ;
84 i f ( n o r m a l i z e > 0 ) n o r m a l i z e = 1 ; else n o r m a l i z e = −1;
85 f o r ( i n t i = 0 ; i < p o l y . n−1; ++ i ) {
86 d o c l i p p i n g ( p o l y [ i ] , p o l y [ i + 1 ] , c l i p p e d [ c u r r e n t c l i p p e d ] , c l i p p e d [1− c u r r e n t c l i p p e d ] ) ;
87 c u r r e n t c l i p p e d = 1− c u r r e n t c l i p p e d ;
88 }
89 d o c l i p p i n g ( p o l y [ p o l y . n −1] , p o l y [ 0 ] , c l i p p e d [ c u r r e n t c l i p p e d ] , c l i p p e d [1− c u r r e n t c l i p p e d ] ) ;
90 c u r r e n t c l i p p e d = 1− c u r r e n t c l i p p e d ;
91 return 0;
92 }
 

7.5 Rasterung von Linien/Kreisen (Bresenham)


 
1 / / r u f t do something ( x , y ) m i t a l l e n ( x , y ) auf ,
2 / / d i e e i n e g e r a s t e r t e L i n i e von ( x0 , y0 ) nach ( x1 , y1 ) b i l d e n
3 void l i n e ( i n t x0 , i n t y0 , i n t x1 , i n t y1 ) {
4 i n t dx = x1 − x0 , dy = y1 − y0 ;
5 i n t i n c r E = 2 ∗ dy , incrNE = 2 ∗ ( dy − dx ) ;
6 i n t d = 2 ∗ dy − dx , x = x0 , y = y0 ;
7 do something ( x , y ) ;
8 while ( x < x1 ) {
9 i f ( d > 0 ) { d += incrNE ; ++y ; } else d += i n c r E ;
10 do something (++ x , y ) ;
11 }
12 }
13 / / r u f t do something ( x , y ) m i t a l l e n ( x , y ) auf ,
14 / / d i e einen g e r a s t e r t e n A c h t e l k r e i s um den Ursprung b i l d e n
15 void c i r c l e ( i n t r a d i u s ) {
16 i n t d e l t a E = 3 , deltaSE = −2 ∗ r a d i u s + 5 ;
17 i n t d = 1 − radius , x = 0 , y = radius ;
18 do something ( x , y ) ;
19 while ( x < y ) {
20 i f ( d < 0 ) d += d e l t a E ; else { d += deltaSE ; deltaSE += 2 ; −−y ; }
21 d e l t a E += 2 ; deltaSE += 2 ;
22 do something (++ x , y ) ;
23 }
24 }
 

8 DATENSTRUKTUREN 30

8 Datenstrukturen
8.1 Disjunkte Mengen (Union-Find)
 
1 # include <a l g o r i t h m >
2 # include <f u n c t i o n a l >
3 # include <v e c t o r >
4 v e c t o r <i n t > make set ( i n t n ) {
5 r e t u r n v e c t o r <i n t >(n , −1);
6 }
7 i n t r o o t ( v e c t o r <i n t >& v , i n t i ) {
8 return v [ i ] < 0 ? i : ( v [ i ] = r o o t ( v , v [ i ] ) ) ;
9 }
10 void j o i n ( v e c t o r <i n t >& v , i n t i , i n t j ) {
11 i f ( ( i = r o o t ( v , i ) ) == ( j = r o o t ( v , j ) ) ) r e t u r n ;
12 i f ( v [ j ] < v [ i ] ) swap ( i , j ) ;
13 v [ i ] += v [ j ] ;
14 v[ j ] = i ;
15 }
16 i n t c o u n t r o o t s ( const v e c t o r <i n t >& v ) {
17 r e t u r n c o u n t i f ( v . begin ( ) , v . end ( ) , bind2 ( l e s s <i n t > ( ) , 0 ) ) ;
18 }
19 v e c t o r <i n t > g e t r o o t s ( const v e c t o r <i n t >& v ) {
20 v e c t o r <i n t > r ;
21 r e m o v e c o p y i f ( v . begin ( ) , v . end ( ) , b a c k i n s e r t e r ( r ) , bind2nd ( g r e a t e r e q u a l <i n t > ( ) , 0 ) ) ;
22 return r ;
23 }
 

8.2 Heap
In der STL gibt es make heap, is heap, sort heap, push heap und pop heap. Achtung: Diese Funktionen stellen das
größte Element an die Spitze des Heaps.
 
1 / / h i e r m i t i n t , aber es r e i c h t , wenn o p e r a t o r < d e f i n i e r t i s t
2 void l i f t ( v e c t o r <i n t >& v , i n t i ) {
3 for ( int j ; i > 0; i = j ) {
4 j = ( i − 1) / 2;
5 i f ( ! ( v [ j ] < v [ i ] ) ) break ;
6 swap ( v [ i ] , v [ j ] ) ;
7 }
8 }
9 void s i n k ( v e c t o r <i n t >& v , i n t i ) {
10 for ( i n t j ; ( j = 2 ∗ i + 1) < i n t ( v . size ( ) ) ; i = j ) {
11 i f ( j + 1 < i n t ( v . s i z e ( ) ) && v [ j ] < v [ j + 1 ] ) ++ j ;
12 i f ( ! ( v [ i ] < v [ j ] ) ) break ;
13 swap ( v [ i ] , v [ j ] ) ;
14 }
15 }
 

8.3 Fenwick-Baum
 
1 # include <v e c t o r >
2 / / v e c t o r <i n t > oder sowas e r s c h a f f e n , am Anfang m i t N u l l e n g e f u e l l t
3 / / Element veraendern UND k u m u l a t i v e Summe auslesen geht i n O( l o g n )
4
5 / / v [ i ] += k
6 void i n c r ( v e c t o r <i n t >& a , i n t i , i n t k ) {
7 a [ i ] += k ;
8 while ( i > 0 ) {
9 i &= i − 1 ;
10 a [ i ] += k ;
11 }
8 DATENSTRUKTUREN 31

12 }
13 / / Summe von a [ 0 ] b i s a [ i ] ( i n k l . )
14 i n t g e t ( v e c t o r <i n t >& a , i n t i ) {
15 int r = a [ 0 ] ;
16 while (++ i < i n t ( a . s i z e ( ) ) ) {
17 r −= a [ i ] ;
18 i |= i − 1;
19 }
20 return r ;
21 }
 

8.4 Trie
8.4.1 Trie mit verketteter Liste
 
1 struct t r i e {
2 s t r u c t t r i e ∗ next , ∗down ;
3 char l e t t e r ;
4 } node [ 1 0 0 0 0 0 0 ] ; / ∗ g g f . Anzahl anpassen ∗ /
5 i n t nodes = 0 ; / ∗ so macht man a l l e T r i e s u n g u e l t i g ∗ /
6 s t r u c t t r i e ∗ r o o t = NULL ; / ∗ so l o e s c h t man einen e i n z e l n e n T r i e ∗ /
7 / ∗ A u f r u f m i t add(& r o o t , s t r ) ; g i b t t r u e zurueck , wenn Wort noch n i c h t vorhanden war ∗ /
8 i n t add ( s t r u c t t r i e ∗∗ r o o t p p , char ∗word ) {
9 s t r u c t t r i e ∗p , ∗∗ prev pp ;
10 i n t n = nodes ;
11 do {
12 f o r ( prev pp = r o o t p p ; ( p = ∗ prev pp ) ! = NULL && p−>l e t t e r < ∗word ;
13 prev pp = &(p−>n e x t ) ) {}
14 i f ( p == NULL | | p−>l e t t e r ! = ∗word ) {
15 p = node + nodes ++;
16 p−>n e x t = ∗ prev pp ;
17 p−>down = NULL ;
18 p−>l e t t e r = ∗word ;
19 ∗ prev pp = p ;
20 }
21 r o o t p p = &p−>down ;
22 } while ( ∗ word + + ) ;
23 r e t u r n n < nodes ;
24 }
25 / ∗ A u f r u f m i t check ( r o o t , s t r ) ; g i b t t r u e zurueck , wenn Wort vorhanden ∗ /
26 i n t check ( s t r u c t t r i e ∗ r o o t , char ∗word ) {
27 do {
28 while ( r o o t ! = NULL && r o o t −>l e t t e r < ∗word ) r o o t = r o o t −>n e x t ;
29 i f ( r o o t == NULL | | r o o t −>l e t t e r ! = ∗word ) r e t u r n 0 ;
30 r o o t = r o o t −>down ;
31 } while ( ∗ word + + ) ;
32 return 1;
33 }
 

8.4.2 Trie mit Array


 
1 # define ALPHA ’A ’
2 struct t r i e {
3 s t r u c t t r i e ∗down [ 2 6 ] ;
4 bool e n d o f w o r d ;
5 } node [ 1 0 0 0 0 0 ] ; / / g g f . Anzahl anpassen
6 i n t nodes = 0 ; / / so macht man a l l e T r i e s u n g u e l t i g
7 s t r u c t t r i e ∗ r o o t = NULL ; / / so l o e s c h t man einen e i n z e l n e n T r i e
8 / / A u f r u f m i t add(& r o o t , s t r ) ; g i b t t r u e zurueck , wenn Wort noch n i c h t vorhanden war
9 bool add ( s t r u c t t r i e ∗∗ r o o t p t r , char ∗word ) {
10 s t r u c t t r i e ∗p ;
11 do {
8 DATENSTRUKTUREN 32

12 p = ∗root ptr ;
13 i f ( p == NULL ) {
14 p = node + nodes ++;
15 f o r ( i n t i = 0 ; i < 2 6 ; ++ i ) p−>down [ i ] = NULL ;
16 p−>e n d o f w o r d = f a l s e ;
17 ∗root ptr = p;
18 }
19 r o o t p t r = p−>down + ( ∗ word − ALPHA ) ;
20 } while ( ∗ word + + ) ;
21 r e t u r n p−>e n d o f w o r d ? f a l s e : ( p−>e n d o f w o r d = t r u e ) ;
22 }
23 / / A u f r u f m i t check ( r o o t , s t r ) ; g i b t t r u e zurueck , wenn Wort vorhanden
24 bool check ( s t r u c t t r i e ∗ r o o t , char ∗word ) {
25 while ( ∗ word ) {
26 i f ( r o o t == NULL ) r e t u r n f a l s e ;
27 r o o t = r o o t −>down [ ∗ word++ − ALPHA ] ;
28 }
29 r e t u r n r o o t ! = NULL && r o o t −>e n d o f w o r d ;
30 }
 

8.5 Balancierter binärer Suchbaum (AVL)


 
1 # include <a l g o r i t h m >
2 struct a v l t {
3 a v l t ∗ l e f t , ∗ r i g h t , ∗up ;
4 i n t h e i g h t , s i z e , key ;
5
6 void r e s e t ( ) ; i n t balance ( ) ; a v l t ∗ l e f t r o t ( ) ; a v l t ∗ r i g h t r o t ( ) ; a v l t ∗ f i x u p ( ) ;
7 avl t ∗ latch ( avl t ∗ , avl t ∗); avl t ∗ find ( int ) ;
8 a v l t ∗minimum ( ) ; a v l t ∗maximum ( ) ; a v l t ∗ pred ( ) ; a v l t ∗ succ ( ) ;
9 };
10 i n l i n e void a v l t : : r e s e t ( ) {
11 h e i g h t = max ( l e f t ! = NULL ? l e f t −>h e i g h t + 1 : 0 , r i g h t ! = NULL ? r i g h t −>h e i g h t + 1 : 0 ) ;
12 s i z e = 1 + ( l e f t ! = NULL ? l e f t −>s i z e : 0 ) + ( r i g h t ! = NULL ? r i g h t −>s i z e : 0 ) ;
13 }
14 i n l i n e i n t a v l t : : balance ( ) {
15 r e t u r n ( r i g h t ! = NULL ? r i g h t −>h e i g h t + 1 : 0 ) − ( l e f t ! = NULL ? l e f t −>h e i g h t + 1 : 0 ) ;
16 }
17 avl t ∗avl t :: leftrot () {
18 a v l t ∗temp = r i g h t ;
19 i f ( ( r i g h t = temp−> l e f t ) ! = NULL ) r i g h t −>up = t h i s ;
20 temp−> l e f t = t h i s ; temp−>up = up ; up = temp ;
21 r e s e t ( ) ; temp−>r e s e t ( ) ;
22 r e t u r n temp ;
23 }
24 avl t ∗avl t :: rightrot () {
25 a v l t ∗temp = l e f t ;
26 i f ( ( l e f t = temp−>r i g h t ) ! = NULL ) l e f t −>up = t h i s ;
27 temp−>r i g h t = t h i s ; temp−>up = up ; up = temp ;
28 r e s e t ( ) ; temp−>r e s e t ( ) ;
29 r e t u r n temp ;
30 }
31 avl t ∗ avl t : : fixup () {
32 i n t b a l = balance ( ) ;
33 i f ( b a l == 2 ) {
34 i f ( r i g h t −>balance ( ) < 0 ) r i g h t = r i g h t −>r i g h t r o t ( ) ;
35 return l e f t r o t ( ) ;
36 } else i f ( b a l == −2) {
37 i f ( l e f t −>balance ( ) > 0 ) l e f t = l e f t −> l e f t r o t ( ) ;
38 return r i g h t r o t ( ) ;
39 }
40 return this ;
41 }
42 a v l t ∗ a v l t : : l a t c h ( a v l t ∗ root , a v l t ∗ parent ) {
8 DATENSTRUKTUREN 33

43 i f ( r o o t == NULL ) { l e f t = r i g h t = NULL ; up = p a r e n t ; r e s e t ( ) ; r e t u r n t h i s ; }
44 i f ( key < r o o t −>key ) r o o t −> l e f t = l a t c h ( r o o t −>l e f t , r o o t ) ;
45 else i f ( r o o t −>key < key ) r o o t −>r i g h t = l a t c h ( r o o t −>r i g h t , r o o t ) ;
46 r o o t −>r e s e t ( ) ;
47 r e t u r n r o o t −>f i x u p ( ) ;
48 }
49 a v l t ∗ a v l t : : f i n d ( i n t value ) {
50 a v l t ∗temp = t h i s ;
51 while ( temp ! = NULL ) {
52 i f ( v a l u e < temp−>key ) temp = temp−> l e f t ;
53 else i f ( temp−>key < v a l u e ) temp = temp−>r i g h t ;
54 else r e t u r n temp ;
55 }
56 r e t u r n NULL ;
57 }
58 a v l t ∗ a v l t : : minimum ( ) {
59 a v l t ∗temp = t h i s ;
60 while ( temp−> l e f t ! = NULL ) temp = temp−> l e f t ;
61 r e t u r n temp ;
62 }
63 a v l t ∗ a v l t : : maximum ( ) {
64 a v l t ∗temp = t h i s ;
65 while ( temp−>r i g h t ! = NULL ) temp = temp−>r i g h t ;
66 r e t u r n temp ;
67 }
68 a v l t ∗ a v l t : : pred ( ) {
69 a v l t ∗temp = t h i s ;
70 i f ( l e f t ! = NULL ) r e t u r n l e f t −>maximum ( ) ;
71 while ( temp−>up ! = NULL && temp == temp−>up−> l e f t ) temp = temp−>up ;
72 r e t u r n temp−>up ;
73 }
74 a v l t ∗ a v l t : : succ ( ) {
75 a v l t ∗temp = t h i s ;
76 i f ( r i g h t ! = NULL ) r e t u r n r i g h t −>minimum ( ) ;
77 while ( temp−>up ! = NULL && temp == temp−>up−>r i g h t ) temp = temp−>up ;
78 r e t u r n temp−>up ;
79 }