1 : // ソートテスト その1 2 : #include <stdio.h> 3 : #include <stdlib.h> 4 : #include <assert.h> 5 : #ifdef __cplusplus 6 : #include <algorithm> 7 : #include <string> 8 : #endif 9 : 10 : #ifndef TYPE 11 : #define TYPE int 12 : #define QSORT_INT 13 : #endif 14 : 15 : 16 : #define swap(a,b) do { TYPE tmp = (a); (a) = (b); (b) = tmp; } while (0) 17 : 18 : 19 : 20 : // バブル・ソート 21 : void bubble_sort(TYPE* data, size_t size) { 22 : size_t i, j; 23 : for (i = 0; i < size-1; ++i) { 24 : for (j = size; --j > i;) { 25 : if (data[j] < data[j-1]) 26 : swap(data[j], data[j-1]); 27 : } 28 : } 29 : } 30 : 31 : 32 : // 選択ソート 33 : void selection_sort(TYPE* data, size_t size) { 34 : size_t i, j; 35 : for (i = 0; i < size; ++i) { 36 : size_t min = i; 37 : for (j = i+1; j < size; ++j) { 38 : if (data[j] < data[min]) 39 : min = j; 40 : } 41 : swap(data[i], data[min]) ; 42 : } 43 : } 44 : 45 : 46 : // 挿入ソート 47 : void insert_sort(TYPE* data, size_t size) { 48 : size_t i, j; 49 : for (i = 1; i < size; ++i) { 50 : TYPE tmp = data[i]; 51 : for (j = i; j > 0 && tmp < data[j-1]; --j) 52 : data[j] = data[j-1]; 53 : data[j] = tmp; 54 : } 55 : } 56 : 57 : 58 : // 挿入ソート (やなうらお版) 59 : void yane_insert_sort(TYPE* data, size_t size) { 60 : size_t i, j; 61 : for (i = 1; i < size; i++) { 62 : TYPE tmp = data[i]; 63 : if (data[i-1] > tmp) { 64 : j = i; 65 : do { 66 : data[j] = data[j-1]; 67 : --j; 68 : } while ( j > 0 && data[j-1] > tmp); 69 : data[j] = tmp; 70 : } 71 : } 72 : } 73 : 74 : 75 : // 挿入ソート(old) ※2007頃までのwikipediaに載っていたバージョン. 76 : void old_insert_sort(TYPE* data, size_t size) { 77 : size_t i, j, k; 78 : for (i = 0; ++i < size;) { 79 : for (j = i, k = i-1; j > 0 && data[j] < data[k]; --j, --k) 80 : swap(data[j], data[k]); 81 : } 82 : } 83 : 84 : 85 : // コム・ソート 86 : void comb_sort(TYPE* data, size_t size) { 87 : size_t h = size * 10 / 13; 88 : for (;;) { 89 : int swapFlag = 0; 90 : size_t i = 0; 91 : for (i = 0; i + h < size; ++i) { 92 : if (data[i + h] < data[i]) { 93 : swap(data[i + h], data[i]); 94 : swapFlag = 1; 95 : } 96 : } 97 : if (h <= 1) { 98 : if (!swapFlag) 99 : break; 100 : } else { 101 : h = h * 10 / 13; 102 : } 103 : } 104 : } 105 : 106 : 107 : // コム・ソート11 108 : void comb_sort11(TYPE* data, size_t size) { 109 : size_t h = size * 10 / 13; 110 : for (;;) { 111 : size_t i; 112 : int swapFlag = 0; 113 : for (i = 0; i + h < size; ++i) { 114 : if (data[i + h] < data[i]) { 115 : swap(data[i + h], data[i]); 116 : swapFlag = 1; 117 : } 118 : } 119 : if (h <= 1) { 120 : if (!swapFlag) 121 : break; 122 : } else if ((h == 9) | (h == 10)) { 123 : h = 11; 124 : } else { 125 : h = h * 10 / 13; 126 : } 127 : } 128 : } 129 : 130 : 131 : // 工夫なしのquickソート. 132 : void quick_sort(TYPE* data, size_t size) { 133 : TYPE m; 134 : TYPE *l, *r, *e; 135 : if (size <= 1) 136 : return; 137 : m = data[size / 2]; 138 : l = data; 139 : e = data + size; 140 : r = e - 1; 141 : for (;;) { 142 : while (*l < m) 143 : ++l; 144 : while (m < *r) 145 : --r; 146 : if (l >= r) 147 : break; 148 : swap(*l, *r); 149 : ++l; 150 : } 151 : quick_sort(data, l - data); 152 : quick_sort(l , e - l ); 153 : } 154 : 155 : 156 : 157 : // quickソート+挿入ソート (32個以下になったら挿入ソートに切替) 158 : void ex_quick_sort(TYPE* data, size_t size) { 159 : TYPE m; 160 : TYPE *l, *r, *e; 161 : if (size <= 32) { 162 : if (size <= 1) 163 : return; 164 : insert_sort(data, size); 165 : return; 166 : } 167 : m = data[size / 2]; 168 : l = data; 169 : e = data + size; 170 : r = e - 1; 171 : for (;;) { 172 : while (*l < m) 173 : ++l; 174 : while (m < *r) 175 : --r; 176 : if (l >= r) 177 : break; 178 : swap(*l, *r); 179 : ++l; 180 : } 181 : ex_quick_sort(data, l - data); 182 : ex_quick_sort(l , e - l ); 183 : } 184 : 185 : 186 : 187 : // quickソート+挿入ソート (32個以下になったら挿入ソートに切替) 188 : void y_quick_sort(TYPE* data, size_t size) { 189 : TYPE m; 190 : TYPE *l, *r, *e; 191 : if (size <= 32) { 192 : if (size <= 1) 193 : return; 194 : yane_insert_sort(data, size); 195 : return; 196 : } 197 : m = data[size / 2]; 198 : l = data; 199 : e = data + size; 200 : r = e - 1; 201 : for (;;) { 202 : while (*l < m) 203 : ++l; 204 : while (m < *r) 205 : --r; 206 : if (l >= r) 207 : break; 208 : swap(*l, *r); 209 : ++l; 210 : } 211 : y_quick_sort(data, l - data); 212 : y_quick_sort(l , e - l ); 213 : } 214 : 215 : 216 : #ifndef UNUSE_QSORT 217 : // qsort用の比較関数. 218 : int qsort_cmp(const void* a0, const void* b0) { 219 : const TYPE* a = (const TYPE* )a0; 220 : const TYPE* b = (const TYPE* )b0; 221 : #if defined QSORT_INT 222 : return *a - *b; 223 : #else 224 : if (*a < *b) 225 : return -1; 226 : else if (*a > *b) 227 : return 1; 228 : return 0; 229 : #endif 230 : } 231 : 232 : 233 : 234 : // Cライブラリの qsort を使った場合. 235 : void c_qsort(TYPE* data, size_t size) { 236 : qsort(data, size, sizeof(TYPE), qsort_cmp); 237 : } 238 : #endif 239 : 240 : 241 : #ifdef __cplusplus 242 : // std::sort を使ったモノ. 243 : void std_sort(TYPE* data, size_t size) { 244 : std::sort(data, data+size); 245 : } 246 : #endif 247 : 248 : 249 : 250 : // =========================================================================== 251 : #ifdef _WIN32 252 : #include <windows.h> 253 : typedef unsigned __int64 PerfCnt_tick_t; 254 : PerfCnt_tick_t PerfCnt_getTick() { PerfCnt_tick_t c; QueryPerformanceCounter((LARGE_INTEGER*)&c); return c; } 255 : PerfCnt_tick_t PerfCnt_tickPerSec() { static PerfCnt_tick_t s = 0; if (!s) QueryPerformanceFrequency((LARGE_INTEGER*)&s); return s; } 256 : #else 257 : #include <time.h> 258 : typedef clock_t PerfCnt_tick_t; 259 : #define PerfCnt_getTick() clock() 260 : #define PerfCnt_tickPerSec() CLOCKS_PER_SEC 261 : #endif 262 : 263 : 264 : // =========================================================================== 265 : typedef void (*SortFunc)(TYPE*, size_t size); 266 : 267 : double benchmark(SortFunc sortFunc, size_t size, size_t count, int seed) { 268 : unsigned i, j, ofs = 0; 269 : PerfCnt_tick_t elapsed, start_time; 270 : TYPE* data = (TYPE*) calloc(1, size * count * sizeof(TYPE) + 16); 271 : if (data == 0) { printf("not enough memory.\n"); exit(1); } 272 : srand(seed); 273 : for (i = 0; i < size * count; ++i) 274 : data[i] = rand(); 275 : start_time = PerfCnt_getTick(); 276 : for (j = 0; j < count; ++j) { 277 : sortFunc(&data[ofs], size); 278 : ofs += size; 279 : } 280 : elapsed = PerfCnt_getTick() - start_time; 281 : free(data); 282 : return elapsed * 1.0 / (PerfCnt_tickPerSec()*count); 283 : } 284 : 285 : 286 : 287 : struct St { 288 : size_t size; 289 : size_t count; 290 : int on2flag; 291 : double elaped[11]; 292 : }; 293 : 294 : 295 : // 296 : int main(int argc, char *argv[]) { 297 : int on2flag = 1; 298 : St st[128]; 299 : const char* ttl[12] = {0}; 300 : unsigned i; 301 : unsigned n = 0; 302 : unsigned seed = 1; //time(0); 303 : if (argc < 3) { 304 : printf("usage> sort_test1 [-na] size1 count1 [size2 count2 ...]\n" 305 : " -na 以降O(n^2)なアルゴリズム無視\n" 306 : ); 307 : return 1; 308 : } 309 : for (i = 1; i < argc && n < 128; i += 2) { 310 : if (strcmp(argv[i],"-na") == 0) { 311 : on2flag = 0; 312 : ++i; 313 : } 314 : memset(&st[n], 0, sizeof st[0]); 315 : st[n].size = (i < argc) ? atoi(argv[i+0]) : 10; 316 : st[n].count = (i+1 < argc) ? atoi(argv[i+1]) : 1; 317 : st[n].on2flag = on2flag; 318 : ++n; 319 : } 320 : 321 : printf("\nsort_test1 : sizeof(TYPE)=%dbytes\n", sizeof(TYPE)); 322 : for (i = 0; i < n; ++i) { 323 : St* t = &st[i]; 324 : printf("個数 %9d, 処理回数 %9d\n", t->size, t->count); 325 : if (t->on2flag) { // O(n^2) 326 : t->elaped[ 0] = benchmark(&bubble_sort , t->size, t->count, seed); ttl[ 0] = "bubble sort "; 327 : t->elaped[ 1] = benchmark(&selection_sort , t->size, t->count, seed); ttl[ 1] = "selection sort "; 328 : t->elaped[ 2] = benchmark(&insert_sort , t->size, t->count, seed); ttl[ 2] = "insert sort "; 329 : t->elaped[ 3] = benchmark(&yane_insert_sort, t->size, t->count, seed); ttl[ 3] = "insert sort(yane) "; 330 : } 331 : { 332 : t->elaped[ 4] = benchmark(&comb_sort , t->size, t->count, seed); ttl[ 4] = "comb sort "; 333 : t->elaped[ 5] = benchmark(&comb_sort11 , t->size, t->count, seed); ttl[ 5] = "comb sort11 "; 334 : t->elaped[ 6] = benchmark(&quick_sort , t->size, t->count, seed); ttl[ 6] = "quick sort "; 335 : t->elaped[ 7] = benchmark(&ex_quick_sort , t->size, t->count, seed); ttl[ 7] = "quick+insert sort "; 336 : t->elaped[ 8] = benchmark(&y_quick_sort , t->size, t->count, seed); ttl[ 8] = "quick+insert(yane)"; 337 : #ifdef __cplusplus 338 : t->elaped[ 9] = benchmark(&std_sort , t->size, t->count, seed); ttl[ 9] = "std::sort "; 339 : #endif 340 : #ifndef UNUSE_QSORT 341 : t->elaped[10] = benchmark(&c_qsort , t->size, t->count, seed); ttl[10] = "qsort "; 342 : #endif 343 : } 344 : } 345 : ttl[11] = 0; 346 : 347 : printf("\n"); 348 : printf("%18s ,", "個数"); 349 : for (unsigned i = 0; i < n; ++i) { 350 : printf("%9d個,", st[i].size); 351 : }; 352 : printf("\n"); 353 : for (unsigned j = 0; j < 11; ++j) { 354 : if (ttl[j] == 0) 355 : continue; 356 : printf("%-18s ,", ttl[j]); 357 : for (unsigned i = 0; i < n; ++i) { 358 : double e = st[i].elaped[j]*1000000.0; 359 : if (e > 0) 360 : printf("%11.3f,", e); 361 : else 362 : printf("%11s,", "---"); 363 : }; 364 : printf("\n"); 365 : } 366 : return 0; 367 : }