import liste.*;

/**
 * Sortiert eine Liste nach dem MergeSort-Algorithmus
 * 
 * @author Rainer Helfrich
 * @version Januar 2021
 */
public class MergeSort extends SortierenMitBenchmark
{
    /**
     * Die Liste, die gefüllt und sortiert werden soll
     */
    public MergeSort(Liste<Integer> l)
    {
        super(l);
    }

    /**
     * Gibt eine (ggf. neue) Liste zurück, die die Zahlen der Eingabeliste in sortierter Reihenfolge enthält
     * @param l Die zu sortierende Liste; wird u.U. verändert.
     * @return Eine Liste mit den sortierten Elementen der Eingabeliste
     */
    protected Liste<Integer> sortiere(Liste<Integer> l)
    {
        if (l.laenge() <= 1)
            return l;
        Class c = l.getClass();
        try
        {
            Liste<Integer> links = (Liste<Integer>)c.getConstructor().newInstance();
            int laenge = l.laenge();
            for (int i = 0; i < laenge/2; i++)
            {
                links.anhaengen(l.getNtenWert(0));
                l.entferneBei(0);
            }
            Liste<Integer> rechts = l;
            links = sortiere(links);
            rechts = sortiere(rechts);
            Liste<Integer> out = (Liste<Integer>)c.getConstructor().newInstance();
            while(!links.istLeer() && !rechts.istLeer())
            {
                int lw = links.getNtenWert(0);
                int rw = rechts.getNtenWert(0);
                if (lw < rw)
                {
                    out.anhaengen(lw);
                    links.entferneBei(0);
                }
                else
                {
                    out.anhaengen(rw);
                    rechts.entferneBei(0);
                }
            }
            while(!links.istLeer())
            {
                out.anhaengen(links.getNtenWert(0));
                links.entferneBei(0);
            }
            while(!rechts.istLeer())
            {
                out.anhaengen(rechts.getNtenWert(0));
                rechts.entferneBei(0);
            }
            return out;
        }
        catch(Exception x)
        {
            return null;
        }
    }
}
