Home > Informatik > Stufe Q1 > ADTs > ADTs im Abitur

14.61 Aufgaben mit Stacks - Lösungshinweise

Allgemeines - Abstrakte Datentypen - Stack - Queue - Dictionary - ADTs im Abitur - Axiome

Kopieren eines Stacks

Diese Quelltext sollte erweitert werden:

import java.util.ArrayList;

public class Test
{
    Stack stapel1, stapel2;

    public Test()
    {
       stapel1 = new Stack();
       stapel1.push(new Bruch(3,4));
       stapel1.push(new Bruch(5,8));
       stapel1.push(new Bruch(1,7));
       
       stapel2 = new Stack();
       kopiere(stapel1,stapel2);
      
       show(stapel1);
       show(stapel2);
    }
    
    public void kopiere(Stack quelle, Stack ziel)
    {
    
    }
    
    public void show(Stack s)
    {
       while (!s.empty())
       {
          Bruch b = (Bruch) s.top();
          b.show();
          s.pop();
       }
    }
}

Vor allem sollte die Kopier-Methode vervollständig werden. Der die Klasse Stack "datengekapselt" ist, haben Sie keine Ahnung, wie der Stack intern implemementiert wurde. Sie können nur mit den öffentlichen Methoden push, pop, top und empty auf den Stack zugereifen, und dummerweise haben Sie immer nur Zugriff auf das oberste Stack-Elemente.

Hier ein kleiner Hinweis, wie Sie die Aufgabe lösen könnten:

Sie erzeugen in der Methode kopiere zunächst einen weiteren Stack, einen lokalen Stack, den Sie vielleicht temp nennen. In einer while-Schleife nehmen Sie das oberste Element des Stacks quelle , pushen es auf temp und löschen es anschließend aus quelle. Dann nehmen Sie wieder das oberste Element von quelle, pushen es auf temp und löschen es anschließend. Löschen müssen Sie das jeweils oberste Element des Stacks, weil Sie nur so an das jeweils darunterliegende Element herankommen. Am Ende der while-Schleife ist quelle leer, und temp enthält alle Elemente von quelle , allerdings in umgekehrter Reihenfolge.

Jetzt wiederholen Sie das Ganze, nur kopieren Sie diesmal den Stack temp in den Stack ziel hinein, nach dem gleichen Verfahren. Der Stack temp ist dann anschließend leer, und in ziel sind alle Elemente von temp enthalten, allerdings wieder in umgekehrter Reihenfolge. Das ist aber nicht schlimm, denn temp enthielt ja die Elemente von quelle in umgekehrter Reihenfolge. Wenn beim zweiten Kopiervorgang die Umkehrung umgekehrt wird, ist das Original wieder hergestellt. Das heißt, ziel ist jetzt eine exakte Kopie von quelle .

Allerdings ist quelle nach der ersten while-Schleife leer. Wir hatten ja gesehen, dass ein Stack-Parameter keine unabhängige Kopie des übergebenen Stacks ist, sondern die Adresse des Original-Stacks. Verändert man also den Parameter, verändert man auch den übergebenen Stack, also das Original. Daher ist quelle nach der ersten Kopier-Aktion leer, und das gilt dann auch für den übergebenen Original-Stack.

Wie kann man das verhindern? Ganz einfach, wir müssen in der zweiten while-Schleife die temp -Elemente nicht nur nach ziel kopieren, sondern parallel auch wieder nach quelle . Am Ende der while-Schleife haben Sie dann zwei komplette und identische Stacks.

Hier nun ein möglicher Konstruktor, der die Methode kopiere testet:

    public Test()
    {
       stapel1 = new Stack();
       stapel1.push(new Bruch(3,4));
       stapel1.push(new Bruch(5,8));
       stapel1.push(new Bruch(1,7));
       
       stapel2 = new Stack();
     
       kopiere(stapel1,stapel2);
       System.out.println("Stapel 1:");
       show(stapel1);
      
       kopiere(stapel2,stapel1);
       System.out.println("Stapel 2:");
       show(stapel2);
       
       System.out.println("Stapel 1:");
       show(stapel1);
    }

Der Stack stapel1 wird nach stapel2 kopiert, dann wird stapel1 angezeigt und dadurch gelöscht. Wenn jetzt sofort stapel2 angezeigt würde, wäre auch stapel2 hinterher gelöscht. Darum wird vor dem anzeigen von stapel2 dieser wieder zurück nach stapel1 kopiert. Dass das funktioniert, zeigt dann das erneute Anzeigen von stapel1 am Ende des Quelltextes. Danach ist stapel1 natürlich leer, da die kopier-Methode nicht mehr aufgerufen wurde.

Verbinden von zwei Stacks

Diese Quelltext sollte erweitert werden:

import java.util.ArrayList;

public class Test
{
    Stack stapel1, stapel2, stapel12;

    public Test()
    {
       stapel1 = new Stack();
       stapel1.push(new Bruch(1,4));
       stapel1.push(new Bruch(1,8));
       stapel1.push(new Bruch(1,7));
       
       stapel2 = new Stack();
       stapel2.push(new Bruch(2,4));
       stapel2.push(new Bruch(2,8));
       stapel2.push(new Bruch(2,7));
       
       stapel12 = verbinde(stapel1,stapel2);
       System.out.println("Stapel 1+2:");
       show(stapel12);
    }
    
    public Stack verbinde(Stack teil1, Stack teil2)
    {
    }
   
    public void show(Stack s)
    {
    }
}

Die show-Methode kennen Sie bereits aus der ersten Aufgabe zum Thema Stacks. Beim Verbinden der beiden Stacks können Sie sich an der Kopier-Methode der ersten Aufgabe orientieren.

Als erstes fertigen Sie eine Kopie von stapel2 an, in der die Reihenfolge der Stack-Elemente genau umgekehrt ist. Diese Kopie kopieren Sie dann auf den stapel1. Dabei wird die Kopie gelöscht, was ja aber nicht schlimm ist. Der erweiterte stapel1 wird dann von verbinde als Rückgabeparameter zurückgegeben.