Implement the quicksort algorithm in as many different ways as possible

#ifndef GYM_ALGORITHM_QUICK_SORT_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4
#define GYM_ALGORITHM_QUICK_SORT_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4

#include <stdlib.h>
#include "heap_sort.h"
#include "insertion_sort.h"

namespace pratique
{
    namespace details
    {
        inline size_t random( size_t distance )
        {
            return static_cast<size_t>( rand() ) % distance;
        }

        template <typename Iterator>
        struct NullRandomizer
        {
            inline void operator()( Iterator, Iterator, size_t ) {}
        };

        template <typename Iterator>
        struct Randomizer
        {
            inline void operator()( Iterator begin, Iterator sentinel, size_t distance )
            {
                exchange( sentinel, begin + details::random( distance ) );
            }
        };
    }

    namespace ternary_version
    {
        #define DEFINE_TERNARY_VERSION_QUICK_SORT( PARTITION )                         \
            template <typename Iterator>                                               \
            void quick_sort( Iterator begin, Iterator end )                            \
            {                                                                          \
                if ( begin < end ) {                                                   \
                    std::pair<Iterator, Iterator> separator = PARTITION( begin, end ); \
                    quick_sort( begin, separator.first );                              \
                    quick_sort( separator.second, end );                               \
                }                                                                      \
            }

        #define DEFINE_HYBRID_TERNARY_VERSION_1_QUICK_SORT( PARTITION )                    \
            template <size_t N, typename Iterator>                                         \
            void hybrid_quick_sort_v1( Iterator begin, Iterator end )                      \
            {                                                                              \
                if ( begin < end ) {                                                       \
                    if (static_cast<size_t>(std::distance(begin, end)) > N) {              \
                        std::pair<Iterator, Iterator> separator = PARTITION( begin, end ); \
                        hybrid_quick_sort_v1<N, Iterator>( begin, separator.first );       \
                        hybrid_quick_sort_v1<N, Iterator>( separator.second, end );        \
                    } else {                                                               \
                        pratique::insertion_sort( begin, end );                            \
                    }                                                                      \
                }                                                                          \
            }

        #define DEFINE_HYBRID_TERNARY_VERSION_2_QUICK_SORT( PARTITION )                        \
            namespace details                                                                  \
            {                                                                                  \
                template <size_t N, typename Iterator>                                         \
                void hybrid_quick_sort_v2( Iterator begin, Iterator end )                      \
                {                                                                              \
                    if ( begin < end ) {                                                       \
                        if (static_cast<size_t>(std::distance(begin, end)) > N) {              \
                            std::pair<Iterator, Iterator> separator = PARTITION( begin, end ); \
                            hybrid_quick_sort_v2<N, Iterator>( begin, separator.first );       \
                            hybrid_quick_sort_v2<N, Iterator>( separator.second, end );        \
                        }                                                                      \
                    }                                                                          \
                }                                                                              \
            }                                                                                  \
                                                                                               \
            template <size_t N, typename Iterator>                                             \
            void hybrid_quick_sort_v2( Iterator begin, Iterator end )                          \
            {                                                                                  \
                details::hybrid_quick_sort_v2<N, Iterator>( begin, end );                      \
                pratique::insertion_sort( begin, end );                                        \
            }

        #define DEFINE_HYBRID_TERNARY_VERSION_3_QUICK_SORT( PARTITION )                            \
            namespace details                                                                      \
            {                                                                                      \
                template <size_t N, typename Iterator, typename Diff>                              \
                void hybrid_quick_sort_v3( Iterator begin, Iterator end, Diff division )           \
                {                                                                                  \
                    size_t distance = 0;                                                           \
                    for ( ; ( distance = std::distance( begin, end ) ) > N && division > 0; ) {    \
                        division /= 2, division += division / 2; /* allow 1.5 log2(N) divisions */ \
                        std::pair<Iterator, Iterator> separator = PARTITION( begin, end );         \
                        if ( ( separator.first - begin ) >= ( end - separator.second ) ) {         \
                            hybrid_quick_sort_v3<N, Iterator, Diff>(                               \
                                begin, separator.first, division                                   \
                            );                                                                     \
                            begin = separator.second;                                              \
                        } else {                                                                   \
                            hybrid_quick_sort_v3<N, Iterator, Diff>(                               \
                                separator.second, end, division                                    \
                            );                                                                     \
                            end = separator.first;                                                 \
                        }                                                                          \
                    }                                                                              \
                    if ( distance > N ) {                                                          \
                        pratique::heap_sort( begin, end );                                         \
                    } else if ( distance > 0 ) {                                                   \
                        pratique::insertion_sort( begin, end );                                    \
                    }                                                                              \
                }                                                                                  \
            }                                                                                      \
                                                                                                   \
            template <size_t N, typename Iterator>                                                 \
            void hybrid_quick_sort_v3( Iterator begin, Iterator end )                              \
            {                                                                                      \
                details::hybrid_quick_sort_v3<N, Iterator>(                                        \
                    begin, end, std::distance( begin, end )                                        \
                );                                                                                 \
            }


