Einfhrung in die Programmierung Wintersemester 200910 Prof Dr

  • Slides: 32
Download presentation
Einführung in die Programmierung Wintersemester 2009/10 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering

Einführung in die Programmierung Wintersemester 2009/10 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 1

Kapitel 15: Fallstudien Inhalt ● Sortieren: Mergesort (auch mit Schablonen) ● Matrixmultiplikation (Schablonen /

Kapitel 15: Fallstudien Inhalt ● Sortieren: Mergesort (auch mit Schablonen) ● Matrixmultiplikation (Schablonen / Ausnahmen) ● Klassenhierarchien G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 2

Kapitel 15 Fallstudien Mergesort Beobachtung: Sortieren ist einfach, wenn man zwei sortierte Teilfolgen hat.

Kapitel 15 Fallstudien Mergesort Beobachtung: Sortieren ist einfach, wenn man zwei sortierte Teilfolgen hat. 2: 27 < 39 3: 38 < 39 6: 80 < 92 8 27 38 80 103 Teilfolge 1 11 39 43 92 Teilfolge 2 1: 11 < 27 4: 39 < 80 5: 43 < 80 7: 92 < 103 ? G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 3

Kapitel 15 Fallstudien T 26 94 41 54 103 65 57 78 27 103

Kapitel 15 Fallstudien T 26 94 41 54 103 65 57 78 27 103 80 38 11 43 11 26 27 38 T T 39 41 43 54 57 26 94 27 103 41 80 54 103 38 11 26 94 103 65 27 103 11 43 41 57 80 39 54 78 38 92 26 94 41 54 103 65 57 78 27 103 80 38 11 43 39 92 S 26 94 41 54 65 103 57 78 27 103 38 80 11 43 39 92 65 43 57 39 92 65 78 80 92 94 103 78 92 26 11 M 39 M 41 27 54 38 26 41 54 94 57 65 78 103 27 38 80 103 11 39 43 57 39 65 43 78 80 94 103 92 103 M 92 G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 4

Fallstudien Kapitel 15 =2 G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 5

Fallstudien Kapitel 15 =2 G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 5

Kapitel 15 Fallstudien Mergesort ● Eingabe: unsortiertes Feld von Zahlen ● Ausgabe: sortiertes Feld

Kapitel 15 Fallstudien Mergesort ● Eingabe: unsortiertes Feld von Zahlen ● Ausgabe: sortiertes Feld ● Algorithmisches Konzept: „Teile und herrsche“ (divide and conquer) Ø Zerlege Problem solange in Teilprobleme bis Teilprobleme lösbar Ø Löse Teilprobleme Ø Füge Teilprobleme zur Gesamtlösung zusammen Hier: 1. Zerteile Feld in Teilfelder bis Teilproblem lösbar (→ bis Feldgröße = 2) 2. Sortiere Felder Größe 2 (→ einfacher Vergleich zweier Zahlen) 3. Füge sortierte Teilfelder durch Mischen zu sortierten Feldern zusammen G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 6

Kapitel 15 Fallstudien Mergesort Annahme: ● Programmentwurf Feldgröße ist Potenz von 2 1. Teilen

Kapitel 15 Fallstudien Mergesort Annahme: ● Programmentwurf Feldgröße ist Potenz von 2 1. Teilen eines Feldes → einfach! 2. Sortieren a) eines Feldes der Größe 2 → einfach! b) eines Feldes der Größe > 2 → rekursiv durch Teilen & Mischen 3. Mischen → nicht schwer! G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 7

