26.12.2013 Aufrufe

Informatik/Jahrgangsstufe Q/Klausuren/Themensortiert/03 Baeume.pdf

Informatik/Jahrgangsstufe Q/Klausuren/Themensortiert/03 Baeume.pdf

Informatik/Jahrgangsstufe Q/Klausuren/Themensortiert/03 Baeume.pdf

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

Aufgabe 1: Begründen oder widerlegen Sie die folgenden Aussagen:<br />

(1) Jeder Knoten eines Binärbaums hat zwei nichtleere Teilbäume<br />

(2) Beim Löschen eines Elements aus einem Binärbaum ändert sich die Höhe<br />

dieses Baumes.<br />

(3) Beim Einfügen eines Elements in einen Binärbaum kann die Höhe dieses<br />

Baumes unverändert bleiben.<br />

(4) Die Inorder-Ausgabe eines Suchbaums ist immer Sortiert.<br />

(5) Ein Binärbaum der Höhe 4 besitzt höchstens 15 Knoten.<br />

(6) Ein Binärbaum mit der Höhe 5 besitzt mindestens 7 Knoten.


Aufgabe 1: Bäume − Binärbaume – Suchbäume<br />

Im Unterricht haben wir drei verschiedene Gruppen von Bäumen kennen<br />

gelernt: Gruppe A: Suchbäume<br />

Gruppe B: Binärbäume<br />

Gruppe C: Bäume<br />

Gruppe D: keine Bäume (Graphen)<br />

Diese stehen in einem rechts veranschaulichten Hierarchieverhältnis.<br />

(D) Graphen<br />

(C) Bäume<br />

(B) Binärbäume<br />

(A) Suchbäume<br />

a) Ordnen Sie jede der nachfolgenden Strukturen einer dieser Gruppen zu und begründen Sie<br />

kurz, warum die Struktur zur angegebenen Hierarchie gehört.<br />

(1) (2) C<br />

(3)<br />

B<br />

F<br />

E<br />

P<br />

(4)<br />

10<br />

(5) 04.<strong>03</strong>.2002<br />

6<br />

9<br />

19.09.2001<br />

25.05.2002<br />

4<br />

5 7 8<br />

08.07.2001<br />

24.12.2001<br />

01.10.20<strong>03</strong><br />

b) Zeichnen Sie den Graphen eines zu Anfang leeren Suchbaumes, in den nacheinander die<br />

folgenden Elemente eingefügt werden (Eine Zeichnung reicht aus!):<br />

3, 1, 7, 2, 12, 6, 4, 10, 8, 5, 11, 9<br />

c) Geben Sie zum nachfolgenden Binärbaum die Preorder-, Inorder- und Postorder-<br />

Traversierung an.<br />

oder<br />

Binärbäumen<br />

Spass<br />

Traversieren<br />

von<br />

riesen<br />

das<br />

macht<br />

d) Löschen Sie nacheinander die folgenden Elemente aus dem rechts<br />

abgebildeten Suchbaum.<br />

9, 8, 7, 3, 6,<br />

Halten Sie sich dabei exakt an das im Unterricht entwickelte<br />

Verfahren SuchLöschen (Anlage I). Zeichnen Sie nach jeder<br />

Löschaktion den Graphen des daraus resultierenden Baumes.<br />

(Insgesamt sind also 5 Bäume zu zeichnen!)<br />

einen<br />

e) Entwickeln Sie eine Funktion, welche die Anzahl der Blätter eines Baumes berechnet.<br />

Verwenden Sie wann immer möglich die Binbaum-Methoden (Anlage II).<br />

function TBinBaum.Blattanzahl: integer;<br />

1<br />

2<br />

3<br />

5<br />

6<br />

8<br />

7 10<br />

4 9 11


Aufgabe 3: Zeichnen Sie den Graphen eines zu Anfang leeren Suchbaumes, in den<br />

nacheinander die folgenden Elemente eingefügt werden (Eine Zeichnung reicht<br />

aus!):<br />

3, 1, 7, 2, 12, 6, 4, 10, 8, 5, 11, 9<br />

Aufgabe 4: Geben Sie zum nachfolgenden Binärbaum die Preorder-, Inorder- und Postorder-<br />

Traversierung an.<br />

der<br />

Freitag<br />

ist<br />

ein<br />

guter<br />

Tag<br />

zum<br />

Klausur<br />

schreiben<br />

Aufgabe 5: Löschen Sie nacheinander die folgenden Elemente aus dem rechts abgebildeten<br />

Suchbaum.<br />

9, 8, 7, 3, 6,<br />

6<br />

Halten Sie sich dabei exakt an das im Unterricht<br />

3<br />

entwickelte Verfahren SuchLöschen (Anlage I). Zeichnen<br />

Sie nach jeder Löschaktion den Graphen des daraus<br />

2 5<br />

resultierenden Baumes. (Insgesamt sind also 5 Bäume zu<br />

zeichnen!)<br />

1<br />

8<br />

7 10<br />

4 9 11<br />

Aufgabe 6: Entwickeln Sie eine Funktion, welche die Anzahl der Knoten eines Baumes<br />

zählt, die genau einen nichtleeren Teilbaum besitzen. Die Funktion angewendet<br />

auf den Baum aus Aufgabe 5 würde als Ergebnis die Zahl 2 liefern, da nur die<br />

Knoten 2 und 5 genau einen nichtleeren Teilbaum besitzen.<br />

Verwenden Sie wann immer möglich die Binbaum-Methoden (Anlage II).<br />

function TBinBaum.HalbbaumAnzahl: integer;<br />

Aufgabe 7: Die Inhalte eines Suchbaums sollen in einen File geschrieben werden.<br />

a) Begründen Sie, warum eine Methode SaveToFile, welche in der Klasse<br />

TSuchbaum deklariert würde, nur Textdateien erzeugen könnte.<br />

b) Begründen Sie, warum eine Methode LoadFromFile in der Klasse<br />

TSuchbaum sogar unsinnig wäre.


Aufgabe 1:<br />

Binärbäume − Suchbäume<br />

Hinweis: Sämtliche Abbildungen finden Sie im Anhang I.<br />

a) Begründen oder widerlegen Sie:<br />

(1) Der Baum aus ABBILDUNG 1 gehört zur Gruppe der Suchbäume.<br />

(2) Der Baum aus ABBILDUNG 2 ist kein Suchbaum.<br />

(3) Ein Binärbaum der Höhe 3 hat höchstens sechs Elemente.<br />

(4) Das Suchen in einem Suchbaum mit 7 Elementen benötigt höchstens drei<br />

Vergleiche.<br />

(5) Die InOrder Ausgabe des Baums aus ABBILDUNG 2 lautet:<br />

Karl, Emil, Otto, Bert, Fritz, Josef, Paul, Doris, Gerd, Moritz<br />

(6) Der Baum aus ABBILDUNG 3 könnte eine Datenstruktur für das Expertensystem<br />

„Tiereraten“ sein.<br />

(7) Beim Expertensystem „Tiereraten“ müssen die Baumelemente in PreOrder-<br />

Notation in einem File abgelegt werden, damit die Rekonstruktion der<br />

Wissensstruktur möglich ist.<br />

b) Im Unterricht haben Sie Algorithmen kennen gelernt, mit Hilfe derer Elemente in<br />

Suchbäume eingefügt und Elemente aus Suchbäumen gelöscht werden können.<br />

(1) Fügen Sie in einen anfangs leeren Suchbaum nacheinander folgende Elemente ein.<br />

30, 10, 20, 40, 50, 45, 35, 25, 15, 5<br />

Eine Zeichnung genügt.<br />

(2) Löschen Sie in dem so entstandenen Baum nacheinander die folgenden Elemente.<br />

25, 50, 30<br />

Zeichnen Sie nach jeder Löschoperation den resultierenden Suchbaum.<br />

(3) Geben Sie zu Ihrem Suchbaum aus Teilaufgabe (1) die zugehörige PostOrder-<br />

Ausgabe an.<br />

(4) Die PreOrderAusgabe eines Suchbaums lautet:<br />

8, 4, 0, 2, 6, 14, 10, 12, 18, 16, 20<br />

Zeichnen Sie den zugehörigen Suchbaum.<br />

c) Gegeben sei die folgende Datenstruktur eines Binärbaums über dem Inhalt integer.<br />

type TIntBinBaum = class(TBinBaum)<br />

public<br />

Wurzelinhalt: integer;<br />

constructor Create(w: Integer);<br />

function WurzelinhaltToString: string; override;<br />

end;<br />

(1) Implementieren Sie die Methode WurzelinhaltToString.<br />

(2) Erweitern Sie die Klasse TIntBinBaum um eine Methode, welche das größte<br />

Element des Baums bestimmt.<br />

Achtung: Es handelt sich hier nicht um einen Suchbaum!<br />

(3) Erweitern Sie nun die Klasse TIntBinBaum um eine Methode<br />

procedure StrukturierteAusgabe(Memo: TMemo);<br />

die den Baum „strukturiert“ auf einem Memofeld ausgibt. ABBILDUNG 4 zeigt, wie<br />

dies gemeint ist.


Anlage I:<br />

6<br />

3<br />

9<br />

1<br />

4<br />

7<br />

1 0<br />

0<br />

2<br />

5<br />

8<br />

ABBILDUNG 1: SUCHBAUM ?<br />

Karl<br />

Emil<br />

Otto<br />

Bert<br />

Fritz<br />

Josef<br />

Paul<br />

Doris<br />

Gerd<br />

Moritz<br />

ABBILDUNG 2: SUCHBAUM ?<br />

Kann<br />

sprechen?<br />

Lebt im<br />

Käfig?<br />

