Fragen über Stack

Jaklin

Mitglied
Hallo, ich muss Ergänzungen im Konstruktor sowie in den Methoden peek, pop, push und empty vornehmen.Aber ich bekomme einen Laufzeitfehler! Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10! Kann bitte jemand mir helfen ! Ich weiß nicht was ich hier falsch mache ?

⚠️ Achtung: wie in den Schnittstellenkommentaren angedeutet ist es nicht nötig, den Stack zu vergrößern!

Java:
class IntArrayStack
{
    private final int[] _stack;
    private int _anzElemente;

    /**
     * Erzeugt einen Stack mit einer Maximalgroesse.
     *
     * @param size Maximalgröße des Stacks. Muss größer als 0 sein.
     */
    public IntArrayStack(int size)
    {
        _anzElemente=0;
        if (size <= 0)
        {
            throw new IllegalArgumentException();
        }
       
        // Hier Code einfuegen
        _stack=new int[size];
    }
   
    /**
     * Gibt an, ob der Stack Elemente enthält.
     *
     * @return true, wenn der Stack leer ist
     */
    public boolean empty()
    {
        // Hier Code einfuegen
       if(_anzElemente==0) {
         
           return true;
       }
       return false;
    }

    /**
     * Gibt das zuletzt hinzugefügte Element zurück, ohne den Zustand des
     * Stacks zu verändern.
     *
     * @return zuletzt hinzugefügtes Element oder 0, wenn der Stack leer ist
     */
    public int peek()
    {
        // Hier Code einfuegen
     
        if(_anzElemente==0){
            return 0;
        }
        return _stack[_anzElemente];
    }

    /**
     * Gibt das zuletzt hinzugefügte Element zurück und entfernt es
     * vom Stack. Gibt 0 zurück, wenn der Stack leer ist.
     *
     * @return zuletzt hinzugefügtes Element
     */
    public int pop()
    {
         //int v=_stack.length;
        if(_anzElemente==0)
        {
            return 0;
        }
        // Hier Code einfuegen
         _anzElemente --;
        return _stack[_anzElemente+1];

    }

    /**
     * Fuegt dem Stack ein neues Element hinzu. Lässt den Stack
     * unverändert, wenn die maximale Anzahl an Elementen erreicht ist.
     *
     * @param x Element, das hinzugefuegt werden soll.
     */
    public void push(int x)
    {
        // Hier Code einfuegen
        // Fuegt dem Stack ein neues Element hinzu.
        if(_anzElemente<_stack.length){
        for ( int i = 0; i < _stack.length; i++)
        {
         _stack[i]=x;
         _anzElemente ++ ;

    }
        }

}
}
 

Anhänge

  • error123.PNG
    error123.PNG
    21,6 KB · Aufrufe: 2

White_Fox

Top Contributor
Schau dir mal den ersten Index eines Arrays an, welchen Wert der hat. Und wieviele Elemente willst du in ein Array legen, wenn du bis einschließlich zehn zählst?
 

KonradN

Super-Moderator
Mitarbeiter
Ich denke, das mit dem Index ist erst einmal richtig. Der Fehler ist in der Methode push.

Beschreibe erst einmal, was bei push zu tun ist. Das ist immer der erste Schritt. Erst plausibel in Worten etwas beschreiben. Das ist dann auch einfach zu verstehen. Dann den Code anhand der Erkenntnisse prüfen.

Einfache Frage: Brauchst da z.B. eine Schleife? Und was machst Du da in der Schleife?
 

Jaklin

Mitglied
Ich denke, das mit dem Index ist erst einmal richtig. Der Fehler ist in der Methode push.

Beschreibe erst einmal, was bei push zu tun ist. Das ist immer der erste Schritt. Erst plausibel in Worten etwas beschreiben. Das ist dann auch einfach zu verstehen. Dann den Code anhand der Erkenntnisse prüfen.

Einfache Frage: Brauchst da z.B. eine Schleife? Und was machst Du da in der Schleife?
Ich will auf Index zugreifen und danach das Element einfügen (pushen) ,deswegen habe ich For-Schleife benutzt! Sollte man ohne For-Schleife implementieren?
 

temi

Top Contributor
Zu deinem Problem hat @KonradN bereits geschrieben. Von mir nur eine Anmerkung. Deine Lösung für empty() ist korrekt, aber lässt sich auch noch stark vereinfachen:
Java:
if(_anzElemente == 0) {       
    return true;
}

return false;


// Kann man vereinfachen zu:

return _anzElemente == 0;

Die Erklärung dazu ist einfach. Der Ausdruck der Bedingung _anzElemente == 0 ergibt einen boolean-Wert. Die Methode empty() soll einen boolean-Wert als Ergebnis zurück geben. Demnach kannst du hier direkt das Ergebnis des Vergleichs zurück geben.

