#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" );
}