Aufgabenstellung: Ein vom Benutzer angegebener arithmetischer

Werbung
Algorithmen und Datenstrukturen
Übung 10: Auf Platte / Diskette gespeicherte Bayer-Bäume
Implementierung in C++1
Die Klasse BBaum
Sie übernimmt die Verwaltung des auf einer Datei hinterlegten Bayer-Baums:
/* Programm fuer einen auf Platte (Disk) gespeicherten Bayer-Baum:
Die Eingabedaten sind ganzzahlige Schlüssel. Sie koennen ueber
Konsole oder ueber eine Textdatei eingegeben werden. Einfuegen
und Loeschen kann direkt ueber die Konsole erfolgen. Weiterhin
kann nach einem Schluessel gesucht werden. Nach jeder Operation
wird der Baum bzw. der Suchpfad ausgegeben. Das Programm schreibt
die Daten in eine Binaer-Datei auf der Platte. Der Name der Datei
kann ueber die Konsole eingegeben werden. Falls die Datei schon
Daten im Bayer-Baum Format enthaelt, wird dieser Bayer-Baum
weiterhin benutzt. Im anderen Fall wird eine solche Datei erzeugt.
*/
#include
#include
#include
#include
<fstream.h>
<iomanip.h>
<stdlib.h>
<ctype.h>
#define MAERER 5
// Anzahl Verkettungen im Bayer-Baum Knoten
enum status {unvollstaendigesEinfuegen, erfolgreich, doppelterSchluessel,
Unterlauf, nichtGefunden};
typedef int dtype;
struct knoten {
int n;
//
//
dtype s[MAERER-1]; //
long z[MAERER];
//
Anzahl der Elemente, die in einem Knoten
gespeichert sind (n < MAERER)
Datenelemente (aktuell sind n)
'Zeiger' auf andere Knoten (aktuell sind n+1)
};
// Logische Ordnung:
//
z[0], s[0], z[1], s[1], ..., z[n-1], s[n-1], z[n]
// Die Klasse zum auf einer Datei hinterlegten Bayer-Baum
class BBaum {
private:
enum {NIL=-1};
long wurzel, freieListe;
knoten wurzelKnoten;
fstream datei;
status einf(long w, dtype x, dtype &y, long &u);
void ausg(long w, int nLeer);
int knotenSuche(dtype x, const dtype *a, int n)const;
status loe(long w, dtype x);
void leseKnoten(long w, knoten &Knoten);
void schreibeKnoten(long w, const knoten &Knoten);
void leseStart();
long holeKnoten();
void freierKnoten(long w);
public:
BBaum(const char *BaumDateiname);
1
Vgl. PR44_2
1
Algorithmen und Datenstrukturen
~BBaum();
void einfuegen(dtype x);
void einfuegen(const char *eingabeDateiname);
void gibAus(){cout << "Dateninhalt:\n"; ausg(wurzel, 0);}
void loeschen(dtype x);
void zeigeSuche(dtype x);
};
Zur Verwaltung des Bayer-Baums in einer Datei ist besonders wichtig:
- Die Wurzel wurzel (d. h. die Position des Wurzelknotens
- eine Liste mit Informationen über den freien Speicherplatz in der Datei (adressiert über
freieListe).
Zu solchen freien Speicherplätzen kann es beim Löschen von Schlüsselelementen kommen.
Zweckmäßigerweise wird dann dieser freie Speicherbereich nicht aufgefüllt, sondern in einer Liste
freier Speicherbereiche eingekettet. freieListe zeigt auf das erste Element in dieser Liste.
Solange das Programm läuft sind „wurzel“ und „freieListe“ Datenelemente der Klasse BBaum
(in einer Datei abgelegter Bayer-Baum). Für die Belegung dieser Dateielemente wird am
Dateianfang (1.Seite) Speicherplatz reserviert. Am Ende der Programmausführung werden die
Werte zu „wurzel“ bzw. „freieListe“ in der Datei abgespeichert.
Bsp.: Der folgende Bayer-Baum
20
10
15
60
80
ist bspw. folgendermaßen organisiert:
10
wurzel
15
60
80
20
freieListe
Zeiger haben hier ganzzahlige Werte des Typs long (mit -1L als NIL), die für die Positionen und
Bytenummern stehen.
Erzeugen des Bayer-Baums (Konstruktor)
BBaum::BBaum(const char *BaumDateiname)
{
ifstream test(BaumDateiname, ios::in | ios::nocreate);
int NewFile = test.fail();
test.clear(); test.close();
if (NewFile)
{
datei.open(BaumDateiname, ios::out | ios::in |
ios::trunc | ios::binary);
wurzel = freieListe = NIL;
long start[2] = {NIL, NIL};
datei.write((char*)start, 2 * sizeof(long));
}
else
{
2
Algorithmen und Datenstrukturen
long start[2];
datei.open(BaumDateiname, ios::out | ios::in |
ios::nocreate | ios::binary);
datei.seekg(-1L, ios::end);
char zeichen;
datei.read(&zeichen, 1);
datei.seekg(0L, ios::beg);
datei.read((char *)start, 2 * sizeof(long));
if (zeichen != sizeof(int))
{ cout << "Falsches Dateiformat.\n"; exit(1);
}
wurzel = start[0];
freieListe = start[1];
wurzelKnoten.n = 0;
// Signal fuer Funktion leseKnoten
leseKnoten(wurzel, wurzelKnoten);
gibAus();
}
}
Einfügen
void BBaum::einfuegen(dtype x)
{ long zNeu;
dtype xNeu;
status code = einf(wurzel, x, xNeu, zNeu);
if (code == doppelterSchluessel)
cout << "Doppelter Schluessel wurde ignoriert.\n";
if (code == unvollstaendigesEinfuegen)
{ long wurzel0 = wurzel;
wurzel = holeKnoten();
wurzelKnoten.n = 1; wurzelKnoten.s[0] = xNeu;
wurzelKnoten.z[0] = wurzel0; wurzelKnoten.z[1] = zNeu;
schreibeKnoten(wurzel, wurzelKnoten);
}
}
Löschen
void BBaum::loeschen(dtype x)
{
long wurzel0;
switch (loe(wurzel, x))
{
case nichtGefunden:
cout << x << " nicht gefunden.\n";
break;
case Unterlauf:
wurzel0 = wurzel;
wurzel = wurzelKnoten.z[0]; freierKnoten(wurzel0);
if (wurzel != NIL) leseKnoten(wurzel, wurzelKnoten);
break;
}
}
3
Herunterladen