Kann<br />

miauen?<br />

Papagei<br />

Katze<br />

Kann<br />

bellen?<br />

Hund<br />

ABBILDUNG 3: WISSENSSTRUKTUR BEIM „TIERERATEN“ ?<br />

ABBILDUNG 4: STRUKTURIERTE AUSGABE IM MEMO (UM 90° LINKS GEDREHT)


Aufgabe 1:<br />

Binärbäume<br />

Im Morsealphabet ist jeder Buchstabe durch eine Aneinanderreihung von Punkten (·) und<br />

Strichen (-) codiert. Die Codierung der Buchstaben lautet wie folgt:<br />

Morsealphabet<br />

A ·- B -·· C -·-· D -··· E · F ··-· G --· H ···· I ·· J ·--- K -·- L ·-·· M –-<br />

N -· O --- P ·--· Q --·- R ·-· S ··· T - U ··- V ···- W ·-- X -··- Y -·-- Z --··<br />

Eine Möglichkeit, den Morse-Code zu verwalten, ist die Speicherung der Codes in einem<br />

Binärbaum. Der Morsepunkt bewirkt dabei eine Verzweigung nach<br />

links, der Morsestrich eine Verzweigung nach rechts. In jedem<br />

Knoten des Baumes steht der Buchstabe, der durch den im Baum<br />

vorausgegangenen Punkt-Strich-Code repräsentiert wird.<br />

a) Stelle den Morsecode wie oben beschrieben als Baum dar. Der<br />

Pfad zum Buchstaben R müsste in deinem Baum wie rechts<br />

abgebildet aussehen.<br />

Solltest du keinen Baum erstellen können, so erhältst du diese<br />

Lösung von dem Aufsicht führenden Lehrer.<br />

b) Übersetze mit Hilfe des in a) entwickelten Baumes den folgenden<br />

Morsetext. Die |-Zeichen trennen die einzelnen Buchstaben.<br />

-|---|·-··|·-··|·|-·-|·-··|·-|··-|···|··-|·-·<br />

...<br />

R<br />

−<br />

•<br />

•<br />

...<br />

...<br />

c) Beschreibe, wie man algorithmisch vorgeht, wenn man einen Text mit Hilfe des Baumes<br />

übersetzen möchte. Es ist kein exakter Algorithmus gefordert!<br />

d) Wieso ist eine Trennung der einzelnen Buchstaben (hier durch ein |-Zeichen)<br />

erforderlich? Begründe mit Hilfe des Baums aus Aufgabenteil a).<br />

Für die Umsetzung dieser Speichermöglichkeit in DELPHI bietet sich das folgende<br />

interface an:<br />

uses BinBaum;<br />

type TMorsebaum = class(TBinBaum)<br />

public<br />

Inhalt: char;<br />

constructor Create(c: char);<br />

function WurzelinhaltToString: string; override;<br />

function Einlesen: TMorsebaum;<br />

function MorsetextToKlartext(Morse: string): char;<br />

function KlartextToMorsetext(Klar: char): string;<br />

end;<br />

e) Implementiere die folgenden Methoden dieses Datentyps:<br />

(i) constructor Create(c: char);<br />

Erzeugt ein Blatt dessen Knoteninhalt der Buchstabe c ist.<br />

(ii) function WurzelinhaltToString: string; override;<br />

Liefert den Knoteninhalt als string.<br />

(iii) function MorsetextToKlartext(Morse: string): char;<br />

Gibt zu einem Zeichen in Morsecode (Morse) den entsprechenden Buchstaben<br />

im Klartext zurück.<br />

MorsetextToKlartext(´··-·´) liefert den Buchstaben ´F´.<br />

(iv) ... siehe nächste Seite ...


(iv) function KlartextToMorsetext(Klar: char): string;<br />

Sucht im Baum den Buchstaben Klar und gibt den entsprechenden Morsetext<br />

zurück.<br />

KlartextToMorsetext(´V´) liefert den Morsecode ´···−´.<br />

Hinweis: Am besten ist diese Aufgabe zu lösen, wenn du dir eine<br />

Hilfsfunktion/-prozedur schreibst, welche rekursiv alle möglichen<br />

Morsecodes durchläuft.<br />

f) Eine andere Möglichkeit der Verwaltung der Morsecodes wäre durch ein Array gegeben:<br />

const CodeTabelle: array['A'..'Z'] of string[4]=<br />

('·-','-··','-·-·','-···','·','··-·',<br />

'--·','····','··','·---','-·-','·-··',<br />

'--','-·','---','·--·','--·-','·-·',<br />

'···','-','··-','···-','·--','-··-','-·--','--··');<br />

Welche Nachteile hat diese Art der Verwaltung gegenüber der Verwaltung in Form eines<br />

Baums? Welche Vorteile ergeben sich aus dieser Art der Speicherung?


ellt?<br />

Aufgabe 3: Aus dem Unterricht kennen Sie den Datentyp des Binärbaums (Anlage I).<br />

beißt?<br />

miaut?<br />

Hund Löwe Katze Fisch<br />

a) Beschreiben Sie die wesentlichen Merkmale dieser Datenstruktur.<br />

b) Der Datentyp wird um folgende Methode erweitert:<br />

function TBinBaum.wasBerechneIch: string;<br />

begin<br />

if leer<br />

then result:= ´´<br />

else result:= LinkerTeilbaum.wasBerechneIch +<br />

WurzelinhaltToString +<br />

RechterTeilbaum.wasBerechneIch;<br />

end;<br />

Welches Funktionsergebnis wird für den links abgebildeten Baum<br />

zurückgegeben?<br />

c) Schreiben Sie eine Methode für den Datentyp TBinBaum, welche die Anzahl<br />

der Tiere in einer Wissensstruktur berechnet. Hinweis: In den Blättern eines<br />

Wissensbaums standen stets Tiernamen.<br />

d) Erläutern und formulieren Sie einen Algorithmus, welcher die Inhalte eines<br />

Binärbaums zeilenweise ausgibt. Eine exakte Implementierung ist hier nicht<br />

gefordert. Hinweis: Sie dürfen auf bereits bekannte Datenstrukturen (Lineare<br />

Liste, Stapel, Schlange, etc.) zurückgreifen.


Aufgabe 1: Binärbäume − hier: Termbäume<br />

In der fünften Klasse lernt man, nach welchen Rechengesetzen Terme berechnet werden:<br />

Klammer- vor Punkt- und Punkt- vor Strichrechnung. Zur Veranschaulichung werden<br />

sogenannte Rechenbäume oder Termbäume benutzt, welche die Reihenfolge der Berechnung<br />

veranschaulichen. Zwei Beispiele:<br />

Beispiel 1: 2 + 3 * 6 − 4 / 1<br />

Beispiel 2: 5 * (6 + 2) − 7 / 4 + 2 * 5<br />

–<br />

+<br />

+<br />

/<br />

−<br />

*<br />

2<br />

* 4<br />

1<br />

*<br />

/<br />

2 5<br />

3 6<br />

5<br />

+<br />

7 4<br />

6 2<br />

a) Stelle die zugehörigen Terme auf:<br />

*<br />

/<br />

2<br />

+<br />

–<br />

+<br />

7<br />

/<br />

*<br />

+<br />

2<br />

1<br />

5 5<br />

5 4<br />

3 2<br />

b) Stelle die zugehörigen Termbäume zu den Termen (I) 7 * 6 − (3 * 5 − 2 + 1) und<br />

(II) 3 − 8 / 4 * 3 + 5 auf.<br />

c) Durchläuft man einen Termbaum in Preorder, so erhält man den sogenannten Präfix-<br />

Term, durchläuft man ihn in Postorder, so erhält man den Postfix-Term.<br />

Gib sowohl den Präfix-Term als auch den Postfix-Term der Beispiel-Termbäume an<br />

(Beispiel 1 und 2).<br />

d) Gegeben ist nun der Präfix-Term (I) – * 2 + 2 3 + 6 1. Stelle den zugehörigen Termbaum<br />

auf. Versuche das gleiche mit den Präfix-Termen (II) * + 8 7 − 7 / 4 2 und<br />

(III) + + + 1 1 1 + + 1 1 + 1 . Begründe bei (III) dein Ergebnis.<br />

e) Gegeben ist nun der Postfix-Term (I) 1 3 5 * + 6 − 8 3 * −. Stelle den zugehörigen<br />

Termbaum auf. Versuche das gleiche mit den Postfix-Termen (II) 8 7 7 * + 4 2 / − und<br />

(III) 1 * + 3 4 – *. Begründe bei (III) dein Ergebnis.<br />

In der Anlage (Anlage I) findest du eine mögliche Klassendefinition TTermbaum für einen<br />

Termbaum. Dieser ist abgeleitet vom Datentyp Binärbaum und erbt somit alle in TBinbaum<br />

definierten Methoden.<br />

f) Schreibe die Methode ToPostorder der Klasse TTermbaum, welche den Termbaum<br />

als Postfix-Term zurückgibt.<br />

g) Beschreibe algorithmisch, wie die Funktion FromPreorder aus einem Präfix-Term<br />

den zugehörigen Termbaum erstellen kann. „Befehle“ wie „Lies nächstes Zeichen“,<br />

„Prüfe, ob Zeichen ein Operator ist“, etc. sind dabei in Ordnung.


unit TermBaum;<br />

interface<br />

uses BinBaum<br />

const Operatoren: set of char= ['+','-','*','/','^']; { Menge der Operatoren }<br />

Operanden: set of char= ['0'..'9']; { Menge der Operanden }<br />

type TTermbaum = class(TBinBaum)<br />

Inhalt: char; { nur Ziffern als Operanden erlaubt }<br />

