eini-i einführung in die informatik für naturwissenschaftler und ingenieure i kapitel 10 claudio...
TRANSCRIPT
EINI-IEINI-IEinführung in die Informatik Einführung in die Informatik für Naturwissenschaftler und für Naturwissenschaftler und
Ingenieure IIngenieure I
Kapitel 10
Claudio Moraga; Gisbert Dittrich
FBI Unido
2
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Gliederung Kapitel 10Gliederung Kapitel 10
• Beispiel: Warteschlange– Ansatz zur Realisierung– struct Warteschlange, Impl. von Operationen– Benutzung von "Warteschlange"
• Warteschlange als ADT (abstrakter Datentyp)– private - public– Neuimplementierung mit Anmerkungen– Anmerkung zu ADTs
• Breitensuche in binären Bäumen – unter Verwendung von Warteschlangen
3
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Realisierung von WarteschlangenRealisierung von Warteschlangen
• Arbeitsweise – Initialisierung– Einfügen von Elementen am Ende – Entfernen von Elementen am Anfang
• ausgezeichnete Elemente Kopf und Fuß• Liste von Elementen
– (möchte mich nicht am Anfang auf eine feste Anzahl von Elementen festlegen; sonst: Feld möglich)
4
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Realisierung von WarteschlangenRealisierung von Warteschlangen
• Operationen:– Einfügen am Ende– Entfernen am Anfang– Initialisierung - .............
• Wunsch nach Verkapselung: – Daten und Operationen zusammen behandeln
• Annahme: Nutzelemente sind natürliche Zahlen. • Also Listenelemente: struct IntListe { int Element; IntListe * weiter;};
5
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Zur RealisierungZur Realisierung
DieListe
Kopf Fuss
struct Warteschlange {IntListe * DieListe;IntListe * Kopf, * Fuss;
Einfuegen(int) IntListe * Einfuegen(int);
Entfernen() IntListe * Entfernen();
Init() IntListe * Init();
DerKopf() int DerKopf();
ListenDruck(...)
Warteschlange
void ListenDruck(ofstream *);
};
6
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
KonsequenzKonsequenz
• Kapselung: Gemeinsames Deklarieren von– Daten für die Operationen – Signatur der Operationen auf den Daten
• Vorteile:– alle Eigenschaften in einer einzigen Struktur
(hier: des Datentyps Warteschlange)
– -->:• Lokalität der Änderungen
• Übersichtlichkeit
• Verständlichkeit
7
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Vereinbarung der WarteschlangeVereinbarung der Warteschlange
• Problem: – Es fehlt noch der Code für die Operationen.
• Lösung:– Der Code wird getrennt von der struct-Definition angegeben.
• In Analogie zu: – Angabe der Signatur der benutzten Funktionen als
Funktionsprototypen, davon getrennte Angabe des Codes.
8
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
VereinbarungVereinbarung
IntListe * Warteschlange::Init() {DieListe = Kopf = Fuss = NULL;return DieListe;};
Typ des Rückgabewerts
Name des Typs
Name der Funktion
“das zum TypWarteschlange gehörende Init”
9
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
AnmerkungenAnmerkungen
• struct bildet Namensraum:– Die in der struct-Definition definierten Namen
(z. B. Kopf, Fuss) sind hier sichtbar.
• Bei Definition einer Funktion muß der Name der struct mit angegeben werden, um die Zuordnung zu ermöglichen .– Z.B. kann Init ja auch bei anderen Typen
vorkommen.
10
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Weitere BeispieleWeitere Beispiele
int Warteschlange::DerKopf() {return
(DieListe == NULL ? -1 : DieListe->Element);};
void Warteschlange::ListenDruck(ofstream *aus) {IntListe * Laeufer = Kopf;*aus << endl;while (Laeufer != NULL) {
*aus << Laeufer->Element << " # ";Laeufer = Laeufer->weiter;}
*aus << endl;};
11
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Weitere BeispieleWeitere Beispiele
IntListe * Warteschlange::Entfernen() {if (Kopf == NULL)
DieListe = Kopf;else {
if (Kopf == Fuss) {Kopf = Fuss = NULL;}else {
Kopf = Kopf->weiter;}DieListe = Kopf;
}return DieListe;
};
Name einer struct Qualifizierungs-
zeichen
In der struct sichtbare Größen
12
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Benutzung der WarteschlangeBenutzung der Warteschlange
Definition der Warteschlange W
Benutzung der Operationendurch qualifizierten Zugriff
void main() {ofstream *out = new ofstream("aus.aus");Warteschlange W;
W.Init();for (int i=1; i < 10; i++) W.Einfuegen(i);W.ListenDruck(out);
}
13
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
IntListe * Warteschlange::Einfuegen(int i){IntListe *K = new IntListe;K->Element = i;K->weiter = NULL;if (DieListe == NULL){
Kopf = Fuss = K; }
else {Fuss->weiter = K; Fuss = K;
} DieListe = Kopf; return DieListe;
};
Weitere Beispiele
iK
DieListe
Kopf Fuss
Kopf
Fuss
14
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Zugriff über Qualifikation
void main() {ofstream *out = new ofstream("aus.aus");Warteschlange W;
W.Init();for (int i=1; i < 10; i++) W.Einfuegen(i);W.ListenDruck(out); W.Einfuegen(117);*out << "\nNach Einfuegen von 117: " << endl;W.ListenDruck(out);*out << "\nKopf: " << W.DerKopf() << endl;W.Entfernen();*out<<"\nNach Entfernen des ersten Elements: "<<endl;W.ListenDruck(out);*out << "\nKopf: " << W.DerKopf() << endl;
}
Definition der Warteschlange
15
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
1 # 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 #
Nach Einfuegen von 117:
1 # 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 # 117 #
Kopf: 1
Nach Entfernen des ersten Elements:
2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 # 117 #
Kopf: 2
Programm
Ausgabe
16
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
BeobachtungenBeobachtungen
• Die "Interna" (hier: Kopf, Fuss, DieListe) werden "außen" überhaupt nicht benötigt.
• Diese Interna könnten/sollten privat, d.h. verborgen bleiben
• Zugriff von außen nur über die entsprechenden Operationen
17
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
//// 10_1_Warteschlange Version 1// demonstriert Warteschlangen//
#include <iostream.h>#include <stdlib.h>#include <fstream.h>
const int maxLen = 70;
struct IntListe {int Element;IntListe * weiter;};
1
18
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
struct Warteschlange {IntListe * DieListe;IntListe * Einfuegen(int);IntListe * Entfernen();IntListe * Init();int DerKopf();void ListenDruck(ofstream *);IntListe * Kopf, * Fuss;};
IntListe * Warteschlange::Init() {DieListe = Kopf = Fuss = NULL;return DieListe;};
2
19
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
int Warteschlange::DerKopf() {return (DieListe == NULL? -1 : DieListe->Element);};
IntListe * Warteschlange::Einfuegen(int i) {IntListe * K = new IntListe;K->Element = i;K->weiter = NULL;if (DieListe == NULL){
Kopf = Fuss = K;}else {
Fuss->weiter = K;Fuss = K;}
DieListe = Kopf; return DieListe;
};3
20
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
IntListe * Warteschlange::Entfernen() {if (Kopf == NULL){
DieListe = NULL;return NULL;}
else {if (Kopf == Fuss) {Kopf = Fuss = NULL;}else {
Kopf = Kopf->weiter;}DieListe = Kopf;return DieListe;}
};void Warteschlange::ListenDruck(ofstream *aus) {
IntListe * Laeufer = Kopf;*aus << endl;while (Laeufer != NULL) {
*aus << Laeufer->Element << " # ";Laeufer = Laeufer->weiter;}
*aus << endl;}; // 4
21
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
int main() {ofstream *out = new ofstream("aus.aus");Warteschlange W;
W.Init();for (int i=1; i < 10; i++) W.Einfuegen(i);W.ListenDruck(out);W.Einfuegen(117);*out << "\nNach Einfuegen von 117: " << endl;W.ListenDruck(out);*out << "\nKopf: " << W.DerKopf() << endl;W.Entfernen();*out << "\nNach Entfernen des ersten Elements:"<< endl;W.ListenDruck(out);*out << "\nKopf: " << W.DerKopf() << endl;
return 0;} // 5
22
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Abstrakter DatentypAbstrakter Datentyp
• Warteschlange als eine Art Datenkapsel mit– internem Zustand (Kopf, Fuss, DieListe)
– Zugriffsoperationen (Einfuegen etc.)
– Zustand von außen nur über Zugriffsfunktionen änderbar, nicht direkt!
23
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
innererZustand
(verborgen)
Zugriff und Änderungnur durch wohldefinierteOperationen
24
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Operationen auf Warteschlangen Operationen auf Warteschlangen
DieListe
Kopf Fuss
Einfuegen(int)
Entfernen()
Init()
DerKopf()
ListenDruck(...)
privatöffentlich
25
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
NeudeklarationNeudeklaration
struct Warteschlange {private:
IntListe * DieListe;IntListe * Kopf, * Fuss;
public:void Einfuegen(int);void Entfernen();void Init();int DerKopf();void ListenDruck(ofstream *);
};
neu
beachte:void
Programm
26
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
AnmerkungenAnmerkungen
• public – bewirkt, daß auf die darauf folgenden Namen von
außen zugegriffen werden darf; dies geschieht durch Qualifikation.
• private – bewirkt, daß die darauf folgenden Namen vor dem
expliziten Zugriff von außen (durch Qualifikation) geschützt sind.
27
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
BeispielBeispiel
• Warteschlange W sei definiert• Legal sind z.B.:
– W.Init()– W.Einfuegen(45)– W.DerKopf()
• Illegal sind z.B.:- W.Kopf- W.DieListe- W.Fuss
28
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Ein Rückgabewert impliziert die Weitergabe von interner Strukturinformation nach außen.
Dies kann unerwünscht sein.
--> Datenkapselung.
Wieso void? Wieso void?
29
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
void Warteschlange::Einfuegen(int i) {IntListe *K = new IntListe;K->Element = i;K->weiter = NULL;if (DieListe == NULL){
Kopf = Fuss = K;}
else {Fuss->weiter = K;Fuss = K;
} DieListe = Kopf;
};
Änderungen:Typ der
Rückgabe wird void;returneliminiert
Änderungen:Typ der
Rückgabe wird void;returneliminiert
IntListe * Warteschlange::Einfuegen(int i){IntListe *K = new IntListe;K->Element = i;K->weiter = NULL;if (DieListe == NULL){
Kopf = Fuss = K; }
else {Fuss->weiter = K; Fuss = K;
} DieListe = Kopf; return DieListe;
};
30
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Anmerkung: „Trick“Anmerkung: „Trick“
• Kopf ist als privat deklariert– auf Kopf kann also von außen nicht zugegriffen
werden,
– kann also Kopf weder lesen noch von außen verändern.
• Trick: definiere eine öffentliche Zugriffsfunktion DerKopf()– damit kann ich den Wert von Kopf lesen
– analog: schreiben.
31
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Warteschlange als Warteschlange als abstrakter Datentypabstrakter Datentyp
• Warteschlange wurde hier als
abstrakter Datentyp (ADT) definiert.• ADTs sind charakterisiert durch
– Offenlegen der Schnittstellen (Signaturen)– Verbergen der Implementation
(d.h. Zugriff nur über wohldefinierte Operationen)
• Wichtige Konstruktion in der Softwaretechnik, insb. im objektorientierten Entwurf. Wichtig im nächsten Semester.
32
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
//// 10_2_Warteschlange_2// demonstriert Warteschlangen// mit private/public Komponenten//
#include <iostream.h>#include <stdlib.h>#include <fstream.h>
const int maxLen = 70;
struct IntListe {int Element;IntListe * weiter;};
// 1
33
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
struct Warteschlange {private:
IntListe * DieListe;IntListe * Kopf, * Fuss;
public:void Einfuegen(int);void Entfernen();void Init();int DerKopf();void ListenDruck(ofstream *);
};
void Warteschlange::Init() {DieListe = Kopf = Fuss = NULL;};
int Warteschlange::DerKopf() {return (DieListe == NULL? -1 :DieListe->Element);}; // 2
34
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
void Warteschlange::Einfuegen(int i) {IntListe *K = new IntListe;K->Element = i;K->weiter = NULL;if (DieListe == NULL){
Kopf = Fuss = K;}
else {Fuss->weiter = K;Fuss = K;}
DieListe = Kopf;};// 3
35
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
void Warteschlange::Entfernen() {if (Kopf == NULL){
DieListe = NULL;}else {
if (Kopf == Fuss) {Kopf = Fuss = NULL;}else {
Kopf = Kopf->weiter;}DieListe = Kopf;}};
void Warteschlange::ListenDruck(ofstream *aus) {IntListe * Laeufer = Kopf;*aus << endl;while (Laeufer != NULL) {
*aus << Laeufer->Element << " # ";Laeufer = Laeufer->weiter;}
*aus << endl;}; // 4
36
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
int main() {ofstream *out = new ofstream("aus.aus.neu");Warteschlange W;
W.Init();for (int i=1; i < 10; i++) W.Einfuegen(i);W.ListenDruck(out);W.Einfuegen(117);*out << "\nNach Einfuegen von 117: " << endl;W.ListenDruck(out);*out << "\nKopf: " << W.DerKopf() << endl;W.Entfernen();*out << "\nNach Entfernen des ersten Elements: "<< endl;W.ListenDruck(out);*out << "\nKopf: " << W.DerKopf() << endl;return 0;
}// 5
37
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Zurück zur BreitensucheZurück zur Breitensuche
• Strategie– Verwendung einer Warteschlange Q, die aus Knoten
des Baums besteht,– Füge zunächst den Wurzelknoten in Q ein,
• der Kopf K von Q wird gedruckt.• nach dem Druck:
– ist K.LSohn != NULL, so wird dieser Knoten in Q eingefügt,
– ist K.RSohn != NULL, so wird dieser Knoten in Q eingefügt,
• das geschieht solange, bis Q leer ist
38
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Änderung imTyp des Listen-
elements
Anpassung der Datentypen
struct BinBaum {char text[maxLen];int zaehler;BinBaum * LSohn, *RSohn;
};struct BaumListe {
BinBaum * Element;BaumListe * weiter;};
struct Warteschlange {private:
BaumListe * DieListe;BaumListe * Kopf, * Fuss;
public:void Einfuegen(BinBaum *);void Entfernen();void Init();
int IstLeer();BinBaum * DerKopf();
};
39
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Zentrale ProzedurZentrale Prozedur
void KnotenDruck(BinBaum *, ofstream *);void BreitenSuche(BinBaum *K, ofstream *aus) {
Warteschlange W;
W.Init();W.Einfuegen(K);while (!W.IstLeer()) {
BinBaum *L = W.DerKopf();W.Entfernen();W.Einfuegen(L->LSohn);W.Einfuegen(L->RSohn);KnotenDruck(L, aus);
}}
Programm:
40
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
// 10_3_Breitensuche// demonstriert Breitensuche in einem// binaeren Suchbaum.//#include <iostream.h>#include <fstream.h>#include <string.h>
const int maxLen = 70;
struct BinBaum {char text[maxLen];int zaehler;BinBaum * LSohn, *RSohn;
};struct BaumListe {
BinBaum * Element;BaumListe * weiter;}; // 1
41
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
// 10_3_Breitensuche Forts.struct Warteschlange {
private:BaumListe * DieListe;BaumListe * Kopf, * Fuss;
public:void Einfuegen(BinBaum *);void Entfernen();void Init();
bool IstLeer();BinBaum * DerKopf();
};BinBaum * Einlesen(ifstream *); // Funktionsprototypenvoid BreitenSuche(BinBaum *, ofstream *); void InOrder(BinBaum *, ofstream *);BinBaum * Einfuegen(BinBaum *, char *);void KnotenDruck(BinBaum *, ofstream *);void Schreiben(char *, int, ofstream *);
// 2
42
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
// 10_3_Breitensuche Forts.void Warteschlange::Init() {
DieListe = Kopf = Fuss = NULL;}
BinBaum * Warteschlange::DerKopf() { return (DieListe == NULL? NULL : DieListe->Element);}
void Warteschlange::Einfuegen(BinBaum * B) {if (B != NULL) {
BaumListe *K = new BaumListe;K->Element = B;K->weiter = NULL;if (DieListe == NULL)
Kopf = Fuss = K;else {
Fuss->weiter = K; Fuss = K;}DieListe = Kopf;}} // 3
43
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
// 10_3_Breitensuche Forts.
void Warteschlange::Entfernen() {if (Kopf == NULL){
DieListe = NULL;}else {
Kopf = Kopf->weiter;}DieListe = Kopf;
}
bool Warteschlange::IstLeer() {return (DieListe == NULL? true: false);}
// 4
44
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
// 10_3_Breitensuche Forts.
main() {BinBaum * BST;ifstream *EingabeDatei;ofstream *BreitAusgabeDatei =
new ofstream("breit.doc");ofstream *TiefAusgabeDatei =
new ofstream("tief.doc");
EingabeDatei = new ifstream("Beweis.txt"); BST = Einlesen(EingabeDatei);InOrder(BST, TiefAusgabeDatei);BreitenSuche(BST, BreitAusgabeDatei);
}// 5
45
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
// 10_3_Breitensuche Forts.
BinBaum * Einlesen(ifstream *inp) {
BinBaum *bst = NULL;char gelesen[maxLen];
*inp >> gelesen;while (!(*inp).eof()) {
bst = Einfuegen(bst, gelesen);*inp >> gelesen;
}return bst;
}
// 6
46
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
// 10_3_Breitensuche Forts.
BinBaum * Einfuegen(BinBaum *B, char * k) {
if (B == NULL) {BinBaum *Hilf = new BinBaum;strcpy(Hilf->text, k);Hilf->zaehler = 1;
Hilf->LSohn = Hilf->RSohn = NULL;B = Hilf;}
else {int Vergl = strcmp(B->text,k);if (Vergl < 0)
B->RSohn = Einfuegen(B->RSohn, k);else if (Vergl > 0)
B->LSohn = Einfuegen(B->LSohn, k);else if (Vergl == 0)
B->zaehler += 1;}return B;} // 7
47
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
// 10_3_Breitensuche Forts.
void BreitenSuche(BinBaum *K, ofstream *aus) {// void KnotenDruck(BinBaum *, ofstream *);Warteschlange W;
W.Init();W.Einfuegen(K);while (!W.IstLeer()) {
BinBaum *L = W.DerKopf();W.Entfernen();W.Einfuegen(L->LSohn);W.Einfuegen(L->RSohn);KnotenDruck(L, aus);
}}
// 8
48
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
// 10_3_Breitensuche Forts.
void InOrder(BinBaum *K, ofstream *aus) {
if (K != NULL) {InOrder(K->LSohn, aus);KnotenDruck(K, aus);InOrder(K->RSohn, aus);}
}void KnotenDruck(BinBaum *T, ofstream *aus){
Schreiben(T->text, T->zaehler, aus);}
void Schreiben(char * s, int k, ofstream *aus) {*aus << k << "\t\t\t" << s << endl;
}// 9
49
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Suche in WWW-Seiten.Suche in WWW-Seiten.
K1K1.1
K1.2
K1.3
K1.1.1
K1.1.2
K1.1.3 usw.
Weitere Anwendung:WWW-Seite enthält eingebettete Links. Annahme: in Kapiteln organisiertes "Buch".
50
Kap 10: Warteschlange als ADTVorl “EINI-I"
22.1.2001
Hierarchische StrukturHierarchische Struktur
Breitensuche: liest erst alle Kapitelköpfe, bevor die einzelnenUnterkapitel gelesen werden (z.B. Überblick)
Tiefensuche: geht in die Tiefe, z. B. gezieltere Suche
ETC.
K1
K1.1 K1.2
K1.1.1 K1.1.2 K1.1.3