        namespace v1
        {
            /*
             * v is the sentinel
             * __________________________________
             * |  < v  |  = v  | ------ |  > v  |
             * ----------------------------------
             *  |       |       |      |         |
             * begin smaller    i    bigger     end
             *
             * loop invariant:
             *     1. any items belong to [begin, smaller) < v
             *     2. any items belong to [smaller, i) = v
             *     3. any items belong to [bigger+1, end) > v
             */
            template <typename Iterator>
            inline std::pair<Iterator, Iterator> partition( Iterator begin, Iterator end )
            {
                assert( begin < end );
                size_t distance = std::distance(begin, end);
                auto sentinel = *begin;

                Iterator smaller = begin;
                Iterator bigger = begin + distance - 1;
                for ( Iterator i = begin; i <= bigger; ) {
                    if ( *i < sentinel ) {
                        exchange( smaller, i );
                        ++smaller;
                        ++i;
                    } else if ( *i > sentinel ) {
                        exchange( i, bigger );
                        --bigger;
                    } else {
                        ++i;
                    }
                }
                return std::pair<Iterator, Iterator>( smaller, bigger + 1 );
            }

            DEFINE_TERNARY_VERSION_QUICK_SORT( v1::partition )
            DEFINE_HYBRID_TERNARY_VERSION_1_QUICK_SORT( v1::partition )
            DEFINE_HYBRID_TERNARY_VERSION_2_QUICK_SORT( v1::partition )
            DEFINE_HYBRID_TERNARY_VERSION_3_QUICK_SORT( v1::partition )
        }

        namespace v1_1
        {
            /*
             * v is the sentinel
             * __________________________________
             * |  < v  |  = v  | ------ |  > v  |
             * ----------------------------------
             *  |       |       |        |       |
             * begin  equal     i      bigger   end
             *
             * loop invariant:
             *     1. any items belong to [begin, equal) < v
             *     2. any items belong to [equal, i) = v
             *     3. any items belong to [bigger, end) > v
             */
            template <typename Iterator>
            inline std::pair<Iterator, Iterator> partition( Iterator begin, Iterator end )
            {
                assert( begin < end );
                size_t distance = std::distance(begin, end);
                auto sentinel = *begin;

                Iterator equal = begin;
                Iterator bigger = begin + distance;
                for ( Iterator i = begin + 1; i != bigger; ) {
                    if ( *i < sentinel ) {
                        exchange( equal++, i++ );
                    } else if ( *i > sentinel ) {
                        exchange( --bigger, i );
                    } else {
                        ++i;
                    }
                }
                return std::pair<Iterator, Iterator>( equal, bigger );
            }

            DEFINE_TERNARY_VERSION_QUICK_SORT( v1_1::partition )
            DEFINE_HYBRID_TERNARY_VERSION_1_QUICK_SORT( v1_1::partition )
            DEFINE_HYBRID_TERNARY_VERSION_2_QUICK_SORT( v1_1::partition )
            DEFINE_HYBRID_TERNARY_VERSION_3_QUICK_SORT( v1_1::partition )
        }

        namespace v2
        {
            /*
             * v is the sentinel
             * __________________________________
             * | = v | < v | ------ | > v | = v |
             * ----------------------------------
             *  |     |     |      |       |     |
             * begin  p     i      j       q    end
             *
             * loop invariant I:
             *     1. any items belong to [begin, p) = v
             *     2. any items belong to [p, i) < v
             *     3. any items belong to [j+1, q) > v
             *     4. any items belong to [q, end) = v
             * loop invariant II:
             *     derives from the above one ......
             */
            template <typename Iterator>
            inline std::pair<Iterator, Iterator> partition( Iterator begin, Iterator end )
            {
                assert( begin < end );
                size_t distance = std::distance(begin, end);
                std::pair<Iterator, Iterator> separator( begin, end );
                if ( distance > 1 ) {
                #if ( defined( DEBUG ) || defined( _DEBUG ) || defined( DBG ) )
                    std::vector<typename std::iterator_traits<Iterator>::value_type> old_values( begin, end );
                #endif
                    auto sentinel = *begin;

                    // loop invariant I BEGIN
                    Iterator p = begin + 1, i = p, j = begin + distance - 1, q = j + 1;
                    while ( i <= j ) {
                        while ( *i <= sentinel ) {
                            if ( *i == sentinel ) {
                                exchange( p++, i );
                            }
                            ++i;
                            if ( i > j ) {
                                break;
                            }
                        }

                        while ( *j >= sentinel ) {
                            if ( *j == sentinel ) {
                                exchange( --q, j );
                            }
                            --j;
                            if ( j < i ) {
                                break;
                            }
                        }
                        if ( i < j ) {
                            exchange_without_doubt( i, j );
                        }
                    }
                    // loop invariant I END

                    while ( p > begin ) {
                        exchange( --i, --p );
                    }
                    while ( q != end ) {
                        exchange( ++j, q++ );
                    }

                    separator.first = i;
                    separator.second = j + 1;
                #if ( defined( DEBUG ) || defined( _DEBUG ) || defined( DBG ) )
                    if ( separator.first != end ) {
                        for ( auto i = begin; i != separator.first; ++i ) {
                            assert( *i < *separator.first );
                        }
                    }
                    if ( separator.second != begin ) {
                        for ( auto i = separator.second; i != end; ++i ) {
                            assert( *i > *( separator.second - 1 ) );
                        }
                    }
                #endif
                }
                return separator;
            }

            DEFINE_TERNARY_VERSION_QUICK_SORT( v2::partition )
            DEFINE_HYBRID_TERNARY_VERSION_1_QUICK_SORT( v2::partition )
            DEFINE_HYBRID_TERNARY_VERSION_2_QUICK_SORT( v2::partition )
            DEFINE_HYBRID_TERNARY_VERSION_3_QUICK_SORT( v2::partition )
        }

