Grundgebiete der Informatik 2: Algorithmen und Programmiertechniken Tutorium zur Klausurvorbereitung RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 1 Termine 2. Teil des Tutoriums und Lösungsvorschlag zu Blatt 12: am 18.07.2006, 15:00 Uhr AH 5 Letzte Fragestunde: am 14.07.2006, 14.30 Uhr AH 5 Scheine: nach Ankündigung auf den Internetseiten des Lehrstuhls i3 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 2 Klausurtermine Termine: 20.07., 14.30 Uhr, 05.09., 13.30 Uhr Fachrichtung/DPO Teil Termin ET/TI (DPO 4) 1 (Kraiss) 05.09.2006 ET/TI (DPO 4) 2 (Nagl) 20.07.2006 ET/TI (DPO 98) 1+2 (Kraiss + Nagl) 05.09.2006 Wirt.-Ing. Elekt. Energiet. (DPO 3) 2 (Nagl) 20.07./05.09. Mag. TR 2. Hauptfach ET (DPO 1) 1 (Kraiss) 05.09.2006 Mag. TR 2. Hauptfach ET (DPO 1) 2 (Nagl) 20.07.2006 Lehramt (SII, ET) 1+2 (Kraiss + Nagl) 05.09.2006 ET/TI (DPO 87) (Kraiss + Nagl + Walke) mündl. Prüf. ET/TI (DPO 4) Nachholklausur für den 20.07. 2 (Nagl) 13.09.2005 Hörsaalverteilung kurzfristig auf www-i3.informatik.rwth-aachen.de/ggdi RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 3 EBNF • • • • Gibt mögliche Programmstruktur vor Darstellungsform für kontextfreie Grammatiken Äquivalent zu Syntaxdiagrammen Sequenz, Option [ ], Wiederholung { }, Alternative |, Rekursion number ident factor ( expression ! factor ) Rekursion factor ::= number | ident | ( expression ) | ! factor NichtterminalSymbol RWTH Aachen – Lehrstuhl für Informatik 3 Metasymbole der EBNF TerminalSymbol Grundlagen der Informatik: Algorithmen und Programmiertechniken 4 Ableiten eines Worts aus einer EBNF • Wort: Folge von Terminalsymbolen, die durch Anwendung von Regeln einer Grammatik/EBNF erzeugt wurde • Beispiel bezieht sich auf EBNF aus Aufgabe 1 if ( a + b == !c) { cout << "test"; } 1 if ( expression ) { statementList } 2 6 if ( simpleExpression relation simpleExpression ) { statement } 4 3 4 8 if ( factor addOperator factor == factor) { cout << string; } 5 7 5 5 if (ident + ident == if (ident + ident == RWTH Aachen – Lehrstuhl für Informatik 3 ! factor ) { cout << string; } 5 ! ident) { cout << string; } Grundlagen der Informatik: Algorithmen und Programmiertechniken 5 Ebenen der Syntax & Semantik • Lexikalische Syntax: Schlüsselwörter, Bezeichner, Literale, Begrenzer, ... EBNF • Kontextfreie Syntax (Aufbausyntax): Beschreibt Aufbau eines Programms Ausdrücke, Anweisungen, Deklarationen, Programmstruktur • Kontextsensitive Syntax: Beschreibt Beziehungen zwischen Teilen eines Programms • Semantik: Beschreibt die Bedeutung der Elemente, aus denen ein Programm aufgebaut ist RWTH Aachen – Lehrstuhl für Informatik 3 Umgangssprachlich Umgangssprachlich Grundlagen der Informatik: Algorithmen und Programmiertechniken 6 Beispiel für Ebenen der Syntax #include <iostream.h> int summiere(int a, int b) { return a + b ; } int main() { int a, b, summe ; cin >> a >> b; summe = summiere(a,b); cout << summe << endl; } Lexikalische Syntax • Literale: 1.8e6 ; ``Hallo`` • Schlüsselworte: int, return • Bezeichner: summiere, a, b • Begrenzer: ; { } ( ) space tab • Kommentare: Eine lexikalische Einheit, die aber ignoriert wird Kontextfreie Syntax Ausdrücke Deklarationen Anweisungen Programmstruktur Kontextsensitive Syntax Zur Deklaration RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 7 Alte Klausuraufgabe 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include "iostream" using namespace std; void StraightInsertion(char ffeld[], int start, int ende) { int j; char elem for (int i=start+1; i<=ende, i++) { // aktuelles Element merken elem=ffeld[k]; /* an der richtigen Stelle in den bereits sortierten Anfang Einfuegen */ j=i; while ((j>start) & (elem<ffeld[j-1]) { ffeld[j] = ffeld[j-1]; j--; } ffeld[j] = elem; } } RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 8 Alte Klausuraufgabe 4 void StraightInsertion(char ffeld[], int start, int ende){ … 21 22 23 24 25 26 27 28 29 30 31 … } int main() { char feld[] ={ 'v', k, 'a', 'h', 'j', 'l', 'e', 'b'}; StraightInsertion(*feld, 0, 7); for (int i=0;i<8;i++) { cout << feld[i] << ' '; } return 0; } RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 9 Kontrollstrukturen • Fallunterscheidungen if ( zahl > 0 ) { // Anweisungsfolge } Einseitig bedingte Anweisung if ( zahl > 0 ) { // Anweisungsfolge } else { // Alternative A. } Zweiseitig bedingte Anweisung RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 10 Kontrollstrukturen • Auswahlanweisung enum Wochentag { Mo, Di, Mi, Do, Fr, Sa, So }; Wochentag Tag; switch ( Tag ) { case Mo: // Anweisungen break; case Di: case Mi: // Anweisungen break; default: // Anweisungen break; } RWTH Aachen – Lehrstuhl für Informatik 3 Fall „Mo“ Fälle ‚ „Di“ und „Mi“ Alle anderen Fälle (optional) Grundlagen der Informatik: Algorithmen und Programmiertechniken 11 Kontrollstrukturen • Schleifen – Wiederholte Ausführung einer Anweisungsfolge (Block) – Unterscheidung • Anzahl der Iterationen bekannt for-Schleife // Berechnung der Fakultät int eingabe, fakultaet = 1; cin >> eingabe; for ( int i=1; i < eingabe; i++ ) { fakultaet *= i; } • Anzahl der Iterationen unbekannt while-Schleife // Reaktion auf Messfuehler while ( Messfuehler.GibWert() > 0 ) { cout << "Aktueller Wert: " << Messfuehler.GibWert() << endl; } cout << "Wert ist nicht mehr positiv!" << endl; RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 12 Prozedur vs. Funktion vs. Methode • Prozedur – – – – Führt eine Anweisungsfolge aus Basiert auf Parametern, verändert diese gegebenenfalls Kein Rückgabewert Beenden der Prozedur durch return; (optional) void Ausgabe( int a ) { cout << a << endl; } • Funktion – Wie Prozedur, aber: – Hat Rückgabewert ungleich void – Beenden der Funktion & Rückgabe durch return-Anweisung int Eingabe() { int eingabe; cin >> eingabe; // Auf Groß-/Kleinschreibung achten! return eingabe; } • Methode – Gehört zu einer Klasse (bspw. ADT) "member function" – Kann Prozedur oder Funktion sein – Durch Klassenzugehörigkeit: Zugriff auf private Klassen-Elemente RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 13 Variablen, Pointer, Referenzen Prinzipiell • Pointer varTyp varBezeichner; – Deklaration: Vor jedem Var.-Bezeichner * • Referenzen – Deklaration: Vor jedem Var.-Bezeichner – Muss direkt initialisiert werden & • Dereferenzierung: * "Folgt dem Zeiger" • Adresse von: & "Liefert Zeiger auf" int a; int *pa; int &ra = a; // Integer-Variable, Name:"a" // Pointer/Zeiger auf Integer-Variable // Referenz auf Integer-Variable pa = &a; // Pointer "pa" zeigt nun auf "a" a = 10; cout << a; *pa = 20; cout << a; ra = 30; cout << a; RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 14 Parameterübergabe: Beispiel Call by Reference Call by Value #include "iostream.h" void f(int &x, int y, int *z) { y++; x=*z+y; x++; ++(*z); } a b c vor 1. Aufruf 1 2 3 nach 1. Aufruf 7 2 4 nach 2. Aufruf 8 2 5 int main() { int a=1, b=2, c=3; f(a, b, &c); //1. Aufruf cout << "1. Aufruf: " << a << b << c << char(13) << char(10); f(a, b, &c); //2. Aufruf cout << "2. Aufruf: " << a << b << c << char(13) << char(10); return 0; } RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 15 Datentypen: vordefinierte, Typdeklaration • Vordefinierte Typen (Beispiele): [unsigned] int, char, [unsigned] double, short, float, ... Objektdeklaration double dbl; • Arrays: int i[41]; int *i[41]; Objektdeklarationen • Typdeklaration: typedef int *pIntT; • Verwendung: pIntT pi; RWTH Aachen – Lehrstuhl für Informatik 3 Objektdeklaration Grundlagen der Informatik: Algorithmen und Programmiertechniken 16 Datentypen: Arrays, Strukturen, ... • Aufzählungstypen [typedef] enum Werktag {di, mi}; • Arrays typedef int* IntPtrFeld[41]; Typdeklaration • Strukturen [typedef] struct MyStruct { int i; MyStruct* next; }; • Verwendung MyStruct aStruct; IntPtrFeld anArray; RWTH Aachen – Lehrstuhl für Informatik 3 Objektdeklarationen Grundlagen der Informatik: Algorithmen und Programmiertechniken 17 Datentypen: komplexes Beispiel struct MyStruct { int i; SomeType* info; }; typedef MyStruct ComplexArray[7]; ComplexArray anArray; 1 27 3 8 5 22 53 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 18 Speicherallokation und Freigabe • Speicher auf dem Heap allokieren: iPtr int* iPtr; iPtr=new int; *iPtr=42; ... • Allokierten Speicher wieder freigeben: delete iPtr; iPtr iPtr=NULL; RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 19 Datentypen: Zugriff auf Strukturkomponenten struct MyStruct { int i; MyStruct* next; }; MyStruct s; MyStruct *ps; ps=&s; s.i=9; (*ps).i=9; ps->i=9; RWTH Aachen – Lehrstuhl für Informatik 3 s->i=9; //falsch ps.i=9; //falsch Grundlagen der Informatik: Algorithmen und Programmiertechniken 20 Datenstrukturen: Verkettete Liste struct lElemT{ int value; lElemT *next; }; head lElemT* head; ... head=NULL; Laufzeiger 3 9 77 z.B. Element einfügen newElem z head 122 37 // z: Einfuegestelle lElemT *newElem=new lElemT; newElem->value=37; 3 9 77 122 newElem->next=z->next; z->next=newElem; RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 21 Graphrealisierungen 2 1 1 3 2 3 • knotenorientiert – Adjazenzlisten = Liste von Knoten, jeder Knoten hat Liste seiner Nachfolger 1 2 3 • sequentiell • verkettet – charakteristische Adjazenzmatrix = Matrix, Knoten in Zeilenund Spaltenüberschriften, Kantengewichte bzw. 1/0 in Zellen • kantenorientiert – Kantenlisten 2 3 3 1 1 1 1 1 2 3 1 2 3 1 1 2 • sequentiell 2 3 3 • verkettet – charakteristische Inzidenzmatrix = Knoten in Zeilenüberschriften, Kanten in Spaltenüberschriften 1 2 1 -1 -1 2 1 3 RWTH Aachen – Lehrstuhl für Informatik 3 2 3 3 -1 1 1 Grundlagen der Informatik: Algorithmen und Programmiertechniken 22 Sortierenalgorithmen RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 23 Aufwandsabschätzung in O-Notation • O-Notation – Gibt Größenordnung an – Abstrahiert von "unwichtigen" Details/Faktoren – Oft Abschätzung für besten, mittleren und schlechtesten Fall z.B.: • Quadratischer Aufwand: an bn c a·log(n)+c 2 • Logarithmischer Aufwand: 2 O(n ) O(log(n)) • Linearer Aufwand an c O (n) • Konstanter Aufwand c O(1) RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 24 Sortierverfahren (1) Sortieren durch Einfügen (Straight Insertion) Bester Fall: O(n) Mittlerer Fall: O(n²) Schlechtester Fall: O(n²) sortiert Bubblesort "Größte Blase steigt auf" RWTH Aachen – Lehrstuhl für Informatik 3 Bester Fall: O(n) Mittlerer Fall: O(n²) Schlechtester Fall: O(n²) sortiert Grundlagen der Informatik: Algorithmen und Programmiertechniken 25 Sortierverfahren (2) Quicksort a <a Bester Fall: O(n log2 n) Mittlerer Fall: O(n log2 n) Schlechtester Fall: O(n²) a Rekursion! RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 26 Suchverfahren • Lineare Suche: – Laufe von vorne nach hinten bis Element gefunden Bester Fall: O(1) Mittlerer Fall: O(n) Schlechtester Fall: O(n) • Binäre Suche: – Sortierung vorausgesetzt ! – vergleiche mit mittlerem Element: • gleich: gefunden • kleiner: wiederhole Suche in linker Hälfte • größer: wiederhole Suche in rechter Hälfte Bester Fall: O(1) Mittlerer Fall: O(log2 n) Schlechtester Fall: O(log2 n) – wenn Hälfte leer: nicht gefunden RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 27 Module RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 28 Getrennte Übersetzung ausführbares Programm #include "a.h" a.cpp/cc Compile a.obj a.h Link a.h a.h *.h *.cpp/cc RWTH Aachen – Lehrstuhl für Informatik 3 Compile Compile Compile *.obj *.obj *.obj Grundlagen der Informatik: Algorithmen und Programmiertechniken 29 Module Zugriff Schnittstelle Modul Rumpf • Datenabstraktion – abstrahiert von Realisierung der Datenstruktur • Funktionale Abstraktion – abstrahiert vom Algorithmus • Ziele: • Änderungen im Rumpf ohne Auswirkungen auf Verwender, Wartbarkeit • Zergliederung in Teile • Arbeitsteilung • Modul-Test • Entwurf vor Realisierung, Softwarearchitektur RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 30 Modularten • ADO : Abstraktes Daten-Objekt – Datenabstraktion – Exakt ein Objekt zur Laufzeit – Alle Operationen auf diesem Objekt – Allokation/Erzeugung und De-Allokation/Zerstörung durch Laufzeitsystem DA • ADT : Abstrakter Daten-Typ – Datenabstraktion – Schablone, beliebig viele Instanzen zur Laufzeit erzeugbar – Instanz bei jeder Operation angeben – Allokation/Erzeugung und Deallokation/Zerstörung in Verantwortung des Programmierers • FM : Funktionales Modul – Funktionale Abstraktion FA – Transformierendes Modul Funktionsbibliothek – Kein "Gedächtnis" Keine Seiteneffekte RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 31 Realisierung der Modularten (ADO, FM) bool ElementEinfuegen(int Element); HeaderDatei (.h) ADO bool ElementLoeschen(int Element); ... Schnittstelle Rumpf ImplementierungsDatei (.cc/.cpp) static BinBaum baum; //Datenspeicher bool ElementEinfuegen(int wert) { ... } ... FM: ohne Datenspeicher, sonst gleiche Realisierung RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 32 Realisierung der Modularten (ADT) class BinBaum { public: RefKnoten ErzeugeNeuenKnoten(int wert) ... private: ADT IntKnoten* wurzel; Schnittstelle Rumpf ... }; Header-Datei (.h) struct BinBaum::IntKnoten { ... } BinBaum::RefKnoten BinBaum::ErzeugeNeuenKnoten(int wert) { ... } ImplementierungsDatei (.cc/.cpp) RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 33 Funktionales Modul (FM) - Umsetzung //trig.h Header-Datei=Schnittstelle double sinus(double x); double tan(double x); double cos(double x); ... #include "trig.h" double sinus(double x) { ... } .cpp/.cc-Datei=Rumpf double tan(double x) { ... double cos(double x) { ... } RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 34 Beispiel: ADT-BinBaum • ADT-BinBaum: – Realisierung eines ADT BinBaum – Jeder Knoten hat Zeiger auf Vater – Beispiel für Entwicklung einer Datenstruktur • Beispiel für Verwendung des ADT – main • ADO Menge erstellen: – Realisierung mit Hilfe des ADT BinBaum – Menge nutzt BinBaum zur Speicherung • ADO-BinBaum: – selber BinBaum, jetzt als ADO • Beispiel für Verwendung des ADO – main RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 35 Definieren von Datenstrukturen Ziel: Binärer Baum mit Zeiger auf Vater Idee: 3 3 3 3 RWTH Aachen – Lehrstuhl für Informatik 3 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 36 Definieren von Datenstrukturen Konkreteres Modell: 3 3 3 3 RWTH Aachen – Lehrstuhl für Informatik 3 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 37 Definieren von Datenstrukturen Umsetzung in Programmiersprache C++: struct BinBaum::IntKnoten { IntKnoten* vater; int inhalt; 3 IntKnoten* linkesKind; IntKnoten* rechtesKind; }; IntKnoten* wurzel; RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 38 ADT-Umsetzung: Header-Datei // BinBaum.h: Schnittstelle für den ADT BinBaum. class BinBaum { // Der außen verwendete opake Datentyp für Bäume private: struct IntKnoten { int inhalt; IntKnoten* vater; IntKnoten* linkesKind; IntKnoten* rechtesKind; }; "Geheime" Definition von IntKnoten IntKnoten* m_Wurzel; public: typedef IntKnoten* RefKnoten; BinBaum(); // Konstruktor RefKnoten RefKnoten RefKnoten RefKnoten zusätzlicher "opaker" Datentyp zur gezielten Identifikation einzelner Knoten GibWurzel(); GibLinkesKind(RefKnoten vater); GibRechtesKind(RefKnoten vater); GibVater(RefKnoten aktuellerKnoten); Navigation Manipulation RefKnoten ErzeugeNeuenKnoten(int wert); void SetzeWurzel( RefKnoten neueWurzel ); void EinhaengenKnotenLinks( RefKnoten vater, RefKnoten neuesKind ); void EinhaengenKnotenRechts( RefKnoten vater, RefKnoten neuesKind ); void SetzeWert( RefKnoten zuAendernderKnoten, int wert ); int GibWert( RefKnoten zuLesenderKnoten ); ... }; RWTH Aachen – Lehrstuhl für Informatik 3 Zugriff auf Inhalt Grundlagen der Informatik: Algorithmen und Programmiertechniken 39 ADT-Umsetzung: .cpp/.cc-Datei #include "BinBaum.h" BinBaum::RefKnoten BinBaum::ErzeugeNeuenKnoten(int wert) { Methode IntKnoten *knoten = new IntKnoten; gehört zur Klasse BinBaum knoten->inhalt = wert; knoten->vater = NULL; knoten->linkesKind = NULL; knoten->rechtesKind = NULL; Knoten erzeugen Initialisieren, vgl. Definition der Struktur return knoten; } BinBaum::RefKnoten BinBaum::GibLinkesKind(RefKnoten vater) { return vater->linkesKind; aussen } intern darf die Struktur zugegriffen werden RWTH Aachen – Lehrstuhl für Informatik 3 ist Struktur von vater nicht zugreifbar Grundlagen der Informatik: Algorithmen und Programmiertechniken 40 Beispiel: ADT-BinBaum • ADT-BinBaum: – Realisierung eines ADT BinBaum – Jeder Knoten hat Zeiger auf Vater – Beispiel für Entwicklung einer Datenstruktur • Beispiel für Verwendung des ADT – main • ADO Menge erstellen: – Realisierung mit Hilfe des ADT BinBaum – Menge nutzt BinBaum zur Speicherung • ADO-BinBaum: – selber BinBaum, jetzt als ADO • Beispiel für Verwendung des ADO – main RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 41 ADT-Umsetzung: Verwendung #include "BinBaum.h" BinBaum baum; Instanz des ADTs (der Klasse) Aufruf von Methoden der Instanz void main() { BinBaum::RefKnoten kn=baum.ErzeugeNeuenKnoten(42); baum.SetzeWurzel(kn); ... kn=baum.GibLinkesKind(baum.GibWurzel()); cout << baum.GibWert(kn); } Anmerkung: ADT in der Klausur immer als Klasse in der Praxis (und auch in Vorlesung und Übung) auch anders RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 42 Beispiel: ADT-BinBaum • ADT-BinBaum: – Realisierung eines ADT BinBaum – Jeder Knoten hat Zeiger auf Vater – Beispiel für Entwicklung einer Datenstruktur • Beispiel für Verwendung des ADT – main • ADO Menge erstellen: – Realisierung mit Hilfe des ADT BinBaum – Menge nutzt BinBaum zur Speicherung – Nur Schnittstelle verwenden! • ADO-BinBaum: – selber BinBaum, jetzt als ADO • Beispiel für Verwendung des ADO – main RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 43 ADO-Umsetzung: Header Datei Bei ADO: nur öffentliche Schnittstelle = Header-Datei ADO //Menge.h //Realisierung einer Menge basierend auf einem Binärbaum //Fuegt das Element item in die Menge ein //Rueckgabewert: true, wenn erfolgreich // false, wenn item schon Element der Menge bool ElementEinfuegen(int Element); //Entfernt das Element item aus der Menge //Rueckgabewert: true, wenn erfolgreich // false, wenn item nicht Element der Menge bool ElementLoeschen(int Element); Menge ADT BinBaum //Testet, ob item in der Menge enthalten ist //Rueckgabewert: true, wenn ja // false, sonst bool istElement(int Element); //Testet, ob die Menge leer ist //Rueckgabewert: true, wenn ja false, sonst bool istLeer(); RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 44 ADO-Umsetzung: .cpp/.cc-Datei #include "Menge.h" #include "BinBaum.h" BinBaum baum; genau ein Datenobjekt vom Typ BinBaum bool ElementEinfuegen(int wert) { BinBaum::RefKnoten knoten; BinBaum::RefKnoten neuerKnoten; Implementierung von Funktionen if (baum.GibWurzel()==NULL) { //ist der Baum leer? neuerKnoten=baum.ErzeugeNeuenKnoten(wert); baum.SetzeWurzel(neuerKnoten); return true; } else { ... } return false; } ... RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 45 Beispiel: ADT-BinBaum • ADT-BinBaum: – Realisierung eines ADT BinBaum – Jeder Knoten hat Zeiger auf Vater – Beispiel für Entwicklung einer Datenstruktur • Beispiel für Verwendung des ADT – main • ADO Menge erstellen: – Realisierung mit Hilfe des ADT BinBaum – Menge nutzt BinBaum zur Speicherung • ADO-BinBaum: – gleicher BinBaum wie oben, jetzt als ADO • Beispiel für Verwendung des ADO – main RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 46 ADO-Umsetzung (mit Typ): Header-Datei // BinBaum.h: Schnittstelle für den ADO BinBaum. struct IntKnoten; typedef IntKnoten* RefKnoten; RefKnoten RefKnoten RefKnoten RefKnoten Vorabdeklaration des Privaten Typs, Definition folgt im Rumpf GibWurzel(); GibLinkesKind(RefKnoten vater); GibRechtesKind(RefKnoten vater); GibVater(RefKnoten aktuellerKnoten); Verwender kann diesen Typ zum gezielten Zugriff auf einzelne Knoten nutzen RefKnoten ErzeugeNeuenKnoten(int wert); void SetzeWurzel( RefKnoten neueWurzel ); void EinhaengenKnotenLinks( RefKnoten vater, RefKnoten neuesKind ); void EinhaengenKnotenRechts( RefKnoten vater, RefKnoten neuesKind ); void SetzeWert( RefKnoten zuAendernderKnoten, int wert ); int GibWert( RefKnoten zuLesenderKnoten ); ... Methoden-Deklarationen Auch ein ADO kann einen Typ exportieren: • Die eigentliche Datenstruktur (der Baum) existiert nur ein mal => ADO. • Zusätzlich gibt es einen weiteren Typ zur Identifikation von Knoten. RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 47 ADO-Umsetzung(mit Typ): .cpp/.cc-Datei #include "BinBaum.h" struct IntKnoten { int inhalt; IntKnoten *vater, *linkesKind, *rechtesKind; Vollständige Definition des Typs }; IntKnoten* m_Wurzel; Wurzel des Baumes, private Variable RefKnoten ErzeugeNeuenKnoten(int wert){ IntKnoten *knoten = new IntKnoten; knoten->inhalt = wert; knoten->vater = NULL; knoten->linkesKind = NULL; knoten->rechtesKind = NULL; return knoten; } ... RWTH Aachen – Lehrstuhl für Informatik 3 MethodenImplementierungen Grundlagen der Informatik: Algorithmen und Programmiertechniken 48 Beispiel: ADT-BinBaum • ADT-BinBaum: – Realisierung eines ADT BinBaum – Jeder Knoten hat Zeiger auf Vater – Beispiel für Entwicklung einer Datenstruktur • Beispiel für Verwendung des ADT – main • ADO Menge erstellen: – Realisierung mit Hilfe des ADT BinBaum – Menge nutzt BinBaum zur Speicherung • ADO-BinBaum: – selber BinBaum, jetzt als ADO • Beispiel für Verwendung des ADO – main RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 49 Generizität RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 50 Generizität Allgemein • Gewisse „Stellschrauben“ (generische Instanzparameter) in der Realisierung von einzelnen Funktionen oder auch ganzen ADTs offenlassen – Nützlich bei Kollektionen: Stellschrauben sind Eintragstyp und Größe template <class T, int size> class Buffer { public: void enqueue(T x); ... private: T internesFeld[size] ... }; • „Stellschrauben“ werden vom Verwender je nach Bedarf „festgezogen“ (Erzeugung spezieller Typ-Instanzen) typedef Buffer<int, 100> IntBuffer; typedef Buffer<Person*, 20> PersonBuffer; ... IntBuffer myIntBuffer; myIntBuffer.enqueue(42); myIntBuffer.enqueue(„Ich will rein!“); //Fehler Compile-Zeit • Nutzen: Vermeidung von Code-Redundanz (kein Extra-Buffer für jeden Eintragstyp und jede Größe zu implementieren) RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 51 ADT DLList: Schnittstelle (.h) class DLList { public: DLList(); void append(int item); void deleteCurrent(); void deleteIndex(int index); void toStart(); first void toEnd(); void next(); void prev(); int read(); value 24 ... ListItem private: struct ListItem { prev next int value; ListItem *next, *prev; }; ListItem *first; ListItem *last; ListItem *current; current 32 66 last 12 // Zeiger auf das erste Element der Liste // Zeiger auf das letzte Element der Liste // Zeiger auf das aktuelle Element }; RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 52 ADT DLList: Rumpf (.cc) ... void DLList::prev() { if (current == NULL) { cerr << "DLList::prev: current == NULL" << endl; return; } if (current == first) { cerr << "DLList::next: am Anfang der Liste" << endl; return; } current = current->prev; } int DLList::read() { if (current == NULL) return -1; return current->value; } ... RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 53 ADT GenDLList: Schnittstelle (.h) template<class Value_T> class GenDLList { public: GenDLList(); void append(Value_T item); void deleteCurrent(); void deleteIndex(int index); void toStart(); void toEnd(); void next(); void prev(); Value_T read(); Value_T readNext(); ... private: struct ListItem { Value_T value; ListItem *next, *prev; }; ListItem *first; ListItem *last; ListItem *current; // Zeiger auf das erste Element der Liste // Zeiger auf das letzte Element der Liste // Zeiger auf das aktuelle Element }; RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 54 ADT GenDLList: Rumpf (.cc) #ifndef __INC_GenDLList_cc #define __INC_GenDLList_cc ... template<class Value_T> void GenDLList<Value_T>::prev() { if (current == NULL) { cerr << "GenDLList::prev: current == NULL" << endl; return; } if (current == first) { cerr << "GenDLList::next: am Anfang der Liste" << endl; return; } current = current->prev; } template<class Value_T> Value_T GenDLList<Value_T>::read() { if (current == NULL) return NULL; return current->value; } ... #endif RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 55 ADT LecAdm: Schnittstelle (.h) #include „GenDLList.cc“ class LecAdm { public: void AddLecture(std::string lecName); void RemoveLecture(std::string lecName); ... private: // 1. Deklaration der Typ-Instanz 'IntList' typedef GenDLList<int> IntList; students lectures // 2. Deklaration der Verbundtypen // 'Student' und 'Lecture' struct Student { int matNr; std::string name; }; ... name struct Lecture { std::string name; IntList listeners; }; Student matNr „Andy Wand“ „Berhard Diener“ „Mario Ahner“ 1111 2222 3333 name Lecture IntList listeners ... „GgdI2" 1111 2222 „Physik1" ... 2222 3333 ... // 3. Deklaration der Typ-Instanzen 'StudentList' und 'LectureList' typedef GenDLList<Student*> StudentList; typedef GenDLList<Lecture*> LectureList; // 4. Deklaration der Listen (Datenobjekte) 'students' und 'lectures' StudentList students; LectureList lectures; }; RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 56 ADT LecAdm: Rumpf (.cc) #include „LecAdm.h“ void LecAdm::AddLecture(string lecName) { Lecture* newLec = new Lecture; newLec->name = lecName; lectures.append(newLec); } bool LecAdm::AddStudentToLecture(int matNr, string lecName) { lectures.toStart(); while (!lectures.isAtEnd() && lectures.read()->name != lecName) { lectures.next(); } if (lectures.read()->name == lecName) { lectures.read()->listeners.append(matNr); return true; } else { return false; } } ... RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 57 Objektorientierung RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 58 Objektorientierung: Klassen und Vererbung class GraphicObject { private: ... public: virtual void draw(...); } GraphicObject void draw() ... Rectangle void draw() void setUL() void setLR() ... class Rectangle: public GraphicObject { private: ... public: void draw(...); void setUL(int x, int y); void setLR (int x, int y); } RWTH Aachen – Lehrstuhl für Informatik 3 Circle void draw() void setMid() void setRad() ... class Circle: public GraphicObject { private: ... public: void draw(...); void setMid(int x, int y); void setRad(int x, int y); } Grundlagen der Informatik: Algorithmen und Programmiertechniken 59 Objektorientierung: Dynamische Bindung GraphicObject *go; Circle *c; Rectangle *r; GraphicObjectList gl; r=new Rectangle(); r->setUL(10,10); r->setLR(15,25); gl.add(r); class GraphicObject { private: ... public: virtual void draw(...); } speziellste Methode ausführen c=new Circle(); c->setMid(25,30); c->setRad(10); GraphicObjectList GraphicObject* Rectangle gl.add(c); RWTH Aachen – Lehrstuhl für Informatik 3 Circle ... gl.gotoFirst(); while (gl.hasCurrent()) { go=gl.getCurrent(); go->draw(); gl.gotoNext(); } Grundlagen der Informatik: Algorithmen und Programmiertechniken 60 Objektorientierung: Vorsicht mit virtual! class A { public: void f(); virtual void g(); }; class B : public A { public void f(); void g(); }; void A::f() { cout << "f } void A::g() { cout << "g } void B::f() { cout << "f } void B::g() { cout << "g } void main() { A *a; B *b; b=new B(); b->f(); b->g(); a=b; a->f(); a->g(); von A"; } f und g von B kein virtual f von A virtual g von B von A"; Ausgabe: von B"; von B"; RWTH Aachen – Lehrstuhl für Informatik 3 f g f g von von von von B B A B Grundlagen der Informatik: Algorithmen und Programmiertechniken 61 ADO-Umsetzung: Verwendung Es muss keine Instanz angelegt werden, da genau eine Instanz existiert #include "BinBaum.h" void main() { RefKnoten kn=ErzeugeNeuenKnoten(42); SetzeWurzel(kn); ... kn=GibLinkesKind(GibWurzel()); cout << GibWert(kn); } Daher muss auch keine Instanz beim Zugriff angegeben werden Der Typ RefKnoten wird zum Zugriff auf einzelne Knoten genutzt RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 62 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 63 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 64 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 65 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 66 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 67 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 68 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 69 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 70 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 71 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 72 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 73 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 74 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 75 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 76 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 77 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 78 RWTH Aachen – Lehrstuhl für Informatik 3 Grundlagen der Informatik: Algorithmen und Programmiertechniken 79