Kapitel 15 Fallstudien Mergesort: Version 1 void Msort(const int size, int a[]) { if

Kapitel 15 Fallstudien Mergesort: Version 1 void Msort(const int size, int a[]) { if (size == 2) { // sortieren if (a[0] > a[1]) Swap(a[0], a[1]); return; } // teilen int k = size / 2; Msort(k, &a[0]); Msort(k, &a[k]); // mischen Merge(k, &a[0], &a[k]); } void Swap(int& a, int& b) { int c = b; b = a; a = c; } sortieren (einfach) sortieren durch Teilen & Mischen Werte vertauschen per Referenz G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 8

Kapitel 15 Fallstudien Mergesort: Version 1 void Merge(const int size, int a[], int b[])

Kapitel 15 Fallstudien Mergesort: Version 1 void Merge(const int size, int a[], int b[]) { int* c = new int[2*size]; // mischen int i = 0, j = 0; for (int k = 0; k < 2 * size; k++) if ((j == size) || (i < size && a[i] < b[j])) c[k] = a[i++]; else c[k] = b[j++]; // umkopieren for (int k = 0; k < size; k++) { a[k] = c[k]; b[k] = c[k+size]; } delete[] c; dynamischen Speicher anfordern dynamischen Speicher freigeben } G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 9

Kapitel 15 Fallstudien Mergesort: Version 1 void Print(const int size, int a[]) { for

Kapitel 15 Fallstudien Mergesort: Version 1 void Print(const int size, int a[]) { for (int i = 0; i < size; i++) { cout << a[i] << "t"; if ((i+1) % 8 == 0) cout << endl; } Hilfsfunktion für Testprogramm int main() { const int size = 32; int a[size]; for (int k = 0; k < size; k++) a[k] = rand(); Print(size, a); Msort(size, a); Print(size, a); Programm zum Testen } G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 10

Kapitel 15 Fallstudien Mergesort: Version 1 Ausgabe: 41 26962 2995 292 18467 24464 11942

Kapitel 15 Fallstudien Mergesort: Version 1 Ausgabe: 41 26962 2995 292 18467 24464 11942 12382 6334 5705 4827 17421 26500 28145 5436 18716 19169 23281 32391 19718 15724 16827 14604 19895 11478 9961 3902 5447 29358 491 153 21726 41 5447 15724 21726 153 5705 16827 23281 292 6334 17421 24464 491 9961 18467 26500 2995 11478 18716 26962 3902 11942 19169 28145 4827 12382 19718 29358 5436 14604 19895 32391 OK, funktioniert für int … was ist mit char, float, double … ? Idee: Schablonen! G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 11

Fallstudien Kapitel 15 Mergesort: Version 2 template <class T> void Msort(const int size, T

Fallstudien Kapitel 15 Mergesort: Version 2 template <class T> void Msort(const int size, T a[]) { if (size == 2) { // sortieren if (a[0] > a[1]) Swap<T>(a[0], a[1]); return; } // teilen int k = size / 2; Msort<T>(k, &a[0]); Msort<T>(k, &a[k]); // mischen Merge<T>(k, &a[0], &a[k]); } template <class T> void Swap(T& a, T& b) { T c = b; b = a; a = c; } G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 12

Kapitel 15 Fallstudien Mergesort: Version 2 template <class T> void Merge(const int size, T

Kapitel 15 Fallstudien Mergesort: Version 2 template <class T> void Merge(const int size, T a[], T b[]) { T* c = new T[2*size]; // mischen int i = 0, j = 0; for (int k = 0; k < 2 * size; k++) { if ((j == size) || (i < size && a[i] < b[j])) c[k] = a[i++]; else c[k] = b[j++]; // umkopieren for (int k = 0; k < size; k++) { a[k] = c[k]; b[k] = c[k+size]; } delete[] c; } G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 13

Fallstudien Kapitel 15 Mergesort: Version 2 template <class T> void Print(const int size, T

Fallstudien Kapitel 15 Mergesort: Version 2 template <class T> void Print(const int size, T a[]) { … } int main() { const int size = 32; int a[size]; for (int k = 0; k < size; k++) a[k] = rand(); Print<int>(size, a); Msort<int>(size, a); Print<int>(size, a); float b[size]; for (int k = 0; k < size; k++) b[k] = rand() * 0. 01 f; Print<float>(size, b); Msort<float>(size, b); Konstante vom Typ float Print<float>(size, b); (nicht double) } G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 14

Kapitel 15 Fallstudien Mergesort: Version 2 Ausgabe: 41 26962 2995 292 18467 24464 11942

Kapitel 15 Fallstudien Mergesort: Version 2 Ausgabe: 41 26962 2995 292 18467 24464 11942 12382 6334 5705 4827 17421 26500 28145 5436 18716 19169 23281 32391 19718 15724 16827 14604 19895 11478 9961 3902 5447 29358 491 153 21726 41 5447 15724 21726 153 5705 16827 23281 292 6334 17421 24464 491 9961 18467 26500 2995 11478 18716 26962 3902 11942 19169 28145 4827 12382 19718 29358 5436 14604 19895 32391 147. 71 287. 03 282. 53 87. 23 115. 38 238. 11 68. 68 97. 41 18. 69 313. 22 255. 47 275. 29 199. 12 303. 33 276. 44 7. 78 256. 67 176. 73 326. 62 123. 16 262. 99 46. 64 327. 57 30. 35 170. 35 151. 41 200. 37 221. 9 98. 94 77. 11 128. 59 18. 42 7. 78 97. 41 176. 73 275. 29 18. 42 98. 94 199. 12 276. 44 18. 69 115. 38 200. 37 282. 53 30. 35 123. 16 221. 9 287. 03 46. 64 128. 59 238. 11 303. 33 68. 68 147. 71 255. 47 313. 22 77. 11 151. 41 256. 67 326. 62 87. 23 170. 35 262. 99 327. 57 G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 15

Kapitel 15 Fallstudien Mergesort: Version 2 Schablone instantiiert mit Typ string funktioniert auch! Schablone

Kapitel 15 Fallstudien Mergesort: Version 2 Schablone instantiiert mit Typ string funktioniert auch! Schablone instantiiert mit Typ Complex funktioniert nicht! Warum? Vergleichsoperatoren sind nicht überladen für Typ Complex! in Msort: if (a[0] > a[1]) Swap<T>(a[0], a[1]); in Merge: if ((j == size) || (i < size && a[i] < b[j])) Entweder Operatoren überladen oder überladene Hilfsfunktion (z. B. Less): bool Less(Complex &x, Complex &y) { if (x. Re() < y. Re()) return true; return (x. Re() == y. Re() && x. Im() < y. Im())); } hier: lexikographische Ordnung G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 16

Kapitel 15 Fallstudien MATRIX Multiplikation (für quadratische Matrizen) class Matrix { private: double **f.

Kapitel 15 Fallstudien MATRIX Multiplikation (für quadratische Matrizen) class Matrix { private: double **f. Elem; unsigned int f. Dim; … public: Matrix(unsigned int a. Dim); Matrix(const Matrix& a. Mat); double* double unsigned int Dim() { return f. Dim; } void Set(unsigned int a. Row, unsigned int a. Col, double a. Val); double Get(unsigned int a. Row, unsigned int a. Col); void Mult(const Matrix& a. Mat); void Print(); ~Matrix(); }; G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 17

Fallstudien Kapitel 15 MATRIX Multiplikation Konstruktor Matrix: : Matrix(unsigned int a. Dim) : f.

Fallstudien Kapitel 15 MATRIX Multiplikation Konstruktor Matrix: : Matrix(unsigned int a. Dim) : f. Dim(a. Dim) { if (f. Dim == 0) throw "matrix of dimension 0"; f. Elem = new double* [f. Dim]; if (f. Elem == 0) throw "memory exceeded"; for (unsigned int i = 0; i < f. Dim; i++) { f. Elem[i] = new double[f. Dim]; if (f. Elem[i] == 0) throw "memory exceeded"; } } Destruktor Matrix: : ~Matrix() { for (unsigned int i = 0; i < f. Dim; i++) delete[] f. Elem[i]; delete[] f. Elem; } G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 18

Fallstudien Kapitel 15 kopieren Kopierkonstruktor Matrix: : Matrix(const Matrix& a. Mat) : f. Dim(a.

Fallstudien Kapitel 15 kopieren Kopierkonstruktor Matrix: : Matrix(const Matrix& a. Mat) : f. Dim(a. Mat. f. Dim) { if (f. Dim == 0) throw "matrix of dimension 0"; f. Elem = new double* [f. Dim]; if (f. Elem == 0) throw "memory exceeded"; for (unsigned int i = 0; i < f. Dim; i++) { f. Elem[i] = new double[f. Dim]; if (f. Elem[i] == 0) throw "memory exceeded"; } for (unsigned int i = 0; i < f. Dim; i++) for (unsigned int j = 0; j < f. Dim; j++) f. Elem[i][j] = a. Mat. f. Elem[i][j]; } Speicherallokation MATRIX Multiplikation G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 19

Kapitel 15 Fallstudien MATRIX Multiplikation void Matrix: : Set(unsigned int a. Row, unsigned int

Kapitel 15 Fallstudien MATRIX Multiplikation void Matrix: : Set(unsigned int a. Row, unsigned int a. Col, double a. Val) { if (a. Row >= f. Dim || a. Col >= f. Dim) throw "index overflow"; f. Elem[a. Row][a. Col] = a. Val; } double Matrix: : Get(unsigned int a. Row, unsigned int a. Col) { if (a. Row >= f. Dim || a. Col >= f. Dim) throw "index overflow"; return f. Elem[a. Row][a. Col]; } Indexbereichsprüfung! G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 20

Fallstudien Kapitel 15 MATRIX Multiplikation A und B sind quadratische Matrizen der Dimension n.

Fallstudien Kapitel 15 MATRIX Multiplikation A und B sind quadratische Matrizen der Dimension n. C = A ¢ B ist dann: void Matrix: : Mult(const Matrix& a. Mat) { if (a. Mat. f. Dim != f. Dim) throw "incompatible dimensions"; Matrix t. Mat(*this); for (unsigned int i = 0; i < f. Dim; i++) for (unsigned int j = 0; j < f. Dim; j++) { double sum = 0. 0; for (unsigned int k = 0; k < f. Dim; k++) sum += t. Mat. Get(i, k) * a. Mat. f. Elem[k][j]; f. Elem[i][j] = sum; } } G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 21

Kapitel 15 Fallstudien MATRIX Multiplikation Nächste Schritte 1. Ausnahmen vom Typ char* ersetzen durch

Kapitel 15 Fallstudien MATRIX Multiplikation Nächste Schritte 1. Ausnahmen vom Typ char* ersetzen durch unterscheidbare Fehlerklassen: z. B. class Matrix. Error als Basisklasse, ableiten: Matrix. Index. Overflow, Matrix. Dimension. Mismatch, … 2. Umwandeln in Schablone: template <class T> class Matrix { … also nicht nur Multiplikation für double, sondern auch int, Complex, Rational, … G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 22

Kapitel 15 Fallstudien Code nach Fehlermeldungen durchforsten … Konstruktoren: throw "matrix of dimension 0";

Kapitel 15 Fallstudien Code nach Fehlermeldungen durchforsten … Konstruktoren: throw "matrix of dimension 0"; Matrix. Zero. Dimension throw "memory exceeded"; Matrix. Memory. Exceeded Get / Set: Matrix. Index. Overflow throw "index overflow"; Mult: throw "incompatible dimensions"; Matrix. Dimension. Mismatch G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 23

Kapitel 15 Fallstudien Klassenhierachie für Ausnahmen class Matrix. Error class Matrix. Zero. Dimension class

Kapitel 15 Fallstudien Klassenhierachie für Ausnahmen class Matrix. Error class Matrix. Zero. Dimension class Matrix. Memory. Exceeded class Matrix. Index. Overflow class Matrix. Dimension. Mismatch Minimale Lösung in C++: class Matrix. Error {}; class Matrix. Zero. Dimension Matrix. Memory. Exceeded Matrix. Index. Overflow Matrix. Dimension. Mismatch : : public Matrix. Error() {}; {}; G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 24

Kapitel 15 Fallstudien Schablone MATRIX Multiplikation (für quadratische Matrizen) typedef unsigned int uint; template

Kapitel 15 Fallstudien Schablone MATRIX Multiplikation (für quadratische Matrizen) typedef unsigned int uint; template <class T> class Matrix { private: T **f. Elem; uint f. Dim; public: Matrix(uint a. Dim); Matrix(const Matrix& a. Mat); ursprünglichen Typ der Nutzdaten ersetzen durch generischen Typ T uint Dim() { return f. Dim; } void Set(uint a. Row, uint a. Col, T a. Val); T Get(uint a. Row, uint a. Col); void Mult(const Matrix& a. Mat); void Print(); ~Matrix(); }; G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 25

Kapitel 15 Fallstudien Schablone MATRIX Multiplikation mit vernünftiger Ausnahmebehandlung Konstruktor template <class T> Matrix:

Kapitel 15 Fallstudien Schablone MATRIX Multiplikation mit vernünftiger Ausnahmebehandlung Konstruktor template <class T> Matrix: : Matrix(uint a. Dim) : f. Dim(a. Dim) { if (f. Dim == 0) throw Matrix. Zero. Dimension(); f. Elem = new T* [f. Dim]; if (f. Elem == 0) throw Matrix. Memory. Exceeded(); for (uint i = 0; i < f. Dim; i++) { f. Elem[i] = new T[f. Dim]; if (f. Elem[i] == 0) throw Matrix. Memory. Exceeded(); } } Destruktor template <class T> Matrix: : ~Matrix() { for (uint i = 0; i < f. Dim; i++) delete[] f. Elem[i]; delete[] f. Elem; } G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 26

Fallstudien Kapitel 15 kopieren Kopierkonstruktor template <class T> Matrix: : Matrix(const Matrix& a. Mat)

Fallstudien Kapitel 15 kopieren Kopierkonstruktor template <class T> Matrix: : Matrix(const Matrix& a. Mat) : f. Dim(a. Mat. f. Dim) { if (f. Dim == 0) throw Matrix. Zero. Dimension(); f. Elem = new T* [f. Dim]; if (f. Elem == 0) throw Matrix. Memory. Exceeded(); for (uint i = 0; i < f. Dim; i++) { f. Elem[i] = new T[f. Dim]; if (f. Elem[i] == 0) throw Matrix. Memory. Exceeded(); } for (uint i = 0; i < f. Dim; i++) for (uint j = 0; j < f. Dim; j++) f. Elem[i][j] = a. Mat. f. Elem[i][j]; } Speicherallokation Schablone MATRIX Multiplikation mit vernünftiger Ausnahmebehandlung G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 27

Fallstudien Kapitel 15 Schablone MATRIX Multiplikation mit vernünftiger Ausnahmebehandlung template <class T> void Matrix:

Fallstudien Kapitel 15 Schablone MATRIX Multiplikation mit vernünftiger Ausnahmebehandlung template <class T> void Matrix: : Set(uint a. Row, uint a. Col, T a. Val) { if (a. Row >= f. Dim || a. Col >= f. Dim) throw Matrix. Index. Overflow(); f. Elem[a. Row][a. Col] = a. Val; } template class <T> double Matrix: : Get(uint a. Row, uint a. Col) { if (a. Row >= f. Dim || a. Col >= f. Dim) throw Matrix. Index. Overflow(); return f. Elem[a. Row][a. Col]; } G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 28

Fallstudien Kapitel 15 Schablone MATRIX Multiplikation mit vernünftiger Ausnahmebehandlung template <class T> void Matrix:

Fallstudien Kapitel 15 Schablone MATRIX Multiplikation mit vernünftiger Ausnahmebehandlung template <class T> void Matrix: : Mult(const Matrix& a. Mat) { if (a. Mat. f. Dim != f. Dim) throw Matrix. Incompatible. Dimensions(); Matrix t. Mat(*this); for (uint i = 0; i < f. Dim; i++) for (uint j = 0; j < f. Dim; j++) { T sum = 0. 0; for (uint k = 0; k < f. Dim; k++) sum += t. Mat. Get(i, k) * a. Mat. f. Elem[k][j]; f. Elem[i][j] = sum; } } G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 29

Kapitel 15 Fallstudien class A { private: int a; public: A(int a); int Get_a();

Kapitel 15 Fallstudien class A { private: int a; public: A(int a); int Get_a(); void Show(bool cr = true); }; Klassenhierarchie Erzwingen der Verwendung des Konstruktors der Oberklasse: Attribute durch private schützen, Zugriff nur durch public Methoden! ) class B : public A { private: int b; public: B(int a, int b); int Get_b(); void Show(bool cr = true); }; ) class C : public B { private: int c; public: C(int a, int b, int c); int Get_c(); void Show(bool cr = true); }; G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 30

Fallstudien Kapitel 15 A: : A(int aa) : a(aa) {} int A: : Get_a()

Fallstudien Kapitel 15 A: : A(int aa) : a(aa) {} int A: : Get_a() { return a; } void A: : Show(bool cr) { cout << a << ' '; if (cr) cout << endl; } B: : B(int aa, int bb) : A(aa), b(bb) {} int B: : Get_b() { return b; } void B: : Show(bool cr) { A: : Show(false); cout << b << ' '; if (cr) cout << endl; } C: : C(int aa, int bb, int cc) : B(aa, bb), c(cc) {} int C: : Get_c() { return c; } void C: : Show(bool cr) { B: : Show(false); cout << c << ' '; if (cr) cout << endl; } a(aa) G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 31

Fallstudien Kapitel 15 Test int main(void) { A a(1); B b(1, 2); C c(1,

Fallstudien Kapitel 15 Test int main(void) { A a(1); B b(1, 2); C c(1, 2, 3); a. Show(); b. Show(); c. Show(); Ausgabe C c 2(2*c. Get_a(), 2*c. Get_b(), 2*c. Get_c()); c 2. Show(); return 0; } G. Rudolph: Einführung in die Programmierung ▪ WS 2009/10 32