        namespace v3
        {
            /*
             * v is the sentinel
             * __________________________________
             * | < v | = v | ------ | = v | > v |
             * ----------------------------------
             *  |     |     |      |       |     |
             * begin equal  i      j     bigger end
             *
             * loop invariant:
             *     1. any items belong to [begin, equal) < v
             *     2. any items belong to [equal, i) = v
             *     3. any items belong to [j+1, bigger) = v
             *     4. any items belong to [bigger, end) > v
             */
            template <typename Iterator>
            inline std::pair<Iterator, Iterator> partition( Iterator begin, Iterator end )
            {
                assert( begin < end );
                size_t distance = std::distance(begin, end);
                std::pair<Iterator, Iterator> separator( begin, end );
                if ( distance > 1 ) {
                    auto sentinel = *begin;

                    Iterator equal = begin, i = begin + 1, bigger = begin + distance, j = bigger - 1;
                    while ( i <= j ) {
                        while ( *i <= sentinel ) {
                            if ( *i < sentinel ) {
                                exchange( equal++, i );
                            }
                            ++i;
                            if ( i > j ) {
                                break;
                            }
                        }

                        while ( *j >= sentinel ) {
                            if ( *j > sentinel ) {
                                exchange( --bigger, j );
                            }
                            --j;
                            if ( j < i ) {
                                break;
                            }
                        }
                        if ( i < j ) {
                            assert( *i > sentinel && *j < sentinel );
                            exchange_without_doubt( i, j );
                            exchange( equal++, i++ );
                            exchange( --bigger, j-- );
                        }
                    }

                    separator.first = equal;
                    separator.second = bigger != ( begin + distance ) ? bigger : end;
                }
                return separator;
            }

            DEFINE_TERNARY_VERSION_QUICK_SORT( v3::partition )
            DEFINE_HYBRID_TERNARY_VERSION_1_QUICK_SORT( v3::partition )
            DEFINE_HYBRID_TERNARY_VERSION_2_QUICK_SORT( v3::partition )
            DEFINE_HYBRID_TERNARY_VERSION_3_QUICK_SORT( v3::partition )
        }
    }

    #define DEFINE_QUICK_SORT( PARTITION )                                                                         \
        template <typename Iterator>                                                                               \
        void quick_sort( Iterator begin, Iterator end )                                                            \
        {                                                                                                          \
            if ( begin < end ) {                                                                                   \
                Iterator separator = PARTITION<pratique::details::NullRandomizer, Iterator>( begin, end );         \
                quick_sort( begin, separator );                                                                    \
                quick_sort( separator + 1, end );                                                                  \
            }                                                                                                      \
        }

    #define DEFINE_RANDOMIZED_QUICK_SORT( PARTITION )                                                              \
        template <typename Iterator>                                                                               \
        void randomized_quick_sort( Iterator begin, Iterator end )                                                 \
        {                                                                                                          \
            if ( begin < end ) {                                                                                   \
                Iterator separator = PARTITION<pratique::details::Randomizer, Iterator>( begin, end );             \
                randomized_quick_sort( begin, separator );                                                         \
                randomized_quick_sort( separator + 1, end );                                                       \
            }                                                                                                      \
        }

    #define DEFINE_HYBRID_QUICK_SORT_V1( PARTITION )                                                               \
        template <size_t N, typename Iterator>                                                                     \
        void hybrid_quick_sort_v1( Iterator begin, Iterator end )                                                  \
        {                                                                                                          \
            if ( begin < end ) {                                                                                   \
                if ( static_cast<size_t>( std::distance(begin, end) ) > N ) {                                      \
                    Iterator separator = PARTITION<pratique::details::NullRandomizer, Iterator>( begin, end );     \
                    hybrid_quick_sort_v1<N, Iterator>( begin, separator );                                         \
                    hybrid_quick_sort_v1<N, Iterator>( separator + 1, end );                                       \
                } else {                                                                                           \
                    pratique::insertion_sort( begin, end );                                                        \
                }                                                                                                  \
            }                                                                                                      \
        }

    #define DEFINE_HYBRID_QUICK_SORT_V2( PARTITION )                                                               \
        namespace details                                                                                          \
        {                                                                                                          \
            template <size_t N, typename Iterator>                                                                 \
            void hybrid_quick_sort_v2( Iterator begin, Iterator end )                                              \
            {                                                                                                      \
                if ( begin < end ) {                                                                               \
                    if ( static_cast<size_t>( std::distance(begin, end) ) > N ) {                                  \
                        Iterator separator = PARTITION<pratique::details::NullRandomizer, Iterator>( begin, end ); \
                        hybrid_quick_sort_v2<N, Iterator>( begin, separator );                                     \
                        hybrid_quick_sort_v2<N, Iterator>( separator + 1, end );                                   \
                    }                                                                                              \
                }                                                                                                  \
            }                                                                                                      \
        }                                                                                                          \
        template <size_t N, typename Iterator>                                                                     \
        void hybrid_quick_sort_v2( Iterator begin, Iterator end )                                                  \
        {                                                                                                          \
            details::hybrid_quick_sort_v2<N, Iterator>( begin, end );                                              \
            pratique::insertion_sort( begin, end );                                                                \
        }


