15.02.2013 Aufrufe

b2aat6n

b2aat6n

b2aat6n

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.

Listing 8<br />

Auf einen leeren Stack testen.<br />

[Test]<br />

public void Enthaelt_nach_der_Entnahme_des_top_Elementes_keine_weiteren_Elemente()<br />

{<br />

sut.Pop();<br />

Assert.That(sut.top, Is.Null);<br />

}<br />

Listing 9<br />

Mehrere Push-Aufrufe.<br />

[Test]<br />

public void Macht_das_naechste_uebergebene_Element_zum_top_Element() {<br />

sut.Push("b");<br />

Assert.That(sut.top.Data, Is.EqualTo("b"));<br />

}<br />

[Test]<br />

public void Legt_das_vorhandene_Element_bei_Uebergabe_eines_weiteren_unter_dieses() {<br />

sut.Push("b");<br />

Assert.That(sut.top.Next.Data, Is.EqualTo("a"));<br />

}<br />

in einem ersten Test geprüft werden, ob<br />

dieses Element bei Aufruf der Pop-Methode<br />

zurückgegeben wird, siehe Listing 7.<br />

Nun kann überprüft werden, ob der<br />

Stack denn nach dem Pop auch wieder leer<br />

ist, siehe Listing 8. Und jetzt hilft alles<br />

nichts, wir müssen uns mit mehr als einem<br />

Push befassen. Dabei kommt es darauf an,<br />

das neue Element vor das bisherige top-<br />

Element einzuordnen. Dazu muss der top-<br />

Zeiger geändert werden sowie der Next-<br />

Zeiger des top-Elements. Listing 9 zeigt die<br />

entsprechenden Tests.<br />

Daraus ergibt sich dann die fertige Implementierung<br />

des Stacks wie in Listing 10.<br />

Reflexion<br />

Die testgetriebene Vorgehensweise hat mir<br />

keine großen Probleme bereitet. Das lag<br />

zum Großteil daran, dass ich meine Skizze<br />

zur Hand hatte. So konnte ich bei Fragen<br />

sofort nachsehen, wie die top- und Next-<br />

Zeiger jeweils aussehen müssen. Und dadurch,<br />

dass die Tests auf die Interna zugreifen<br />

können, musste ich nicht schon für den<br />

ersten Test gleich zwei Methoden implementieren.<br />

Das ist ein großer Vorteil, der<br />

bei einem so kleinen Beispiel wie einem<br />

Stack möglicherweise nicht so deutlich<br />

wird. Ich habe diesen Effekt jedoch schon<br />

in einigen Fällen als vorteilhaft empfunden,<br />

bei denen es um den internen Zustand<br />

von Klassen ging. Immer da, wo<br />

mehrere Methoden auf einem internen Zustand<br />

arbeiten, kann es sich lohnen, den<br />

Zustand für die Tests sichtbar zu machen,<br />

um bei der Implementierung Methode für<br />

Methode vorgehen zu können.<br />

Queue<br />

Bei der Warteschlange bin ich so verfahren<br />

wie schon beim Stack: Ich habe mir überlegt,<br />

wie man eineWarteschlange in einer Datenstruktur<br />

darstellen kann. Meine Überlegung<br />

hier: Bei einer Warteschlange sollte es offensichtlich<br />

zwei Zeiger geben, die jeweils auf<br />

ein Element verweisen. Zum einen auf das<br />

zuletzt eingefügte Element, um dort bei der<br />

Enqueue-Methode ein weiteres Element ergänzen<br />

zu können, sowie einen Zeiger auf<br />

das nächste zu entnehmende Element für<br />

die Dequeue-Methode. In meiner ersten<br />

Skizze malte ich also das erste und letzte<br />

Element einer Warteschlange und verwies<br />

darauf jeweils mit den Zeigern enqueue und<br />

dequeue, wie es Abbildung 2 zeigt.<br />

Listing 10<br />

LÖSUNG<br />

Die fertige Implementierung<br />

des Stacks.<br />

public class Stack :<br />

IStack {<br />

internal Element top;<br />

public TElement Pop() {<br />

if (top == null) {<br />

throw new<br />

InvalidOperationException();<br />

}<br />

var result = top.Data;<br />

top = top.Next;<br />

return result;<br />

}<br />

public void Push(TElement element) {<br />

var newTop = new Element {<br />

Data = element,<br />

Next = top<br />

};<br />

top = newTop;<br />

}<br />

}<br />

Im Anschluss habe ich überlegt, wie die<br />

Elemente untereinander sinnvoll zu verbinden<br />

sind. Dabei gibt es mehrere Möglichkeiten:<br />

❚ Jedes Element zeigt mit Next auf das ihm<br />

folgende.<br />

❚ Jedes Element zeigt mit Prev auf das<br />

hinter ihm liegende.<br />

❚ Jedes Element enthält sowohl Next- als<br />

auch Prev-Zeiger.<br />

Die doppelte Verkettung habe ich nicht<br />

weiter berücksichtigt, da ich vermutete,<br />

dass es auch ohne gehen muss. Dabei stand<br />

nicht der Reflex im Vordergrund, dass eine<br />

doppelteVerkettung mehr Speicher braucht<br />

als eine einfache. Ich dachte eher daran,<br />

dass ich bei doppelter Verkettung beim Einfügen<br />

und Entfernen von Elementen zwei<br />

Zeiger korrigieren muss. Das erschien mir in<br />

jedem Fall mühsamer, als nur einen Zeiger<br />

korrigieren zu müssen. Es siegte sozusagen<br />

die pure Faulheit.<br />

Es blieb noch die Frage zu klären, ob<br />

Next- oder Prev-Zeiger sinnvoller sind. Das<br />

habe ich mir wieder anhand meiner Skizze<br />

überlegt. Wenn ein neues Element in die<br />

Warteschlange eingefügt wird, muss enqueue<br />

anschließend auf das neue Element<br />

zeigen. Bei Verwendung von Next-Zeigern<br />

muss dann nichts korrigiert werden, bei<br />

Prev-Zeigern muss das bisher erste Element<br />

auf das neue erste zurückverweisen.<br />

Beides ist kein Problem, es ergibt sich also<br />

hier noch keine Präferenz für eines der bei-<br />

www.dotnetpro.de dotnetpro.dojos.2011 41<br />

[Abb. 2]<br />

enqueue-<br />

und<br />

dequeue-<br />

Zeiger.

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

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!