经典排序算法
写了一晚上,
纯C写的经典排序算法
下图为从在0-100,000范围内生成100,000个随机数
之后进行排序
各个排序算法的运行速率如下图所示
(Ps.计数排序真是吊啊,传说中的O(n))
另附排序算法对比图
排序法 |
平均时间 |
最差情形 |
稳定度 |
额外空间 |
备注 |
冒泡 |
O(n2) |
O(n2) |
稳定 |
O(1) |
n小时较好 |
交换 |
O(n2) |
O(n2) |
不稳定 |
O(1) |
n小时较好 |
选择 |
O(n2) |
O(n2) |
不稳定 |
O(1) |
n小时较好 |
插入 |
O(n2) |
O(n2) |
稳定 |
O(1) |
大部分已排序时较好 |
基数 |
O(logRB) |
O(logRB) |
稳定 |
O(n) |
B是真数(0-9), R是基数(个十百) |
Shell |
O(nlogn) |
O(ns) 1<s<2<n |
不稳定 |
O(1) |
s是所选分组 |
快速 |
O(nlogn) |
O(n2) |
不稳定 |
O(nlogn) |
n大时较好 |
归并 |
O(nlogn) |
O(nlogn) |
稳定 |
O(1) |
n大时较好 |
堆 |
O(nlogn) |
O(nlogn) |
不稳定 |
O(1) |
n大时较好 |
参考资料:
白话经典算法 http://blog.csdn.net/MoreWindows
太阳落雨 http://blog.csdn.net/cjf_iceking/
JustDoIt http://www.cnblogs.com/TenosDoIt/p/3665038.html
《算法之美》
《算法导论》
《算法:C语言实现(第1-4部分)》
1 /************************************************************************* 2 > File Name: sort_set.c 3 > Author: Juntaran 4 > Mail: JuntaranMail@gmail.com 5 > Created Time: Wed 27 Jul 2016 04:01:46 PM CST 6 ************************************************************************/ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <time.h> 11 #include <string.h> 12 13 #define MaxRandom 100000 // 随机数生成范围 14 #define LengthOfWaitSort 100000 // 随机数生成个数 15 16 17 /*******************************************************************/ 18 // 验证输出 19 void printAfterSort(int* nums, int length) 20 { 21 for (int i = 0; i < length; ++i) 22 { 23 printf("%4d",nums[i]); 24 } 25 printf("\n"); 26 } 27 /*******************************************************************/ 28 29 30 /*******************************************************************/ 31 // 直接插入排序 32 void InsertSort(int* nums, int length) 33 { 34 int insertNum; 35 for (int i = 0; i < length; ++i) 36 { 37 insertNum = nums[i]; // 待插入的元素 38 int j = i; 39 while (j>0 && insertNum<nums[j-1]) 40 { 41 nums[j] = nums[j-1]; 42 j --; 43 } 44 nums[j] = insertNum; 45 } 46 // 输出 47 printf("Insert Sort:\n"); 48 printAfterSort(nums, length); 49 } 50 /*******************************************************************/ 51 52 53 /*******************************************************************/ 54 // 二分插入排序 55 void BinaryInsertSort(int* nums, int length) 56 { 57 int insertNum; 58 int middle; 59 for (int i = 0; i < length; ++i) 60 { 61 insertNum = nums[i]; 62 int left = 0; // 已排序数组左边界 63 int right = i - 1; // 已排序数组右边界 64 while (left <= right) // 二分法寻找插入位置 65 { 66 middle = (left + right) / 2; 67 if (insertNum > nums[middle]) 68 { 69 left = middle + 1; 70 } 71 else 72 { 73 right = middle - 1; 74 } 75 } 76 for (int j = i; j > left; --j) 77 { 78 nums[j] = nums[j-1]; 79 } 80 nums[left] = insertNum; 81 } 82 // 输出 83 printf("Binary Insert Sort:\n"); 84 printAfterSort(nums, length); 85 } 86 /*******************************************************************/ 87 88 89 /*******************************************************************/ 90 // 希尔排序 91 void ShellSort(int* nums, int length) 92 { 93 int insertNum; 94 int gap = (length + 1) / 2; // 本次初始增量取了上界 95 while (gap) 96 { 97 for (int i = gap; i < length; ++i) 98 { 99 insertNum = nums[i]; // 待插入排序 100 int j = i; 101 while (j>=gap && insertNum<nums[j-gap]) 102 { 103 nums[j] = nums[j-gap]; 104 j -= gap; 105 } 106 nums[j] = insertNum; // 插入 107 } 108 gap = gap / 2; // 缩小增量 109 } 110 // 输出 111 printf("Shell Sort:\n"); 112 printAfterSort(nums, length); 113 } 114 /*******************************************************************/ 115 116 117 /*******************************************************************/ 118 // 直接选择排序 119 void SelcetSort(int* nums, int length) 120 { 121 int temp; 122 for (int i = 0; i < length; ++i) 123 { 124 for (int j = i+1; j < length; ++j) 125 { 126 if (nums[j] < nums[i]) 127 { 128 temp = nums[i]; 129 nums[i] = nums[j]; 130 nums[j] = temp; 131 } 132 } 133 } 134 // 输出 135 printf("Selcet Sort:\n"); 136 printAfterSort(nums, length); 137 } 138 /*******************************************************************/ 139 140 141 /*******************************************************************/ 142 // 堆排序 143 144 // 堆的建立或调整 145 void filterDown(int current, int last, int* nums) 146 { 147 int child = 2 * current + 1; // child为current的子女位置 148 int temp = nums[current]; // 暂存子树根结点 149 while (child <= last) // 判断是否到最后结尾 150 { 151 if (child<last && nums[child]<nums[child+1]) 152 { 153 child ++; // 让child指向两个孩子中的最大的 154 } 155 if (temp >= nums[child]) // temp的关键码大则不作调整 156 { 157 break; 158 } 159 else // 否则孩子中大者上移 160 { 161 nums[current] = nums[child]; 162 current = child; 163 child = 2 * child + 1; 164 } 165 } 166 nums[current] = temp; 167 } 168 169 // 排序 170 void HeapSort(int* nums, int length) 171 { 172 for (int i = (length-2)/2; i >= 0; --i) 173 { 174 filterDown(i, length-1, nums); // 建立堆 175 } 176 for (int i = length-1; i > 0; --i) 177 { 178 int temp = nums[i]; 179 nums[i] = nums[0]; 180 nums[0] = temp; 181 filterDown(0, i-1, nums); // 不断调整堆为最大堆 182 } 183 // 输出 184 printf("Heap Sort:\n"); 185 printAfterSort(nums, length); 186 } 187 /*******************************************************************/ 188 189 190 /*******************************************************************/ 191 // 冒泡排序 192 void BubbleSort(int* nums, int length) 193 { 194 int temp; 195 for (int i = 0; i < length; ++i) 196 { 197 for (int j = i+1; j < length; ++j) 198 { 199 if (nums[i] > nums[j]) 200 { 201 temp = nums[i]; 202 nums[i] = nums[j]; 203 nums[j] = temp; 204 } 205 } 206 } 207 // 输出 208 printf("Bubble Sort:\n"); 209 printAfterSort(nums, length); 210 } 211 /*******************************************************************/ 212 213 214 /*******************************************************************/ 215 // 鸡尾酒排序(双向冒泡) 216 void ShakerSort(int* nums, int length) 217 { 218 int left = 0; 219 int right = length - 1; 220 int temp; 221 int flag; // 左右有序标志位 222 223 while (left < right) 224 { 225 for (int i = left; i < right; ++i) // 从左向右冒泡 226 { 227 if (nums[i] > nums[i+1]) 228 { 229 temp = nums[i]; 230 nums[i] = nums[i+1]; 231 nums[i+1] = temp; 232 flag = i; 233 } 234 } 235 right = flag; 236 237 for (int j = right; j > left; --j) // 从右向左冒泡 238 { 239 if (nums[j] < nums[j-1]) 240 { 241 temp = nums[j]; 242 nums[j] = nums[j-1]; 243 nums[j-1] = temp; 244 flag = j; 245 } 246 } 247 left = flag; 248 } 249 // 输出 250 printf("Shaker Sort:\n"); 251 printAfterSort(nums, length); 252 } 253 /*******************************************************************/ 254 255 256 /*******************************************************************/ 257 // 快速排序 递归 258 void quick_sort(int* nums, int left, int right) 259 { 260 if (left < right) 261 { 262 int i = left; 263 int j = right; 264 int flag = nums[left]; 265 266 while (i < j) 267 { 268 while (i<j && nums[j]>=flag) // 从右向左找第一个比基数小的元素 269 { 270 j --; 271 } 272 if (i < j) 273 { 274 nums[i++] = nums[j]; 275 } 276 277 while (i<j && nums[i]<=flag) // 从左向右找第一个比基数大的元素 278 { 279 i ++; 280 } 281 if (i < j) 282 { 283 nums[j--] = nums[i]; 284 } 285 } 286 287 nums[i] = flag; 288 quick_sort( nums, left, i-1 ); 289 quick_sort( nums, i+1, right); 290 } 291 } 292 293 void QuickSort(int* nums, int length) 294 { 295 int left = 0; 296 int right = length - 1; 297 quick_sort(nums, left, right); 298 // 输出 299 printf("Quick Sort:\n"); 300 printAfterSort(nums, length); 301 } 302 /*******************************************************************/ 303 304 305 /*******************************************************************/ 306 // 快速排序 非递归 307 308 int q_partition(int* nums, int low, int high) 309 { 310 int flag = nums[low]; // 选第一个元素作为枢纽元 311 312 while (low < high) 313 { 314 while (low<high && nums[high]>=flag) 315 high --; 316 // 从后向前找到第一个小于flag的元素, 317 // 放到low位置 318 nums[low] = nums[high]; 319 320 while (low<high && nums[low]<=flag) 321 low ++; 322 // 从前向后找到第一个大于flag的元素, 323 // 放到high位置 324 nums[high] = nums[low]; 325 } 326 nums[low] = flag; // flag元素放到low的位置 327 return low; 328 } 329 330 void QuickSort_Unrecursion(int* nums, int length) 331 { 332 int q_stack[length*2]; // 递归层数设置 333 // 栈中保存下次需要排序的子数组的 334 // 开始位置和结束位置 335 int top = -1; 336 q_stack[++top] = 0; 337 q_stack[++top] = length - 1; 338 339 while (top > 0) // 栈非空 340 { 341 int high = q_stack[top--]; 342 int low = q_stack[top--]; 343 int middle = q_partition(nums, low, high); 344 345 if (middle + 1 < high) // 右边子数组入栈 346 { 347 q_stack[++top] = middle + 1; 348 q_stack[++top] = high; 349 } 350 if (low < middle - 1) // 左边子数组入栈 351 { 352 q_stack[++top] = low; 353 q_stack[++top] = middle - 1; 354 } 355 } 356 // 输出 357 printf("Quick Sort Unrecursion:\n"); 358 printAfterSort(nums, length); 359 } 360 361 /*******************************************************************/ 362 363 364 /*******************************************************************/ 365 // 归并排序 366 367 // 合并数组 368 void merge(int* sourceArr, int* tempArr, int left, int middle, int right) 369 { 370 int i = left; 371 int j = middle + 1; 372 int k = left; 373 374 while (i!=middle+1 && j!=right+1) 375 { 376 if (sourceArr[i] >= sourceArr[j]) 377 { 378 tempArr[k++] = sourceArr[j++]; 379 } 380 else 381 { 382 tempArr[k++] = sourceArr[i++]; 383 } 384 } 385 while (i != middle+1) 386 { 387 tempArr[k++] = sourceArr[i++]; 388 } 389 while (j != right+1) 390 { 391 tempArr[k++] = sourceArr[j++]; 392 } 393 for (i = left; i <= right; ++i) 394 { 395 sourceArr[i] = tempArr[i]; 396 } 397 } 398 // 内部递归 399 void recursive(int* sourceArr, int* tempArr, int left, int right) 400 { 401 int middle; 402 if (left < right) 403 { 404 middle = (left + right) / 2; 405 recursive(sourceArr, tempArr, left, middle); 406 recursive(sourceArr, tempArr, middle+1, right); 407 merge(sourceArr, tempArr, left, middle, right); 408 } 409 } 410 // 函数入口 411 void MergeSort(int* nums, int length) 412 { 413 int left = 0; 414 int right = length - 1; 415 int* tempArr = (int*)malloc(sizeof(int)*length); 416 recursive(nums, tempArr, left, right); 417 // 输出 418 printf("Merge Sort:\n"); 419 printAfterSort(nums, length); 420 } 421 /*******************************************************************/ 422 423 424 /*******************************************************************/ 425 // 计数排序 426 void CountingSort(int* nums, int length) 427 { 428 int* mark_array = (int*)malloc(sizeof(int)*MaxRandom); 429 memset(mark_array, 0, MaxRandom*sizeof(int)); 430 431 for (int i = 0; i < length; ++i) 432 { 433 mark_array[nums[i]] ++; // 统计元素出现次数 434 } 435 int k = 0; 436 for (int i = 0; i < MaxRandom; ++i) 437 { 438 if (mark_array[i] != 0) 439 { 440 for (int j=0; j < mark_array[i]; ++j) 441 { 442 nums[k++] = i; 443 } 444 } 445 } 446 // 输出 447 printf("Counting Sort:\n"); 448 printAfterSort(nums, length); 449 } 450 /*******************************************************************/ 451 452 453 /*******************************************************************/ 454 // 基数排序 455 // 取一个数字从低到高第pos位的位数 456 int GetNumInPos(int num,int pos) 457 { 458 int temp = 1; 459 for (int i = 0; i < pos-1; i++) 460 { 461 temp *= 10; 462 } 463 return (num / temp) % 10; 464 } 465 // 取一个数字的位数 466 int GetDigt(int num) 467 { 468 int n = 0; 469 while (num > 0) 470 { 471 n ++; 472 num /= 10; 473 } 474 return n; 475 } 476 477 void RadixSort(int* nums, int length) 478 { 479 int digitRandom = GetDigt(MaxRandom); // 得到最大随机数位数 480 int* radixArray[10]; // 对应0-9序列 481 for (int i = 0; i < 10; ++i) 482 { 483 radixArray[i] = (int*)malloc(sizeof(int)*(length+1)); 484 radixArray[i][0] = 0; // index为0处记录这组数据个数 485 } 486 487 for (int pos = 1; pos <= digitRandom; ++pos) 488 { 489 490 for (int i = 0; i < length; ++i) // 分配过程 491 { 492 int num = GetNumInPos(nums[i], pos); 493 int index = ++radixArray[num][0]; 494 radixArray[num][index] = nums[i]; 495 } 496 497 for (int i = 0, j = 0; i < 10; ++i) // 收集 498 { 499 for (int k = 1; k <= radixArray[i][0]; ++k) 500 { 501 nums[j++] = radixArray[i][k]; 502 } 503 radixArray[i][0] = 0; // 复位 504 } 505 } 506 // 输出 507 printf("Radix Sort:\n"); 508 printAfterSort(nums, length); 509 } 510 /*******************************************************************/ 511 512 513 514 int main() 515 { 516 clock_t start_time, finish_time; 517 double duration; 518 519 srand( (unsigned)time(NULL) ); // 生成随机数种子 520 int length = LengthOfWaitSort; 521 int nums[length]; 522 int temp[length]; 523 printf("Initial array:\n"); 524 for (int i = 0; i < length; ++i) // 输出随机数组nums 525 { 526 nums[i] = rand()%(MaxRandom-1); // MaxRandom-1以内生成20个随机数 527 printf("%4d", nums[i]); 528 } 529 memcpy(temp, nums, length*sizeof(int)); // 用一个temp数组记录排序前的数组 530 printf("\n\n"); 531 532 start_time = clock(); 533 InsertSort(nums, length); // 直接插入排序 534 finish_time = clock(); 535 duration = (double)(finish_time - start_time) / CLOCKS_PER_SEC * 1000; 536 printf( "%f ms\n\n", duration ); 537 memcpy(nums, temp, length*sizeof(int)); // 复原nums数组 538 539 start_time = clock(); 540 BinaryInsertSort(nums, length); // 二分插入排序 541 finish_time = clock(); 542 duration = (double)(finish_time - start_time) / CLOCKS_PER_SEC * 1000; 543 printf( "%f ms\n\n", duration ); 544 memcpy(nums, temp, length*sizeof(int)); // 复原nums数组 545 546 start_time = clock(); 547 ShellSort(nums, length); // 希尔排序 548 finish_time = clock(); 549 duration = (double)(finish_time - start_time) / CLOCKS_PER_SEC * 1000; 550 printf( "%f ms\n\n", duration ); 551 memcpy(nums, temp, length*sizeof(int)); // 复原nums数组 552 553 start_time = clock(); 554 SelcetSort(nums, length); // 直接选择排序 555 finish_time = clock(); 556 duration = (double)(finish_time - start_time) / CLOCKS_PER_SEC * 1000; 557 printf( "%f ms\n\n", duration ); 558 memcpy(nums, temp, length*sizeof(int)); // 复原nums数组 559 560 start_time = clock(); 561 HeapSort(nums, length); // 堆排序 562 finish_time = clock(); 563 duration = (double)(finish_time - start_time) / CLOCKS_PER_SEC * 1000; 564 printf( "%f ms\n\n", duration ); 565 memcpy(nums, temp, length*sizeof(int)); // 复原nums数组 566 567 start_time = clock(); 568 BubbleSort(nums, length); // 冒泡排序 569 finish_time = clock(); 570 duration = (double)(finish_time - start_time) / CLOCKS_PER_SEC * 1000; 571 printf( "%f ms\n\n", duration ); 572 memcpy(nums, temp, length*sizeof(int)); // 复原nums数组 573 574 start_time = clock(); 575 ShakerSort(nums, length); // 鸡尾酒排序 576 finish_time = clock(); 577 duration = (double)(finish_time - start_time) / CLOCKS_PER_SEC * 1000; 578 printf( "%f ms\n\n", duration ); 579 memcpy(nums, temp, length*sizeof(int)); // 复原nums数组 580 581 start_time = clock(); 582 QuickSort(nums, length); // 快速排序 递归 583 finish_time = clock(); 584 duration = (double)(finish_time - start_time) / CLOCKS_PER_SEC * 1000; 585 printf( "%f ms\n\n", duration ); 586 memcpy(nums, temp, length*sizeof(int)); // 复原nums数组 587 588 start_time = clock(); 589 QuickSort_Unrecursion(nums, length); // 快速排序 非递归 590 finish_time = clock(); 591 duration = (double)(finish_time - start_time) / CLOCKS_PER_SEC * 1000; 592 printf( "%f ms\n\n", duration ); 593 memcpy(nums, temp, length*sizeof(int)); // 复原nums数组 594 595 start_time = clock(); 596 MergeSort(nums, length); // 归并排序 597 finish_time = clock(); 598 duration = (double)(finish_time - start_time) / CLOCKS_PER_SEC * 1000; 599 printf( "%f ms\n\n", duration ); 600 memcpy(nums, temp, length*sizeof(int)); // 复原nums数组 601 602 start_time = clock(); 603 CountingSort(nums, length); // 计数排序 604 finish_time = clock(); 605 duration = (double)(finish_time - start_time) / CLOCKS_PER_SEC * 1000; 606 printf( "%f ms\n\n", duration ); 607 memcpy(nums, temp, length*sizeof(int)); // 复原nums数组 608 609 start_time = clock(); 610 RadixSort(nums, length); // 基数排序 611 finish_time = clock(); 612 duration = (double)(finish_time - start_time) / CLOCKS_PER_SEC * 1000; 613 printf( "%f ms\n\n", duration ); 614 memcpy(nums, temp, length*sizeof(int)); // 复原nums数组 615 616 617 return 0; 618 }