    namespace clrs_v1
    {
        /*
         * v is the sentinel
         * _______________________________
         * |   <= v   |   > v  | ----- |v|
         * -------------------------------
         *  |        |          |         |
         * begin   small        i        end
         *
         * loop invariant:
         *     1. any items belong to [begin, small+1) <= v
         *     2. any items belong to [small+1, i) > v
         */
        template <template <typename> class Randomizer, typename Iterator>
        inline Iterator partition( Iterator begin, Iterator end )
        {
            assert( begin < end );
            int distance = static_cast<int>( std::distance(begin, end) );
            Iterator last = begin + distance - 1;
            Randomizer<Iterator>()( begin, last, distance );
            auto sentinel = *last;

        #if 0
            Iterator smaller = begin;
            bool first_time = true;
            for ( Iterator i = begin; i < last; ++i ) {
                if ( *i <= sentinel ) {
                    if ( !first_time ) {
                        ++smaller;
                    } else {
                        first_time = false;
                    }
                    exchange( smaller, i );
                }
            }
            if ( !first_time ) {
                ++smaller;
            }
            exchange( smaller, last );
            return smaller;
        #else
            int smaller = -1;
            for ( Iterator i = begin; i != last; ++i ) {
                if ( *i <= sentinel ) {
                    ++smaller;
                    exchange( begin + smaller, i );
                }
            }
            auto separator = begin + smaller + 1;
            exchange( separator, last );
            return separator;
        #endif
        }

        DEFINE_QUICK_SORT( clrs_v1::partition )
        DEFINE_RANDOMIZED_QUICK_SORT( clrs_v1::partition )
        DEFINE_HYBRID_QUICK_SORT_V1( clrs_v1::partition )
        DEFINE_HYBRID_QUICK_SORT_V2( clrs_v1::partition )
    }

    namespace clrs_v2
    {
        /*
         * v is the sentinel
         * _______________________________
         * |v|  <= v   |   > v  | ------ |
         * -------------------------------
         *  |         |          |        |
         * begin    small        i       end
         *
         * loop invariant:
         *     1. any items belong to [begin, small+1) <= v
         *     2. any items belong to [small+1, i) > v
         */
        template <template <typename> class Randomizer, typename Iterator>
        inline Iterator partition( Iterator begin, Iterator end )
        {
            assert( begin < end );
            size_t distance = std::distance(begin, end);
            Randomizer<Iterator>()( begin, begin, distance );
            auto sentinel = *begin;

            Iterator smaller = begin;
            for ( Iterator i = begin + 1; i != end; ++i ) {
                if ( *i <= sentinel ) {
                    ++smaller;
                    exchange( smaller, i );
                }
            }
            exchange( smaller, begin );
            return smaller;
        }

        DEFINE_QUICK_SORT( clrs_v2::partition )
        DEFINE_RANDOMIZED_QUICK_SORT( clrs_v2::partition )
        DEFINE_HYBRID_QUICK_SORT_V1( clrs_v2::partition )
        DEFINE_HYBRID_QUICK_SORT_V2( clrs_v2::partition )
        //template <typename Iterator>
        //void quick_sort(Iterator begin, Iterator end)
        //{
        //    if (begin < end) {
        //        Iterator separator = partition<details::NullRandomizer, Iterator>(begin, end);
        //        quick_sort(begin, separator);
        //        quick_sort(separator + 1, end);
        //    }
        //}

        //template <size_t N, typename Iterator>
        //void hybrid_quick_sort_v1(Iterator begin, Iterator end)
        //{
        //    if (begin < end) {
        //        if (static_cast<size_t>(std::distance(begin, end)) > N) {
        //            Iterator separator = partition<details::NullRandomizer, Iterator>(begin, end);
        //            hybrid_quick_sort_v1<N, Iterator>(begin, separator);
        //            hybrid_quick_sort_v1<N, Iterator>(separator + 1, end);
        //        } else {
        //            pratique::insertion_sort(begin, end);
        //        }
        //    }
        //}

        static size_t biggest_height = 12000;
        template <size_t N, typename Iterator>
        void debug_hybrid_quick_sort(Iterator begin, Iterator end, size_t height)
        {
            if (begin < end) {
                if (height > biggest_height) {
                    biggest_height = height;
                    FILE * pf = fopen("c:\\biggest_height.txt", "a");
                    if (pf != NULL) {
                        fprintf(pf, "height=%u, end - begin = %u\n", static_cast<unsigned int>(biggest_height), static_cast<unsigned int>(end - begin));
                        for (auto i = begin; i != end; ++i) {
                            fprintf(pf, "%d ", *i);
                        }
                        fprintf(pf, "\n\n");
                        fclose(pf);
                    }
                }
                if (static_cast<size_t>(std::distance(begin, end)) > N) {
                    Iterator separator = partition<pratique::details::NullRandomizer, Iterator>(begin, end);
                    debug_hybrid_quick_sort<N, Iterator>(begin, separator, height + 1);
                    debug_hybrid_quick_sort<N, Iterator>(separator + 1, end, height + 1);
                } else {
                    pratique::insertion_sort(begin, end);
                }
            }
        }
    }

