1 /*---------------------------
2
3 程序功能:比较七种排序算法的时间消耗
4
5 七种算法:1.冒泡排序、2.直接插入排序、3.简单选择排序、4.希尔排序、5.堆排序、6.归并排序、7.快速排序。
6
7 统一规约:1,排序为从小到大 升序排序
8 2,Max 表示排序数组的大小
9 3,rt 记录前一次运行算法的时间,求差的结果为当前排序时间
10 4,a[] 为排序数组, a2[] 为恢复数组,每次一个排序结束后由a2[]进行恢复
11 5,char_len 字符串长度
12 6,save[] 用在归并事的保存数据
13 7,Distance 设置快排的比较间隔,小于这个值就会进行插入排序。
14
15
16 --------------------------- */
17 #include<iostream>
18 //#include<stdio.h>
19 #include<ctime>
20 #include<cstdlib>
21 #include<cmath>
22 #include<algorithm>
23
24 #define Max 1000000
25 #define char_len 100
26 #define Distance 10
27
28
29 int a[Max]={0};
30 int a2[Max]={0};
31 int save[Max];
32
33 double rt=0.0;
34
35 //计算排序时间函数 用到了 函数指针, 可以调用到 随意函数 来计算排序时间
36 void printTime( void (*sort )(int a[Max] ) , char name[char_len] ){
37 clock_t tick;
38 double t;
39
40 //实际排序
41 sort(a);
42 tick=clock();
43 //算排序总时间
44 t=(double)tick/CLK_TCK;
45
46 printf( "Total time used of %s is: %lf second\n\n ", name , t-rt);
47 rt=t;
48 }
49
50 //初始化数组 + 随机函数
51 void init_array(){
52 int i=0;
53 srand((unsigned)time(NULL)); /*随机种子*/
54
55 for(i = 1 ; i<Max; i++){
56 a2[i]=a[i]=rand()*i;
57
58 // if( i%100==0)
59 // printf("\n");
60 // printf("%d ",a[i]);
61 }
62 }
63
64 //初始化数组 + 将用a2[] 来恢复 a [] 的值 ,恢复到 开始状态
65 void init_array2(){
66 int i=0;
67 for(i = 1 ; i<Max; i++){
68 a[i]=a2[i];
69 }
70 }
71 //打印数组
72 void print_array(){
73 int i;
74 for( i=0; i<Max; i++){
75 if( i%10==0)
76 printf("\n");
77 printf("%d ",a[i]);
78 }
79 }
80
81
82
83
84 /*
85 第一个算法 : 冒泡排序---------------------------------------------------------------------------
86
87 */
88 //冒泡 a[]
89 void bubble_sort( int a[]){
90 int i,j,k;
91
92 for(i=Max ; i>0 ; i--){
93 for( j=1; j<i-1;j++){
94 if( a[j]>a[j+1] ){
95 k=a[j];
96 a[j]=a[j+1];
97 a[j+1]=k;
98 }
99 }
100 }
101 // print_array();
102 }
103
104
105
106 /*
107 第二个算法 : 直接插入排序---------------------------------------------------------------------------
108
109 */
110
111
112 //插入排序对 a 中 从 left ---> right 的数据排序, 如此设计可提供快排和归并调用
113 void insertionsort(int a[], int left, int right){
114 int i , j , k ;
115
116 for( i=left+1; i<=right; i++){
117 k= a[i];
118 for( j = i-1; j>0 ; j--){
119 if( a[j]> k ){
120 a[j+1]=a[j];
121 }else{
122 // a[j+1]=k;
123 break;
124 }
125 }
126 a[j+1]=k;
127 }
128 }
129
130 //插入排序接口
131 void insert_sort( int a[]){
132
133 insertionsort(a , 1, Max-1 );
134
135 // print_array();
136
137 }
138
139
140
141
142
143 /*
144 第三个算法 : 简单选择排序---------------------------------------------------------------------------
145
146 */
147
148
149 //查找最值的 递归函数, 对 begin --- > end 中选择最小值的 下表
150 int SelectMin( int begin, int end){
151 int c, b ;
152 int center= (begin+end)/2;
153
154 if( begin<end){
155 c=SelectMin(begin,center);
156 b= SelectMin(center+1, end);
157 return a[c] < a[b] ? c : b ;
158 }else{
159 return begin;
160 }
161
162
163 }
164 //选择排序主函数, 对 a[] 排序。
165 void select_sort( int a[]){
166 int i, j, k,min;
167 for( i =1; i<Max; i++){
168 /**/min=0xfffffff;
169 for(j=i;j<Max; j++){
170 if(a[j]<min ){
171 min=a[j];
172 k=j;
173 }
174 }
175 // k = SelectMin( i,Max-1);
176
177 //将每次选择的最小值和前面的数进行对调,数组前半部分有序
178 if( i!=k ){
179 j=a[i];
180 a[i]=a[k];
181 a[k]=j;
182 }
183 }
184 // print_array();
185 }
186
187
188 /*
189 第四个算法 : 希尔排序---------------------------------------------------------------------------
190
191 */
192
193
194 //希尔排序 a, 对 公差为 dk 的 元素排序。
195 void shell_insert(int a[], int dk){
196 int i, j , k ;
197 for(i=dk+1 ; i< Max ; i++){
198 k=a[i];
199 for( j= i-dk; j>0 ; j-=dk){
200 if( a[j]> k ){
201 a[j+dk]=a[j];
202 }else{
203 // a[j+dk]=k;
204 break;
205 }
206 }
207 a[j+dk]=k;
208 }
209 }
210 //希尔主函数,排序 a[];
211 void shell_sort( int a[] ){
212 int k=0;
213
214 //确定公差数量
215 int kp= (int)(log(Max-1)/log(2));
216
217 //printf("%d\n",kp);
218 for( k=0; k<=kp; k++){
219 //有人统计 希尔的公差为 2^(kp-k)+1 时,效率最高
220 shell_insert( a,(int)pow(2,kp-k)-1);
221 }
222 // print_array();
223 }
224
225
226
227 /*
228 第五个算法 : 堆排序 ---------------------------------------------------------------------------
229
230 */
231
232
233 // 堆的调整函数, s 表示 当前调整的位置, length 表示 调整范围: a [] 的 1--->length 位置,
234 void heap_adjust( int a[] , int s , int length ){
235 int i ,k;
236
237 k = a[s];
238
239 //确定a[s]是最大元素;s以后的节点都满足这样的定义;
240 for( i = 2*s ; i<length ; i*=2){
241
242
243 //这里用到 i+1 <length , 不是 i<length , 错了很久,终于搞定了
244 if( (i+1)<length && a[i]<a[i+1] ) i++;
245
246 if( a[i] <= k ) break;
247
248 a[s] = a [ i] ;
249
250 s = i;
251 }
252 a[ s] = k;
253 }
254
255 //堆排主函数, 对 a[] 排序。
256 void heap_sort( int a[] ){
257
258 int i, k;
259
260 //对每个非叶节点进行调整(即有孩子的节点)
261 for( i = (Max-1)/2 ; i>0; i--){
262
263 heap_adjust( a, i, Max);
264 }
265 //将弹出的最大值放在最后,结果就是从小到大
266 for( i = Max-1 ; i > 1; i--){
267 k=a[1];
268 a[1]=a[i];
269 a[i]=k;
270
271 heap_adjust(a, 1, i);
272 }
273 // print_array();
274 }
275
276
277 /*
278
279 第六个算法 : 归并排序 ---------------------------------------------------------------------------
280
281 */
282
283
284
285 //合并函数, a 中的 left1 —> right1 , a中的 left2 --> right2 ,进行归并
286 void merge ( int a[],int left1,int right1,int left2 ,int right2){
287
288
289 int k=0, i , j , m ;
290
291 for( i = left1 , j = left2 ; i<= right1 && j <= right2 ; ){
292
293 //我这里放了一个错误:a[l1]<a[l2] ==== 费了半小时调试
294 if(a[i]<a[j])
295 save[k++]=a[i++];
296 else
297 save[k++]=a[j++];
298 }
299 while(i<=right1)
300 save[k++]=a[i++];
301
302 while(j<=right2)
303 save[k++]=a[j++];
304 for( m= 0 ; m<k; m++){
305 a[left1++]= save[m];
306 }
307 }
308
309 // 归并递归函数 , left 和 right ,表示 a[]中的问题规模
310 void MergeSort(int a[],int left, int right ){
311
312 int center=(left + right ) /2;
313 if(left < right){
314
315 MergeSort(a,left,center);
316 MergeSort(a,center+1,right);
317 merge(a,left,center,center+1,right);
318
319 }
320 }
321
322 //归并 ( 符合函数入口 )
323 void merge_sort ( int a[] ){
324
325 MergeSort( a, 1, Max-1 );
326 // print_array();
327
328 }
329
330
331
332
333 /*
334 第七个算法 : 快速排序---------------------------------------------------------------------------
335
336 */
337
338
339 //交换 a[] 数组下 表 为 h 和 t 的值
340 void swap( int h, int t){
341 int k;
342 k=a[h];
343 a[h]=a[t];
344 a[t]=k;
345 }
346
347 // 在 a[] 中 选择 一个比较适合的比较值
348 int median3(int a[],int left,int right ){
349
350 int center =(left + right)/2;
351
352 if (a[center]<a[left])
353 swap(left,center);
354 if (a[right]<a[left])
355 swap(left,right);
356 if (a[right]<a[center])
357 swap(center,right);
358
359 swap(center,right);
360
361 return a[right];
362 }
363
364 //快排函数, 对 a[] 中的 left -->right 进行切割分块,递归完成。
365 void quickSort(int a[],int left,int right){
366
367 if (left+Distance <=right) {
368
369 int pivot=median3(a,left,right);
370
371 int i=left,j=right;
372
373 for(;;){
374 while (a[++i]<pivot){}
375 while (pivot<a[--j]){}
376 if (i<j)
377 swap(i,j);
378 else
379 break;
380 }
381
382 swap (i,right);
383
384 quickSort(a,left,i-1);
385 quickSort(a,i+1,right);
386 }
387 else
388 insertionsort(a,left,right);
389 }
390
391 //函数接口
392 void quick_sort(int a[] ){
393
394 quickSort(a,1,Max-1);
395
396 // print_array();
397 }
398
399
400
401 /*
402 主函数---------------------------------------------------------------------------
403
404 */
405
406 int main(){
407
408 init_array();
409 /*----------------------------------------------
410
411 第一段测试代码,建议将Max 调整 10000--100000
412
413 目的为:对每个算法的运行都有一个比较
414 ----------------------------------------------*/
415 /*
416
417 printTime( &bubble_sort ," 冒泡算法");
418 init_array2();
419 printTime( &insert_sort ,"插入算法");
420 init_array2();
421 printTime( &select_sort ,"选择算法");
422 init_array2();
423 printTime( &shell_sort ,"希尔算法");
424
425 init_array2();
426 printTime( &heap_sort ,"堆算法 ");
427
428 init_array2();
429 printTime( &merge_sort ,"归并算法");
430
431 init_array2();
432 printTime( &quick_sort ,"快排算法");*/
433
434 /*----------------------------------------------
435
436 第二段测试代码,建议将Max 调整 100000--10000000(十万 到 一千万, 后三个可以到一亿)
437
438 目的为:对快速算法来个更刺激的比较
439 ----------------------------------------------*/
440 /*
441 init_array2();
442 printTime( &shell_sort ,"希尔算法");*/
443 init_array2();
444 printTime( &heap_sort ,"堆算法 ");
445
446 init_array2();
447 printTime( &merge_sort ,"归并算法");
448
449 init_array2();
450 printTime( &quick_sort ,"快排算法");
451
452 init_array2();
453 printTime( &sort ,"快排算法");
454
455
456 /*----------------------------------------------
457
458 第三段测试代码,建议将Max 调整 10--100。并将每个算法后
459
460 目的为:表示每个算法都是可以的到真确的排序结果
461 ----------------------------------------------*/
462 /*
463 init_array2();printf("冒泡算法");
464 bubble_sort (a);printf("\n");
465 print_array();
466
467 init_array2();printf("\n插入算法");
468 insert_sort(a);printf("\n");
469 print_array();
470
471 init_array2();printf("\n选择算法");
472 select_sort(a);printf("\n");
473 print_array();
474
475
476 init_array2();printf("\n希尔算法");
477 shell_sort(a);printf("\n");
478 print_array();
479
480 init_array2();printf("\n堆算法 ");
481 heap_sort(a);printf("\n");
482 print_array();
483
484 init_array2();printf("\n归并算法");
485 merge_sort(a);printf("\n");
486 print_array();
487
488 init_array2();printf("\n快排算法");
489 quick_sort(a);printf("\n");
490 print_array();*/
491
492
493 printf("\n");
494
495
496 return 0;
497 }
498