list_sort.hpp

Back to Doubly-linked list

pastel/sys/list/

#ifndef PASTELSYS_LIST_SORT_HPP
#define PASTELSYS_LIST_SORT_HPP

#include "pastel/sys/list/list_sort.h"

#include <vector>

namespace Pastel
{

    template <
        typename Settings,
        template <typename> class Customization,
        typename Less>
    List<Settings, Customization>& sort(
        List<Settings, Customization>& list,
        Less less)
    {
        using Set = List<Settings, Customization>;

        if (list.size() < 2)
        {
            // Nothing to do.
            return list;
        }

        // Shamelessly copied from Microsoft Stl implementation:/

        integer MaxBins = 25;
        Set tempList;
        std::vector<Set> binSet(MaxBins + 1);
        integer maxBin = 0;

        while (!list.empty())
        {
            // sort another element, using bins
            // don't invalidate iterators
            tempList.splice(tempList.begin(), list, list.begin());

            integer bin = 0;
            for (bin = 0; bin < maxBin && !binSet[bin].empty();++bin)
            {
                // merge into ever larger bins
                merge(binSet[bin], tempList, less);
                binSet[bin].swap(tempList);
            }

            // i e [0, maxBin[ => binSet[i].empty()
            // =>
            // tempList contains all of the elements
            // thus far in an ordered list.

            if (bin == MaxBins)
            {
                merge(binSet[bin - 1], tempList, less);
            }
            else
            {   // spill to new bin, while they last
                binSet[bin].swap(tempList);
                if (bin == maxBin)
                {
                    ++maxBin;
                }
            }
        }

        for (integer bin = 1; bin < maxBin; ++bin)
        {
            // Merge up
            merge(binSet[bin], binSet[bin - 1], less);
        }

        // Result in last bin
        list.splice(list.begin(), binSet[maxBin - 1]);

        return list;
    }

}

#endif