Du kannst allerdings auch deine Lösung beibehalten. Wie schon geschrieben, sie ist nicht falsch.
 

Jaklin

Mitglied
Du kennst den Index ja bereits, deshalb benötigst du keine Schleife dazu.
Ich habe das jetzt so geschrieben :
Java:
 public void push(int x)
    {
        // Hier Code einfuegen
        // Fuegt dem Stack ein neues Element hinzu.
        if(_anzElemente<_stack.length){
        
         _stack[_anzElemente]=x;
        
        }

}
aber ich bekomme noch einige Fehler !
 

Anhänge

  • error122.PNG
    error122.PNG
    18,3 KB · Aufrufe: 1

Jaklin

Mitglied
Dein Code ist nicht korrekt! Überlege genau, was die Methode machen soll. Wo würde das nächste Element eingefügt werden?
erst _anzElemente ist gleich "0" das nächste Mal mit _anzElemente ++ wird _anzElemente gleich "1" und das nächste Element wird so befüllt
_stack[1]=x; und es wird weiter so befüllt für die weitere Indexe bis _anzElemente<_stack.length ist .Ich weiß nicht, warum es immer noch nicht klappt !

Java:
public void push(int x)
    {
        // Hier Code einfuegen
        // Fuegt dem Stack ein neues Element hinzu.
        if(_anzElemente<_stack.length)
        {
        
       _stack[_anzElemente]=x;
        
      _anzElemente++;
    
        }
        
}
 

Jaklin

Mitglied
Hier der ganze Code ! Immer noch Laufzeitfehler !
Java:
class IntArrayStack
{
    private final int[] _stack;
    private int _anzElemente;

    /**
     * Erzeugt einen Stack mit einer Maximalgroesse.
     *
     * @param size Maximalgröße des Stacks. Muss größer als 0 sein.
     */
    public IntArrayStack(int size)
    {
        _anzElemente=0;
        if (size <= 0)
        {
            throw new IllegalArgumentException();
        }
       
        // Hier Code einfuegen
        _stack=new int[size];
    }
   
    /**
     * Gibt an, ob der Stack Elemente enthält.
     *
     * @return true, wenn der Stack leer ist
     */
    public boolean empty()
    {
        // Hier Code einfuegen
       if(_anzElemente==0) {
         
           return true;
       }
       return false;
    }

    /**
     * Gibt das zuletzt hinzugefügte Element zurück, ohne den Zustand des
     * Stacks zu verändern.
     *
     * @return zuletzt hinzugefügtes Element oder 0, wenn der Stack leer ist
     */
    public int peek()
    {
        // Hier Code einfuegen
     
        if(_anzElemente==0){
            return 0;
        }
        return _stack[_anzElemente];
    }

    /**
     * Gibt das zuletzt hinzugefügte Element zurück und entfernt es
     * vom Stack. Gibt 0 zurück, wenn der Stack leer ist.
     *
     * @return zuletzt hinzugefügtes Element
     */
    public int pop()
    {
       
        if(_anzElemente==0)
        {
            return 0;
        }
        // Hier Code einfuegen
         _anzElemente --;
        return _stack[_anzElemente+1];

    }

    /**
     * Fuegt dem Stack ein neues Element hinzu. Lässt den Stack
     * unverändert, wenn die maximale Anzahl an Elementen erreicht ist.
     *
     * @param x Element, das hinzugefuegt werden soll.
     */
    public void push(int x)
    {
        // Hier Code einfuegen
        // Fuegt dem Stack ein neues Element hinzu.
        if(_anzElemente<_stack.length){
       
       
         _stack[_anzElemente]=x;
       
      _anzElemente++;
   
        }else{
            throw new IllegalArgumentException();
           
        }
       
       

}
}
 
Zuletzt bearbeitet:

LimDul

Top Contributor
Vergleich mal peek mit pop. Sollte peek nicht das Element lieferen, was pop auch liefern würde?

Was ist, wenn genau 1 Element in der Liste ist, und du rufst peek auf? An welcher Stelle im Array steht das Element?
 

Jaklin

Mitglied
Vergleich mal peek mit pop. Sollte peek nicht das Element lieferen, was pop auch liefern würde?

Was ist, wenn genau 1 Element in der Liste ist, und du rufst peek auf? An welcher Stelle im Array steht das Element?
bei pop muss _anzElemente, eine weniger werden ! Aber was da zurück gibt muss mit das Element im peek übereinstimmen. Deswegen habe ich unter pop return _stack[_anzElement+1] geschrieben !peek gibt das letzte Element zurück deswegen habe ich nur return _stack[_anzElemente] geschrieben! Wenn nur ein Element ist unter peek() wird nur _stack[0] zurück gegeben und unter pop() wird das gleiche zurückgegeben und _anzElement wird "0"
 

KonradN