    namespace clrs_v3
    {
        /*
         * v is the sentinel
         * _______________________________
         * |   < v   |   >= v   | -----|v|
         * -------------------------------
         *  |         |          |        |
         * begin    bigger       i       end
         *
         * loop invariant:
         *     1. any items belong to [begin, bigger) < v
         *     2. any items belong to [bigger, i) >= v
         */
        template <template <typename> class Randomizer, typename Iterator>
        inline Iterator partition( Iterator begin, Iterator end )
        {
            assert( begin < end );
            size_t distance = std::distance(begin, end);
            Iterator last = begin + distance - 1;
            Randomizer<Iterator>()( begin, last, distance );
            auto sentinel = *last;

            Iterator i = begin;
            for ( ; *i < sentinel; ++i ) {}
            if ( i != last ) {
                Iterator bigger = i;
                for ( ++i; i != end; ++i ) {
                    if ( *i < sentinel ) {
                        exchange( bigger++, i );
                    }
                }
                exchange_without_doubt( bigger, last );
                i = bigger;
            }

            return i;
        }

        DEFINE_QUICK_SORT( clrs_v3::partition )
        DEFINE_RANDOMIZED_QUICK_SORT( clrs_v3::partition )
        DEFINE_HYBRID_QUICK_SORT_V1( clrs_v3::partition )
        DEFINE_HYBRID_QUICK_SORT_V2( clrs_v3::partition )
    }

    namespace clrs_v4
    {
        /*
         * v is the sentinel
         * _________________________________
         * |v|  ----  |   < v   |   >= v   |
         * ---------------------------------
         *  |        |           |          |
         * begin     i         bigger      end
         *
         * loop invariant:
         *     1. any items belong to [i + 1, bigger) < v
         *     2. any items belong to [bigger, end) >= v
         */
        template <template <typename> class Randomizer, typename Iterator>
        inline Iterator partition( Iterator begin, Iterator end )
        {
            assert( begin < end );
            int distance = static_cast<int>( std::distance(begin, end) );
            Randomizer<Iterator>()( begin, begin, distance );
            auto sentinel = *begin;
            auto bigger = begin + distance;

        #if 0
            for ( int i = distance - 1; i >= 0; --i ) {
                if ( *( begin + i ) >= sentinel ) {
                    exchange( begin + i, --bigger );
                }
            }
        #else
            for ( auto i = bigger; i != begin; --i ) {
                if ( *( i - 1 ) >= sentinel ) {
                    exchange( --bigger, i - 1 );
                }
            }
        #endif
            return bigger;
        }

        DEFINE_QUICK_SORT( clrs_v4::partition )
        DEFINE_RANDOMIZED_QUICK_SORT( clrs_v4::partition )
        DEFINE_HYBRID_QUICK_SORT_V1( clrs_v4::partition )
        DEFINE_HYBRID_QUICK_SORT_V2( clrs_v4::partition )
    }

    namespace algorithm_iv_v1
    {
        /*
         * v is the sentinel
         * __________________________________
         * |   <= v   |   ------   |  >= v   |
         * ----------------------------------
         *  |          |          |          |
         * begin     small      bigger      end
         *
         * loop invariant:
         *     1. any items belong to [begin, small) <= v
         *     2. any items belong to [bigger+1, end) >= v
         */
        template <template <typename> class Randomizer, typename Iterator>
        inline Iterator partition( Iterator begin, Iterator end )
        {
            assert( begin < end );
        #if ( defined( DEBUG ) || defined( _DEBUG ) || defined( DBG ) )
            std::vector<typename std::iterator_traits<Iterator>::value_type> old_values( begin, end );
        #endif
            size_t distance = std::distance(begin, end);
            Randomizer<Iterator>()( begin, begin, distance );
            auto sentinel = *begin;
        #if 0
            Iterator smaller = begin + 1, bigger = begin + distance - 1;
            while ( smaller <= bigger ) {
                while ( smaller <= bigger && *smaller <= sentinel ) {
                    ++smaller;
                }
                while ( smaller <= bigger && *bigger >= sentinel ) {
                    --bigger;
                }
                if ( smaller < bigger ) {
                    exchange_without_doubt( smaller, bigger );
                }
            }
            exchange( begin, bigger );
        #else
            Iterator smaller = begin, bigger = begin + distance;
            for ( ; ; ) {
                for ( ++smaller; smaller != end && *smaller < sentinel; ++smaller ) {}
                for ( --bigger; *bigger > sentinel; --bigger ) {}
                if ( smaller < bigger ) {
                    exchange_without_doubt( smaller, bigger );
                } else {
                    break;
                }
            }
            exchange( begin, bigger );
        #endif
        #if ( defined( DEBUG ) || defined( _DEBUG ) || defined( DBG ) )
            for ( auto i = begin; i != bigger; ++i ) {
                assert( *i <= sentinel );
            }
            for ( auto i = bigger + 1; i != end; ++i ) {
                assert( *i >= sentinel );
            }
        #endif
            return bigger;
        }

        DEFINE_QUICK_SORT( algorithm_iv_v1::partition )
        DEFINE_RANDOMIZED_QUICK_SORT( algorithm_iv_v1::partition )
        DEFINE_HYBRID_QUICK_SORT_V1( algorithm_iv_v1::partition )
        DEFINE_HYBRID_QUICK_SORT_V2( algorithm_iv_v1::partition )
    }

