Zeichen und Texte
Felder (Arrays) und
Zeiger (Pointers) - Teil II
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}
1
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
std::cout << c;
Zeichen → {0,...,127}
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
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"
“kennt” 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
2
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
char s[] = "bool";
Muster “fest verdrahtet” in
diesem Program (aber
siehe Details im Skript)
// determine search string length m
unsigned int m = 0;
for (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* t = new char[m];
unsigned int w = 0; // number of characters read so far
unsigned int i = 0; // index where t logically starts
...
3
Anwendung: String matching
Anwendung: String matching
#include<iostream>
#include<iostream>
int main ()
{
// search string
char s[] = "bool";
Rechne die Musterlänge
aus (das geht, weil s nullterminiert ist)
int main ()
{
// search string
char s[] = "bool";
G
a
l
l
Gallia
i
// determine search string length m
unsigned int m = 0;
for (char* p = s; *p != '\0'; ++p) ++m;
// determine search string length m
unsigned int m = 0;
for (char* p = s; *p != '\0'; ++p) ++m;
// cyclic text window of size m
char* t = new char[m];
// cyclic text window of size m
char* 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
char s[] = "bool";
i
a
i
l
l
Gallia
int main ()
{
// search string
char s[] = "bool";
i
a
l
l
i
Gallia
// determine search string length m
unsigned int m = 0;
for (char* p = s; *p != '\0'; ++p) ++m;
// determine search string length m
unsigned int m = 0;
for (char* p = s; *p != '\0'; ++p) ++m;
// cyclic text window of size m
char* t = new char[m];
// cyclic text window of size m
char* 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
...
4
Anwendung: String matching
Anwendung: String matching
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
...
// 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
}
}
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
std::cout << "\n";
delete[] t;
return 0;
}
G
i
v
i
s
a
j
std::cout << "\n";
delete[] t;
return 0;
w == 0
w == 0
}
5
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];
(false 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
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
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 == 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
}
6
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
G
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!
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
G
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
std::cout << "\n";
delete[] t;
return 0;
}
i
a
l
l
s
a
i
v
i
j
std::cout << "\n";
delete[] t;
return 0;
w == 4
w == 5
}
7
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
j
i
s
a
v
(i+j)%m
i
v
i
s
a
j
std::cout << "\n";
delete[] t;
return 0;
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
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
}
8
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+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
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
s
a
v
(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
}
9
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.C
(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
./string_matching < eratosthenes.C
// Program: eratosthenes.C
Anwendung: String matching
Aufruf des Programms z.B. durch
./string_matching < eratosthenes.C >
match.out
// Calculate prime numbers in {2,...,999} using
Ausgabe:
// Eratosthenes' sieve.
#include <iostream>
int main()
{
Ausgabe wird nicht auf den
Bildschirm geschrieben,
sondern in die angegebene
Datei (Umlenkung der
Ausgabe)
// definition and initialization: provides us with
// Booleans crossed_out[0],..., crossed_out[999]
bool
10
Anwendung: String matching
Aufruf des Programms z.B. durch
./string_matching < eratosthenes.C >
match.out
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
Mehrdimensionale Felder
Mehrdimensionale Felder
sind Felder von Feldern
Mehrdimensionale Felder
sind Felder von Feldern
int a[2][3]
a hat zwei Elemente, und jedes
von ihnen ist ein Feld der Länge 3
mit zugrundeliegendem Typ int
Im Speicher: flach
a[0][0]
int a[2][3]
a[0][1]
a[0]
a[0][2]
a[1][0]
a[1][1]
a[1][2]
Kolonnen
Im Kopf: Matrix,
Tabelle,...
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]
11
Mehrdimensionale Felder
sind Felder von Feldern von Feldern...
T a[expr1]...[exprk]
Mehrdimensionale Felder
Initialisierung:
erste Dimension
kann weggelassen werden
int a[][3] =
{
{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]
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
Implizite Typdefinition: *p ist vom Typ int[3],
also ist p ein Zeiger auf int[3]
Ohne Klammern: p ist ein Feld von 3 Zeigern auf int
int *p [3]; // int* p[3]
12
Zeiger auf Felder
Felder von Zeigern
Wie iteriert man natürlich über ein mehrsich
ht t)!
c
i
dimensionales Feld?
n n krip
ma n (S
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
e
ss
mu schau
n”
n
arf
int a[2][3];
0
m-1
1
int (*p)[3] = a; // Zeiger
acherstes Element
eite auf
0
h
ein ed
epmist ein
BFeld von 3 Zeigern auf int
Ohne Klammern:
G
i
”
e
ax- ur b
t
n
y n,//n int* p[3]
int e*pS [3];
ch
rke
Sol t me
h
nic
.
.
.
.
.
.
.
n-1
.
Felder von Zeigern
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
a
a ist Zeiger auf das erste
Element eines Feldes von
n Zeigern auf int
.
.
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
a
0
int** a = new int*[n];
.
1
Felder von Zeigern
.
1
m-1
0
int** a = new int*[n];
a[0]
0
a[1]
1
for (int i = 0; i < n; ++i)
1
m-1
a[0]
0
a[1]
1
a[i] = new int[m];
zugrundeliegender Typ: int*
a[n-1]
n-1
a[n-1]
n-1
i == 0
13
Felder von Zeigern
Felder von Zeigern
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
a
for (int i = 0; i < n; ++i)
a
0
int** a = new int*[n];
m-1
1
0
a[0]
.
a[i] = new int[m];
.
.
for (int i = 0; i < n; ++i)
a[0] ist Zeiger auf das
erste Element eines
Feldes von m int’s
n-1
a[n-1]
m-1
1
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
.
i == 1
.
0
int** a = new int*[n];
0
a[0]
a[n-1]
n-1
a[n-1]
a
0
a[1] ist Zeiger auf das
erste Element eines
Feldes von m int’s
1
a[0] ist Zeiger auf das
erste Element eines
Feldes von m int’s
a
a[1]
.
Felder von Zeigern
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
a[i] = new int[m];
.
i == 1
Felder von Zeigern
for (int i = 0; i < n; ++i)
0
.
a[1]
i == 0
int** a = new int*[n];
m-1
1
a[0]
a[i] = new int[m];
1
a[1]
0
int** a = new int*[n];
.
for (int i = 0; i < n; ++i)
0
.
a[i] = new int[m];
1
n-1
m-1
1
a[0]
.
.
1
a[1]
a[n-1] ist Zeiger auf das
erste Element eines
Feldes von m int’s
.
.
.
.
.
a[n-1]
.
.
.
.
n-1
i == n-1
14
Felder von Zeigern
Felder von Zeigern
Wie bekommen wir mehrdimensionale
Felder mit variablen Dimensionen?
a
a
0
Wahlfreier Zugriff:
m-1
j
1
a[0]
a[i][j]
.
.
*(a[i]+j)
Zeiger
a[i]+j
.
.
.
.
.
a[n-1]
.
.
.
.
0
a[0]
1
a[1]
.
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
000111
111
000111
000
111
000
111
000
111
S 111
000
111
000
000
111
000
111
000
111
Startposition
000
111
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!
.
n-1
Fabrik-Halle (n × m quadratische Zellen)
Lösung
.
i
Anwendung: kürzeste Wege
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000111
000111
000
Hindernisse111
000
111
000
111
000
000
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 T
111
000
111
000
111
.
.
.
a[1]
a[i]
Speicherlayout im Heap :
.
Ein (scheinbar) anderes
Problem
Finde die Längen der kürzesten Wege zu allen möglichen Zielen!
3
2
3
Startposition
eines Roboters4
Zielposition
des Roboters
.
a[n-1]
4
freie Zellen
.
.
5
6
7
5
6
7
8
111
000
000
111
000
111
000
111
000
000
000111
111
000111
111
000 9
111
000
111
000
111
000
1
0 111
00010
111
000
111
000
111
000
11
2
1 111
000
111
000
111
000
111
000
10
3
2 111
000
111
000
111
000
111
000
4
3 111
000 9
111
000
111
000
111
5
4 111
000 8
6
5
6
7
9
10
11
12
11
10
9
8
111
000
00015 16 17 18
111
000
111
000
111
000
111
00014 15 16 17
111
000
000
000
12 111
13 111
14 111
15 16
000
111
000
111
000
111
000
111
000
111
000
111
000
111
13 111
17
000
000
111
000
111
000
111
000
111
000
12 111
20
19
18
000
111
000
111
000
111
000
11 111
000
111
00021 20 19
111
000
111
10 111
22 21 20
000
000
111
00023 22 21
111
9 111
000
19
18
17
18
19
Zielposition
des Roboters;
21 kürzester Weg
hat Länge 21
22
20
i22
15
Ein (scheinbar) anderes
Problem
Finde die Längen der kürzesten Wege zu allen möglichen Zielen!
Das löst auch
das OriginalProblem:
4
starte in T;
folge einem
Weg mit (jeweils um
eins) sinkenden Längen!
2
3
3
4
5
6
7
5
6
7
8
111
000
000
111
000
111
000
111
000
000
9
000111
111
000111
111
000
111
000
111
000
111
000
10
1
0 111
000
111
000
111
000
111
000
11
2
1 111
000
111
000
111
000
111
000
3
2 111
00010
111
000
111
000 9
111
4
3 111
000
111
000
000
111
5
4 111
000 8
6
5
6
7
9
10
11
12
11
10
9
8
111
000
000
111
00015 16 17 18
111
000
111
000
111
00014 15 16 17
111
000
000
000
12 111
13 111
14 111
15 16
000
111
000
000
000111
111
000111
111
00017
111
000
13 111
000
111
000
111
000
111
000
111
000
111
000
12 111
20 19 18
000
111
000
111
00021 20 19
111
11 111
000
000
111
000
111
10 111
000
00022 21 20
111
000
111
9 111
00023 22 21
19
18
17
18
19
Zielposition
des Roboters;
21 kürzester Weg
hat Länge 21
22
20
Ein (scheinbar) anderes
Problem
Finde die Längen der kürzesten Wege zu allen möglichen Zielen!
Das löst auch
das OriginalProblem:
4
starte in T;
folge einem
Weg mit (jeweils um
eins) sinkenden Längen!
2
3
3
4
5
6
7
5
6
7
8
111
000
000
111
000
111
000
111
000
000
9
000111
111
000111
111
000
111
000
111
000
111
000
10
1
0 111
000
111
000
111
000
111
000
11
2
1 111
000
111
000
111
000
111
000
3
2 111
00010
111
000
111
000 9
111
4
3 111
000
111
000
000
111
5
4 111
000 8
6
5
6
7
i22
Finde die Längen der kürzesten Wege zu allen möglichen Zielen!
Das löst auch
das OriginalProblem:
4
starte in T;
folge einem
Weg mit (jeweils um
eins) sinkenden Längen!
2
3
3
4
5
6
7
5
6
7
8
111
000
000
111
000
111
000
111
000
000
000111
111
000111
111
000 9
111
000
111
000
111
000
1
0 111
00010
111
000
111
000
111
000
11
2
1 111
000
111
000
111
000
111
000
10
3
2 111
000
111
000
111
000
111
000
4
3 111
000 9
111
000
111
000
111
5
4 111
000 8
6
5
6
7
9
10
11
12
11
10
9
8
i22
10
11
12
11
10
9
8
111
000
000
111
00015 16 17 18
111
000
111
000
111
00014 15 16 17
111
000
000
000
12 111
13 111
14 111
15 16
000
111
000
000
000111
111
000111
111
00017
111
000
13 111
000
111
000
111
000
111
000
111
000
111
000
12 111
20 19 18
000
111
000
111
00021 20 19
111
11 111
000
000
111
000
111
10 111
000
00022 21 20
111
000
111
9 111
00023 22 21
19
18
17
18
19
Zielposition
des Roboters;
21 kürzester Weg
hat Länge 21
22
20
i22
Ein (scheinbar) anderes
Problem
111
000
00015 16 17 18
111
000
111
000
111
000
111
00014 15 16 17
111
000
000
000
12 111
13 111
14 111
15 16
000
111
000
111
000
111
000
111
000
111
000
111
000
111
13 111
17
000
000
111
000
111
000
111
000
111
000
12 111
20
19
18
000
111
000
111
000
111
000
11 111
000
111
00021 20 19
111
000
111
10 111
22 21 20
000
000
111
00023 22 21
111
9 111
000
9
19
18
17
18
19
Zielposition
des Roboters;
21 kürzester Weg
hat Länge 21
22
20
Ein (scheinbar) anderes
Problem
Finde die Längen der kürzesten Wege zu allen möglichen Zielen!
Das löst auch
das OriginalProblem:
4
starte in T;
folge einem
Weg mit (jeweils um
eins) sinkenden Längen!
2
3
3
4
5
6
7
5
6
7
8
111
000
000
111
000
111
000
111
000
000
000111
111
000111
111
000 9
111
000
111
000
111
000
1
0 111
00010
111
000
111
000
111
000
11
2
1 111
000
111
000
111
000
111
000
10
3
2 111
000
111
000
111
000
111
000
4
3 111
000 9
111
000
111
000
111
5
4 111
000 8
6
5
6
7
9
10
11
12
11
10
9
8
111
000
00015 16 17 18
111
000
111
000
111
000
111
00014 15 16 17
111
000
000
000
12 111
13 111
14 111
15 16
000
111
000
111
000
111
000
111
000
111
000
111
000
111
13 111
17
000
000
111
000
111
000
111
000
111
000
12 111
20
19
18
000
111
000
111
000
111
000
11 111
000
111
00021 20 19
111
000
111
10 111
22 21 20
000
000
111
00023 22 21
111
9 111
000
19
18
17
18
19
Zielposition
des Roboters;
21 kürzester Weg
hat Länge 21
22
20
i22
16
Ein (scheinbar) anderes
Problem
Finde die Längen der kürzesten Wege zu allen möglichen Zielen!
Das löst auch
das OriginalProblem:
4
starte in T;
folge einem
Weg mit (jeweils um
eins) sinkenden Längen!
2
Weglänge 21
(optimal)
3
3
4
5
6
7
5
6
7
8
111
000
000
111
000
111
000
111
000
000
9
000111
111
000111
111
000
111
000
111
000
111
000
10
1
0 111
000
111
000
111
000
111
000
11
2
1 111
000
111
000
111
000
111
000
3
2 111
00010
111
000
111
000 9
111
4
3 111
000
111
000
000
111
5
4 111
000 8
6
5
6
7
9
10
11
12
11
10
9
8
111
000
000
111
00015 16 17 18
111
000
111
000
111
00014 15 16 17
111
000
000
000
12 111
13 111
14 111
15 16
000
111
000
000
000111
111
000111
111
00017
111
000
13 111
000
111
000
111
000
111
000
111
000
111
000
12 111
20 19 18
000
111
000
111
00021 20 19
111
11 111
000
000
111
000
111
10 111
000
00022 21 20
111
000
111
9 111
00023 22 21
19
18
17
18
19
Zielposition
des Roboters;
21 kürzester Weg
hat Länge 21
22
20
Markierung aller Zellen mit
ihren Weglängen
Schritt 0: Alle Zellen
000 mit Weglänge 0:
111
111111
000
000111
000
000
111
000
000
000111
111
000111
111
000
111
000111
111
000111
000
111
000
000
111
0 111
000
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
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
111
000
000
000111
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
i22
Markierung aller Zellen mit
ihren Weglängen
Markierung aller Zellen mit
ihren Weglängen
Schritt 1: Alle Zellen
000 mit Weglänge 1:
111
Schritt 2: Alle Zellen mit Weglänge 2:
Unmarkierte
Nachbarn der
Zelle(n) mit
Weglänge 0
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
111
000
000
111
000
1 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
111
000
111
000
111
000
000
111
000
111
000111
000
111
000111
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
2
Unmarkierte
Nachbarn der
Zelle(n) mit
Weglänge 1
111
000
000
111
000
111
000
111
000
000
000
111
000111
111
000111
111
000
111
000
111
000
111
000
1
0 111
000
111
000
111
000
111
2
1 111
000
000
111
000
111
2 111
000
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
111
000
111
000
111
000
111
000
000
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
T
000
111
000
111
000
111
000
111
17
Markierung aller Zellen mit
ihren Weglängen
Das Kürzeste-Wege-Programm
Schritt 3: Alle Zellen mit Weglänge 3:
3
2
3
Unmarkierte
Nachbarn der
Zelle(n) mit
Weglänge 2
111111
000
000111
000
000
111
000
000
000111
111
000111
111
000
111
000
111
000
111
000
1
0 111
000
111
000
111
000
111
2
1 111
000
000
111
000
111
2 111
3
000
000
111
000
111
3 111
000
111
000
000
111
000
111
111
000
000
111
000
111
000
111
000
111
000
111
000111
111
000111
000
000
111
000
000
000111
111
000111
111
000
111
000
111
000
111
000
000 111
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
Das Kürzeste-Wege-Programm
Eingabeformat:
8 12
------X-----
Zeilen
Kolonnen
-XXX--X------SX--------
for (int r=0; r<n+2; ++r)
floor[r] = new int[m+2];
Wächter (sentinels)
Ziel
---X---X---Hindernis
---X---X-T-freie Zelle
-------X----
Das Kürzeste-Wege-Programm
Kolonnen
m m +1
11111111111111111111111111111111111
00000000000000000000000000000000000
00000000000000000000000000000000000
11111111111111111111111111111111111
000
111
000
111
00000000000000000000000000000000000
11111111111111111111111111111111111
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
n
000
111
000
111
00000000000000000000000000000000000
11111111111111111111111111111111111
00000000000000000000000000000000000
11111111111111111111111111111111111
00000000000000000000000000000000000
n +1 11111111111111111111111111111111111
0
1
0
int m; std::cin >> m; // number of columns
int** floor = new int*[n+2];
111
000
000
111
000
111
000
111
000
111
000
000
111
000111
000
111
000111
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
T
000
111
000
111
000
111
000
111
---X---X----
int n; std::cin >> n; // number of rows
// (n+2) x (m+2) to hold the floor plus extra walls around
111
000
000
111
000
111
000
111
000
111
000
111
---X---XXX--
Start
Einlesen der Dimensionen und Bereitstellung eines zweidimensionalen Feldes
für die Weglängen
// dynamically allocate twodimensional array of dimensions
111
000
000
111
000
111
000
111
000
000
000111
111
000111
111
000
111
000
111
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
Zeilen
18
Das Kürzeste-Wege-Programm
Einlesen der Hallenbelegung und
Initialisierung der Längen
Das Kürzeste-Wege-Programm
int tr = 0;
int tc = 0;
Einlesen der Hallenbelegung und
Initialisierung der Längen
int tr = 0;
Zielkoordinaten (Zeilen-/Kolonnenindex)
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;
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;
}
}
Das Kürzeste-Wege-Programm
Einlesen der Hallenbelegung und
Initialisierung der Längen
int tr = 0;
Das Kürzeste-Wege-Programm
Einlesen der Hallenbelegung und
Initialisierung der Längen
int tr = 0;
int tc = 0;
int tc = 0;
for (int r=1; r<n+1; ++r)
for (int c=1; c<m+1; ++c) {
char entry = '-';
Eingabezeichen in
Zeile r ∈ {1,...,n} und
Kolonne c ∈ {1,...,m}
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;
Länge bereits
bekannt
(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;
}
(entry == 'S') floor[r][c] = 0;
else if (entry == 'T') floor[tr = r][tc = c] = -1;
else if (entry == '-') floor[r][c] = -1;
lies die Eingabe Zeile für Zeile
(z.B. durch Umlenkung der
Eingabe auf die Datei
shortest_path0.dat)
else if (entry == '-') floor[r][c] = -1;
}
19
Das Kürzeste-Wege-Programm
Einlesen der Hallenbelegung und
Initialisierung der Längen
Das Kürzeste-Wege-Programm
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 c=1; c<m+1; ++c) {
char entry = '-';
for (int r=1; r<n+1; ++r)
for (int c=1; c<m+1; ++c) {
Ziel: setze
Koordinaten
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 == '-') floor[r][c] = -1;
}
else if (entry == 'X') floor[r][c] = -2;
else if (entry == '-') floor[r][c] = -1;
-1: Länge noch
unbekannt
Das Kürzeste-Wege-Programm
(entry == 'S') floor[r][c] = 0;
else if (entry == 'T') floor[tr = r][tc = c] = -1;
Einlesen der Hallenbelegung und
Initialisierung der Längen
}
-2: Länge nicht
relevant (Hindernis)
Das Kürzeste-Wege-Programm
Hinzufügen der umschliessenden
“Wände”
int tr = 0;
int tc = 0;
for (int r=0; r<n+2; ++r)
for (int r=1; r<n+1; ++r)
Kolonnen 0 und m +1
floor[r][0] = floor[r][m+1] = -2;
for (int c=1; c<m+1; ++c) {
for (int c=0; c<m+2; ++c)
char entry = '-';
Zeilen 0 und n +1
floor[0][c] = floor[n+1][c] = -2;
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;
}
-1: Länge noch
unbekannt
(freie Zelle)
20
Das Kürzeste-Wege-Programm
11111111111111111111111111111111111
00000000000000000000000000000000000
00000000000000000000000000000000000
11111111111111111111111111111111111
00000000000000000000000000000000000
11111111111111111111111111111111111
000
111
000
111
000
111
00000000000000000000000000000000000
11111111111111111111111111111111111
000
111
000
111
000
000 −1 111
111
000 −1 −1 −1 −1 −1 111
111
000
111
000
000
000
000
−1 111
−1 111
−1 −1 −1 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
−1 111
−1
−1
−1
−1
−1
−1
−1
000111
000
111
000
111
000
000 000111
111
000
111
000
111
000
111
000
111
−1 −1 −1 −1 −1 −1 −1 −1 111
000
000 −1 −1 0 111
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000 −1 −1 −1 111
111
000
111
−1 −1 −1 111
−1
−1
000
000
000
111
000
111
000
111
000
111
000
111
000
111
000
000
111
000 −1 −1 −1 111
111
000
111
−1 −1 −1 −1 111
000 −1 −1 −1 111
111
000
000
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
−1 −1 −1 −1 111
000 −1 −1 −1 111
111
000
000
000
111
000 −1 −1 −1 111
111
000
111
000
111
000
111
000
111
000
111
−1
−1
−1
−1
−1
−1
−1
−1
−1
−1
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
−1 −1 −1 −1 −1 −1 −1 111
000
111
000
000 −1 −1 −1 −1 111
00000000000000000000000000000000000
11111111111111111111111111111111111
000
111
00000000000000000000000000000000000
11111111111111111111111111111111111
00000000000000000000000000000000000
11111111111111111111111111111111111
Start
-2
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;
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] = i; // label cell with i
progress = true;
}
}
if (!progress) break;
}
Das Kürzeste-Wege-Programm
for (int i=1;; ++i) {
bool progress = false;
Haben wir für dieses i
eine Zelle gefunden?
Das Kürzeste-Wege-Programm
for (int i=1;; ++i) {
bool progress = false;
for (int r=1; r<n+1; ++r)
Iteriere über alle
“echten” Zellen
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;
}
Hauptschleife: finde und
markiere alle Zellen mit
Weglängen i=1,2,3...
if (!progress) break;
}
21
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
bool progress = false;
for (int r=1; r<n+1; ++r)
Fall 1: Hindernis, oder
schon markiert
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 ||
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
}
}
r
}
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;
?
i-1 i-2
if (!progress) break;
}
Betrachte Zelle in Zeile r
∈ {1,...,n} und Kolonne
c ∈ {1,...,m}:
i-1
Durch die Wächter hat jede “echte” Zelle 4 Nachbarn!
c
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 ||
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;
i-1 i-2 i-3
}
}
Markiere Zelle mit i
r
i
i-1 i-2
if (!progress) break;
}
Fall 2: Ein Nachbar hat
bereits Weglänge 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 ) {
}
Betrachte Zelle in Zeile r
∈ {1,...,n} und Kolonne
c ∈ {1,...,m}:
for (int i=1;; ++i) {
}
if (!progress) break;
i-1
c
}
Falls keine Zelle mehr markiert
werden konnte, sind wir fertig
(sonst geht’s weiter mit i+1)
22
Das Kürzeste-Wege-Programm
Markieren des kürzesten Weges durch
“Rückwärtslaufen” vom Ziel zum Start
int r = tr; int c = tc;
Das Kürzeste-Wege-Programm
int r = tr; int c = tc;
Zielzelle
while (floor[r][c] > 0) {
int d = floor[r][c] - 1;
floor[r][c] = -3;
floor[r][c] = -3;
if
if
(floor[r-1][c] == d) --r;
(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)
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;
Das Kürzeste-Wege-Programm
Markieren des kürzesten Weges durch
“Rückwärtslaufen” vom Ziel zum Start
int r = tr; int c = tc;
d = um eins kleinere
Weglänge
while (floor[r][c] > 0) {
int d = floor[r][c] - 1;
while (floor[r][c] > 0) {
int d = floor[r][c] - 1;
floor[r][c] = -3;
floor[r][c] = -3;
if
if
(floor[r-1][c] == d) --r;
(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
}
Solange Startzelle
noch nicht erreicht...
while (floor[r][c] > 0) {
int d = floor[r][c] - 1;
}
Markieren des kürzesten Weges durch
“Rückwärtslaufen” vom Ziel zum Start
++c; // (floor[r][c+1] == d)
else
Markiere Zelle (mit -3
zur Unterscheidung):
sie liegt auf dem
kürzesten Weg
++c; // (floor[r][c+1] == d)
}
23
Das Kürzeste-Wege-Programm
Das Kürzeste-Wege-Programm
11111111111111111111111111111111111
00000000000000000000000000000000000
00000000000000000000000000000000000
11111111111111111111111111111111111
00000000000000000000000000000000000
11111111111111111111111111111111111
000
111
000
111
000
111
000
111
000
111
000
111
000
000
000
000
−3 111
−3 111
−3 −3 −3 111
15 16 17 18 19 111
000 −3 111
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 −3 111
111
000
111
9
−3
14
15
16
17
18
000
000
111
000
111
000
111
000
111
000
111
000
111
00010 −3 −3 111
111
000 −3 −3 0 111
111
000
111
000
000
000
111
000
111
−3 −3 −3 −3 17 111
000
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
000
111
000
00011 12 13 111
111
000
000111
111
000−3 18 111
000
000
111
000 3 2 1 111
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
4
3
2
10
11
12
20
−3
−3
19
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000 5 4 3 111
111
000
9 10 11 111
21 −3 19 20 111
000
000
000
111
000
111
000
111
000
111
000
000
111
000 6 5 4 111
111
000
111
22
−3
20
21
000 8 9 10 111
111
000
000
111
000
111
000
111
000
111
000
111
000
111
000
111
000
7
6
5
6
7
8
9 111
00023 22 21 22 111
00000000000000000000000000000000000
11111111111111111111111111111111111
00000000000000000000000000000000000
11111111111111111111111111111111111
00000000000000000000000000000000000
11111111111111111111111111111111111
Markieren des kürzesten Weges durch
“Rückwärtslaufen” vom Ziel zum Start
int r = tr; int c = tc;
while (floor[r][c] > 0) {
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;
Gehe zu einer
Nachbarzelle mit
Weglänge d und
wiederhole...
else if (floor[r][c-1] == d) --c;
else
++c; // (floor[r][c+1] == d)
}
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)
std::cout << 'S';
else if (r == tr && c == tc) std::cout << 'T';
ooSX-oooooo-
for (int c=1; c<m+1; ++c)
if
---X---XXXo-
(floor[r][c] == 0)
std::cout << 'S';
else if (r == tr && c == tc) std::cout << 'T';
---X---X-oo-
---X---XXXo---X---X-oo-
else if (floor[r][c] == -3)
std::cout << 'o';
else if (floor[r][c] == -3)
std::cout << 'o';
else if (floor[r][c] == -2)
std::cout << 'X';
---X---X-o--
else if (floor[r][c] == -2)
std::cout << 'X';
---X---X-o--
else
std::cout << '-';
---X---X-T--
else
std::cout << '-';
---X---X-T--
std::cout << "\n";
}
oXXX-oX----for (int r=1; r<n+1; ++r) {
ooSX-oooooo-
for (int c=1; c<m+1; ++c)
std::cout << "\n";
-------X----
-------X----
}
24
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) {
for (int r=1; r<n+1; ++r) {
ooSX-oooooo-
for (int c=1; c<m+1; ++c)
if
oXXX-oX-----
(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)
if
---X---XXXo-
(floor[r][c] == 0)
std::cout << 'S';
else if (r == tr && c == tc) std::cout << 'T';
---X---X-oo-
---X---XXXo---X---X-oo-
else if (floor[r][c] == -3)
std::cout << 'o';
---X---X-o--
else if (floor[r][c] == -2)
std::cout << 'X';
---X---X-o--
---X---X-T--
else
std::cout << '-';
---X---X-T--
std::cout << "\n";
-------X----
}
-------X----
}
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)
---X---XXXo---X---X-oo-
Heap bereitgestellten Felder
delete[] floor[r];
delete[] floor;
Feld für die Zeile mit
Index r
std::cout << 'o';
else if (floor[r][c] == -2)
std::cout << 'X';
---X---X-o--
else
std::cout << '-';
---X---X-T--
std::cout << "\n";
Last, but not least : lösche die auf dem
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)
ooSX-oooooo-
for (int c=1; c<m+1; ++c)
if
Das Kürzeste-Wege-Programm
Feld von Zeigern auf die
n +2 Zeilen
-------X----
}
25
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 : der leichteste bisher...
26
© Copyright 2026 Paperzz