常见排序算法实现和性能对比
一、相关基本知识
1、稳定排序和非稳定排序
在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的;
若具有相同关键字的记录之间的相对次序发生改变,则称这种排序方法是不稳定的。
2、内排序和外排序
在排序过程中,所有需要排序的数都在内存,并在内存中调整它们的存储顺序,称为内排序;
在排序过程中,只有部分数被调入内存,并借助内存调整数在外存中的存放顺序排序方法称为外排序。
3、算法的时间复杂度和空间复杂度
所谓算法的时间复杂度,是指执行算法所需要的计算工作量。
所谓算法的空间复杂度,一般是指执行这个算法所需要的内存空间。
二、常见算法列举
1、稳定
冒泡排序(bubble sort) — O(n2)
鸡尾酒排序 (Cocktail sort, 双向的冒泡排序) — O(n2)
插入排序 (insertion sort)— O(n2)
桶排序 (bucket sort)— O(n); 需要 O(k) 额外空间
计数排序 (counting sort) — O(n+k); 需要 O(n+k) 额外空间
合并排序 (merge sort)— O(n log n); 需要 O(n) 额外空间
原地合并排序 — O(n2)
二叉排序树排序 (Binary tree sort) — O(n log n)期望时间; O(n2)最坏时间; 需要 O(n) 额外空间
鸽巢排序 (Pigeonhole sort) — O(n+k); 需要 O(k) 额外空间
基数排序 (radix sort)— O(n·k); 需要 O(n) 额外空间
Gnome 排序 — O(n2)
图书馆排序 — O(n log n) with high probability, 需要 (1+ε)n 额外空间
2、不稳定
选择排序 (selection sort)— O(n2)
希尔排序 (shell sort)— O(n log n) 如果使用最佳的现在版本
组合排序 — O(n log n)
堆排序 (heapsort)— O(n log n)sq
平滑排序 — O(n log n)
快速排序 (quicksort)— O(n log n) 期望时间, O(n2) 最坏情况; 对于大的、乱数列表一般相信是最快的已知排序
Introsort — O(n log n)
Patience sorting — O(n log n + k) 最坏情况时间,需要 额外的 O(n + k) 空间,也需要找到最长的递增子串行(longest increasing subsequence)
3、不实用的排序算法
Bogo排序 — O(n × n!) 期望时间,无穷的最坏情况。
Stupid sort — O(n3); 递归版本需要 O(n2) 额外存储器
珠排序(Bead sort) — O(n) or O(√n), 但需要特别的硬件
Pancake sorting — O(n), 但需要特别的硬件
三、实现代码
1 /* 2 * 3 * Copyright (c) 2012, 4 * All rights reserved. 5 * 6 * 文件名称:sort.cpp 7 * 文件标识: 8 * 摘 要:各种常见排序算法实现 9 * 10 ************************************************** 11 * 12 * 当前版本:V0.01 13 * 作 者: (tojoyccnu@163.com) 14 * 创建日期:2012.7.11 15 * 16 * 修订版本:V0.001 17 * 作 者:xionghuatao 18 * 创建日期:2012.7.11 19 * 修订描述:创建文件 20 * 21 */ 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <memory.h> 26 #include <windows.h> 27 28 void printarray(int *data, int size); 29 30 __int64 FileTimeToQuadWord(PFILETIME pft) { 31 return (Int64ShllMod32(pft->dwHighDateTime, 32) | pft->dwLowDateTime); 32 33 } 34 35 /* 36 函数名称:select_sort 37 算法简述: 选择排序 38 1、在待排序序列中选择最小的记录与第一个位置交换。 39 2、在剩余待排序序列再次选择最小记录与第二个位置交换。 40 3、重复2 41 42 时间复杂度: O(n2) 43 空间复杂度: O(1) 44 稳定性:不稳定 45 */ 46 void select_sort(int *data, int datasize) { 47 int index; 48 int tmpindex; 49 int minindex; 50 51 for (index = 0; index < datasize; ++index) { 52 minindex = index; 53 54 //待排序序列中,查找最小关键字数据 55 for (tmpindex = index + 1; tmpindex < datasize; ++tmpindex) { 56 if (data[minindex] > data[tmpindex]) { 57 minindex = tmpindex; 58 } 59 } 60 61 if (minindex != index) { 62 int tmp = data[index]; 63 data[index] = data[minindex]; 64 data[minindex] = tmp; 65 } 66 } 67 } 68 69 /* 70 函数名称:gnome_sort 地精算法 71 算法简述: 号称最简单的排序算法,只有一层循环,默认情况下前进冒泡,一旦遇到冒泡的情况发生就往回冒,直到把这个数字放好为止。 72 时间复杂度: O(n2) 73 空间复杂度: O(1) 74 稳定性:稳定 75 */ 76 void gnome_sort(int *data, int datasize) { 77 int i = 0; 78 int tmp; 79 80 while (i < datasize) { 81 if (i == 0 || data[i - 1] < data[i]) { 82 ++i; 83 } else { 84 tmp = data[i]; 85 data[i] = data[i - 1]; 86 data[--i] = tmp; 87 } 88 } 89 } 90 91 /* 92 函数名称:bubble_sort 冒泡排序 93 算法简述: 依次比较相邻的两个数,将小数放在前面,大数放在后面 94 时间复杂度: O(n2) 95 空间复杂度: O(1) 96 稳定性:稳定 97 */ 98 void bubble_sort(int *data, int datasize) { 99 int i, j; 100 int flag; 101 102 for (i = datasize - 1; i >= 0; --i) { 103 flag = 0; 104 for (j = 0; j < i; ++j) { 105 if (data[j] > data[j + 1]) { 106 int tmp = data[j]; 107 data[j] = data[j + 1]; 108 data[j + 1] = tmp; 109 flag = 1; 110 } 111 } 112 113 //flag == 0 表示已排序,为发生交换 114 if (!flag) 115 return; 116 } 117 } 118 119 /* 120 函数名称:cocktail_sort 121 算法简述: 鸡尾酒排序(冒泡排序的轻微改变,来回排序) 122 时间复杂度: O(n2) 123 空间复杂度: O(1) 124 稳定性:稳定 125 */ 126 void cocktail_sort(int *data, int datasize) { 127 int bottom = 0; 128 int top = datasize - 1; 129 int swap = 1; 130 int i, tmpdata; 131 132 while (swap) { 133 swap = 0; 134 135 //至上而下,冒泡排序最大值 136 for (i = 0; i < top; ++i) { 137 if (data[i] > data[i + 1]) { 138 tmpdata = data[i]; 139 data[i] = data[i + 1]; 140 data[i + 1] = tmpdata; 141 swap = 1; 142 } 143 } 144 145 --top; 146 147 //至下而上, 冒泡排序最小值 148 for (i = top - 1; i >= bottom; --i) { 149 if (data[i] > data[i + 1]) { 150 tmpdata = data[i]; 151 data[i] = data[i + 1]; 152 data[i + 1] = tmpdata; 153 swap = 1; 154 } 155 } 156 157 ++bottom; 158 } 159 } 160 161 /* 162 函数名称:insert_sort 简单插入排序 163 算法简述: 插入排序,也称递减增量排序算法,是插入排序的一种高速而稳定的改进版本。 164 希尔排序是基于插入排序的以下两点性质而提出改进方法的:插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率 165 但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位 166 167 时间复杂度: O(n2) 168 空间复杂度: O(1) 169 稳定性:稳定 170 */ 171 void insert_sort(int *data, int size) { 172 int i, j, t; 173 174 for (i = 1; i < size; ++i) { 175 t = data[i]; 176 177 for (j = i - 1; j >= 0 && data[j] > t; --j) { 178 data[j + 1] = data[j]; 179 } 180 181 data[j + 1] = t; 182 } 183 } 184 185 /* 186 函数名称:shell_sort 希尔排序 187 算法简述: 希尔排序,也称递减增量排序算法,是插入排序的一种高速而稳定的改进版本。 188 希尔排序是基于插入排序的以下两点性质而提出改进方法的:插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率 189 但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位 190 191 时间复杂度: O(n log n) 192 空间复杂度: O(1) 193 稳定性:不稳定 194 */ 195 196 void shell_sort(int *data, int size) { 197 int i, j; 198 int d; 199 int tmp; 200 201 for (d = size / 2; d > 0; d /= 2) { 202 for (i = d; i < size; ++i) { 203 tmp = data[i]; 204 for (j = i - d; j >= 0 && tmp < data[j]; j -= d) { 205 data[j + d] = data[j]; 206 } 207 data[j + d] = tmp; 208 } 209 } 210 } 211 212 /* 213 函数名称:merge_sort 归并排序,二路归并排序, 自底向上 214 算法简述: 归并排序是建立在归并操作上的一种有效的排序算法。 215 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序, 216 再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并 217 218 时间复杂度: O(n log n) 219 空间复杂度: O(n) 220 稳定性:稳定 221 */ 222 int merge(int *data, int low, int midd, int high) { 223 if (!(NULL != data && low >= 0 && low <= midd && low <= high)) { 224 return 1; 225 } 226 227 int *tmp = (int *) malloc((high - low + 1) * sizeof(int)); 228 229 if (NULL == tmp) { 230 return 2; 231 } 232 233 int i = low; 234 int j = midd + 1; 235 int index = 0; 236 237 while (i <= midd && j <= high) { 238 if (data[i] <= data[j]) { 239 tmp[index++] = data[i++]; 240 } else { 241 tmp[index++] = data[j++]; 242 } 243 } 244 245 while (i <= midd) { 246 tmp[index++] = data[i++]; 247 } 248 249 while (j <= high) { 250 tmp[index++] = data[j++]; 251 } 252 253 memcpy((void *) (data + low), tmp, sizeof(int) * (high - low + 1)); 254 free(tmp); 255 256 return 0; 257 } 258 259 void merge_pass(int *data, int n, int size) { 260 int i; 261 int sortlength = 2 * n; 262 263 for (i = 0; (i + sortlength - 1) < size; i = i + sortlength) { 264 merge(data, i, i + n - 1, i + sortlength - 1); 265 } 266 267 if (i + n - 1 < size - 1) { 268 merge(data, i, i + n - 1, size - 1); 269 } 270 } 271 272 void merge_sort(int *data, int size) { 273 int i; 274 275 for (i = 1; i < size; i = (i << 1)) { 276 merge_pass(data, i, size); 277 } 278 } 279 280 //堆排序用到的辅助函数 281 int parent(int i) { 282 return (int) ((i - 1) / 2); 283 } 284 285 int left(int i) { 286 return (2 * i + 1); 287 } 288 289 int right(int i) { 290 return (2 * i + 2); 291 } 292 293 /* 294 函数名称:heap_sort 堆排序 295 算法简述: 利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性, 296 使得每次从无序中选择最大记录(最小记录)变得简单 297 298 时间复杂度: O(n log n) 299 空间复杂度: O(1) 300 稳定性:不稳定 301 */ 302 void maxheap_shit(int *data, int index, int size) { 303 int i, j; 304 int tmp; 305 306 i = index; 307 j = 2 * i + 1; //左子节点 308 309 while (j < size) { 310 if (j + 1 < size && data[j + 1] > data[j]) { 311 ++j; 312 } 313 314 if (data[j] > data[i]) { 315 tmp = data[i]; 316 data[i] = data[j]; 317 data[j] = tmp; 318 319 i = j; 320 j = 2 * i + 1; 321 } else { 322 break; 323 } 324 } 325 } 326 327 void heap_sort(int *data, int size) { 328 int i, k, tmp; 329 330 for (i = (size - 1) / 2; i >= 0; --i) { 331 maxheap_shit(data, i, size); 332 } 333 334 for (k = size - 1; k > 0; --k) { 335 tmp = data[k]; 336 data[k] = data[0]; 337 data[0] = tmp; 338 339 maxheap_shit(data, 0, k); 340 } 341 } 342 343 /* 344 函数名称:quick_sort 快速排序 345 算法简述: 希尔排序,也称递减增量排序算法,是插入排序的一种高速而稳定的改进版本。 346 希尔排序是基于插入排序的以下两点性质而提出改进方法的:插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率 347 但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位 348 349 时间复杂度: O(n log n) 350 空间复杂度: O(1) 351 稳定性:不稳定 352 */ 353 354 int midian3(int *data, int first, int midian, int end) { 355 if (data[first] < data[midian]) { 356 if (data[midian] < data[end]) { 357 return midian; 358 } else if (data[first] < data[end]) { 359 return end; 360 } else { 361 return first; 362 } 363 } else if (data[first] < data[end]) { 364 return first; 365 } else if (data[midian] < data[end]) { 366 return end; 367 } else { 368 return midian; 369 } 370 371 return first; 372 } 373 374 void swap_num(int *a, int *b) { 375 int tmp = *a; 376 377 *a = *b; 378 *b = tmp; 379 } 380 381 int partition(int *data, int left, int right, int p) { 382 swap_num(&data[p], &data[left]); 383 int pivot = data[left]; 384 385 while (left < right) { 386 while (left < right && data[right] > pivot) { 387 --right; 388 } 389 390 if (left != right) { 391 data[left] = data[right]; 392 left++; 393 } 394 395 while (left < right && data[left] < pivot) { 396 ++left; 397 } 398 399 if (left != right) { 400 data[right] = data[left]; 401 right--; 402 } 403 } 404 405 data[left] = pivot; 406 407 return left; 408 } 409 410 void q_sort(int *data, int tmpleft, int tmpright) { 411 if (tmpleft >= tmpright) 412 return; 413 414 int pivot = partition( 415 data, tmpleft, tmpright, 416 midian3(data, tmpleft, tmpright, tmpleft + (tmpright - tmpleft) / 2)); 417 418 q_sort(data, tmpleft, pivot - 1); 419 420 q_sort(data, pivot + 1, tmpright); 421 } 422 423 void quick_sort(int *data, int size) { 424 q_sort(data, 0, size - 1); 425 } 426 427 //log 函数 428 int lg(int n) { 429 int k; 430 for (k = 0; n > 1; n >>= 1) 431 ++k; 432 return k; 433 } 434 435 int partition2(int *data, int tmpleft, int tmpright, int p) { 436 int i; 437 int index = tmpleft; 438 439 swap_num(&data[p], &data[tmpright]); 440 int pivot = data[tmpright]; 441 442 for (i = tmpleft; i < tmpright; i++) { 443 if (data[i] < pivot) 444 swap_num(&data[index++], &data[i]); 445 } 446 447 //将标准与index指向的元素交换,返回index,即分割位置 448 swap_num(&data[tmpright], &data[index]); 449 return index; 450 } 451 452 void intro_q_sort(int *data, int begin, int end, int depthlimt) { 453 if (begin >= end) 454 return; 455 456 if (end - begin + 1 >= 16) { 457 if (depthlimt == 0) { 458 //heap_rangesort(data, begin, end); 459 heap_sort(&data[begin], end - begin + 1); 460 return; 461 } 462 463 --depthlimt; 464 465 int pivot = partition(data, begin, end, 466 midian3(data, begin, begin + (end - begin) / 2, end)); 467 intro_q_sort(data, pivot + 1, end, depthlimt); 468 intro_q_sort(data, begin, pivot - 1, depthlimt); 469 470 } else { 471 insert_sort(&data[begin], end - begin + 1); 472 } 473 } 474 475 void introsort(int *data, int size) { 476 if (size != 1) { 477 intro_q_sort(data, 0, size - 1, lg(size)); 478 479 insert_sort(data, size); 480 } 481 } 482 483 void printarray(int *data, int size) { 484 int i = 0; 485 486 for (i = 0; i < size; i++) { 487 printf("%d ", data[i]); 488 489 if (i && (i % 15 == 0)) { 490 printf("\n"); 491 } 492 } 493 494 printf("\n"); 495 } 496 497 #define NUMCNT 50000 498 499 typedef void (*pfsortfunc)(int *data, int size); 500 501 typedef struct sort_item { 502 char sortinfo[60]; 503 pfsortfunc on_sort; 504 } ST_sort_item; 505 506 static struct sort_item sort_list[] = { { "IntroSort 内省排序算法", introsort }, { 507 "ShellSort 希尔排序算法", shell_sort }, { "QuickSort 快速排序算法", quick_sort }, { 508 "HeapSort 堆排序算法 ", heap_sort }, { "MergeSort 归并排序算法", merge_sort } }; 509 510 void main() { 511 int *beforesort; 512 int *tmpsort; 513 int i; 514 int sizelen = NUMCNT; 515 int bytelen = sizelen * sizeof(int); 516 int tmp = 0; 517 518 srand (GetTickCount()); 519 520 for( tmp = 0; tmp < 20; tmp++) 521 { 522 sizelen = NUMCNT * (tmp + 1); 523 bytelen = sizelen * sizeof(int); 524 beforesort = (int *)malloc(bytelen); 525 tmpsort = (int *)malloc(bytelen); 526 527 if (NULL == beforesort || NULL == tmpsort) 528 { 529 continue; 530 } 531 532 //获得原始数据 533 for (i = 0; i < sizelen; i++) 534 { 535 beforesort[i] = rand() %1000000 + rand() % 9000; 536 } 537 538 printf("第 %d 次, 数据规模 %d\n", tmp + 1, sizelen); 539 540 int k; 541 for (k = 0; k < sizeof(sort_list) / sizeof(struct sort_item); k++) 542 { 543 544 struct sort_item *ptmpitem = &sort_list[k]; 545 546 memcpy(tmpsort, beforesort, bytelen); 547 548 FILETIME ftKernelTimeStart, ftKernelTimeEnd; 549 FILETIME ftUserTimeStart, ftUserTimeEnd; 550 FILETIME ftDummy; 551 __int64 qwKernelTimeElapsed, qwUserTimeElapsed, qwTotalTimeElapsed; 552 553 int start1 = GetTickCount(); 554 555 GetThreadTimes(GetCurrentThread(), &ftDummy, &ftDummy, 556 &ftKernelTimeStart, &ftUserTimeStart); //取得开始时间 557 558 ptmpitem->on_sort(tmpsort, sizelen); 559 560 GetThreadTimes(GetCurrentThread(), &ftDummy, &ftDummy, 561 &ftKernelTimeEnd, &ftUserTimeEnd);//取得结束时间 562 int end1 = GetTickCount(); 563 564 qwKernelTimeElapsed = FileTimeToQuadWord(&ftKernelTimeEnd) - FileTimeToQuadWord(&ftKernelTimeStart); 565 qwUserTimeElapsed = FileTimeToQuadWord(&ftUserTimeEnd) - FileTimeToQuadWord(&ftUserTimeStart); 566 567 qwTotalTimeElapsed = qwKernelTimeElapsed + qwUserTimeElapsed; 568 569 printf("%s: 耗时: %8d ms, %8ld 100ns\n", ptmpitem->sortinfo, end1 - start1, qwTotalTimeElapsed); 570 571 } 572 573 printf("\n"); 574 575 free(beforesort); 576 free(tmpsort); 577 } 578 579 getchar(); 580 }
四、各算法性能
第 1 次, 数据规模 50000
IntroSort 内省排序算法: 耗时: 16 ms, 156001 100ns
ShellSort 希尔排序算法: 耗时: 15 ms, 156001 100ns
QuickSort 快速排序算法: 耗时: 16 ms, 156001 100ns
HeapSort 堆排序算法 : 耗时: 16 ms, 156001 100ns
MergeSort 归并排序算法: 耗时: 172 ms, 1560010 100ns
第 2 次, 数据规模 100000
IntroSort 内省排序算法: 耗时: 31 ms, 312002 100ns
ShellSort 希尔排序算法: 耗时: 47 ms, 468003 100ns
QuickSort 快速排序算法: 耗时: 47 ms, 312002 100ns
HeapSort 堆排序算法 : 耗时: 47 ms, 468003 100ns
MergeSort 归并排序算法: 耗时: 577 ms, 5148033 100ns
第 3 次, 数据规模 150000
IntroSort 内省排序算法: 耗时: 31 ms, 312002 100ns
ShellSort 希尔排序算法: 耗时: 78 ms, 780005 100ns
QuickSort 快速排序算法: 耗时: 63 ms, 468003 100ns
HeapSort 堆排序算法 : 耗时: 93 ms, 624004 100ns
MergeSort 归并排序算法: 耗时: 484 ms, 4680030 100ns
第 4 次, 数据规模 200000
IntroSort 内省排序算法: 耗时: 46 ms, 468003 100ns
ShellSort 希尔排序算法: 耗时: 109 ms, 1092007 100ns
QuickSort 快速排序算法: 耗时: 63 ms, 624004 100ns
HeapSort 堆排序算法 : 耗时: 93 ms, 936006 100ns
MergeSort 归并排序算法: 耗时: 609 ms, 6084039 100ns
第 5 次, 数据规模 250000
IntroSort 内省排序算法: 耗时: 62 ms, 624004 100ns
ShellSort 希尔排序算法: 耗时: 141 ms, 1404009 100ns
QuickSort 快速排序算法: 耗时: 78 ms, 780005 100ns
HeapSort 堆排序算法 : 耗时: 124 ms, 1248008 100ns
MergeSort 归并排序算法: 耗时: 765 ms, 7488048 100ns
第 6 次, 数据规模 300000
IntroSort 内省排序算法: 耗时: 78 ms, 780005 100ns
ShellSort 希尔排序算法: 耗时: 172 ms, 1716011 100ns
QuickSort 快速排序算法: 耗时: 93 ms, 780005 100ns
HeapSort 堆排序算法 : 耗时: 141 ms, 1404009 100ns
MergeSort 归并排序算法: 耗时: 1623 ms, 15756101 100ns
第 7 次, 数据规模 350000
IntroSort 内省排序算法: 耗时: 93 ms, 936006 100ns
ShellSort 希尔排序算法: 耗时: 203 ms, 2028013 100ns
QuickSort 快速排序算法: 耗时: 109 ms, 1092007 100ns
HeapSort 堆排序算法 : 耗时: 188 ms, 1872012 100ns
MergeSort 归并排序算法: 耗时: 1965 ms, 19032122 100ns
第 8 次, 数据规模 400000
IntroSort 内省排序算法: 耗时: 94 ms, 936006 100ns
ShellSort 希尔排序算法: 耗时: 249 ms, 2340015 100ns
QuickSort 快速排序算法: 耗时: 125 ms, 1092007 100ns
HeapSort 堆排序算法 : 耗时: 234 ms, 2184014 100ns
MergeSort 归并排序算法: 耗时: 2200 ms, 21372137 100ns
第 9 次, 数据规模 450000
IntroSort 内省排序算法: 耗时: 156 ms, 1404009 100ns
ShellSort 希尔排序算法: 耗时: 266 ms, 2496016 100ns
QuickSort 快速排序算法: 耗时: 140 ms, 1404009 100ns
HeapSort 堆排序算法 : 耗时: 265 ms, 2652017 100ns
MergeSort 归并排序算法: 耗时: 2559 ms, 24960160 100ns
第 10 次, 数据规模 500000
IntroSort 内省排序算法: 耗时: 141 ms, 1404009 100ns
ShellSort 希尔排序算法: 耗时: 312 ms, 2808018 100ns
QuickSort 快速排序算法: 耗时: 156 ms, 1404009 100ns
HeapSort 堆排序算法 : 耗时: 281 ms, 2808018 100ns
MergeSort 归并排序算法: 耗时: 2714 ms, 26520170 100ns
第 11 次, 数据规模 550000
IntroSort 内省排序算法: 耗时: 141 ms, 1404009 100ns
ShellSort 希尔排序算法: 耗时: 343 ms, 3432022 100ns
QuickSort 快速排序算法: 耗时: 172 ms, 1716011 100ns
HeapSort 堆排序算法 : 耗时: 296 ms, 2964019 100ns
MergeSort 归并排序算法: 耗时: 3011 ms, 29484189 100ns
第 12 次, 数据规模 600000
IntroSort 内省排序算法: 耗时: 141 ms, 1404009 100ns
ShellSort 希尔排序算法: 耗时: 390 ms, 3900025 100ns
QuickSort 快速排序算法: 耗时: 187 ms, 1716011 100ns
HeapSort 堆排序算法 : 耗时: 359 ms, 3432022 100ns
MergeSort 归并排序算法: 耗时: 3260 ms, 32760210 100ns
第 13 次, 数据规模 650000
IntroSort 内省排序算法: 耗时: 172 ms, 1716011 100ns
ShellSort 希尔排序算法: 耗时: 390 ms, 3744024 100ns
QuickSort 快速排序算法: 耗时: 218 ms, 2184014 100ns
HeapSort 堆排序算法 : 耗时: 375 ms, 3588023 100ns
MergeSort 归并排序算法: 耗时: 3557 ms, 34476221 100ns
第 14 次, 数据规模 700000
IntroSort 内省排序算法: 耗时: 187 ms, 1872012 100ns
ShellSort 希尔排序算法: 耗时: 437 ms, 4368028 100ns
QuickSort 快速排序算法: 耗时: 218 ms, 2184014 100ns
HeapSort 堆排序算法 : 耗时: 406 ms, 4056026 100ns
MergeSort 归并排序算法: 耗时: 3838 ms, 37440240 100ns
第 15 次, 数据规模 750000
IntroSort 内省排序算法: 耗时: 202 ms, 2028013 100ns
ShellSort 希尔排序算法: 耗时: 468 ms, 4680030 100ns
QuickSort 快速排序算法: 耗时: 234 ms, 2340015 100ns
HeapSort 堆排序算法 : 耗时: 468 ms, 4524029 100ns
MergeSort 归并排序算法: 耗时: 4087 ms, 39936256 100ns
第 16 次, 数据规模 800000
IntroSort 内省排序算法: 耗时: 203 ms, 2028013 100ns
ShellSort 希尔排序算法: 耗时: 577 ms, 5772037 100ns
QuickSort 快速排序算法: 耗时: 250 ms, 2496016 100ns
HeapSort 堆排序算法 : 耗时: 484 ms, 4680030 100ns
MergeSort 归并排序算法: 耗时: 4368 ms, 41808268 100ns
第 17 次, 数据规模 850000
IntroSort 内省排序算法: 耗时: 234 ms, 2340015 100ns
ShellSort 希尔排序算法: 耗时: 561 ms, 5616036 100ns
QuickSort 快速排序算法: 耗时: 281 ms, 2652017 100ns
HeapSort 堆排序算法 : 耗时: 531 ms, 5304034 100ns
MergeSort 归并排序算法: 耗时: 4664 ms, 44772287 100ns
第 18 次, 数据规模 900000
IntroSort 内省排序算法: 耗时: 219 ms, 2184014 100ns
ShellSort 希尔排序算法: 耗时: 593 ms, 5616036 100ns
QuickSort 快速排序算法: 耗时: 297 ms, 2964019 100ns
HeapSort 堆排序算法 : 耗时: 561 ms, 5616036 100ns
MergeSort 归并排序算法: 耗时: 4914 ms, 47268303 100ns
第 19 次, 数据规模 950000
IntroSort 内省排序算法: 耗时: 249 ms, 2496016 100ns
ShellSort 希尔排序算法: 耗时: 624 ms, 6240040 100ns
QuickSort 快速排序算法: 耗时: 296 ms, 2964019 100ns
HeapSort 堆排序算法 : 耗时: 624 ms, 5772037 100ns
MergeSort 归并排序算法: 耗时: 5258 ms, 50388323 100ns
第 20 次, 数据规模 1000000
IntroSort 内省排序算法: 耗时: 281 ms, 2652017 100ns
ShellSort 希尔排序算法: 耗时: 702 ms, 7020045 100ns
QuickSort 快速排序算法: 耗时: 327 ms, 3120020 100ns
HeapSort 堆排序算法 : 耗时: 671 ms, 6708043 100ns
MergeSort 归并排序算法: 耗时: 5819 ms, 52572337 100ns