17. Erweiterung der Implementierung mit verketteter Liste Inhaltsverzeichnis 19. Persistenz

18. Rekursion

Die rekursive Struktur der inneren Klasse Node legt nahe, die Methoden equals und copy (alternativ) rekursiv zu implementieren:

def equals(that: ExtQ[E]) =

   nodeEquals(this.ältester,

     that.asInstanceOf[ExtListQ[E]].ältester)

private def nodeEquals(erster: Option[Node[E]],

     zweiter: Option[Node[E]]): Boolean =

   erster == None && zweiter == None || // beide Listen zu Ende, oder [1]

   erster != None && zweiter != None && // keine der Listen zu Ende, und

     erster.get.wert == zweiter.get.wert && // Inhalte gleich, und

     nodeEquals(erster.get.verbindung, zweiter.get.verbindung)

def copy(q: ExtQ[E]) = {

   val that = q.asInstanceOf[ExtListQ2[E]]

   this.ältester = nodeCopy(that.ältester)

   this.jüngster =

     if (this.ältester == None)

        None

     else

        lastNode(this.ältester) }

private def nodeCopy(quelle: Option[Node[E]]): Option[Node[E]] =

   if (quelle == None) // Liste zu Ende

     None

   else

     Some(new Node[E](quelle.get.wert,

        nodeCopy(quelle.get.verbindung)))

private def lastNode(node: Option[Node[E]]): Option[Node[E]] =

   // require node != None

   if (node.get.verbindung == None)

     node

   else

     lastNode(node.get.verbindung);

Dieser Algorithmus ist etwas ineffektiv, weil verkettete die Liste nach ihrer Erzeugung nochmals durchlaufen werden muss, um den jüngsten Knoten (lastNode()) zu finden. In einem weniger eleganten Programm kann dies erspart bleiben:

private var jung: Option[Node[E]] = None

private def nodeCopy(quelle: Option[Node[E]]) =

   if (quelle == None)

     None

   else {

     val neu = Some(new Node[E](quelle.get.wert,

           nodeCopy(quelle.get.verbindung)))

     if (jung == None && neu != None) // jüngster Knoten

        jung = neu;

     neu }

Jetzt kann in copy der Knoten jüngster ohne Durchlauf ermittelt werden:

   this.jüngster = jung;

Mit Hilfe von Objektdiagrammen kann nun der Auf- und Abbau des Stapels im Zuge der rekursiven Aufrufe demonstriert werden.

Auch mit der Reihungstechnik ist es möglich, equals und copy rekursiv zu implementieren. So kann gezeigt werden, dass Rekursion immer eine Alternative zu Wiederholungen (for bzw. while) ist – die Entscheidung ist eine Abwägung zwischen Einfachheit/Verständlichkeit und Effizienz des Algorithmus.

17. Erweiterung der Implementierung mit verketteter Liste Inhaltsverzeichnis 19. Persistenz

[1] && bindet stärker als ||; ferner berechnet || (bzw. &&) seinen rechten Operanden nicht, wenn der linke true (bzw. false) ergibt


Version: 5. Dezember 2010

© Prof. Solymosi, 2010, Beuth-Hochschule für Technik Berlin