constructor create(z: char); { Konstruktor mit Übergabe des Wurzelinhalts }<br />

function WurzelinhaltToString: string; override; { Aus TBinbaum geerbt }<br />

function ToPreOrder: string; { Gibt den Termbaum als PreOrder-String aus }<br />

function ToInOrder: string; { Gibt den Termbaum als InOrder-String aus }<br />

function ToPostOrder: string; { Gibt den Termbaum als PostOrder-String aus }<br />

function Auswertung: Integer; { Wertet den Termbaum arithmetisch aus }<br />

end;<br />

function FromPreOrder(var Zeichenkette: string): TTermBaum; { Erzeugung eines Termbaums aus PreOrder-String }<br />

function FromInOrder(var Zeichenkette: string): TTermbaum; { Erzeugung eines Termbaums aus InOrder-String }<br />

function FromPostOrder(var Zeichenkette: string): TTermbaum; { Erzeugung eines Termbaums aus PostOrder-String }<br />

Eine mögliche Oberfläche zur Darstellung von Termbäumen ist die folgende:


Aufgabe 1:<br />

Binärbäume<br />

In der fünften Klasse lernt man, nach welchen Rechengesetzen Terme berechnet werden:<br />

Klammer- vor Punkt- und Punkt- vor Strichrechnung. Zur Veranschaulichung werden<br />

sogenannte Rechenbäume oder Termbäume benutzt, welche die Reihenfolge der Berechnung<br />

veranschaulichen. Zwei Beispiele:<br />

Beispiel 1: 2 + 3 * 6 − 4 / 1<br />

Beispiel 2: 5 * (6 + 2) − 7 / 4 + 2 * 5<br />

–<br />

+<br />

+<br />

/<br />

−<br />

*<br />

2<br />

* 4<br />

1<br />

*<br />

/<br />

2 5<br />

3 6<br />

5<br />

+<br />

7 4<br />

6 2<br />

a) Gib für folgende Termbäume den zugehörigen Term an.<br />

*<br />

/<br />

2<br />

+<br />

–<br />

+<br />

7<br />

/<br />

*<br />

+<br />

2<br />

1<br />

5 5<br />

5 4<br />

3 2<br />

b) Zeichne die Termbäume zu den Termen<br />

(I) 7 * 6 − (3 * 5 − 2 + 1) und<br />

(II) 3 − 8 / 4 * 3 + 5.<br />

c) Durchläuft man einen Termbaum in Preorder, so erhält man den sogenannten Präfix-<br />

Term, durchläuft man ihn in Postorder, so erhält man den Postfix-Term.<br />

Gib sowohl den Präfix-Term als auch den Postfix-Term der Beispiel-Termbäume an<br />

(Beispiel 1 und 2).<br />

d) Gegeben sind nun der Präfix-Terme<br />

(I) – * 2 + 2 3 + 6 1<br />

(II) * + 8 7 − 7 / 4 2 und<br />

(III) + + + 1 1 1 + + 1 1 + 1 1<br />

Stelle die Terme als Termbaum dar.<br />

e) Gegeben sind nun die Postfix-Terme<br />

(I) 1 3 5 * + 6 − 8 3 * −<br />

(II) 8 7 7 * + 4 2 / − und<br />

(III) 1 1 + 1 + 1 1 + 1 + +<br />

Stelle die Terme als Termbaum dar.


f) Die Datenstruktur eines Termbaums ist durch folgendes UML-Diagramm gegeben.<br />

I) Erläutere die Beziehungen dieser Datenstruktur.<br />

II) Begründe, warum eine Vererbung der Klasse TTermbaum von der Klasse TBinTree<br />

nicht sinnvoll ist.<br />

g) Implementiere die private Methode BinTreeToPostOrder, welche die zu dem<br />

übergebenen Binärbaum zugehörige Postfixterm-Darstellung zurückliefert.<br />

h) Vervollständige das folgende Raster der privaten Methode PreOrderToBinTree, welche<br />

aus einem Präfixterm einen Binärbaum erstellt und zurückgibt.<br />

Hinweise: Eine Fehlerprüfung, ob tatsächlich ein Präfixterm vorliegt, ist nicht erforderlich.<br />

Alle Operanden sind Ziffern. Leerzeichen wurden zuvor aus der Zeichenkette entfernt.<br />

const Operatoren: set of char= ['+','-','*','/','^'];<br />

Operanden: set of char= ['0'..'9'];<br />

function NaechstesZeichen(var Zeichenkette: string): char;<br />

begin<br />

result:= Zeichenkette[1];<br />

Delete(Zeichenkette,1,1);<br />

end;<br />

function TTermbaum.PreOrderToBinTree(var Zeichenkette: string): TBinTree;<br />

var ltb, rtb: TBinTree;<br />

Zeichen: char;<br />

begin<br />

Zeichen:= NaechstesZeichen(Zeichenkette);<br />

if Zeichen in Operatoren // prüfe, ob das Zeichen ein Operator ist.<br />

then begin<br />

// hier bitte den richtigen Code ergänzen.<br />

end<br />

else result:= TBinTree.Create(TOperandObjekt.create(StrToInt(Zeichen)));<br />

end;


Materialien<br />

Die Klasse TBinTree<br />

In einem Objekt der Klasse TBinTree werden beliebige Objekte in einem Binärbaum verwaltet. Ein<br />

Binärbaum ist entweder leer oder besteht aus einem Knoten, dem ein Element und zwei binäre<br />

Teilbäume, die so genannten linken und rechten Teilbäume, zugeordnet sind.<br />

Dokumentation der Methoden der Klasse TBinTree<br />

Konstruktor create<br />

nachher Ein leerer Baum existiert<br />

Konstruktor create (pObject: TObject)<br />

nachher Der Binärbaum existiert und hat einen Wurzelknoten mit dem Inhalt pObject und<br />

zwei leeren Teilbäumen.<br />

Konstruktor create (pObject: TObject; pLeftTree, pRightTree: TBinTree)<br />

nachher Der Binärbaum existiert hat einen Wurzelknoten mit dem Inhalt pObject, dem<br />

linken Teilbaum pLeftTree und dem rechten Teilbaum pRightTree.<br />

Anfrage<br />

nachher<br />

Auftrag<br />

nachher<br />

Auftrag<br />

nachher<br />

Anfrage<br />

vorher<br />

nachher<br />

Auftrag<br />

vorher<br />

nachher<br />

Auftrag<br />

vorher<br />

nachher<br />

Anfrage<br />

vorher<br />

nachher<br />

Anfrage<br />

vorher<br />

nachher<br />

Auftrag<br />

nachher<br />

isEmpty: boolean<br />

Diese Anfrage liefert den Wahrheitswert true, wenn der Binärbaum leer ist, sonst<br />

liefert sie den Wert false.<br />

clear<br />

Der Binärbaum ist leer. Auch die Inhaltsobjekte der Knoten wurden freigegeben<br />

und stehen nicht mehr zur Verfügung.<br />

setRootItem (pObject: TObject)<br />

Die Wurzel hat – unabhängig davon, ob der Binärbaum leer ist oder schon eine<br />

Wurzel hat – pObject als Inhalt. Eventuell vorhandene Teilbäume werden nicht<br />

geändert.<br />

getRootItem: TObject<br />

Der Binärbaum ist nicht leer.<br />

Diese Anfrage liefert den Inhalt des Wurzelknotens des Binärbaums.<br />

setLeftTree (pTree: TBinTree)<br />

Der Binärbaum ist nicht leer.<br />

Die Wurzel hat den übergebenen Baum als linken Teilbaum.<br />

setRightTree (pTree: TBinTree)<br />

Der Binärbaum ist nicht leer.<br />

Die Wurzel hat den übergebenen Baum als rechten Teilbaum.<br />

getLeftTree: TBinTree<br />

Der Binärbaum ist nicht leer<br />

Diese Anfrage liefert den linken Teilbaum der Wurzel des Binärbaums. Der<br />

Binärbaum ist unverändert.<br />

getRightTree: TBinTree<br />

Der Binärbaum ist nicht leer<br />

Diese Anfrage liefert den rechten Teilbaum der Wurzel des Binärbaums. Der<br />

Binärbaum ist unverändert.<br />

destroy<br />

Der Binärbaum existiert nicht mehr.


Aufgabe 1:<br />

Bäume<br />

Im Unterricht haben Sie Datenstrukturen für Binärbäume (BinTree) und geordnete<br />

Binärbäume (OrderedTree) kennen gelernt. Beide Datenstrukturen hatten den Nachteil,<br />

dass jeder Knoten lediglich zwei Sohnknoten besaß. Es gibt allerdings Anwendungsbeispiele,<br />

bei denen es hilfreich wäre, dass jeder Knoten beliebig viele Sohnknoten speichert. Beispiele<br />

hierfür sind Entscheidungsbäume bei Strategiespielen (eine Spielsituation hat eine<br />

unterschiedliche Anzahl von Folge-Situationen) oder Ahnenbäume (ein Mensch hat nicht<br />

immer genau zwei Nachkommen).<br />

Im Folgenden sollen Sie Teile einer hierfür geeigneten Datenstruktur Tree modellieren und<br />

implementieren.<br />

a) Die Speicherung der Sohnknoten eines Trees soll mittels einer List (siehe Anlage)<br />

realisiert werden. Folgende Konstruktoren, Aufträge und Anfragen sollen in der Klasse<br />

Tree Berücksichtigung finden:<br />

(1) zwei Konstruktoren zur Erzeugung eines leeren Trees oder eines Trees mit einem<br />

Inhalt vom Typ Object.<br />

(2) eine Anfrage, ob der Tree leer ist<br />

