import java.util.LinkedList;
import java.util.Queue;

public class MergeSortQueue {

    // Méthode de tri principal qui effectue le tri fusion
    public static <T extends Comparable<T>> Queue<T> trier(Queue<T> file) {
        if (file.size() <= 1) {
            return file;
        }

        // Séparer la file en deux moitiés
        Queue<T> file1 = new LinkedList<>();
        Queue<T> file2 = new LinkedList<>();
        scinder(file, file1, file2);

        // Tri de chaque moitié de façon récursive
        file1 = trier(file1);
        file2 = trier(file2);

        // Fusion des deux moitiés triées
        return fusionner(file1, file2);
    }

    // Méthode pour diviser une file en deux moitiés
    private static <T> void scinder(Queue<T> source, Queue<T> file1, Queue<T> file2) {
        int taille = source.size();
        for (int i = 0; i < taille / 2; i++) {
            file1.add(source.poll());
        }
        while (!source.isEmpty()) {
            file2.add(source.poll());
        }
    }

    // Méthode pour fusionner deux files triées en une seule file triée
    private static <T extends Comparable<T>> Queue<T> fusionner(Queue<T> file1, Queue<T> file2) {
        Queue<T> resultat = new LinkedList<>();

        while (!file1.isEmpty() && !file2.isEmpty()) {
            if (file1.peek().compareTo(file2.peek()) <= 0) {
                resultat.add(file1.poll());
            } else {
                resultat.add(file2.poll());
            }
        }

        // Ajouter les éléments restants de chaque file, s'il en reste
        while (!file1.isEmpty()) {
            resultat.add(file1.poll());
        }
        while (!file2.isEmpty()) {
            resultat.add(file2.poll());
        }

        return resultat;
    }

    // Méthode de test pour le tri
    public static void main(String[] args) {
        Queue<Double> file = new LinkedList<>();

        // Remplir la file avec les arguments passés en ligne de commande
        for (String arg : args) {
            file.add(Double.parseDouble(arg));
        }

        // Tri de la file
        Queue<Double> fileTriee = trier(file);

        // Affichage des éléments triés
        for (Double valeur : fileTriee) {
            System.out.print(valeur + " ");
        }
        System.out.println("");
    }
}
