
/**
 * Ein Stack basierend auf einer verketteten Liste
 * 
 * @author Rainer Helfrich
 * @version Oktober 2020
 */
public class LinkedStack<T> extends Stack<T>
{
    /**
     * Das oberste Element des Stacks
     */
    private Listenknoten<T> topNode;

    /**
     * Erzeugt einen neuen leeren Stack
     */
    public LinkedStack()
    {
        topNode = null;
    }

    /**
     * Gibt das oberste Element des Stacks zurück (falls der Stack nicht leer ist)
     * @return Das oberste Element
     */
    public T top()
    {
        if (!isEmpty())
        {
            return topNode.daten;
        }
        return null;
    }

    /**
     * Entfernt das oberste Element vom Stack (falls der Stack nicht leer ist) und gibt es zurück
     * @return Das bisherige oberste Element
     */
    public T pop()
    {
        T top = null;
        if (!isEmpty())
        {
            top = topNode.daten;
            topNode = topNode.nachfolger;
        }
        return top;
    }

    /**
     * Legt ein neues Element auf den Stack
     * @param x Das neue Element
     */
    public void push(T wert)
    {
        topNode = new Listenknoten<T>(wert, topNode);
    }

    /**
     * Gibt zurück, ob der Stack leer ist
     * @return true, wenn der Stack leer ist; false sonst
     */
    public boolean isEmpty()
    {
        return topNode == null;
    }

    /**
     * Ein Listenknoten, wie er bei den verketteten Listen verwendet wurde.
     * Diesmal allerdings als innere Klasse
     */
    private class Listenknoten<T>
    {
        /**
         * Der Datenwert des Listenknotens
         */ 
        public T daten;
        /**
         * Der Nachfolger des Listenknotens
         */
        public Listenknoten<T> nachfolger;

        /**
         * Erzeugt einen neuen Listenknoten
         * 
         * @param daten Der Datenwert des Knotens
         * @param nachfolger Der Nachfolger des Knotens
         */ 
        public Listenknoten(T daten, Listenknoten<T> nachfolger)
        {
            this.daten = daten;
            this.nachfolger = nachfolger;
        }
    }
    
    /**
     * Gibt den Stack in String-Form aus.
     * @return Die String-Repräsentation des Stacks
     */
    @Override
    public String toString()
    {
        String ergebnis = " <";
        Listenknoten k = this.topNode;
        while(k != null)
        {
            ergebnis = k.daten + ergebnis;
            if (k.nachfolger != null)
                ergebnis = ", " + ergebnis;
            k = k.nachfolger;
        }
        return "[ " + ergebnis;
    }
}