Super-Moderator
Mitarbeiter
Schreibe es doch bitte einmal im Detail auf, was wie passiert.

Du kannst sowas mit STift und Papier im Detail durchspielen. Nur so findet man die Fehler.

Also mal es Dir auf. So eine Stack Instanz auf einem Zettel ist dann:
_anzElemente: <eine Zahl>
_stack: <Eine Reihe von Kästchen>

Also wenn Du ein Stack der Größe 3 Erzeugt hast, dann sollte auf Deinem Zettel stehen:
_anzElement: 0
stack: [_][][]

Und unter die drei Felder schreibst du die Indizes, mit denen Du es ansprechen kannst - damit Du nicht versehentlich etwas falsch machst.

Nun fügst Du ein Element ein. Was passiert?

Nun willst du per peek ein Element abrufen: Welches Element musst Du abfragen?
Nun willst du per pop ein Element heraus nehmen: Welches Element musst Du zurück geben? Und wie verändert sich _anzElement?


Und einfach, weil man es nicht gut genug betonen kann: Mal es Dir auf! Wenn Du Dir sowas nicht im Kopf überlegen kannst, dann ist das ok! Aber dann muss man sich helfen können und da geht nichts über Stift und Papier! Das wichtigste Werkzeug in einem Entwicklerteam ist eine Tafel / Whiteboard!
 

KonradN

Super-Moderator
Mitarbeiter
Was das Problem auch etwas aufzeigt: Man muss sich wirklich genau überlegen, was denn eine Variable bedeutet. _anzElement ist die Anzahl der Elemente. Aber in Bezug auf das Array: Auf welches Element verweist denn diese Variable? Verweist es auf das aktuelle Element? Auf das erste freie Element?

Das nur als kleine Hilfe - wenn man sich so Beschreibungen überlegt und aufschreibt, dann kann man sich ggf. die Zeichnung ggf. sparen, da die Zusammenhänmge dadurch so vereinfacht werden, dass diese im Kopf handhabbar werden.
 

White_Fox

Top Contributor
Und einfach, weil man es nicht gut genug betonen kann: Mal es Dir auf! Wenn Du Dir sowas nicht im Kopf überlegen kannst, dann ist das ok! Aber dann muss man sich helfen können und da geht nichts über Stift und Papier! Das wichtigste Werkzeug in einem Entwicklerteam ist eine Tafel / Whiteboard!
Richtig, tatsächlich kann man das gar nicht fett genug schreiben.
 

Jaklin

Mitglied
erst muss ich checken ob array leer ist oder nicht und habe deswegen die empty Methode benutzt . _stack[_anzElemente] ist doch das peek element?ich weiß nicht was genau falsch mit der Implementation ist ! Immer noch solche Meldungen falsch: Das Element was per peek Aufruf zurück gegeben wurde stimmt falsch: Nachdem etwas auf einen vollen Stack gepusht wurde, wird nicht das richtige Element von pop zurückgegeben. nicht
Java:
 public int peek()
    {
        // Hier Code einfuegen
    
    
 
        return !empty()? _stack[_anzElemente]:0;
    
    }

    /**
     * Gibt das zuletzt hinzugefügte Element zurück und entfernt es
     * vom Stack. Gibt 0 zurück, wenn der Stack leer ist.
     *
     * @return zuletzt hinzugefügtes Element
     */
    public int pop()
    {
      
        _anzElemente --;
      
        return  !empty()? _stack[_anzElemente+1] : 0;
    
        
      
        

    }
 

Jaklin

