[pdf zum Drucken]

11/6/2009
Zeichen und Texte
Felder (Arrays) und
Zeiger (Pointers) - Teil II
Zeichen, Texte, String Matching;
Mehrdimensionale Felder;
kürzeste Wege
Texte haben wir schon gesehen:
std::cout << "Prime numbers in {2,...,999}:\n";
String-Literal
Können wir auch “richtig” mit Texten
arbeiten? Ja:
Zeichen: Wert des fundamentalen Typs char
Text:
Der Typ char (“character”)
repräsentiert druckbare Zeichen (z.B.
'a') und Steuerzeichen (z.B. '\n')
char c = 'a'
definiert Variable c vom
Typ char mit Wert 'a';
Der Typ char (“character”)
ist formal ein ganzzahliger Typ
Literal vom Typ
char
Feld mit zugrundeliegendem Typ char
Werte konvertierbar nach int / unsigned
int
Alle arithemtischen Operatoren verfügbar
(Nutzen zweifelhaft: was ist 'a'/'b' ?)
Werte belegen meistens 8 Bit
Wertebereich:
{-128,...,127} oder {0,...,255}
Der ASCII-Code
Der ASCII-Code
definiert konkrete Konversionregeln
char → int / unsigned int
for (char c = 'a'; c <= 'z'; ++c)
wird von fast allen Plattformen benutzt
Ausgabe: abcdefghijklmnopqrstuvwxyz
Zeichen → {0,...,127}
std::cout << c;
Zeichen → {0,...,127}
'A','B',...,'Z'
→ 65, 66,...,90
'A','B',...,'Z'
→ 65, 66,...,90
'a','b',...,'z'
→ 97, 98,...,122
'a','b',...,'z'
→ 97, 98,...,122
1
11/6/2009
Anwendung: String matching
Texte
sind repräsentierbar als Felder mit
zugrundeliegendem Typ char
char text[] = {'b', 'o', 'o', 'l'}
können auch durch String-Literale
definiert ein Feld der Länge
definiert werden
char text[] = "bool"
“speichert” seine Länge!
5, das dem Text “bool” entspricht und null-terminiert
ist (Extrazeichen '\0' wird
am Ende angehängt)
Finde das erste (oder alle) Vorkommen
eines Musters (meist kurz) in einem gegebenen Text (meist lang)!
“Trivialer” Algorithmus:
Gallia est omnis divisa in partes tres
≠
visa
Anwendung: String matching
Anwendung: String matching
Finde das erste (oder alle) Vorkommen
eines Musters (meist kurz) in einem gegebenen Text (meist lang)!
Finde das erste (oder alle) Vorkommen
eines Musters (meist kurz) in einem gegebenen Text (meist lang)!
“Trivialer” Algorithmus:
“Trivialer” Algorithmus:
Gallia est omnis divisa in partes tres
Gallia est omnis divisa in partes tres
≠
≠
visa
visa
Anwendung: String matching
Anwendung: String matching
Finde das erste (oder alle) Vorkommen
eines Musters (meist kurz) in einem gegebenen Text (meist lang)!
#include<iostream>
int main ()
{
// search string
const char s[] = "bool";
Muster “fest verdrahtet” in
diesem Program (aber
siehe Details im Skript)
// determine search string length m
unsigned int m = 0;
for (const char* p = s; *p != '\0'; ++p) ++m;
“Trivialer” Algorithmus:
Gallia est omnis divisa in partes tres
= (gefunden!)
visa
// cyclic text window of size m
char* const t = new char[m];
unsigned int w = 0; // number of characters read so far
unsigned int i = 0; // index where t logically starts
...
2
11/6/2009
Anwendung: String matching
Anwendung: String matching
#include<iostream>
#include<iostream>
int main ()
{
// search string
const char s[] = "bool";
Rechne die Musterlänge
aus (das geht, weil s nullterminiert ist)
int main ()
{
// search string
const char s[] = "bool";
G
a
l
l
Gallia
i
// determine search string length m
unsigned int m = 0;
for (const char* p = s; *p != '\0'; ++p) ++m;
// determine search string length m
unsigned int m = 0;
for (const char* p = s; *p != '\0'; ++p) ++m;
// cyclic text window of size m
char* const t = new char[m];
// cyclic text window of size m
char* const t = new char[m];
unsigned int w = 0; // number of characters read so far
unsigned int i = 0; // index where t logically starts
...
unsigned int w = 0; // number of characters read so far
unsigned int i = 0; // index where t logically starts
...
Anwendung: String matching
Anwendung: String matching
#include<iostream>
#include<iostream>
int main ()
{
// search string
const char s[] = "bool";
i
a
l
l
Gallia
i
int main ()
{
// search string
const char s[] = "bool";
i
a
l
l
i
Gallia
// determine search string length m
unsigned int m = 0;
for (const char* p = s; *p != '\0'; ++p) ++m;
// determine search string length m
unsigned int m = 0;
for (const char* p = s; *p != '\0'; ++p) ++m;
// cyclic text window of size m
char* const t = new char[m];
// cyclic text window of size m
char* const t = new char[m];
unsigned int w = 0; // number of characters read so far
unsigned int i = 0; // index where t logically starts
...
unsigned int w = 0; // number of characters read so far
unsigned int i = 0; // index where t logically starts
...
Anwendung: String matching
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
Leerzeichen und
Zeilenumbrüche
sollen nicht
ignoriert werden
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
i
v
i
s
a
j
std::cout << "\n";
delete[] t;
return 0;
}
std::cout << "\n";
delete[] t;
return 0;
w == 0
}
3
11/6/2009
Anwendung: String matching
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
i
v
i
s
a
j
G
i
v
i
s
a
j
std::cout << "\n";
delete[] t;
return 0;
std::cout << "\n";
delete[] t;
return 0;
w == 0
w == 0
}
}
Anwendung: String matching
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
Konversion
// advance window by replacing first character
nach bool
if (std::cin >> t[i]) {
std::cout << t[i];
(
wenn
++w;
// one more character read
Eingabej = 0;
// restart with first characters
strom leer)
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
G
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
i
false
v
i
s
a
j
G
i
v
i
s
a
j
std::cout << "\n";
delete[] t;
return 0;
std::cout << "\n";
delete[] t;
return 0;
w == 0
w == 1
}
}
Anwendung: String matching
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
G
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
i
v
i
s
a
j
std::cout << "\n";
delete[] t;
return 0;
}
G
a
i
v
i
s
a
j
std::cout << "\n";
delete[] t;
return 0;
w == 1
w == 2
}
4
11/6/2009
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
G
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
a
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
l
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
i
v
i
s
a
j
G
a
l
l
i
s
a
i
v
j
std::cout << "\n";
delete[] t;
return 0;
std::cout << "\n";
delete[] t;
return 0;
w == 3
w == 4
}
}
Anwendung: String matching
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
G
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
a
l
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
l
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
(i+j)%m
i
v
i
s
a
j
i
a
l
l
s
a
i
v
i
j
std::cout << "\n";
delete[] t;
return 0;
std::cout << "\n";
delete[] t;
return 0;
w == 4
w == 5
}
}
Anwendung: String matching
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
i
s
a
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
v
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
i
v
i
s
a
j
std::cout << "\n";
delete[] t;
return 0;
}
i
s
a
v
(i+j)%m
i
v
i
s
a
j
std::cout << "\n";
delete[] t;
return 0;
w == 23
w == 23
}
5
11/6/2009
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
i
s
a
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
v
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
i
v
i
s
a
i
a
v
(i+j)%m
i
v
j
std::cout << "\n";
delete[] t;
return 0;
s
i
s
a
j
std::cout << "\n";
delete[] t;
return 0;
w == 23
w == 23
}
}
Anwendung: String matching
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
i
s
a
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
v
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
(i+j)%m
i
v
i
s
a
i
s
a
(i+j)%m
i
v
i
s
j
std::cout << "\n";
delete[] t;
return 0;
v
a
j
std::cout << "\n";
delete[] t;
return 0;
w == 23
w == 23
}
}
Anwendung: String matching
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
i
s
a
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
v
i
s
a
v
false
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
(i+j)%m
i
v
i
s
a
(i+j)%m
i
v
i
s
a
j
std::cout << "\n";
delete[] t;
return 0;
}
j
std::cout << "\n";
delete[] t;
return 0;
w == 23
w == 23
}
6
11/6/2009
Anwendung: String matching
...
// find pattern in the text being read from std::cin
std::cin >> std::noskipws; // don't skip whitespaces!
for (unsigned int j = 0; j < m;)
// compare search string with window at j-th element
if (w < m || s[j] != t[(i+j)%m])
// input text still too short, or mismatch:
// advance window by replacing first character
if (std::cin >> t[i]) {
std::cout << t[i];
++w;
// one more character read
j = 0;
// restart with first characters
i = (i+1)%m; // of string and window
} else break;
// no more characters in the input
else ++j; // match: go to next character
i
s
a
Anwendung: String matching
v
Aufruf des Programms z.B. durch
./string_matching < eratosthenes.cpp
(i+j)%m
Eingabe wird nicht von der Tastatur, sondern aus der
angegebenen Datei genommen (Umlenkung der Eingabe)
i
v
i
s
a
j
std::cout << "\n";
delete[] t;
return 0;
Fertig! Die ersten 23 Textzeichen wurden ausgegeben
w == 23
}
Anwendung: String matching
Aufruf des Programms z.B. durch
Anwendung: String matching
./string_matching < eratosthenes.cpp
Aufruf des Programms z.B. durch
./string_matching < eratosthenes.cpp
> match.out
// Program: eratosthenes.cpp
// Calculate prime numbers in {2,...,n-1} using
Ausgabe:
// Eratosthenes' sieve.
Ausgabe wird nicht auf den
Bildschirm geschrieben,
sondern in die angegebene
Datei (Umlenkung der
Ausgabe)
#include <iostream>
int main()
{
const unsigned int n = 1000;
// definition and initialization: provides us with
// Booleans crossed_out[0],..., crossed_out[n-1]
bool
Anwendung: String matching
Aufruf des Programms z.B. durch
./string_matching < eratosthenes.cpp
> match.out
Mehrdimensionale Felder
sind Felder von Feldern
dienen zum Speichern von Tabellen,
Matrizen,...
Der triviale Algorithmus ist meistens
schnell, aber nicht immer (Übung)
Knuth-Morris-Pratt-Algorithmus ist
immer schnell
7
11/6/2009
Mehrdimensionale Felder
Mehrdimensionale Felder
sind Felder von Feldern
sind Felder von Feldern
int a[2][3]
Im Speicher: flach
a[0][0]
int a[2][3]
a hat zwei Elemente, und jedes
von ihnen ist ein Feld der Länge 3
mit zugrundeliegendem Typ int
a[0][1]
a[0][2]
a[1][0]
a[1][1]
a[0]
Im Kopf: Matrix,
Tabelle,...
a[1][2]
0
1
2
0
a[0][0]
a[0][1]
a[0][2]
1
a[1][0]
a[1][1]
a[1][2]
Zeilen
a[1]
Mehrdimensionale Felder
Kolonnen
Mehrdimensionale Felder
sind Felder von Feldern von Feldern...
Initialisierung:
int a[2][3] =
T a[expr1]...[exprk]
{
{2,4,6}, {1,3,5}
konstante Ausdrücke!
a hat expr1 Elemente, und jedes
von ihnen ist ein Feld mit expr2
Elementen, von denen jedes ein
Feld mit expr3 Elementen ist,...
}
2
4
6
1
a[0]
3
5
a[1]
Mehrdimensionale Felder
Zeiger auf Felder
Initialisierung:
Wie iteriert man natürlich über ein mehrdimensionales Feld?
erste Dimension
kann weggelassen werden
int a[][3] =
{
int a[2][3];
int (*p)[3] = a; // Zeiger auf erstes Element
{2,4,6}, {1,3,5}
}
2
4
a[0]
Implizite Typdefinition: *p ist vom Typ int[3],
also ist p ein Zeiger auf int[3]
6
1
3
5
a[1]
8
11/6/2009
Zeiger auf Felder
Zeiger auf Felder
Wie iteriert man natürlich über ein mehrdimensionales Feld?
Wie iteriert man natürlich über ein mehrdimensionales Feld?
int a[2][3];
int a[2][3];
int (*p)[3] = a; // Zeiger auf erstes Element
int (*p)[3] = a; // Zeiger auf erstes Element
Ohne Klammern: p ist ein Feld von 3 Zeigern auf int
Ohne Klammern: p ist ein Feld von 3 Zeigern auf int
int *p [3]; // int* p[3]
int *p [3]; // int* p[3]
Felder von Zeigern
Felder von Zeigern
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
a
0
m-1
1
0
.
.
.
1
.
.
.
.
.
.
n-1
.
Felder von Zeigern
a ist Zeiger auf das erste
Element eines Feldes von
n Zeigern auf int
1
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
a
0
1
m-1
0
int** a = new int*[n];
a[0]
0
a[1]
1
a[i] = new int[m];
for (int i = 0; i < n; ++i)
i == 0
n-1
m-1
1
0
a[0]
a[i] = new int[m];
a[n-1]
n-1
a[n-1]
a
for (int i = 0; i < n; ++i)
0
a[1]
Felder von Zeigern
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
int** a = new int*[n];
m-1
1
a[0]
zugrundeliegender Typ: int*
.
.
0
int** a = new int*[n];
.
a[1]
a[0] ist Zeiger auf das
erste Element eines
Feldes von m int’s
a[n-1]
.
.
1
n-1
i == 0
9
11/6/2009
Felder von Zeigern
Felder von Zeigern
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
a
a
0
int** a = new int*[n];
for (int i = 0; i < n; ++i)
m-1
1
0
a[0]
a[i] = new int[m];
.
.
0
int** a = new int*[n];
for (int i = 0; i < n; ++i)
.
1
a[1] ist Zeiger auf das
erste Element eines
Feldes von m int’s
n-1
a[n-1]
.
.
.
.
.
.
.
.
n-1
Speicherlayout im Heap :
a
0
m-1
j
1
a[0]
.
.
*(a[i]+j)
a[i]+j
.
.
.
.
.
a[n-1]
.
.
.
.
0
a[0]
1
a[1]
.
.
.
a[1]
a[i]
.
a[n-1]
a
Zeiger
1
a[n-1] ist Zeiger auf das
erste Element eines
Feldes von m int’s
Felder von Zeigern
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
a[i][j]
.
i == n-1
Felder von Zeigern
Wahlfreier Zugriff:
.
a[1]
i == 1
0
a[i] = new int[m];
.
a[1]
m-1
1
a[0]
.
.
i
...
n-1
.
.
.
.
.
a[n-1]
Anwendung: kürzeste Wege
Anwendung: kürzeste Wege
Fabrik-Halle (n × m quadratische Zellen)
Fabrik-Halle (n × m quadratische Zellen)
111
000
000
111
000
111
000
111
000
000
111
000
000111
111
000111
111
000
111
000
111
000
111
000
S 111
000
111
000
111
000
111
000
111
000
111
Startposition
000
111
000
111
eines Roboters
000
111
000
111
000
111
000
111
000
111
Finde kürzesten Weg
000
111
000
111
des Roboters von S
nach T, der nur freie
Zellen benutzt!
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
000
000111
111
000111
111
000
111
Hindernisse
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
T
000
111
000
111
000
111
000
111
Lösung
freie Zellen
Zielposition
des Roboters
111
000
000
111
000
111
000
111
000
000
111
000
000111
111
000111
111
000
111
000
111
000
111
000
S 111
000
111
000
111
000
111
000
111
000
111
Startposition
000
111
000
111
eines Roboters
000
111
000
111
000
111
000
111
000
111
Finde kürzesten Weg
000
111
000
111
des Roboters von S
nach T, der nur freie
Zellen benutzt!
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
000
000111
000111
111
000
111
Hindernisse111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
T
000
111
000
111
000
111
000
111
freie Zellen
Zielposition
des Roboters
10
11/6/2009
Ein (scheinbar) anderes
Problem
Ein (scheinbar) anderes
Problem
Finde die Längen der kürzesten Wege zu allen möglichen Zielen!
Finde die Längen der kürzesten Wege zu allen möglichen Zielen!
4
3
2
3
Startposition
eines Roboters4
5
6
7
111
000
000
000
5 111
6 111
7 8
000
111
000
000
000111
111
000111
111
000 9
111
000111
111
000111
000
000
111
000
111
000
1 0 111
10
000
111
000
111
00011
111
2 1 111
000
111
000
000
111
3 2 111
000
00010
111
000
111
000
4 3 111
9
000
111
000
111
000 8
111
5 4 111
000
6
5
6
7
111
000
000
111
000
111
00015 16 17 18
111
000
111
00014 15 16 17
111
000
111
000
000
000
12 111
13 111
14 111
15 16
000
111
000
000
000111
111
000111
111
00017
111
13 111
000111
111
000111
000
000
000
111
12 111
000
00020 19 18
111
000
111
000
11 111
21 20 19
000
111
000
111
00022 21 20
111
10 111
000
000
111
000
111
9 111
00023 22 21
9
10
11
12
11
10
9
8
19
18
17
18
19
Zielposition
20 des Roboters;
21 kürzester Weg
hat Länge 21
22
Das löst auch
das OriginalProblem:
starte in T;
folge einem
Weg mit (jeweils um
eins) sinkenden Längen!
Weglänge 21
(optimal)
4
3
2
3
4
5
6
7
111
000
000
000
5 111
6 111
7 8
000
111
000
000
000111
111
000111
111
000 9
111
000111
111
000111
000
000
111
000
111
000
1 0 111
10
000
111
000
111
00011
111
2 1 111
000
111
000
000
111
3 2 111
000
00010
111
000
111
000
4 3 111
9
000
111
000
111
000 8
111
5 4 111
000
6
5
i22
6
7
111
000
000
111
000
111
00015 16 17 18
111
000
111
00014 15 16 17
111
000
111
000
000
000
12 111
13 111
14 111
15 16
000
111
000
000
000111
111
000111
111
00017
111
13 111
000111
111
000111
000
000
000
111
12 111
000
00020 19 18
111
000
111
000
11 111
21 20 19
000
111
000
111
00022 21 20
111
10 111
000
000
111
000
111
9 111
00023 22 21
9
10
11
12
11
10
9
8
19
18
17
18
19
Zielposition
20 des Roboters;
21 kürzester Weg
hat Länge 21
22
i22
Markierung aller Zellen mit
ihren Weglängen
Markierung aller Zellen mit
ihren Weglängen
Schritt 0: Alle Zellen mit Weglänge 0:
Schritt 1: Alle Zellen mit Weglänge 1:
111
000
000
111
000
111
000
111
000
000
111
000
000111
111
000111
111
000
111
000
111
000
111
000
0 111
000
111
000
111
000
111
000
111
000
111
Startposition
000
111
eines Roboters
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
000
000111
111
000111
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
T
000
111
000
111
000
111
000
111
Unmarkierte
Nachbarn der
Zelle(n) mit
Weglänge 0
111
000
000
111
000
111
000
111
000
000
111
000
000111
111
000111
111
000
111
000
111
000
111
000
1
0 111
000
111
000
111
000
111
1 111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
000
000111
111
000111
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
T
000
111
000
111
000
111
000
111
Markierung aller Zellen mit
ihren Weglängen
Markierung aller Zellen mit
ihren Weglängen
Schritt 2: Alle Zellen
000 mit Weglänge 2:
111
Schritt 3: Alle Zellen
000 mit Weglänge 3:
111
2
Unmarkierte
Nachbarn der
Zelle(n) mit
Weglänge 1
111111
000
000111
000
000
111
000
111
000
111
000
111
000
000
000111
111
000111
111
000
111
000
111
000
111
1
0 111
000
000
111
000
111
000
2
1 111
000
111
000
111
000
111
000
2 111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
111
000
000
111
000
111
000
111
000
111
000
111
000
111
111111
000
000111
000
000
111
000
111
000
000
111
000
111
000111
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
T
000
111
000
111
000
111
000
111
3
2
3
Unmarkierte
Nachbarn der
Zelle(n) mit
Weglänge 2
111111
000
000111
000
000
111
000
111
000
111
000
111
000
000
000111
111
000111
111
000
111
000
111
000
111
1
0 111
000
000
111
000
111
000
2
1 111
000
111
000
111
000
111
000
3
2 111
000
111
000
111
000
111
3 111
000
000
111
000
111
000
111
111
000
000
111
000
111
000
111
000
111
000
111
000
111
111111
000
000111
000
000
111
000
111
000
000
111
000
111
000111
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
T
000
111
000
111
000
111
000
111
11
11/6/2009
Das Kürzeste-Wege-Programm
Eingabeformat:
8 12
------X-----
Zeilen
Kolonnen
-XXX--X------SX--------
111
000
000
111
000
111
000
111
000
000
000111
111
000111
111
000
111
000111
111
000111
000
111
000
000
111
S 111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
000
000111
111
000111
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000 T
111
000
111
000
111
Das Kürzeste-Wege-Programm
Einlesen der Dimensionen und Bereitstellung eines zweidimensionalen Feldes
für die Weglängen
int n; std::cin >> n; // number of rows
int m; std::cin >> m; // number of columns
---X---XXX--
Start
// dynamically allocate twodimensional array of dimensions
---X---X----
// (n+2) x (m+2) to hold the floor plus extra walls around
Ziel
---X---X----
int** const floor = new int*[n+2];
---X---X-T--
Hindernis
for (int r=0; r<n+2; ++r)
freie Zelle
-------X----
Das Kürzeste-Wege-Programm
Kolonnen
Zeilen
1
Das Kürzeste-Wege-Programm
Das Kürzeste-Wege-Programm
m m +1
111111111111111111111111111111111111
000000000000000000000000000000000000
000000000000000000000000000000000000
111111111111111111111111111111111111
0
000000000000000000000000000000000000
111111111111111111111111111111111111
000
111
000
111
000
111
000
111
000
111
000
111
1
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000000000000000000000000000000000000
111111111111111111111111111111111111
n
000
111
000
111
000000000000000000000000000000000000
111111111111111111111111111111111111
000000000000000000000000000000000000
111111111111111111111111111111111111
000000000000000000000000000000000000
n +1 111111111111111111111111111111111111
0
Einlesen der Hallenbelegung und
Initialisierung der Längen
int tr = 0;
Einlesen der Hallenbelegung und
Initialisierung der Längen
int tr = 0;
int tc = 0;
Zielkoordinaten (Zeilen-/Kolonnenindex)
for (int r=1; r<n+1; ++r)
for (int c=1; c<m+1; ++c) {
char entry = '-';
std::cin >> entry;
if
(entry == 'S') floor[r][c] = 0;
else if (entry == 'T') floor[tr = r][tc = c] = -1;
else if (entry == 'X') floor[r][c] = -2;
else if (entry == '-') floor[r][c] = -1;
}
Das Kürzeste-Wege-Programm
Einlesen der Hallenbelegung und
Initialisierung der Längen
int tr = 0;
int tc = 0;
for (int r=1; r<n+1; ++r)
for (int c=1; c<m+1; ++c) {
char entry = '-';
lies die Eingabe Zeile für Zeile
(z.B. durch Umlenkung der
Eingabe auf die Datei
shortest_path0.dat)
int tc = 0;
for (int r=1; r<n+1; ++r)
for (int c=1; c<m+1; ++c) {
char entry = '-';
std::cin >> entry;
std::cin >> entry;
if
if
(entry == 'S') floor[r][c] = 0;
Eingabezeichen in
Zeile r ∈ {1,...,n} und
Kolonne c ∈ {1,...,m}
(entry == 'S') floor[r][c] = 0;
else if (entry == 'T') floor[tr = r][tc = c] = -1;
else if (entry == 'T') floor[tr = r][tc = c] = -1;
else if (entry == 'X') floor[r][c] = -2;
else if (entry == 'X') floor[r][c] = -2;
else if (entry == '-') floor[r][c] = -1;
}
Wächter (sentinels)
floor[r] = new int[m+2];
else if (entry == '-') floor[r][c] = -1;
}
12
11/6/2009
Das Kürzeste-Wege-Programm
Das Kürzeste-Wege-Programm
Einlesen der Hallenbelegung und
Initialisierung der Längen
Einlesen der Hallenbelegung und
Initialisierung der Längen
int tr = 0;
int tr = 0;
int tc = 0;
int tc = 0;
for (int r=1; r<n+1; ++r)
for (int r=1; r<n+1; ++r)
Länge bereits
bekannt
for (int c=1; c<m+1; ++c) {
char entry = '-';
for (int c=1; c<m+1; ++c) {
char entry = '-';
std::cin >> entry;
std::cin >> entry;
if
if
(entry == 'S') floor[r][c] = 0;
else if (entry == 'T') floor[tr = r][tc = c] = -1;
else if (entry == 'X') floor[r][c] = -2;
else if (entry == 'X') floor[r][c] = -2;
else if (entry == '-') floor[r][c] = -1;
else if (entry == '-') floor[r][c] = -1;
}
Das Kürzeste-Wege-Programm
-1: Länge noch
unbekannt
Das Kürzeste-Wege-Programm
Einlesen der Hallenbelegung und
Initialisierung der Längen
Einlesen der Hallenbelegung und
Initialisierung der Längen
int tr = 0;
int tr = 0;
int tc = 0;
int tc = 0;
for (int r=1; r<n+1; ++r)
for (int r=1; r<n+1; ++r)
for (int c=1; c<m+1; ++c) {
for (int c=1; c<m+1; ++c) {
char entry = '-';
char entry = '-';
std::cin >> entry;
std::cin >> entry;
if
if
(entry == 'S') floor[r][c] = 0;
(entry == 'S') floor[r][c] = 0;
else if (entry == 'T') floor[tr = r][tc = c] = -1;
else if (entry == 'T') floor[tr = r][tc = c] = -1;
else if (entry == 'X') floor[r][c] = -2;
else if (entry == 'X') floor[r][c] = -2;
else if (entry == '-') floor[r][c] = -1;
}
else if (entry == '-') floor[r][c] = -1;
-2: Länge nicht
relevant (Hindernis)
Das Kürzeste-Wege-Programm
(entry == 'S') floor[r][c] = 0;
else if (entry == 'T') floor[tr = r][tc = c] = -1;
}
Ziel: setze
Koordinaten
}
Das Kürzeste-Wege-Programm
Hinzufügen der umschliessenden
“Wände”
for (int r=0; r<n+2; ++r)
Kolonnen 0 und m +1
floor[r][0] = floor[r][m+1] = -2;
for (int c=0; c<m+2; ++c)
Zeilen 0 und n +1
-1: Länge noch
unbekannt
(freie Zelle)
Start
floor[0][c] = floor[n+1][c] = -2;
-2
111111111111111111111111111111111111
000000000000000000000000000000000000
000000000000000000000000000000000000
111111111111111111111111111111111111
000000000000000000000000000000000000
111111111111111111111111111111111111
000
111
000
111
000
111
000
111
000
111
000
111
−1 −1 −1 −1 −1 111
000 −1 111
111
000
000
000
000111
111
000
000 −1 −1 −1 −1 −1 111
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
−1
−1
−1
−1
−1
−1
−1
−1
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
−1 −1 0 111
−1 111
−1 111
−1 −1 −1 111
000
111
000
000 −1 −1 −1 111
000
111
000
000
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
−1
−1
−1
−1
−1
−1
−1
−1
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000 −1 −1 −1 111
111
000
111
000
111
000
111
000
000
111
−1 −1 −1 111
−1 −1 −1 −1 111
000
111
000
000
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000 −1 −1 −1 111
111
000
111
000
000
111
−1
−1
−1
−1
−1
−1
−1
000
111
000
111
000
111
000
111
000
111
000
111
000 −1 −1 −1 111
111
000
111
000
000
111
000
111
−1 −1 −1 111
−1
−1
−1
−1
000
111
000
111
000
111
000
000
111
000
111
000
000 −1 −1 −1 −1 111
000
111
000
111
−1 −1 −1 −1 −1 −1 −1 111
000
111
000
111
000
111
000000000000000000000000000000000000
111111111111111111111111111111111111
000000000000000000000000000000000000
111111111111111111111111111111111111
000000000000000000000000000000000000
111111111111111111111111111111111111
13
11/6/2009
Das Kürzeste-Wege-Programm
for (int i=1;; ++i) {
bool progress = false;
for (int r=1; r<n+1; ++r)
Hauptschleife: finde und
markiere alle Zellen mit
Weglängen i=1,2,3...
Das Kürzeste-Wege-Programm
for (int i=1;; ++i) {
bool progress = false;
for (int r=1; r<n+1; ++r)
for (int c=1; c<m+1; ++c) {
for (int c=1; c<m+1; ++c) {
if (floor[r][c] != -1) continue;
if (floor[r][c] != -1) continue;
if (floor[r-1][c] == i-1 || floor[r+1][c] == i-1 ||
if (floor[r-1][c] == i-1 || floor[r+1][c] == i-1 ||
floor[r][c-1] == i-1 || floor[r][c+1] == i-1 ) {
floor[r][c-1] == i-1 || floor[r][c+1] == i-1 ) {
floor[r][c] = i; // label cell with i
floor[r][c] = i; // label cell with i
progress = true;
progress = true;
}
}
}
}
if (!progress) break;
if (!progress) break;
}
}
Das Kürzeste-Wege-Programm
for (int i=1;; ++i) {
bool progress = false;
Iteriere über alle
“echten” Zellen
Das Kürzeste-Wege-Programm
for (int i=1;; ++i) {
bool progress = false;
for (int r=1; r<n+1; ++r)
for (int r=1; r<n+1; ++r)
for (int c=1; c<m+1; ++c) {
for (int c=1; c<m+1; ++c) {
Betrachte Zelle in Zeile r
∈ {1,...,n} und Kolonne
c ∈ {1,...,m}:
Fall 1: Hindernis, oder
schon markiert
if (floor[r][c] != -1) continue;
if (floor[r][c] != -1) continue;
if (floor[r-1][c] == i-1 || floor[r+1][c] == i-1 ||
if (floor[r-1][c] == i-1 || floor[r+1][c] == i-1 ||
floor[r][c-1] == i-1 || floor[r][c+1] == i-1 ) {
floor[r][c-1] == i-1 || floor[r][c+1] == i-1 ) {
floor[r][c] = i; // label cell with i
floor[r][c] = i; // label cell with i
progress = true;
progress = true;
}
}
}
}
if (!progress) break;
if (!progress) break;
}
}
Das Kürzeste-Wege-Programm
for (int i=1;; ++i) {
bool progress = false;
for (int r=1; r<n+1; ++r)
for (int c=1; c<m+1; ++c) {
if (floor[r][c] != -1) continue;
Betrachte Zelle in Zeile r
∈ {1,...,n} und Kolonne
c ∈ {1,...,m}:
Das Kürzeste-Wege-Programm
for (int i=1;; ++i) {
bool progress = false;
for (int r=1; r<n+1; ++r)
Fall 2: Ein Nachbar hat
bereits Weglänge i-1
for (int c=1; c<m+1; ++c) {
if (floor[r][c] != -1) continue;
if (floor[r-1][c] == i-1 || floor[r+1][c] == i-1 ||
Fall 2: Ein Nachbar hat
bereits Weglänge i-1
floor[r][c-1] == i-1 || floor[r][c+1] == i-1 ) {
floor[r][c] = i; // label cell with i
floor[r][c] = i; // label cell with i
progress = true;
progress = true;
i-1 i-2 i-3
}
}
Betrachte Zelle in Zeile r
∈ {1,...,n} und Kolonne
c ∈ {1,...,m}:
if (floor[r-1][c] == i-1 || floor[r+1][c] == i-1 ||
floor[r][c-1] == i-1 || floor[r][c+1] == i-1 ) {
i-1 i-2 i-3
}
r
?
Durch die Wächter hat jede “echte” Zelle 4 Nachbarn!
i-1 i-2
}
i-1
if (!progress) break;
}
Haben wir für dieses i
eine Zelle gefunden?
c
Markiere Zelle mit i
r
i
i-1 i-2
i-1
if (!progress) break;
}
c
14
11/6/2009
Das Kürzeste-Wege-Programm
Das Kürzeste-Wege-Programm
for (int i=1;; ++i) {
bool progress = false;
for (int r=1; r<n+1; ++r)
Markieren des kürzesten Weges durch
“Rückwärtslaufen” vom Ziel zum Start
int r = tr; int c = tc;
for (int c=1; c<m+1; ++c) {
const int d = floor[r][c] - 1;
if (floor[r-1][c] == i-1 || floor[r+1][c] == i-1 ||
floor[r][c] = -3;
floor[r][c-1] == i-1 || floor[r][c+1] == i-1 ) {
if
floor[r][c] = i; // label cell with i
else if (floor[r][c-1] == d) --c;
}
if (!progress) break;
}
else
Falls keine Zelle mehr markiert
werden konnte, sind wir fertig
(sonst geht’s weiter mit i+1)
Das Kürzeste-Wege-Programm
Markieren des kürzesten Weges durch
“Rückwärtslaufen” vom Ziel zum Start
Das Kürzeste-Wege-Programm
Markieren des kürzesten Weges durch
“Rückwärtslaufen” vom Ziel zum Start
int r = tr; int c = tc;
while (floor[r][c] > 0) {
const int d = floor[r][c] - 1;
Solange Startzelle
noch nicht erreicht...
while (floor[r][c] > 0) {
const int d = floor[r][c] - 1;
floor[r][c] = -3;
floor[r][c] = -3;
if
if
(floor[r-1][c] == d) --r;
else if (floor[r+1][c] == d) ++r;
else if (floor[r][c-1] == d) --c;
else if (floor[r][c-1] == d) --c;
++c; // (floor[r][c+1] == d)
else
}
d = um eins kleinere
Weglänge
(floor[r-1][c] == d) --r;
else if (floor[r+1][c] == d) ++r;
else
++c; // (floor[r][c+1] == d)
}
Das Kürzeste-Wege-Programm
Markieren des kürzesten Weges durch
“Rückwärtslaufen” vom Ziel zum Start
int r = tr; int c = tc;
const int d = floor[r][c] - 1;
floor[r][c] = -3;
if
Das Kürzeste-Wege-Programm
Markieren des kürzesten Weges durch
“Rückwärtslaufen” vom Ziel zum Start
int r = tr; int c = tc;
while (floor[r][c] > 0) {
(floor[r-1][c] == d) --r;
Markiere Zelle (mit -3
zur Unterscheidung):
sie liegt auf dem
kürzesten Weg
while (floor[r][c] > 0) {
const int d = floor[r][c] - 1;
floor[r][c] = -3;
if
(floor[r-1][c] == d) --r;
else if (floor[r+1][c] == d) ++r;
else if (floor[r+1][c] == d) ++r;
else if (floor[r][c-1] == d) --c;
else if (floor[r][c-1] == d) --c;
else
}
++c; // (floor[r][c+1] == d)
}
int r = tr; int c = tc;
(floor[r-1][c] == d) --r;
else if (floor[r+1][c] == d) ++r;
progress = true;
}
Zielzelle
while (floor[r][c] > 0) {
if (floor[r][c] != -1) continue;
++c; // (floor[r][c+1] == d)
else
Gehe zu einer
Nachbarzelle mit
Weglänge d und
wiederhole...
++c; // (floor[r][c+1] == d)
}
15
11/6/2009
Das
Kürzeste-Wege-Programm
000000000000000000000000000000000000
111111111111111111111111111111111111
111111111111111111111111111111111111
000000000000000000000000000000000000
000000000000000000000000000000000000
111111111111111111111111111111111111
000000000000000000000000000000000000
111111111111111111111111111111111111
000
111
000
111
000
111
000
111
000
111
000
−3 −3 −3 −3 −3 111
000 −3 111
111
00015 16 17 18 19 111
000
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
−3
9
−3
14
15
16
17
18
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
−3 −3 0 111
10 −3 −3 −3 −3 −3 −3 17 111
000
111
000
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000 3 2 1 111
111
000
111
000
000
111
11
12
13
−3
18
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
10
11
12
20
−3
−3
19
000 4 3 2 111
111
000
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
3 111
5
4
000 9 10 11 111
00021 −3 19 20 111
111
000
111
000
111
000
111
000
000
111
000
000
111
000
111
00022 −3 20 21 111
111
9 10 111
8
000 6 5 4 111
111
000
111
000
000
000
111
000
111
000
111
000
111
000
111
000
9 111
23 22 21 22 111
7
6
5
6
7
8
000
000
111
000
111
000000000000000000000000000000000000
111111111111111111111111111111111111
000000000000000000000000000000000000
111111111111111111111111111111111111
000000000000000000000000000000000000
111111111111111111111111111111111111
Das Kürzeste-Wege-Programm
Ausgabe:
auf dem kürzestem Weg
ooooooX----oXXX-oX-----
for (int r=1; r<n+1; ++r) {
ooSX-oooooo-
for (int c=1; c<m+1; ++c)
if
(floor[r][c] == 0)
std::cout << 'S';
else if (r == tr && c == tc) std::cout << 'T';
else if (floor[r][c] == -3)
std::cout << 'o';
else if (floor[r][c] == -2)
std::cout << 'X';
else
std::cout << '-';
std::cout << "\n";
ooooooX-----
---X---X-T--
Ausgabe:
auf dem kürzestem Weg
ooooooX----oXXX-oX-----
for (int r=1; r<n+1; ++r) {
ooSX-oooooo-
for (int c=1; c<m+1; ++c)
(floor[r][c] == 0)
std::cout << 'S';
else if (r == tr && c == tc) std::cout << 'T';
else if (floor[r][c] == -3)
std::cout << 'o';
else if (floor[r][c] == -2)
std::cout << 'X';
else
std::cout << '-';
std::cout << "\n";
ooSX-oooooo-
for (int c=1; c<m+1; ++c)
---X---XXXo-
if
(floor[r][c] == 0)
std::cout << 'S';
else if (r == tr && c == tc) std::cout << 'T';
---X---X-oo---X---X-o----X---X-T--
else if (floor[r][c] == -3)
std::cout << 'o';
else if (floor[r][c] == -2)
std::cout << 'X';
else
std::cout << '-';
std::cout << "\n";
-------X----
}
---X---XXXo---X---X-oo---X---X-o----X---X-T--------X----
}
Das Kürzeste-Wege-Programm
Ausgabe:
Das Kürzeste-Wege-Programm
auf dem kürzestem Weg
ooooooX-----
Ausgabe:
auf dem kürzestem Weg
ooooooX-----
oXXX-oX----for (int r=1; r<n+1; ++r) {
if
(floor[r][c] == 0)
ooSX-oooooostd::cout << 'S';
else if (r == tr && c == tc) std::cout << 'T';
else if (floor[r][c] == -3)
std::cout << 'o';
else if (floor[r][c] == -2)
std::cout << 'X';
else
std::cout << '-';
std::cout << "\n";
oXXX-oX----for (int r=1; r<n+1; ++r) {
for (int c=1; c<m+1; ++c)
}
---X---X-o--
-------X----
oXXX-oX-----
if
---X---X-oo-
Das Kürzeste-Wege-Programm
auf dem kürzestem Weg
for (int r=1; r<n+1; ++r) {
---X---XXXo-
}
Das Kürzeste-Wege-Programm
Ausgabe:
ooSX-oooooo-
for (int c=1; c<m+1; ++c)
---X---XXXo-
if
(floor[r][c] == 0)
std::cout << 'S';
else if (r == tr && c == tc) std::cout << 'T';
---X---X-oo---X---X-o----X---X-T--
else if (floor[r][c] == -3)
std::cout << 'o';
else if (floor[r][c] == -2)
std::cout << 'X';
else
std::cout << '-';
std::cout << "\n";
-------X----
---X---XXXo---X---X-oo---X---X-o----X---X-T--------X----
}
16
11/6/2009
Das Kürzeste-Wege-Programm
Ausgabe:
auf dem kürzestem Weg
ooooooX----oXXX-oX-----
for (int r=1; r<n+1; ++r) {
(floor[r][c] == 0)
Last, but not least : lösche die auf dem
Heap bereitgestellten Felder
for (int r=0; r<n+2; ++r)
std::cout << 'S';
else if (r == tr && c == tc) std::cout << 'T';
else if (floor[r][c] == -3)
std::cout << 'o';
else if (floor[r][c] == -2)
std::cout << 'X';
else
std::cout << '-';
std::cout << "\n";
ooSX-oooooo-
for (int c=1; c<m+1; ++c)
if
Das Kürzeste-Wege-Programm
---X---XXXo---X---X-oo---X---X-o----X---X-T--
delete[] floor[r];
delete[] floor;
Feld für die Zeile mit
Index r
Feld von Zeigern auf die
n +2 Zeilen
-------X----
}
Das Kürzeste-Wege-Programm
Das Programm kann recht langsam
sein, weil für jedes i alle Zellen
durchlaufen werden
Verbesserung: durchlaufe jeweils nur
die Nachbarn der Zellen mit Markierung
i-1
Challenge
17