    namespace algorithm_iv_v2
    {
        template <template <typename> class Randomizer, typename Iterator>
        inline Iterator partition( Iterator begin, Iterator end )
        {
            assert( begin < end );
        #if ( defined( DEBUG ) || defined( _DEBUG ) || defined( DBG ) )
            std::vector<typename std::iterator_traits<Iterator>::value_type> old_values( begin, end );
        #endif
            size_t distance = std::distance( begin, end );
            Randomizer<Iterator>( )( begin, begin, distance );
            auto sentinel = *begin;
            Iterator smaller = begin, bigger = begin + distance;
            for ( ;; ) {
                for ( ++smaller; *smaller < sentinel; ++smaller ) {}
                for ( --bigger; *bigger > sentinel; --bigger ) {}
                if ( smaller < bigger ) {
                    exchange_without_doubt( smaller, bigger );
                } else {
                    break;
                }
            }
            exchange( begin, bigger );
        #if ( defined( DEBUG ) || defined( _DEBUG ) || defined( DBG ) )
            for ( auto i = begin; i != bigger; ++i ) {
                assert( *i <= sentinel );
            }
            for ( auto i = bigger + 1; i != end; ++i ) {
                assert( *i >= sentinel );
            }
        #endif
            return bigger;
        }

        namespace details
        {
            template <typename Iterator, typename Distance>
            inline void put_the_biggest_at_the_tail( Iterator begin, Iterator end, Distance distance)
            {
                assert( distance > 1 );
                Iterator biggest = begin;
                for ( auto i = biggest + 1; i != end; ++i ) {
                    if ( *i > *biggest ) {
                        biggest = i;
                    }
                }
                pratique::exchange( biggest, begin + distance - 1 );
            }

            template <typename Iterator>
            inline void quick_sort( Iterator begin, Iterator end )
            {
                if ( begin < end ) {
                    Iterator separator = partition<pratique::details::NullRandomizer, Iterator>( begin, end );
                    quick_sort( begin, separator );
                    quick_sort( separator + 1, end );
                }
            }

            template <typename Iterator>
            inline void randomized_quick_sort( Iterator begin, Iterator end )
            {
                if ( begin < end ) {
                    Iterator separator = partition<pratique::details::Randomizer, Iterator>( begin, end );
                    randomized_quick_sort( begin, separator );
                    randomized_quick_sort( separator + 1, end );
                }
            }

            template <size_t N, typename Iterator>
            inline void hybrid_quick_sort_v1( Iterator begin, Iterator end )
            {
                if ( begin < end ) {
                    if ( static_cast<size_t>( std::distance( begin, end ) ) > N ) {
                        Iterator separator = partition<pratique::details::NullRandomizer, Iterator>( begin, end );
                        hybrid_quick_sort_v1<N, Iterator>( begin, separator );
                        hybrid_quick_sort_v1<N, Iterator>( separator + 1, end );
                    } else {
                        pratique::insertion_sort( begin, end );
                    }
                }
            }

            template <size_t N, typename Iterator>
            inline void hybrid_quick_sort_v2( Iterator begin, Iterator end )
            {
                if ( begin < end ) {
                    if ( static_cast<size_t>( std::distance( begin, end ) ) > N ) {
                        Iterator separator = partition<pratique::details::NullRandomizer, Iterator>( begin, end );
                        hybrid_quick_sort_v2<N, Iterator>( begin, separator );
                        hybrid_quick_sort_v2<N, Iterator>( separator + 1, end );
                    }
                }
            }
        }

        template <typename Iterator>
        inline void quick_sort( Iterator begin, Iterator end )
        {
            int distance = static_cast<int>( std::distance( begin, end ) );
            if ( distance > 1 ) {
                details::put_the_biggest_at_the_tail( begin, end, distance );
                details::quick_sort( begin, begin + distance - 1 );
            }
        }

        template <typename Iterator>
        inline void randomized_quick_sort( Iterator begin, Iterator end )
        {
            int distance = static_cast<int>( std::distance( begin, end ) );
            if ( distance > 1 ) {
                details::put_the_biggest_at_the_tail( begin, end, distance );
                details::randomized_quick_sort( begin, begin + distance - 1 );
            }
        }

        template <size_t N, typename Iterator>
        inline void hybrid_quick_sort_v1( Iterator begin, Iterator end )
        {
            int distance = static_cast<int>( std::distance( begin, end ) );
            if ( distance > 1 ) {
                details::put_the_biggest_at_the_tail( begin, end, distance );
                details::hybrid_quick_sort_v1<N, Iterator>( begin, begin + distance - 1 );
            }
        }

        template <size_t N, typename Iterator>
        inline void hybrid_quick_sort_v2( Iterator begin, Iterator end )
        {
            int distance = static_cast<int>( std::distance( begin, end ) );
            if ( distance > 1 ) {
                details::put_the_biggest_at_the_tail( begin, end, distance );
                details::hybrid_quick_sort_v2<N, Iterator>( begin, begin + distance - 1 );
                pratique::insertion_sort( begin, end );
            }
        }
    }

    namespace tsing_hua_book_version
    {
        /* It is nearly the same as the above */
        template <template <typename> class Randomizer, typename Iterator>
        inline Iterator partition( Iterator begin, Iterator end )
        {
            assert( begin < end );
            size_t distance = std::distance(begin, end);
            Randomizer<Iterator>()( begin, begin, distance );
            auto sentinel = *begin;

            Iterator smaller = begin;
            Iterator bigger = begin + distance - 1;
            while ( smaller < bigger ) {
                while ( bigger > smaller && *bigger >= sentinel ) {
                    --bigger;
                }
                exchange( smaller, bigger );
                while ( smaller < bigger && *smaller <= sentinel ) {
                    ++smaller;
                }
                exchange( smaller, bigger );
            }
            return smaller;
        }

        DEFINE_QUICK_SORT( tsing_hua_book_version::partition )
        DEFINE_RANDOMIZED_QUICK_SORT( tsing_hua_book_version::partition )
        DEFINE_HYBRID_QUICK_SORT_V1( tsing_hua_book_version::partition )
        DEFINE_HYBRID_QUICK_SORT_V2( tsing_hua_book_version::partition )
    }
}