(3) einen Auftrag zum Leeren des Trees, d. h. alle Inhalte werden gelöscht<br />

(4) eine Anfrage nach dem Inhalt der Wurzel des Trees<br />

(5) einen Auftrag zum Setzen des Inhalts der Wurzel des Trees<br />

(6) eine Anfrage nach einem Teilbaum des Trees, wobei durch eine Nummer bestimmt<br />

wird, der wievielte Teilbaum angefragt wird.<br />

(7) Auftrag zum Anhängen eines neuen Teilbaums an den Tree. Die Teilbäume<br />

benötigen keine spezielle Ordnung.<br />

Zeichnen Sie ein UML-Klassendiagramm der Klasse Tree mit allen Attributen und<br />

Methoden.<br />

Ergänzen Sie das Diagramm um ein Klassendiagramm der Klasse List (ohne Methoden<br />

und Attribute) und setzen Sie beide Klassen sinnvoll in Beziehung zueinander.<br />

b) Dokumentieren Sie die Anfrage nach einem Teilbaum (6) sowie den Auftrag zum Setzen<br />

des Inhalts der Wurzel eines Trees (5) ausführlich mit vorher/nachher-Bedingung. Gehen<br />

Sie auch auf Spezialfälle ein.<br />

c) Implementieren Sie beide Konstruktoren der Klasse Tree (1) sowie die Methode für die<br />

Anfrage nach einem Teilbaum (6). Achten Sie auf die in b) dokumentierten Spezialfälle.<br />

d) Implementieren Sie die Methode<br />

String preOrder(Tree pTree)<br />

welche die Wurzelinhalte des Baums pTree in preorder-Traversierung<br />

semikolongetrennt in einem String ausgibt.<br />

Hinweis: Die Klasse Object verfügt über eine Methode toString(), welche zur<br />

Konvertierung in einen String genutzt werden kann.


Aufgabe 1: AVL-Bäume<br />

Aus dem Unterricht kennen Sie die Datenstruktur TAVLBaum. (siehe Interface in Anlage I)<br />

a) Geben Sie die Definition für einen AVL-Baum an. Erläutern Sie den wesentlichen Vorteil<br />

im Gegensatz zu den ihnen bekannten Baumstrukturen. Erläutern Sie wenigstens zwei<br />

weitere Möglichkeiten der Baumoptimierung.<br />

b) Fügen Sie nacheinander die folgenden Elemente in einen anfangs leeren AVL-Baum ein.<br />

Zeichnen Sie nach jeder AVL-Korrekturoperation (Links-/Rechtsrotation) den Baum neu.<br />

3, 4, 7, 1, 2, 6 und 5<br />

8<br />

c) Löschen Sie im rechts abgebildeten AVL-Baum das<br />

Element mit der Nr. 8. Stellen Sie anschließend die<br />

AVL-Eigenschaft wieder her.<br />

2<br />

5<br />

11<br />

7 9<br />

14<br />

1<br />

3<br />

6 10 13 15<br />

4<br />

d) Das Einfügen und Löschen in AVL-Bäumen kann zur<br />

Störungen der AVL-Balance führen. Skizzieren Sie die um Unterricht entwickelte<br />

Fallunterscheidung, welche alle möglichen Situationen vor und nach den<br />

Korrekturoperationen enthält.<br />

12<br />

e) Implementieren Sie den Teil der Methode<br />

function TAVLBaum.AVLKorrektur: TAVLBaum.<br />

der für einen Baum in rechts abgebildeter Situation die AVL-<br />

Eigenschaft wieder herstellt.<br />

if (Balance = −2) and (LinkerTeilbaum.Balance = −1) then ...<br />

h−1<br />

Y<br />

h<br />

h−2<br />

X<br />

h+1<br />

h−2<br />

f) Die von TAVLBaum abgeleitete Klasse TIntAVLBaum soll<br />

Integer-Werte aufnehmen können. Implementieren Sie für diese Klasse eine Methode<br />

function TIntAVLBaum.AVL_PerfekterAusgleich: TAVLBaum.<br />

Die Funktion soll den Baum InOrder auf einen File abgelegen und den dann per<br />

Halbteilungsmethode eingelesen Baum zurückgeben.<br />

Verwenden Sie wann immer möglich die Methoden des AVL-Baumes bzw. die des ihnen<br />

bekannten Binärbaumes.<br />

5<br />

3<br />

7<br />

1<br />

4 6<br />

2<br />

File:<br />

1 2 3 4 5 6 7<br />

EOF<br />

4<br />

2<br />

6<br />

1<br />

3<br />

5<br />

7


Aufgabe 2:<br />

AVL-Bäume<br />

a) Bauen Sie schrittweise einen AVL-Baum auf. Zeichnen Sie den Baum nach jeder<br />

Korrekturoperation:<br />

10, 20, 30, 110, 100, 90, 80, 70, 60, 50, 40<br />

b) Löschen Sie nun nacheinander die folgenden Elemente. Zeichne Sie nach jedem<br />

Löschvorgang den aktuellen Baum:<br />

50, 40, 30, 20<br />

c) Geben Sie die Prorder- und Postorder-Ausgabe des Baums aus Teilaufgabe a) an.<br />

d) Schreiben Sie eine Funktion, welche einen vorhandenen Baum in PROLOG-<br />

Notation ausgibt.<br />

function TAVLBaum.PrologAusgabe: string;<br />

begin<br />

{ hier kommt der Programmtext hin... }<br />

end;<br />

z. B. sollte der rechts abgebildete Baum die folgende Rückgabe bewirken:<br />

baum(30,baum(10,nil,baum(20,nil,nil)),baum(50,baum(40,nil,nil),baum(60,nil,nil)))<br />

30<br />

10 50<br />

20<br />

40<br />

60<br />

e) Begründen Sie mit Hilfe eines geeigneten Beispiels: Das Löschen eines Elements in einem<br />

AVL-Baum kann auf mehreren Ebenen Korrekturoperationen nach sich ziehen.<br />

f) Ist es möglich, dass nach dem Einfügen eines neuen Elements in einen AVL-Baum die<br />

AVL-Balance eines Knotens −3 beträgt? Begründen Sie!<br />

g) Die Ausgewogenheit eines nichtleeren AVL-Baumes ist definiert durch das Verhältnis<br />

Summe der absoluten Balancen<br />

a = . Dabei meint man mit absoluten Balancen die<br />

Anzahl der Knoten<br />

jeweiligen Beträge der Balancen.<br />

Begründen Sie die untere Schranke: a ≥ 0. Zeigen Sie durch ein Beispiel, dass a = 0<br />

möglich ist.<br />

Geben Sie eine möglichst kleine obere Schranke für diese Maßzahl a an. Begründen Sie<br />

Ihre Wahl anhand geeigneter Beispiele.<br />

Lösung:<br />

Aufgabe 2:<br />

a)<br />

b)<br />

c)<br />

d)<br />

function TAVLBaum.PrologAusgabe: string;<br />

begin<br />

if BaumLeer<br />

then Result:= ´nil´<br />

else Result:= ´baum(´+WurzelinhaltToString+´,´+<br />

+(linkerTeilbaum as TAVLBaum).PrologAusgabe<br />

+´,´<br />

+(rechterTeilbaum as TAVLBaum).PrologAusgabe<br />

+´)´;<br />

end;


Aufgabe 2:<br />

Bäume – Binärbäume – Suchbäume<br />

a) Im Unterricht haben wir verschiedene Gruppen von Bäumen kennen<br />

gelernt: Gruppe A: AVL-Bäume<br />

Gruppe B: Suchbäume<br />

Gruppe C: Binärbäume<br />

Gruppe D: Bäume<br />

Gruppe E: keine Bäume (Graphen)<br />

Diese stehen in einem rechts veranschaulichten Hierarchieverhältnis.<br />

(E) Graphen<br />

(D) Bäume<br />

(C) Binärbäume<br />

(B) Suchbäume<br />

Ordnen Sie jede der nachfolgenden Strukturen in die Gruppenhierarchie ein. Begründen<br />

Sie kurz, warum die Struktur zur angegebenen Hierarchiestufe gehört.<br />

(1) (2)<br />

–6<br />

0<br />

6<br />

3 9<br />

(3)<br />

(A) AVL-Bäume<br />

(4)<br />

100<br />

1<br />

(5) (6)<br />

K<br />

010<br />

110<br />

F<br />

T<br />

001<br />

011<br />

101 111<br />

L<br />

N<br />

b) Das Einfügen und Löschen in AVL-Bäumen kann dazu führen, dass die AVL-Eigenschaft<br />

verloren geht, welche dann durch Rotationen wieder hergestellt werden muss.<br />

Stellen Sie dar, wie die folgenden Elemente nacheinander in einen<br />

anfangs leeren AVL-Baum eingefügt werden. Ihre Darstellung muss<br />

auch die AVL-Korrekturoperationen beinhalten.<br />

7, 6, 1, 4, 2, 5, 3<br />

Stellen Sie das schrittweise Löschen der Elemente 7, 10, 3, 6 im rechts<br />

abgebildeten AVL-Baum dar.<br />

1<br />

2<br />

3<br />

4<br />

6<br />

8<br />

7 10<br />

5 9 11<br />

c) Implementieren Sie eine Methode für den allgemeinen Binärbaum, welche überprüft, ob<br />

die AVL-Eigenschaft erfüllt ist. Verwenden Sie wann immer möglich die Methoden der<br />

Klasse TBinTree (Anlage I). Eventuelle Hilfsmethoden sind ebenfalls zu implementieren.<br />

function TBinTree.AVL_ok: boolean;<br />

d) Die Daten eines Integer-Suchbaumes sollen in einem File abgelegt werden. Die<br />

