经典排序算法

写了一晚上,

纯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 }

 

posted @ 2016-07-27 04:05  Juntaran  阅读(352)  评论(0编辑  收藏  举报