#endif //GYM_ALGORITHM_QUICK_SORT_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4

 

The testing code is:

    void only_a_few_distinct_keys()
    {
    #if ( defined( DEBUG ) || defined( _DEBUG ) || defined( DBG ) )
        {
            int ai[] = { 5, 8, 1, 3, 5, 10, 5, 7, 5, 4, 6 };
            pratique::ternary_version::v3::quick_sort( std::begin( ai ), std::end( ai ) );
            assert( pratique::is_sorted( std::begin( ai ), std::end( ai ) ) );
        }
        {
            int ai[] = { 10, 11, 10, 12, 10, 10, 4, 10, 20, 5, 7 };
            pratique::ternary_version::v3::quick_sort( std::begin( ai ), std::end( ai ) );
            assert( pratique::is_sorted( std::begin( ai ), std::end( ai ) ) );
        }
    #endif
        fprintf( stdout, "------------------- sort a big array in which only a few keys are distinct BEGIN ----------------\n" );
        size_t items;
        for ( auto i = 0; i < _countof( primes ); ++i ) {
            items = primes[i];
            std::vector<size_t> ai( items );
            for ( size_t j = 0; j < items; ++j ) {
                if ( rand() % 10 == 0 ) {
                    ai[j] = static_cast<size_t>( rand() );
                } else {
                    ai[j] = items;
                }
            }

            std::vector<size_t> ai0( ai );
            fprintf( stdout, "%d times for %d unsigned integers (%d bits):\n", i + 1, items, sizeof( ai0[0] ) * 8 );
            {
                uint64_t start_point = get_time_in_milliseconds();
                std::sort( ai0.begin(), ai0.end() );
                uint64_t duration = get_time_in_milliseconds() - start_point;
                fprintf( stdout, "\tSTD sort                               -> %5s milliseconds\n", to_string( duration ).c_str() );
            }

            {
                std::vector<size_t> ai1( ai );
                uint64_t start_point = get_time_in_milliseconds();
                pratique::ternary_version::v1::quick_sort( ai1.begin(), ai1.end() );
                uint64_t duration = get_time_in_milliseconds() - start_point;
                fprintf( stdout, "\tternary version 1 quick sort           -> %5s milliseconds\n", to_string( duration ).c_str() );
                compare( ai0, ai1, "\tternary version 1 quick sort" );
            }

            {
                std::vector<size_t> ai1( ai );
                uint64_t start_point = get_time_in_milliseconds();
                pratique::ternary_version::v1_1::quick_sort( ai1.begin(), ai1.end() );
                uint64_t duration = get_time_in_milliseconds() - start_point;
                fprintf( stdout, "\tternary version 1.1 quick sort         -> %5s milliseconds\n", to_string( duration ).c_str() );
                compare( ai0, ai1, "\tternary version 1.1 quick sort" );
            }

            {
                std::vector<size_t> ai1( ai );
                uint64_t start_point = get_time_in_milliseconds();
                pratique::ternary_version::v2::quick_sort( ai1.begin(), ai1.end() );
                uint64_t duration = get_time_in_milliseconds() - start_point;
                fprintf( stdout, "\tternary version 2 quick sort           -> %5s milliseconds\n", to_string( duration ).c_str() );
                compare( ai0, ai1, "\tternary version 2 quick sort" );
            }

            {
                std::vector<size_t> ai1( ai );
                uint64_t start_point = get_time_in_milliseconds();
                pratique::ternary_version::v3::quick_sort( ai1.begin(), ai1.end() );
                uint64_t duration = get_time_in_milliseconds() - start_point;
                fprintf( stdout, "\tternary version 3 quick sort           -> %5s milliseconds\n", to_string( duration ).c_str() );
                compare( ai0, ai1, "\tternary version 3 quick sort" );
            }
        }
        fprintf( stdout, "-------------------- sort a big array in which only a few keys are distinct END -----------------\n\n" );
    }

    void quick_sort_test()
    {
        only_a_few_distinct_keys();

    #if ( defined( DEBUG ) || defined( _DEBUG ) || defined( DBG ) )
        {
            int ai[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
            pratique::algorithm_iv_v1::partition<pratique::details::NullRandomizer>( std::begin( ai ), std::end( ai ) );
        }
    #endif

    #if ( defined( DEBUG ) || defined( _DEBUG ) || defined( DBG ) )
        {
            std::ifstream ifs( "c:\\data.txt" );
            if ( ifs.is_open() ) {
                std::vector<size_t> ai;
                std::string line;
                while ( !ifs.eof() ) {
                    std::getline( ifs, line );
                    if ( !line.empty() ) {
                        size_t n = strtoul( line.c_str(), NULL, 10 );
                        ai.push_back( n );
                    }
                }
                ifs.close();
                pratique::ternary_version::v3::quick_sort( ai.begin(), ai.end() );
            }
        }
    #endif

        fprintf( stdout, "----------------------------------- Quick sort testing BEGIN ------------------------------------\n" );
        size_t items;
        for ( auto i = 0; i < _countof( primes ); ++i ) {
            SortRunner<size_t> sr( items = primes[i] );

            fprintf( stdout, "%d times for %d unsigned integers (%d bits):\n", i + 1, items, sizeof( size_t ) * 8 );
            std::function<void (std::vector<size_t>::iterator, std::vector<size_t>::iterator)> f;

            {
                f = pratique::ternary_version::v1::quick_sort<std::vector<size_t>::iterator>;
                sr(f, "ternary version 1 quick sort");
            }

            {
                f = pratique::ternary_version::v1::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid ternary version 1.1 quick sort");
            }
            {
                f = pratique::ternary_version::v1::hybrid_quick_sort_v2<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid ternary version 1.2 quick sort");
            }
            {
                f = pratique::ternary_version::v1::hybrid_quick_sort_v3<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid ternary version 1.3 quick sort");
            }

            {
                f = pratique::ternary_version::v1_1::quick_sort<std::vector<size_t>::iterator>;
                sr(f, "ternary version 1.1 quick sort");
            }

            {
                f = pratique::ternary_version::v1_1::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid ternary version 1.1.1 quick sort");
            }
            {
                f = pratique::ternary_version::v1_1::hybrid_quick_sort_v2<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid ternary version 1.1.2 quick sort");
            }
            {
                f = pratique::ternary_version::v1_1::hybrid_quick_sort_v3<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid ternary version 1.1.3 quick sort");
            }

            {
                f = pratique::ternary_version::v2::quick_sort<std::vector<size_t>::iterator> ;
                sr(f, "ternary version 2 quick sort");
            }

            {
                f = pratique::ternary_version::v2::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid ternary version 2.1 quick sort");
            }
            {
                f = pratique::ternary_version::v2::hybrid_quick_sort_v2<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid ternary version 2.2 quick sort");
            }
            {
                f = pratique::ternary_version::v2::hybrid_quick_sort_v3<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid ternary version 2.3 quick sort");
            }

            {
                f = pratique::ternary_version::v3::quick_sort<std::vector<size_t>::iterator > ;
                sr(f, "ternary version 3 quick sort");
            }

            {
                f = pratique::ternary_version::v3::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator >;
                sr(f, "hybrid ternary version 3.1 quick sort");
            }
            {
                f = pratique::ternary_version::v3::hybrid_quick_sort_v2<5, std::vector<size_t>::iterator >;
                sr(f, "hybrid ternary version 3.2 quick sort");
            }
            {
                f = pratique::ternary_version::v3::hybrid_quick_sort_v3<5, std::vector<size_t>::iterator >;
                sr(f, "hybrid ternary version 3.3 quick sort");
            }

            {
                f = pratique::clrs_v1::quick_sort<std::vector<size_t>::iterator>;
                sr(f, "CLRS version 1 quick sort");
            }

            {
                f = pratique::clrs_v1::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid CLRS version 1.1 quick sort");
            }
            {
                f = pratique::clrs_v1::hybrid_quick_sort_v2<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid CLRS version 1.2 quick sort");
            }

            {
                f = pratique::clrs_v2::quick_sort<std::vector<size_t>::iterator> ;
                sr(f, "CLRS version 2 quick sort");
            }

            {
                f = pratique::clrs_v2::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid CLRS version 2.1 quick sort");
            }
            {
                f = pratique::clrs_v2::hybrid_quick_sort_v2<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid CLRS version 2.2 quick sort");
            }

            {
                f = pratique::clrs_v3::quick_sort<std::vector<size_t>::iterator> ;
                sr(f, "CLRS version 3 quick sort");
            }

            {
                f = pratique::clrs_v3::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid CLRS version 3.1 quick sort");
            }
            {
                f = pratique::clrs_v3::hybrid_quick_sort_v2<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid CLRS version 3.2 quick sort");
            }


            {
                f = pratique::clrs_v4::quick_sort<std::vector<size_t>::iterator>;
                sr(f, "CLRS version 4 quick sort");
            }

            {
                f = pratique::clrs_v4::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid CLRS version 4.1 quick sort");
            }
            {
                f = pratique::clrs_v4::hybrid_quick_sort_v2<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid CLRS version 4.2 quick sort");
            }

            {
                f = pratique::tsing_hua_book_version::quick_sort<std::vector<size_t>::iterator>;
                sr(f, "tsing hua version quick sort");
            }

            {
                f = pratique::tsing_hua_book_version::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid tsing hua version 1.1 quick sort");
            }
            {
                f = pratique::tsing_hua_book_version::hybrid_quick_sort_v2<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid tsing hua version 1.2 quick sort");
            }

            {
                f = pratique::algorithm_iv_v1::quick_sort<std::vector<size_t>::iterator>;
                sr(f, "Algorithm IV version 1 quick sort");
            }

            {
                f = pratique::algorithm_iv_v1::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid Algorithm IV version 1.1 quick sort");
            }
            {
                f = pratique::algorithm_iv_v1::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator>;
                sr(f, "hybrid Algorithm IV version 1.2 quick sort");
            }
            {
                f = pratique::algorithm_iv_v2::quick_sort<std::vector<size_t>::iterator>;
                sr( f, "Algorithm IV version 2 quick sort" );
            }

            {
                f = pratique::algorithm_iv_v2::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator>;
                sr( f, "hybrid Algorithm IV version 2.1 quick sort" );
            }
            {
                f = pratique::algorithm_iv_v2::hybrid_quick_sort_v1<5, std::vector<size_t>::iterator>;
                sr( f, "hybrid Algorithm IV version 2.2 quick sort" );
            }

            sr.output(stdout);
        }
        fprintf( stdout, "----------------------------------- Quick sort testing END ------------------------------------\n\n" );
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值