gespeicherten Daten sollen so gespeichert sein, dass eine identische Rekonstruktion der<br />

alten Baumstruktur möglich ist.<br />

Erläutern Sie eine Idee, wie die Daten gespeichert werden müssten. Begründen Sie dabei,<br />

dass über die eigentlichen Daten hinaus keine weitere Informationen abgespeichert<br />

werden müssen, um eine identische Rekonstruktion zu ermöglichen.<br />

Entwickeln Sie einen Grobalgorithmus, der die Rekonstruktion des Baumes erzeugt.<br />

Die Klasse TBinTree<br />

In einem Objekt der Klasse TBinTree werden beliebige Objekte in einem Binärbaum<br />

verwaltet. Ein Binärbaum ist entweder leer oder besteht aus einem Knoten, dem ein<br />

Element und zwei binäre Teilbäume, die so genannten linken und rechten<br />

Teilbäume,


zugeordnet sind.<br />

Dokumentation der Methoden der Klasse TBinTree<br />

Konstruktor create<br />

nachher Ein leerer Baum existiert<br />

Konstruktor create (pObject: TObject)<br />

nachher Der Binärbaum existiert und hat einen Wurzelknoten mit dem Inhalt pObject und<br />

zwei leeren Teilbäumen.<br />

Konstruktor create (pObject: TObject; pLeftTree, pRightTree: TBinTree)<br />

nachher Der Binärbaum existiert hat einen Wurzelknoten mit dem Inhalt pObject, dem<br />

linken Teilbaum pLeftTree und dem rechten Teilbaum pRightTree.<br />

Anfrage<br />

nachher<br />

Auftrag<br />

nachher<br />

Auftrag<br />

nachher<br />

Anfrage<br />

vorher<br />

nachher<br />

Auftrag<br />

vorher<br />

nachher<br />

Auftrag<br />

vorher<br />

nachher<br />

Anfrage<br />

vorher<br />

nachher<br />

Anfrage<br />

vorher<br />

nachher<br />

Auftrag<br />

nachher<br />

isEmpty: boolean<br />

Diese Anfrage liefert den Wahrheitswert true, wenn der Binärbaum leer ist, sonst<br />

liefert sie den Wert false.<br />

clear<br />

Der Binärbaum ist leer. Auch die Inhaltsobjekte der Knoten wurden freigegeben<br />

und stehen nicht mehr zur Verfügung.<br />

setRootItem (pObject: TObject)<br />

Die Wurzel hat – unabhängig davon, ob der Binärbaum leer ist oder schon eine<br />

Wurzel hat – pObject als Inhalt. Eventuell vorhandene Teilbäume werden nicht<br />

geändert.<br />

getRootItem: TObject<br />

Der Binärbaum ist nicht leer.<br />

Diese Anfrage liefert den Inhalt des Wurzelknotens des Binärbaums.<br />

addTreeLeft (pTree: TBinTree)<br />

Der Binärbaum ist nicht leer.<br />

Die Wurzel hat den übergebenen Baum als linken Teilbaum.<br />

addTreeRight (pTree: TBinTree)<br />

Der Binärbaum ist nicht leer.<br />

Die Wurzel hat den übergebenen Baum als rechten Teilbaum.<br />

getLeftTree: TBinTree<br />

Der Binärbaum ist nicht leer<br />

Diese Anfrage liefert den linken Teilbaum der Wurzel des Binärbaums. Der<br />

Binärbaum ist unverändert.<br />

getRightTree: TBinTree<br />

Der Binärbaum ist nicht leer<br />

Diese Anfrage liefert den rechten Teilbaum der Wurzel des Binärbaums. Der<br />

Binärbaum ist unverändert.<br />

destroy<br />

Der Binärbaum existiert nicht mehr.<br />

Lösung:<br />

Aufgabe 2:<br />

a) Die Zuordnung sieht wie folgt aus:


(1): Gruppe E. Nicht D, da es zu einem Element unterschiedliche Wege gibt.<br />

(2): Gruppe B. Nicht A, da die AVL-Eigenschaft in oberster Wurzel verletzt ist (−2).<br />

(3): Gruppe C. Nicht D, da keine Inhalte vorhanden sind.<br />

(4): Gruppe A. AVL-Eigenschaft überall ok und Inhalte (Binärzahlen) aufsteigend sortiert.<br />

(5): Gruppe D. Nicht C, da es vom obersten Knoten drei Nachfolger gibt.<br />

(6): Gruppe C. Nicht B, da die alphabetische Reihenfolge gestört ist ( L nicht kleiner K).<br />

b) Die Lösungen der Teilaufgaben lauten wie folgt:<br />

b.1) Das Einfügen gestaltet sich wie folgt:<br />

7,6,1 7 R(7) 6 4,2 6 R(4), L(1)<br />

6<br />

5<br />

6<br />

6<br />

1<br />

7<br />

1<br />

7<br />

2<br />

7<br />

2<br />

7<br />

1<br />

4<br />

1<br />

4<br />

1<br />

4<br />

L(2)<br />

6<br />

2<br />

R(6)<br />

4<br />

3<br />

4<br />

5<br />

4<br />

7<br />

2<br />

6<br />

2<br />

6<br />

2<br />

5<br />

1 5<br />

7<br />

1 3 5<br />

7<br />

1<br />

b.1) Das Löschen gestaltet sich wie folgt:<br />

7<br />

6<br />

L(8)<br />

6<br />

10<br />

6<br />

3<br />

8<br />

3<br />

10<br />

3<br />

9<br />

2<br />

4<br />

10<br />

2<br />

4<br />

8<br />

11<br />

2<br />

4<br />

8<br />

11<br />

1<br />

3<br />

5 9 11<br />

6<br />

1<br />

6<br />

5<br />

5<br />

9<br />

1<br />

5<br />

2<br />

9<br />

2<br />

9<br />

1<br />

4<br />

8<br />

11<br />

1<br />

4<br />

8<br />

11<br />

5<br />

c) Eine Funktion, welche die AVL-Eigenschaft überprüft lautet wie folgt:<br />

function TBinBaum.AVL_ok: boolean;<br />

var l,r: integer;<br />

begin<br />

if leer then AVL_ok:= true<br />

else begin<br />

l:= LinkerTeilbaum.Baumhoehe;<br />

r:= rechterTeilbaum.Baumhoehe;<br />

AVL_ok:= LinkerTeilbaum.AVL_ok and<br />

RechterTeilbaum.AVL_ok and<br />

(abs(l-r)


function TBinBaum.Baumhoehe: integer;<br />

var l,r: integer;<br />

begin<br />

if leer then Baumhoehe:= 0<br />

else begin<br />

l:= LinkerTeilbaum.Baumhoehe;<br />

r:= RechterTeilbaum.Baumhoehe;<br />

if l>r then Baumhoehe:= l+1<br />

else Baumhoehe:= r+1;<br />

end;<br />

end;<br />

d) Die Speicherung geschieht PreOrder, d. h. in dem File wird beim Beispielbaum aus<br />

Teilaufgabe c) die Zahlenreihenfolge 6, 3, 2, 1, 4, 5, 8, 7, 10, 9, 11 gespeichert.<br />

Baut man nun mit dieser Zahlenreihenfolge wieder einen neuen Suchbaum auf, so ergibt<br />

sich exakt der gleiche Suchbaum wie zuvor.<br />

Ein Grobalgorithmus wäre wie folgt:<br />

Solange Datei nicht am Ende<br />

Tue: Lies nächste Zahl<br />

Baum.Insert(Zahl)


Aufgabe 3:<br />

Bäume - Quadtrees<br />

Quadratische Schwarz-Weiß-Grafiken, deren Seitenlänge (in Pixeln) eine Zweierpotenz ist,<br />

können mit Hilfe der Datenstruktur QuadTree gespeichert werden. Ein QuadTree ist dabei<br />

ein Baum, der entweder vier Teilbäume hat oder ein Blatt ist.<br />

Der Inhalt eines Bildes wird nach folgendem Algorithmus in der Datenstruktur abgelegt:<br />

• Jedem Teilquadrat der Grafik entspricht ein QuadTree.<br />

• Ist die Farbe eines Teilquadrates einheitlich, so wird in den Knoten des zugehörigen<br />

QuadTree der Farbwert (1 = schwarz, 0 = weiß) eingetragen. Der QuadTree besitzt in<br />

diesem Fall leere Teilbäume und ist somit ein Blatt.<br />

• Ist die Farbe nicht einheitlich, so wird dies im Knoten des zugehörigen QuadTree<br />

durch den Wert −1 kenntlich gemacht. Anschließend wird das Quadrat in vier<br />

Teilquadrate zerlegt. Deren Bildinhalte werden im Uhrzeigersinn (links oben, rechts<br />

oben, rechts unten, links unten) in Teilbäume abgelegt und an den aktuellen Knoten<br />

angehängt.<br />

Beispiel: Folgendes 8x8-Schwarz-Weiß-Bild soll in einem QuadTree gespeichert werden:<br />

Der zugehörige QuadTree sieht demnach wie folgt aus:<br />

−1<br />

1<br />

−1 −1 −1<br />

−1 0 0 0<br />

0 0 1 0 0 1 0 −1<br />

1 0 0 0<br />

0 1 0 0<br />

Durchläuft man den Baum in der Reihenfolge Wurzel-Linksaußen-Linksinnen-Rechtsinnen-<br />

Rechtsaußen (WLaLiRiRa), so erhält man die untenstehende Folge von Knoteninhalten, die<br />

als Bilddatei gespeichert werden kann:<br />

−1, −1, −1, 1, 0, 0, 0, 0, 0, 0, 1, −1, 0, 0, 1, 0, −1, 0, 1, 0, −1, 0, 1, 0, 0<br />

