kw3

Werbung
Weiteres Programm
Studium des Breitendurchlaufs
Hierzu
• zunächst Studium von Warteschlangen
• zuerst einfache Warteschlangen aus ganzen Zahlen
• daraus Abstrakter Datentyp Warteschlange
• Anpassung für Baumknoten
Strategie bei den drei behandelten Durchlaufarten durch
binäre Suchbäume heißt Tiefensuche (es wird zunächst in die
Tiefe und nicht in die Breite gegangen).
Alternative: Breitensuche - trage den Baum schichtenweise ab.
Beispiel:
17
6
4
17 # 6 # 23 # 4 # 7 # 18 # 26
23
7
18
Implementation?
26
Idee:
verwalte die Knoten in einer Warteschlange.
• ein Knoten wird gedruckt
• seine Söhne werden in die Warteschlange
eingefügt
bis die Warteschlange leer ist
Initialisierung der Warteschlange: Wurzel
Beispiel:
17
6
4
23
7
18
26
Realisierung?
Wir machen einen Ausflug
in das Gebiet der Warteschlangen.
Eine Warteschlange arbeitet so:
• Einfügen von Elementen am Ende
• Entfernen von Elementen am Anfang
Vereinfachende Annahme für diese einführende
Diskussion: Elemente sind ganze Zahlen.
Berücksichtigt werden muß:
• ausgezeichnete Elemente Anfang (Kopf) und Ende (Fuß)
• Liste der Elemente (möchte mich nicht am Anfang auf eine
feste Anzahl von Elementen festlegen; sonst: Feld möglich)
• Operationen:
• Einfügen am Ende
• Entfernen am Anfang
• Initialisierung
Wunsch:
möchte Daten und Operationen gern zusammen
betrachten können.
struct IntListe {
int Element;
IntListe * weiter;
};
die bekannte
Listendeklaration.
Aber weiter: Kopf, Fuß und Operationen auf der
Warteschlange?
Idee:
deklariere entsprechende struct.
struct Warteschlange {
DieListe
Kopf
Fuss
Einfuegen(int)
Entfernen()
Init()
DerKopf()
ListenDruck(...)
Warteschlange
IntListe * DieListe;
IntListe * Kopf, *Fuss;
IntListe * Einfuegen(int);
IntListe * Entfernen();
IntListe * Init();
int DerKopf();
void ListenDruck(ofstream *);
};
Damit wird die Signatur der Operationen mit den Daten
für die Operationen gemeinsam deklariert.
Vorteil:
• alle Eigenschaften eines Datentyps (hier: Warteschlange)
sind zusammengefaßt.
• die wesentlichen Operationen, die zu einem Datentyp
gehören, werden mit dem Datentypen vereinbart, d.h.
• Lokalität der Änderungen
• Übersichtlichkeit
• Verständlichkeit
Problem: wir kennen die Signaturen der Operationen.
Was ist mit dem Code?
Der wird getrennt von der struct-Definition vereinbart.
(Analogie:
• Angabe der Signatur der benutzten Funktionen in einer
Funktion,
• davon getrennte Angabe des Code
)
Name des Typs
“das zum Typ
Typ des Rückgabewerts
Warteschlange
gehörende Init”
IntListe * Warteschlange::Init() {
Kopf = Fuss = NULL;
return Kopf;
};
Name der Funktion
IntListe * Warteschlange::Init() {
DieListe = Kopf = Fuss = NULL;
return DieListe;
};
Beachte:
• die in der struct-Definition definierten Namen (Kopf,
Fuss) sind hier sichtbar.
• der Name der struct muß angegeben werden, um die
Zuordnung zu ermöglichen (Init kann ja auch bei anderen
Typen vorkommen).
Weitere Beispiele
Konvention
int Warteschlange::DerKopf() {
return (DieListe == NULL ?
-1 : DieListe->Element);
};
void Warteschlange::ListenDruck(ofstream *aus) {
IntListe * Laeufer = Kopf;
while (Laeufer != NULL) {
*aus << Laeufer->Element << endl;
Laeufer = Laeufer->weiter;
}
};
IntListe * Warteschlange::Entfernen() {
if (Kopf == NULL){
DieListe = Kopf;
return NULL;
else {
if (Kopf == Fuss) {
Kopf = Fuss = NULL;
}
else {
Kopf = Kopf->weiter;
}
DieListe = Kopf
return DieListe;
}
};
IntListe * Warteschlange::Einfuegen(int i) {
IntListe *K = new IntListe;
K->Element = i;
K->weiter = NULL;
if (DieListe == NULL){
Kopf = K;
Kopf->weiter = Fuss;
}
else if (Fuss == NULL){
der Code
Kopf->weiter = K;
müßte bekannt
Fuss = K;
}
sein
else {
Fuss->weiter = K;
Fuss = K;
}
DieListe = Fuss;
return DieListe;
};
void main() {
ofstream *out = new ofstream("aus.aus");
Warteschlange W;
Deklaration der Warteschlange
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: ";
W.ListenDruck(out);
*out << "\nKopf: " << W.DerKopf() << endl;
}
Zugriff über Qualifikation
Ausgabe:
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: prog-21.cpp
Beobachtung:
Eigentlich werden die Interna (Kopf, Fuss, DieListe
etc) überhaupt nicht benötigt.
• Die Interna könnten/sollten privat, d.h. verborgen
bleiben.
• Zugriff von außen nur über die entsprechenden Operationen
• Warteschlange als eine Art Datenkapsel mit
• internen Zustand (Kopf, Fuss, DieListe)
• Zugriffsoperationen (Einfuegen etc.)
• Zustand von außen nicht änderbar
Abstrakter
Datentyp
DieListe
Kopf
Fuss
Einfuegen(int)
privat
Entfernen()
Init()
DerKopf()
ListenDruck(...)
öffentlich
Führt zu folgender Deklaration:
neu
struct Warteschlange {
private:
IntListe * DieListe;
IntListe * Kopf, * Fuss;
public:
void Einfuegen(int);
void Entfernen();
void Init();
int DerKopf();
beachte:
void ListenDruck(ofstream *);
void
};
hierbei:
• public deutet an, daß auf die darauf folgenden Namen
von außen (durch Qualifikation) zugegriffen
werden darf.
• private deutet an, daß die darauf folgenden Namen
vor dem Zugriff geschützt sind
Beispiel: Warteschlange W sei deklariert.
Illegal:
Legal z.B.:
W.Kopf
W.DieListe
W.Fuss
W.Init()
W.Einfuegen(45)
W.DerKopf()
Änderungen:
Typ der
Rückgabe
ist void;
return
eliminiert
void Warteschlange::Einfuegen(int i) {
IntListe *K = new IntListe;
K->Element = i;
K->weiter = NULL;
if (DieListe == NULL){
Kopf = K;
Kopf->weiter = Fuss;
}
else if (Fuss == NULL){
Kopf->weiter = K;
Fuss = K;
}
else {
Fuss->weiter = K;
Fuss = K;
}
DieListe = Kopf;
};
Programm: prog-21a.cpp
Allgemeine Anmerkung: Warteschlange wird ein abstrakter
Datentyp (ADT) genannt.
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.
Wesentliches Thema
für das
zweite Semester
Zurü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 geschieht folgendes:
• 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
Anpassung der Datentypen:
struct BaumListe {
BinBaum * Element;
BaumListe * weiter;
};
Änderung im
Typ des Listenelements
struct BinBaum {
char text[maxLen];
int zaehler;
BinBaum * LSohn, *RSohn;
};
struct Warteschlange {
private:
BaumListe * DieListe;
BaumListe * Kopf, * Fuss;
public:
void Einfuegen(BinBaum *);
void Entfernen();
void Init();
int IstLeer();
BinBaum * DerKopf();
};
zentrale Prozedur:
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);
}
}
Programm: prog-22.cc
Herr von Ribbeck auf Ribbeck im Havelland,
Ein Birnbaum in seinem Garten stand,
Und kam die goldene Herbsteszeit
Und die Birnen leuchteten weit und breit,
Da stopfte, wenn's Mittag vom Turme scholl,
Der von Ribbeck sich beide Taschen voll,
Und kam in Pantinen ein Junge daher,
So rief er: »Junge, wiste 'ne Beer?«
Und kam ein Mädel, so rief er: »Lütt Dirn,
Kumm man röwer, ick hebb 'ne Birn.«
So ging es viel Jahre, bis lobesam
Der von Ribbeck auf Ribbeck zu sterben kam.
Er fühlte sein Ende. 's war Herbsteszeit,
Wieder lachten die Birnen weit und breit;
Da sagte von Ribbeck: »Ich scheide nun ab.
Legt mir eine Birne mit ins Grab.«
Und drei Tage drauf, aus dem Doppeldachhaus,
Trugen von Ribbeck sie hinaus,
Alle Bauern und Büdner mit Feiergesicht
Sangen »Jesus meine Zuversicht«,
Und die Kinder klagten, das Herze schwer:
»He is dod nu. Wer giwt uns nu 'ne Beer?«
1
1
6
3
2
9
3
1
1
1
1
1
4
2
1
1
5
2
1
1
Herr
Havelland,Ein
von
Birnbaum
Herbsteszeit
Ribbeck
weit
»Junge,
Garten
Havelland.
Herbsteszeit,
Mittag
auf
war
wenn's
»Ich
'ne
Birnen
Grab.«
Junge
Herunterladen