Home > Informatik > Stufe Q1 > Referenzen > dynamische List

15.42 Quelltext-Analyse, Teil 7

concat() und remove()

Die manipulierende Methode concat verbindet zwei Listen, und remove löscht das aktuelle Element aus der Liste.

concat()
  /**
     * Die Liste pList wird an die Liste angehängt. Anschließend wird pList
     * eine leere Liste. Das aktuelle Objekt bleibt unverändert. Falls pList null
     * oder eine leere Liste ist, bleibt die Liste unverändert.
     */    
    public void concat(List pList)
    {
        last.nachfolger = pList.first;
        last = pList.last;
        pList.first = null;
        pList.last = null;
        pList = null;
    }

Wäre nicht die zweite Bedingung in den Anforderungen, nämlich dass pList nach erfolgtem concat leer sein muss, so wäre die Implementation recht kurz. Der Nachfolger-Zeiger des letzten Listen-Elements der ersten Liste wird einfach auf das erste Listen-Element der zweiten Liste gesetzt, und der last-Zeiger, der jetzt zur gesamten neuen Liste gehört, wird auf das letzte Element der Gesamtliste gesetzt, das ja identisch ist mit dem letzten Element der angehängten Liste.

Die letzten drei Zeilen der Methode sind nur dafür da, pList zur leeren Liste zu machen.

Zurück zum Quelltext...

remove() - fehlerhafte kurze Version
   /** 
     * Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird das aktuelle
     * Objekt gelöscht und das Objekt hinter dem gelöschten Objekt wird zum
     * aktuellen Objekt. Wird das Objekt, das am Ende der Liste steht, gelöscht, 
     * gibt es kein aktuelles Objekt mehr (hasAccess() == false). Wenn die Liste
     * leer ist oder es kein aktuelles Objekt gibt (hasAccess() == false),
     * bleibt die Liste unverändert.
     */
    public void remove()
    {
       if ( (isEmpty()) || (!hasAccess())) return;
       
       Knoten help = first;
       while (help.nachfolger != act) help = help.nachfolger;
       act = act.nachfolger;
       help.nachfolger = act;
    }

Zunächst werden die Fälle behandelt, in denen remove wirkungslos bleibt. Wenn die Liste leer ist oder wenn es kein aktuelles Element gibt, gibt es nichts zu entfernen. Wenn eine der beiden Bedingungen erfüllt ist, wird die Methode mit return einfach beendet.

Andernfalls scheint es ja ein aktuelles Element zu geben, das entfernt werden soll. Um ein Element aus der Liste zu entfernen, muss man eigentlich nur den Vorgängeknoten suchen und dessen Nachfolger-Zeiger auf den Nachfolger des zu entfernenden Elementes setzen.

remove() - hoffentlich korrekte Version
    public void remove()
    {
    // Fall 0: Liste ist leer oder es gibt kein aktuelles Element
       if ( (isEmpty()) || (!hasAccess())) return;
       
    // Fall 2: Liste besteht aus nur einem Element
       if (first == last)
       {
          first = last = act = null; 
          return;
       }
       
    // Fall 3a: es soll vorne gelöscht werden
       if (act == first)
       {
          act = act.nachfolger;
          first = act;
          return;
       }
       
    // Fall 3b: es soll hinten gelöscht werden
       if (act == last)
       {
           Knoten help = first;
           while (help.nachfolger != act) help = help.nachfolger;           
           help.nachfolger = null;
           last = help;
           return;
       }
       
    // Fall 4: es soll in der Mitte gelöscht werden
       Knoten help = first;
       while (help.nachfolger != act) help = help.nachfolger;  
       act = act.nachfolger;
       help.nachfolger = act;
    }

Die erste Version enthielt noch einige Fehler, die sich aber erst beim ausführlichen Testen offenbarten. Die neue Version ist hoffentlich fehlerfrei.

Übung 15-3-1 (Vortrag)

Finden Sie die Fehler in der ersten Version und erläutern Sie (kleiner Vortrag), unter welchen Umständen hier welche Fehler auftreten.

Zurück zum Quelltext...