a) Stellen Sie den QuadTree zur rechts abgebildeten 8x8-<br />

Schwarz-Weiß-Grafik dar. Geben Sie anschließend die Folge<br />

von Knoteninhalten an, die als Bilddatei gespeichert werden<br />

könnte.


) Eine 8x8-Grafik ist in Form einer Bilddatei (nach der oben genannten<br />

Durchlaufstrategie WLaLiRiRa) abgelegt:<br />

−1, −1, 0, −1, 0, 1, 1, 0, −1, 0, 1, 1, 0, 0, −1, −1, 1, 0, 0, 1, 0, 0, −1, 1, 0, 0, 1,<br />

−1, 1, 1, 0, 0, −1, 0, 0, 1, 1<br />

Stellen Sie den zugehörigen QuadTree grafisch dar.<br />

Stellen Sie die zugehörige 8x8 Grafik dar.<br />

Analysieren Sie, was passieren würde, wenn Sie mit dieser Datei statt einer 8x8-Grafik<br />

eine 16x16-Grafik aufbauen würden?<br />

Stellen Sie die zugehörige 16x16-Grafik dar und beschreiben Sie die Veränderungen<br />

bzgl. der 8x8-Grafik.<br />

Begründen Sie, ob es möglich ist, aus dieser Datei eine 4x4-Grafik aufzubauen und<br />

erläutern Sie eventuelle Einschränkungen.<br />

c) Nebenstehend sehen Sie eine Modellierung der<br />

Klasse TQuadTree.<br />

Dokumentieren Sie die Klasse.<br />

d) Implementieren Sie die Methode<br />

LoadFromFile(...) , welche den Aufbau<br />

eines QuadTrees aus einer Datei mit dem angegebenen Dateinamen übernimmt.<br />

Hinweis 1: Damit die Methode aufgerufen werden kann, muss die Wurzel des<br />

QuadTrees bereits erzeugt sein (siehe Oberflächenprozedur). Berücksichtigen Sie dies<br />

in Ihrer Implementierung.<br />

Hinweis 2: Falls Sie die Methode LadeRekursiv_WLaLiRiRa in Ihrer<br />

Implementierung benötigen, so implementieren Sie diese bitte ebenfalls.<br />

Lösung:<br />

type TQuadTreeFile = file of shortint;<br />

procedure TQuadTree.LoadFromFile(dateiname: string);<br />

var ...<br />

begin<br />

...<br />

end;<br />

procedure MI_OeffnenClick(Sender: TObject);<br />

var QT: TQuadTree;<br />

begin<br />

QT:= TQuadTree.Create;<br />

QT.LoadFromFile(´Baum.dat´);<br />

end;<br />

Aufgabe 3:<br />

a) Zur angegebenen Grafik gehört der folgende QuadTree


−1<br />

−1<br />

0<br />

−1 –1<br />

−1 0 0<br />

–1<br />

0 1 0 1 1 0 1 0<br />

0 1 0 1<br />

0 1 0 1<br />

Das Bild entspricht somit der Datei<br />

−1, −1, −1, 0, 1, 0, 1, 0, 0, −1, 0, 1, 0, 1, 0, −1, 0, 1, 0, 1, −1, 1, 0, 1, 0<br />

b.1) Der zugehörige QuadTree sieht wie folgt aus:<br />

−1<br />

−1<br />

–1<br />

−1<br />

–1<br />

0 –1 –1<br />

0<br />

–1 0 0<br />

–1<br />

1 1 0 0 0 0<br />

1 1<br />

0 1 1 0<br />

0<br />

1 1 0<br />

1 0 0 1<br />

1 0 0 1<br />

b.2) Und das zugehörige 8x8-Bild hat folgendes Aussehen:<br />

b.3) Würde man aus der Datei ein 16x16-Bild aufbauen, so wäre es um den Faktor 2<br />

„gezoomt“:<br />

b.4) Aus dieser Datei ist es nicht so ohne weiteres möglich, da der Baum eine Tiefe von 4<br />

Ebenen hat. Die dritte Ebene entspricht aber bereits dem Farbwert eines Pixels, so dass<br />

für die vierte Ebene ein Pixel aufgeteilt werden müsste. Dies ist jedoch nicht möglich.


Eine Möglichkeit bestände darin, die Farbwerte der Teilbäume aus der vierten Ebene zu<br />

einem Farbwert für ein Pixel zusammenzufassen („Rendering“ durch<br />

Mittelwertbildung). Diese Möglichkeit muss jedoch vom Prüfling nicht erkannt werden.<br />

c) Die Dokumentation der Klasse könnte wie folgt aussehen:<br />

Anfrage LoadFromFile:<br />

vorher: Baum mit einem Wurzelelement<br />

nachher: Baum, welcher aus einer Datei ausgelesen wurde<br />

Auftrag SaveToFile:<br />

vorher: Baum exisitert und ist nicht leer<br />

nachher: Der Baum wurde in der Traversierung WLaLiRiRa in die Datei gespeichert.<br />

Auftrag Zeichnen:<br />

vorher: Der Baum ist nicht leer<br />

nachher: Der Baum wurde in der Paintbox ausgegeben<br />

Anfrage Leer:<br />

vorher: Der Baum exisitiert<br />

nachher: Ist der Baum leer, so wird true zurück gegeben, andernfalls false<br />

Auftrag LadeRekursiv_WLaLiRiRa<br />

vorher: Die Datei ist geöffnet<br />

nachher: Der Baum wurde aus der Datei eingelesen.<br />

d) Lediglich der Dateiname wird übergeben, so dass eine Rahmenprozedur die Datei öffnen<br />

muss und eine innere rekursive Prozedur die Inhalte PreOrder einlesen muss.<br />

procedure TQuadTree.LadeRekursiv_WLaLiRiRa(var f:<br />

TQuadTreeFile);<br />

var i: integer;<br />

begin<br />

Readln(f,Farbwert);<br />

if Farbwert=-1<br />

then begin<br />

for i:= 1 to 4<br />

do begin<br />

Teilbaeume[i]:= TQuadTree.Create;<br />

Teilbaeume[i].LadeRekursiv_WLaLiRiRa(f);<br />

end;<br />

end;<br />

end;<br />

procedure TQuadTree.LoadFromFile(dateiname: string);<br />

var datei : TQuadTreeFile;<br />

begin<br />

AssignFile(datei, dateiname);<br />

ReSet(datei);<br />

LadeRekursiv_WLaLiRiRa(datei);<br />

CloseFile(datei);<br />

end;<br />

procedure MI_OeffnenClick(Sender: TObject);


var QT: TQuadTree;<br />

begin<br />

QT:= TQuadTree.Create;<br />

QT.LoadFromFile(´Baum.dat´);<br />

end;


Aufgabe 4:<br />

Baumstrukturen – Suchbäume − AVL-Bäume<br />

a) In einen anfangs leeren Suchbaum werden nacheinander die Elemente<br />

10, 20, 30, 50, 40, 60, 70 eingefügt.<br />

Zeichnen Sie den resultierenden Suchbaum.<br />

b) Erläutern Sie an diesem Beispiel die Nachteile, die sich bei der Verwendung von<br />

Suchbäumen ergeben können.<br />

c) Die Elemente aus Aufgabenteil a) werden nun in einen anfangs leeren AVL-Baum<br />

eingefügt.<br />

Stellen Sie schrittweise die Entwicklung des AVL-Baums dar.<br />

d) Die Elemente 10, 60, 50, 70 werden nacheinander aus dem AVL-Baum aus Teilaufgabe c)<br />

gelöscht.<br />

Stellen Sie schrittweise die Entwicklung des AVL-Baums dar.<br />

e) Rechts abgebildet sehen Sie das UML-Diagramm der Klasse<br />

TAVLTree.<br />

Implementieren Sie die Methode getTreeHeight<br />

Hinweis: Die Dokumentation der Klasse TBinTree finden<br />

Sie in der ANLAGE IV<br />

Lösung:<br />

Aufgabe 4: a)<br />

10<br />

20<br />

30<br />

50<br />

40 60<br />

70<br />

b) Man erkennt direkt, dass der Baum annähernd zu einer linearen Liste entartet. Die Vorteile<br />

der geringen Suchtiefe von O(log n) in einem ausgeglichenen Suchbaum mit n Elementen<br />

gehen verloren.<br />

c)


20<br />

10<br />

10<br />

30<br />

20<br />

20<br />

30 LR(10)<br />

50<br />

40 RR(50), LR(30)<br />

40<br />

10<br />

40<br />

20<br />

50<br />

30<br />

50<br />

10<br />

30 60<br />

40<br />

60 LR(20)<br />

70 LR(50)<br />

20<br />

60<br />

10<br />

30<br />

50<br />

70<br />

d)<br />

40<br />

40<br />

20<br />

60<br />

20<br />

50<br />

30<br />

50<br />

40<br />

70<br />

30<br />

40<br />

70<br />

20<br />

70 20<br />

30<br />

30<br />

30 LR(20) RR(40) 20<br />

40<br />

e) function TAVLTree.getTreeHeight: integer;<br />

function hoehe(tree: TBinTree): integer;<br />

var l, r: integer;<br />

begin<br />

if isEmpty()<br />

then result:= 0<br />

else begin<br />

l:= hoehe(getLeftTree as TBinTree);<br />

r:= hoehe(getRightTree as TBinTree);<br />

if l>r then result:= l + 1<br />

else result:= r + 1;<br />

end;<br />

end;<br />

begin<br />

result:= hoehe(pTree);<br />

end;


Aufgabe 5:<br />

AVL-Bäume<br />