Mitglied
und push habe ich noch so bearbeitet
Java:
 public void push(int x)
    {
        // Hier Code einfuegen
        // Fuegt dem Stack ein neues Element hinzu.
        if(_anzElemente<_stack.length-1){
        
        
         _stack[_anzElemente]=x;
        
      _anzElemente++;
    
      
}
 

KonradN

Super-Moderator
Mitarbeiter
_stack[_anzElemente] ist doch das peek element?
Ganz offensichtlich nicht!

und push habe ich noch so bearbeitet
Java:
 public void push(int x)
    {
        // Hier Code einfuegen
        // Fuegt dem Stack ein neues Element hinzu.
        if(_anzElemente<_stack.length-1){
       
       
         _stack[_anzElemente]=x;
       
      _anzElemente++;
   
     
}
Nicht raten! Du hast eine klare Fehlermeldung, dass peek falsch sein soll. Dann fang nicht an blind zu experimentieren!


Überlege es Dir doch einmal: Wenn Du ein _stack mit 3 Elemente hast, dann greifst Du auf diese Elemente mit den Indices 0, 1 und 2 zu! Also die Indices gehen von 0 bis size-1!

Wenn 0 Elemente enthalten sind, dann packst Du das nächste Element in Index 0.
Wenn 1 Element enthalten ist, dann packst Du das nächste Element in Index 1
Wenn 2 Elemente enthalten sind, dann packst Du das nächste Element in Index 2
Wenn 3 Elemente enthalten sind, dann ist der Stack voll (Bei 3 Elementen).

Also war es richtig, dass Du das nächste Element in anzElemente gepackt hast und auch die Prüfung war richtig!

Nun überlege: Wenn 1 Element vorhanden ist: Welches Element (den Index!) gibst Du dann zurück?
Wenn 2 Elemente vorhanden sind: Welches Element (Index!) gibst Du dann zurück?
Wenn 3 Elemente vorhanden sind: Welches Element (wieder der Index!) gibst Du dann zurück?
 

Jaklin

Mitglied
wenn ein Element ist muss index 0 sein und zwei index 1 und für das dritte Element muss index 2 angezeigt weden aber wir wissen nicht ob das array voll ist oder nicht deswegen können wir nicht so implementieren return !empty()? _stack[_stack.length-1]:0;
 

KonradN

Super-Moderator
Mitarbeiter
Also immer ein Schritt nach dem anderen!

Du hattest ja schon einen Check, der 0 zurück gibt, wenn der Stack leer war. Wenn das die Anforderung ist, dann ist der Part doch schon ok.

Und Du hast ja schon einen Zusammenhang festgestellt:
1 Element im Stack -> Element an index 0 wird zurück gegeben.
2 Elemente im Stack -> Element an index 1 wird zurück gegeben.
3 Elemente im Stack -> Element an index 2 wird zurück gegeben.

Also wenn anzElemente Elemente im Stack sind - welches Element gibst Du dann zurück?

Und noch ein Tipp: Lass unleserliche Dinge, wenn Du noch unsicher in Java bist (oder besser generell!) Wenn Du so unsicher bist in Java, dann lass den ganz weg! Nutz if Statements um Deinen Code zu bauen. Das macht es Dir leichter, deinen eigenen Code zu lesen.
 

Jaklin

Mitglied
_anzElemente ist immer eine höher als index , dann kann man auch so denke ich schreiben ,aber das klappt leider nicht
Java:
 public int peek()
    {
        // Hier Code einfuegen
      
      
  
        return !empty()? _stack[_anzElemente-1]:0;
      
    }
 

KonradN

Super-Moderator
Mitarbeiter
Also das sieht bei peek erst einmal gut aus. Aber schreibe es doch ohne ternären Operator:
Java:
    public int peek()
    {
        if(_anzElemente==0){
            return 0;
        }
        return _stack[_anzElemente-1];
    }

Aber dann wäre noch die Methode pop() und auch noch einmal die Methode push - die hattest Du ja zwischenzeitlich kaputt gemacht.
 

Jaklin

Mitglied
_anzElemente -- wird nicht ausgeführt weil nach return steht aber vor return macht es auch keinen Sinn _anzElemente -- zu schreiben ! Bei push denke ich soweit muss es funktionieren !
Java:
 /**
     * Gibt das zuletzt hinzugefügte Element zurück und entfernt es
     * vom Stack. Gibt 0 zurück, wenn der Stack leer ist.
     *
     * @return zuletzt hinzugefügtes Element
     */
    public int pop()
    {
        
        if( !empty()){
            return  _stack[_anzElemente-1];
        }
        return 0;
       
        _anzElemente --;
      
          
        
      

    }

    /**
     * Fuegt dem Stack ein neues Element hinzu. Lässt den Stack
     * unverändert, wenn die maximale Anzahl an Elementen erreicht ist.
     *
     * @param x Element, das hinzugefuegt werden soll.
     */
    public void push(int x)
    {
        // Hier Code einfuegen
        // Fuegt dem Stack ein neues Element hinzu.
        if(_anzElemente<_stack.length-1){
        
        
         _stack[_anzElemente]=x;
        
      _anzElemente++;
    
      
        
        

}
 

Jaklin

Mitglied
Zieh halt zuerst Eins ab und verzichte beim folgenden Indexzugriff darauf es noch einmal zu tun.
meinst du so ? dann bekomme ich Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 5
Java:
 public int pop()
    {
        _anzElemente --;
        if( !empty()){
            return  _stack[_anzElemente];
        }
        return 0;
      

    }
 

KonradN

Super-Moderator
Mitarbeiter
Nein!

a) Wenn es nicht leer ist:
  • reduzierst Du anzElemente um 1
  • gibst dann den Wert zurück.
==> Das reduzieren kommt also in das if!

b) Was hast Du bei dem push gemacht? Wieso machst Du da noch ein -1?
Das Array ist voll, wenn die Anzahl der Elemente gleich der Größe des Arrays ist. Also wenn das Array 10 Platz hat, dann ist es voll, wenn 10 Elemente drin sind.
 

Neue Themen


Oben