1 : // ソートテスト その2
    2 : #include <stdio.h>
    3 : #include <stdlib.h>
    4 : #include <time.h>
    5 : #include <assert.h>
    6 : #include <algorithm>
    7 : #include <functional>
    8 : #include <vector>
    9 : #include <string>
   10 : 
   11 : 
   12 : template<typename BidiIte> inline
   13 : void insert_sort(const BidiIte& first, const BidiIte& last)
   14 : {
   15 :     typedef typename std::iterator_traits<BidiIte>::value_type  T;
   16 :     using std::iter_swap;
   17 : 
   18 :     BidiIte i = first;
   19 :     while (++i != last) {
   20 :         T       tmp( *i );
   21 :         BidiIte j = i;
   22 :         BidiIte k = i;
   23 :         --k;
   24 :         while (j != first && tmp < *k) {
   25 :             *j = *k;
   26 :             --j;
   27 :             --k;
   28 :         }
   29 :         *j = tmp;
   30 :     }
   31 : }
   32 : 
   33 : 
   34 : template<typename BidiIte, class C> inline
   35 : void insert_sort(const BidiIte& first, const BidiIte& last, C cmp)
   36 : {
   37 :     typedef typename std::iterator_traits<BidiIte>::value_type  T;
   38 :     using std::iter_swap;
   39 : 
   40 :     BidiIte i = first;
   41 :     while (++i != last) {
   42 :         T       tmp( *i );
   43 :         BidiIte j = i;
   44 :         BidiIte k = i;
   45 :         --k;
   46 :         while (j != first && cmp(tmp, *k)) {
   47 :             *j = *k;
   48 :             --j;
   49 :             --k;
   50 :         }
   51 :         *j = tmp;
   52 :     }
   53 : }
   54 : 
   55 : 
   56 : template<typename RAIte>
   57 : void quick_sort(RAIte first, RAIte last)
   58 : {
   59 :     typedef typename std::iterator_traits<RAIte>::value_type    T;
   60 :     using std::iter_swap;
   61 : 
   62 :     std::size_t     size = last - first;
   63 :     if (size <= 32) {
   64 :         if (size > 1)
   65 :             insert_sort(first, last);
   66 :         return;
   67 :     }
   68 :     const T m( *( first + size / 2 ) );
   69 :     RAIte   l = first;
   70 :     RAIte   r = last;
   71 :     for (;;) {
   72 :         while (*l < m)
   73 :             ++l;
   74 :         do {
   75 :             --r;
   76 :         } while (m < *r);
   77 :         if (!(l < r))
   78 :             break;
   79 :         iter_swap(l, r);
   80 :         ++l;
   81 :     }
   82 :     quick_sort(first, l   );
   83 :     quick_sort(l    , last);
   84 : }
   85 : 
   86 : 
   87 : 
   88 : template<typename RAIte, class C>
   89 : void quick_sort(RAIte first, RAIte last, C cmp)
   90 : {
   91 :     typedef typename std::iterator_traits<RAIte>::value_type    T;
   92 :     using std::iter_swap;
   93 : 
   94 :     std::size_t     size = last - first;
   95 :     if (size <= 32) {
   96 :         if (size > 1)
   97 :             insert_sort(first, last, cmp);
   98 :         return;
   99 :     }
  100 :     const T m( *( first + size / 2 ) );
  101 :     RAIte   l = first;
  102 :     RAIte   r = last;
  103 :     for (;;) {
  104 :         while (cmp(*l, m))
  105 :             ++l;
  106 :         do {
  107 :             --r;
  108 :         } while (cmp(m, *r));
  109 :         if (!(l < r))
  110 :             break;
  111 :         iter_swap(l, r);
  112 :         ++l;
  113 :     }
  114 :     quick_sort(first, l   , cmp);
  115 :     quick_sort(l    , last, cmp);
  116 : }
  117 : 
  118 : 
  119 : 
  120 : template<typename BidiIte>
  121 : void bidi_quick_sort(BidiIte first, BidiIte last)
  122 : {
  123 :     typedef typename std::iterator_traits<BidiIte>::value_type  T;
  124 : 
  125 :     using std::iter_swap;
  126 :     std::size_t size = std::size_t(std::distance(first, last));
  127 :     if (size <= 32) {
  128 :         if (size > 1)
  129 :             insert_sort(first, last);
  130 :         return;
  131 :     }
  132 :     BidiIte ite( first );
  133 :     std::advance( ite, size / 2 );
  134 :     const T m( *ite );
  135 :     BidiIte     l = first;
  136 :     BidiIte     r = last;
  137 :     std::size_t lc = 0;
  138 :     std::size_t rc = size;
  139 :     for (;;) {
  140 :         while (*l < m)
  141 :             ++l, ++lc;
  142 :         do {
  143 :             --r, --rc;
  144 :         } while (m < *r);
  145 :         if (lc >= rc)
  146 :             break;
  147 :         iter_swap(l, r);
  148 :         ++l, ++lc;
  149 :     }
  150 :     bidi_quick_sort(first, l   );
  151 :     bidi_quick_sort(l    , last);
  152 : }
  153 : 
  154 : 
  155 : 
  156 : template<typename BidiIte, class C>
  157 : void bidi_quick_sort(BidiIte first, BidiIte last, C cmp)
  158 : {
  159 :     typedef typename std::iterator_traits<BidiIte>::value_type  T;
  160 : 
  161 :     using std::iter_swap;
  162 :     std::size_t size = std::size_t(std::distance(first, last));
  163 :     if (size <= 32) {
  164 :         if (size > 1)
  165 :             insert_sort(first, last, cmp);
  166 :         return;
  167 :     }
  168 :     BidiIte ite( first );
  169 :     std::advance( ite, size / 2 );
  170 :     const T m( *ite );
  171 :     BidiIte     l = first;
  172 :     BidiIte     r = last;
  173 :     std::size_t lc = 0;
  174 :     std::size_t rc = size;
  175 :     for (;;) {
  176 :         while (cmp(*l, m))
  177 :             ++l, ++lc;
  178 :         do {
  179 :             --r, --rc;
  180 :         } while (cmp(m, *r));
  181 :         if (lc >= rc)
  182 :             break;
  183 :         iter_swap(l, r);
  184 :         ++l, ++lc;
  185 :     }
  186 :     bidi_quick_sort(first, l   , cmp);
  187 :     bidi_quick_sort(l    , last, cmp);
  188 : }
  189 : 
  190 : 
  191 : 
  192 : // ===========================================================================
  193 : #ifdef _WIN32
  194 : #include <windows.h>
  195 : typedef unsigned __int64 PerfCnt_tick_t;
  196 : PerfCnt_tick_t PerfCnt_getTick()    { PerfCnt_tick_t c; QueryPerformanceCounter((LARGE_INTEGER*)&c); return c; }
  197 : PerfCnt_tick_t PerfCnt_tickPerSec() { static PerfCnt_tick_t s = 0; if (!s) QueryPerformanceFrequency((LARGE_INTEGER*)&s); return s; }
  198 : #else
  199 : #include <time.h>
  200 : typedef clock_t PerfCnt_tick_t;
  201 : #define PerfCnt_getTick()           clock()
  202 : #define PerfCnt_tickPerSec()        CLOCKS_PER_SEC
  203 : #endif
  204 : 
  205 : 
  206 : // ===========================================================================
  207 : 
  208 : template<typename T>
  209 : T random() {
  210 :     return T(rand());
  211 : }
  212 : 
  213 : template<>
  214 : std::string random<std::string>() {
  215 :     char buf[128];
  216 :     sprintf(buf, "%d%d%d", rand(),rand(),rand());
  217 :     return std::string(buf);
  218 : }
  219 : 
  220 : 
  221 : #define BENCHMARK(name,SORT,T,cmpFlg,size,count,seed) do {          \
  222 :     std::vector<T> data;                                            \
  223 :     srand(seed);                                                    \
  224 :     for (unsigned i = 0; i < size * count; ++i) {                   \
  225 :         data.push_back(random<T>());                                \
  226 :     }                                                               \
  227 :     unsigned                ofs        = 0;                         \
  228 :     PerfCnt_tick_t  start_time = PerfCnt_getTick();                 \
  229 :     for (unsigned j = 0; j < count; ++j) {                          \
  230 :         if (cmpFlg == 0)                                            \
  231 :             SORT(&data[ofs], &data[ofs]+size);                      \
  232 :         else                                                        \
  233 :             SORT(&data[ofs], &data[ofs]+size, std::less<T>() );     \
  234 :         ofs        += size;                                         \
  235 :     }                                                               \
  236 :     PerfCnt_tick_t  elapsed    = PerfCnt_getTick() - start_time;    \
  237 :     printf("%s:%13.3fμ秒 (%e秒)\n", name                           \
  238 :             , elapsed * 1000000.0 / (PerfCnt_tickPerSec() * count)  \
  239 :             , elapsed / double(PerfCnt_tickPerSec() * count) );     \
  240 : } while (0)
  241 : 
  242 : 
  243 : #ifndef TYPE
  244 : #define TYPE    int
  245 : #endif
  246 : 
  247 : //
  248 : int main(int argc, char **argv) {
  249 :     size_t  size  = (argc >= 2) ? atoi(argv[1]) : 100;
  250 :     size_t  count = (argc >= 3) ? atoi(argv[2]) : 1;
  251 :     int    seed  = 1; //time(0);
  252 :     printf("個数 %d, 処理回数 %d\n", size, count);
  253 :     BENCHMARK("std::sort(arg2)      ", std::sort,       TYPE, 0, size, count, seed);
  254 :     BENCHMARK("std::sort(arg3)      ", std::sort,       TYPE, 1, size, count, seed);
  255 :     BENCHMARK("quick sort(arg2)     ", quick_sort,      TYPE, 0, size, count, seed);
  256 :     BENCHMARK("quick sort(arg3)     ", quick_sort,      TYPE, 1, size, count, seed);
  257 :     BENCHMARK("quick sort:bidi(arg2)", bidi_quick_sort, TYPE, 0, size, count, seed);
  258 :     BENCHMARK("quick sort:bidi(arg3)", bidi_quick_sort, TYPE, 1, size, count, seed);
  259 :     return 0;
  260 : }