a) Die nachfolgend aufgeführten Knoteninhalte sollen in einen anfangs leeren AVL-<br />

Baum eingefügt werden. Stellen Sie den schrittweisen Aufbau des AVL-Baums grafisch<br />

dar. Zeichnen Sie auch nach jeder Korrekturoperation den neu entstandenen AVL-Baum.<br />

45; 25; 15; 13; 12; 11; 8; 7; 50; 53; 35; 63<br />

b) Löschen Sie aus dem nachfolgend angegebenen AVL-Baum sukzessive die<br />

Knoteninhalte 16, 30, 40, 11. Geben Sie nach jedem Löschvorgang den entstandenen<br />

Baum an.<br />

30<br />

18<br />

10 23<br />

37<br />

33 40<br />

7<br />

11<br />

20 25<br />

32<br />

5<br />

16<br />

21<br />

c) Implementieren Sie eine Funktion TreeHeight(tree: TBinTree), welche die Höhe eines<br />

Baumes berechnet und zurückgibt. Verwenden Sie wann immer möglich die Methoden<br />

der Klasse TBinTree (Anlage I).<br />

d) Implementieren Sie eine Funktion IsAVLTree(tree: TBinTree), welche überprüft, ob ein<br />

Binärbaum bezüglich seiner Balancierung ein AVL-Baum ist (die Sortierung der<br />

Knoteninhalte soll keine Rolle spielen). Verwenden Sie wann immer möglich die<br />

Methoden der Klasse TBinTree (Anlage I).<br />

Lösung:<br />

Aufgabe 5:<br />

a)


)<br />

c) function TreeHeight(tree: TBinTree): integer;<br />

var l, r: integer;<br />

begin<br />

if tree.isEmpty()<br />

then result := 0<br />

else begin<br />

l:= TreeHeight(tree.getLeftTree);<br />

r:= TreeHeight(tree.getRightTree);<br />

if l> r<br />

then result := l + 1<br />

else result := r + 1;<br />

end;<br />

end;<br />

d) function IsAVLTree(tree: TBinTree): boolean;<br />

var l, r: boolean;


alance: integer;<br />

begin<br />

if tree.isEmpty<br />

then result:= true<br />

else begin<br />

l:= IsAVLTree(tree.getLeftTree);<br />

r:= IsAVLTree(tree.getRightTree);<br />

balance:= TreeHeight(tree.getRightTree) -<br />

TreeHeight(tree.getLeftTree);<br />

result := l and r and (balance in [-1,0,1];<br />

end;<br />

end;


Aufgabe 2:<br />

Bäume<br />

Ein Mobile besteht in der Regel aus Stangen, die untereinander mit Fäden verbunden sind und<br />

an denen an beiden Enden je ein Anhänger befestigt ist. Im einfachsten Fall wollen wir jedoch<br />

auch einen einzelnen Anhänger schon als Mobile auffassen. Folgende Fälle könne also für ein<br />

Mobile unterschieden werden:<br />

Extremfall: Mobile besteht aus einem<br />

Anhänger:<br />

Normalfall: Mobile besteht aus mehreren Stangen,<br />

an deren Ende entweder eine weitere Stange oder<br />

ein Anhänger hängt:<br />

links<br />

10mm<br />

rechts<br />

40mm<br />

links<br />

20mm<br />

rechts<br />

10mm<br />

5000 g<br />

1200 g<br />

100 g<br />

200 g<br />

Bereits an diesem Beispiel erkennt man, dass der Normalfall eines Mobiles auf vielen<br />

einzelnen kleinen Mobiles besteht. Als <strong>Informatik</strong>er können wir dies rekursiv formulieren:<br />

Ein Mobile besteht aus<br />

a) einem Anhänger (Rekursionsanker)<br />

b) aus einer Stange, an denen sich zwei Teilmobiles befinden.<br />

Im Fall a) interessiert uns lediglich die Masse (m) des Anhängers in Gramm.<br />

Die Kraft (F), mit der ein solcher Anhänger an der Stange zieht berechnet sic nach der<br />

physikalischen Vorschrift:F = m⋅g, wobei für die Erdbeschleunigung g = 9,81 m/s 2<br />

angenommen werden kann.<br />

Im Fall b) interessiert uns nur der Aufhängepunkt, also die Werte für die Abstände rechts und<br />

links in Millimetern, wie in der Skizze gezeigt. Wir gehen der Einfachheit halber davon aus,<br />

dass sowohl die Fäden als auch die Stangen gegenüber den Anhängergewichten ein<br />

vernachlässigbares Gewicht haben.<br />

Ein Mobile ist im Gleichgewicht, wenn das Hebelgesetz der Physik erfüllt ist:<br />

F l ⋅ links = F r ⋅ rechts<br />

a) Weisen Sie nach, dass sich das oben dargestellte Mobile überall im Gleichgewicht<br />

befindet.<br />

b) Zeichnen Sie ein Mobile mit mindestens 4 Stangen, welches sich überall im<br />

Gleichgewicht befindet.<br />

c) Zeichnen Sie jeweils ein UML-Klassendiagramm für die Klassen Anhaenger, Stange<br />

und Mobile. Geben Sie im Klassendiagramm alle Datenfelder und Methoden an.


d) Zeichnen Sie nun ein neues Klassendiagramm ohne Methoden und Datenfelder für die<br />

Klassen BinTree und die drei oben genannten Klassen. Veranschaulichen Sie in Ihrem<br />

Diagramm die Beziehungen und begründen Sie Ihre Wahl.<br />

e) Implementieren Sie eine Methode void beispiel(), welches das oben angegebene<br />

Beispiel-Mobile erzeugt.<br />

f) Implementieren Sie für die Klasse Mobile eine Methode int gesamtmasse(),<br />

welche die Gesamtmasse des gespeicherten Mobiles berechnet.<br />

g) Analysieren Sie die folgende Methode und geben Sie an, zu welchem Zweck diese<br />

implementiert wurde.<br />

private boolean rekursiveFunktion(BinTree b) {<br />

if (b.isEmpty()) {<br />

return true;<br />

} else {<br />

if (b.getRootItem() instanceof Anhaenger) {<br />

return true;<br />

} else {<br />

if (b.getRootItem() instanceof Stange) {<br />

return gesamtmasse(b.getLeftTree()) *<br />

((Stange)b.getRootItem()).getLinks() ==<br />

gesamtmasse(b.getRightTree()) *<br />

((Stange)b.getRootItem()).getRechts()<br />

&& rekursiveFunktion(b.getLeftTree())<br />

&& rekursiveFunktion(b.getRightTree());<br />

}<br />

}<br />

}<br />

h) Implementieren Sie die folgenden drei Konstruktoren:<br />

Mobile()<br />

// leeres Mobile<br />

Mobile(int gewicht)<br />

// Mobile mit einem Anhänger<br />

Mobile(Mobile m1, Mobile m1, int l1, int l2) // Mobile mit zwei Teilmobiles (m1<br />

und m2), die an einer Stange in<br />

den Entfernungen l1 bzw. l2<br />

angebracht sind.<br />

Die Klasse BinTree<br />

In einem Objekt der Klasse BinTree werden beliebige Objekte nach dem Binärbaumprinzip<br />

verwaltet. Ein Binärbaum ist entweder leer oder besteht aus einem Knoten, dem ein Element<br />

und zwei binäre Teilbäume, die so genannten linken und rechten Teilbäume, zugeordnet<br />

sind.<br />

Dokumentation der Methoden der Klasse BinTree<br />

Konstruktor BinTree()<br />

nachher Ein leerer Baum existiert<br />

Konstruktor BinTree (Object pObject)<br />

nachher Der Binärbaum existiert und hat einen Wurzelknoten mit dem Inhalt pObject und<br />

zwei leeren Teilbäumen.<br />

Konstruktor BinTree (Object pObject, BinTree pLeftTree, BinTree<br />

pRighttree)<br />

nachher Der Binärbaum existiert, hat einen Wurzelknoten mit dem Inhalt pObject sowie<br />

dem linken Teilbaum pLeftTree und dem rechten Teilbaum pRightTree.<br />

Anfrage isEmpty(): boolean


nachher Diese Anfrage liefert den Wahrheitswert true, wenn der Binärbaum leer ist, sonst<br />

liefert sie den Wert false.<br />

Auftrag clear()<br />

nachher Der Binärbaum ist leer.<br />

Auftrag setRootItem (Object pObject)<br />

nachher Die Wurzel hat – unabhängig davon, ob der Binärbaum leer ist oder schon eine<br />

Wurzel hat – pObject als Inhalt. Eventuell vorhandene Teilbäume werden nicht<br />

geändert.<br />

Anfrage getRootItem(): Object<br />

vorher Der Binärbaum ist nicht leer.<br />

nachher Diese Anfrage liefert den Inhalt des Wurzelknotens des Binärbaums.<br />

Auftrag setLeftTree (BinTree pTree)<br />

vorher Der Binärbaum ist nicht leer.<br />

nachher Die Wurzel hat den übergebenen Baum als linken Teilbaum.<br />

Auftrag setRightTree (BinTree pTree)<br />

vorher Der Binärbaum ist nicht leer.<br />

nachher Die Wurzel hat den übergebenen Baum als rechten Teilbaum.<br />

Anfrage getLeftTree(): BinTree<br />

vorher Der Binärbaum ist nicht leer.<br />

nachher Diese Anfrage liefert den linken Teilbaum der Wurzel des Binärbaums. Der<br />

Binärbaum ist unverändert.<br />

Anfrage getRightTree(): BinTree<br />

vorher Der Binärbaum ist nicht leer.<br />

nachher Diese Anfrage liefert den rechten Teilbaum der Wurzel des Binärbaums. Der<br />

Binärbaum ist unverändert.<br />

Lösung:<br />

Aufgabe 2:<br />

Baumstrukturen<br />

a) 100g⋅20mm⋅9,81m/s 2 = 200g⋅100mm⋅9,81m/s 2 und<br />

1200g⋅10mm⋅9,81m/s 2 = 300g⋅40mm⋅9,81m/s 2<br />

b) verschiedene Lösungen sind denkbar…<br />

c) und d)


e) public void beispiel() {<br />

Anhaenger a1 = new Anhaenger(1200);<br />

Anhaenger a2 = new Anhaenger(100);<br />

Anhaenger a3 = new Anhaenger(200);<br />

Stange s1 = new Stange(10,40);<br />

Stange s2 = new Stange(20,10);<br />

tree = new BinTree(s1,<br />

new BinTree(a1),<br />

new BinTree(s2,<br />

new BinTree(a2),<br />

new BinTree(a3)<br />

)<br />

);<br />

}<br />

f) private int gesamtmasse(BinTree b) {<br />

if (b.isEmpty()) {<br />

return 0;<br />

} else {<br />

if (b.getRootItem() instanceof Anhaenger) {<br />

return ((Anhaenger)b.getRootItem()).getGewicht();<br />

} else {<br />

if (b.getRootItem() instanceof Stange) {<br />

return gesamtmasse(b.getLeftTree()) +<br />

gesamtmasse(b.getRightTree());<br />

} else {<br />

throw new RuntimeException("Kein Mobilebaum!");<br />

}<br />

}<br />

}<br />

}<br />

public int gesamtmasse() {<br />

try {<br />

return gesamtmasse(tree);<br />

} catch (Exception e) {<br />

System.err.println(e.toString());<br />

return -1;<br />

}<br />

}


g) Die Methode überprüft, ob sich das gesamte Mobile im Gleichgewicht befindet. Dazu<br />

werden zwei Fälle unterschieden:<br />

1. Besteht das Mobile nur aus einem Anhänger, so befindet sich das Mobile natürlich im<br />

Gleichgewicht.<br />

2. Ist das Mobile eine Stange, so wird zunächst geprüft, ob sich das Mobile am aktuellen<br />

Knoten im Gleichgewicht befindet (gesamtmasse*laenge auf beiden Seiten gleich).<br />

Anschließend wird noch geprüft, ob sich die beiden Teilmobiles, die links und rechts an<br />

der Stange hängen, ebenfalls im Gleichgewicht befinden. Ist dies der Fall, so befindet<br />

sich das gesamte Mobile im Gleichgewicht, andernfalls nicht.<br />

h) public Mobile() {<br />

tree = new BinTree();<br />

}<br />

public Mobile(int gewicht) {<br />

tree = new BinTree(new Anhaenger(gewicht));<br />

}<br />

public Mobile(Mobile m1, Mobile m2, int l1, int l2) {<br />

Stange stange = new Stange(l1, l2);<br />

tree = new BinTree(stange, m1.getTree(), m2.getTree());<br />

}


Aufgabe 2:<br />

Binärbäume<br />

Im Morsealphabet ist jeder Buchstabe durch eine Aneinanderreihung von Punkten (·) und<br />

Strichen (-) codiert. Die Codierung der Buchstaben lautet wie folgt:<br />

Morsealphabet<br />

A ·- B -·· C -·-· D -··· E · F ··-· G --· H ···· I ·· J ·--- K -·- L ·-·· M –-<br />

N -· O --- P ·--· Q --·- R ·-· S ··· T - U ··- V ···- W ·-- X -··- Y -·-- Z --··<br />

Eine Möglichkeit, den Morse-Code zu verwalten, ist die Speicherung der Codes in einem<br />

Binärbaum. Der Morsepunkt bewirkt dabei eine Verzweigung nach<br />

links, der Morsestrich eine Verzweigung nach rechts. In jedem<br />

Knoten des Baumes steht der Buchstabe, der durch den im Baum<br />

vorausgegangenen Punkt-Strich-Code repräsentiert wird.<br />

a) Stellen Sie den Morsecode wie oben beschrieben als Baum dar.<br />

Der Pfad zum Buchstaben R müsste in Ihrem Baum wie rechts<br />

abgebildet aussehen.<br />

b) Übersetzen Sie den folgenden Morsetext. Die |-Zeichen trennen die<br />

einzelnen Buchstaben.<br />

-|---|·-··|·-··|·|-·-|·-··|·-|··-|···|··-|·-·<br />

...<br />

R<br />

−<br />

•<br />

•<br />

...<br />

...<br />

c) Beschreiben Sie, wie man algorithmisch vorgeht, wenn man einen Text mit Hilfe des<br />

Baumes übersetzen möchte.<br />

d) Begründen Sie, warum eine Trennung der einzelnen Buchstaben (hier durch das<br />

Zeichen | ) erforderlich ist.<br />

Folgende Datenstruktur soll im folgenden für die Speicherung des Morsebaumes verwendet<br />

werden:<br />

Die Morsecodes der Buchstaben 'A' bis 'Z' sind dabei im Datenfeld codeTabelle wie folgt<br />

gespeichert:<br />

private static String[] codeTabelle = {<br />

".-","-..","-.-.","-...",".","..-.","--.","....","..",".---","-.-",".-..","--",<br />

"-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."<br />

};<br />

e) Analysieren Sie die folgende Methode, d. h., erläutern Sie ihre Arbeitsweise, indem Sie die<br />

wesentlichen Zeilen bzw. Abschnitte kommentieren, und erläutern Sie kurz die zentrale<br />

Funktionalität der Methode.


Hinweis: Objekte der Klasse Character enthalten lediglich ein Datenfeld vom Typ char,<br />

welches mithilfe der Methode char charValue() geholt werden kann.<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

private void xxx() {<br />

this.baum = new BinTree();<br />

BinTree hilf;<br />

for (char buchstabe = 'A'; buchstabe


Anfrage isEmpty(): boolean<br />

nachher Diese Anfrage liefert den Wahrheitswert true, wenn der Binärbaum leer ist, sonst<br />

liefert sie den Wert false.<br />

Auftrag clear()<br />

nachher Der Binärbaum ist leer.<br />

Auftrag setRootItem (Object pObject)<br />

nachher Die Wurzel hat – unabhängig davon, ob der Binärbaum leer ist oder schon eine<br />

Wurzel hat – pObject als Inhalt. Eventuell vorhandene Teilbäume werden nicht<br />

geändert.<br />

Anfrage getRootItem(): Object<br />

vorher Der Binärbaum ist nicht leer.<br />

nachher Diese Anfrage liefert den Inhalt des Wurzelknotens des Binärbaums.<br />

Auftrag setLeftTree (BinTree pTree)<br />

vorher Der Binärbaum ist nicht leer.<br />

nachher Die Wurzel hat den übergebenen Baum als linken Teilbaum.<br />

Auftrag setRightTree (BinTree pTree)<br />

vorher Der Binärbaum ist nicht leer.<br />

nachher Die Wurzel hat den übergebenen Baum als rechten Teilbaum.<br />

Anfrage getLeftTree(): BinTree<br />

vorher Der Binärbaum ist nicht leer.<br />

nachher Diese Anfrage liefert den linken Teilbaum der Wurzel des Binärbaums. Der<br />

Binärbaum ist unverändert.<br />

Anfrage getRightTree(): BinTree<br />

vorher Der Binärbaum ist nicht leer.<br />

nachher Diese Anfrage liefert den rechten Teilbaum der Wurzel des Binärbaums. Der<br />

Binärbaum ist unverändert.<br />

Lösung:<br />

Aufgabe 2:<br />

Binärbäume<br />

a) Der Morsebaum hat folgende Struktur:<br />

b) Der Text lautet: TOLLEKLAUSUR<br />

c) Initialisiere den Klartext mit einer leeren Zeichenkette<br />

Lies den Morsetext Zeichen für Zeichen.<br />

Liest man das Zeichen | so<br />

Erweitere den Klartext um das Zeichen im aktuellen Knoten des Baums


Starte wieder an der obersten Wurzel Morsebaums.<br />

Liest man das Zeichen . so<br />

Gehe im Morsebaum nach links runter<br />

Liest man das Zeichen – so<br />

Gehe im Morsebaum nach rechts runter<br />

d) Die Trennungszeichen sind nötig, da man sonst z. B. den Morsecode "---" als den<br />

Buchstaben O aber auch als dreimal den Buchstaben T interpretieren könnte.<br />

e) Die Methode xxx erstellt zunächst einen leeren Binärbaum.<br />

Für alle Buchstaben von A bis Z wird jedes mal am Anfang des (zu Anfang leeren)<br />

Binärbaums gestartet. In der Variablen morsecode steht der zum Zeichen zugehörige<br />

Morsecode.<br />

Ist der Baum noch leer, so wird zunächst eine Wurzel mit unbekanntem Zeichen angelegt.<br />

Danach wird je nach aktuellem Zeichen des zum Buchstaben zugehörigen Morsecodes im<br />

Binärbaum nach links oder rechts verzweigt.<br />

Hat man den ganzen Morsecode abgearbeitet (Ende der for-Schleife), so kann in die<br />

Wurzel des aktuellen Knotens der aktuelle Buchstabe geschrieben werden. Evtl. wird<br />

dabei ein unbekanntes Zeichen aus einem vorherigen Schleifendurchlauf überschrieben.<br />

Die Methode baut den Morsecode für alle Buchstaben von A bis Z auf.<br />

f) public String klarToMorse(char klar) {<br />

klar = Character.toUpperCase(klar);<br />

if (klar >= 'A' && klar

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!