各个排序方式

八大排序比较:冒泡排序,选择排序,插入排序,归并排序,快速排序,桶排序,基数排序的比较啊

排序算法实现与性能分析,评测:
编写程序,实现冒泡排序,简单选择排序,简单插入排序,归并排序,快速排序和其他各类排序方法,产生规模分别为100,1000,10000,100000,1000000的模拟数组,使用上述排序方法对同样的模拟数据进行排序,在验证排序结果正确性(编写排序结果验证函数)的同时,利用系统时间函数分别记录各排序开始时间和结束时间,计算各排序所需时间(若超过5分钟则记录,并在结果分析中标出)。再对已排序数据稍加次序调整,模拟几乎有序数组,再重复上述排序过程。给出评测结果表,总结,分析上述排序结果。

当数组无序

img

当数组几乎有序

img

分析

时间复杂度:

归并排序,快速排序,计数排序,基数排序以及桶数较多的桶排序用时明显更短,而冒泡排序,简单选择排序,简单插入排序用时较长

稳定性:

当数组由无序变为有序,耗时减少越多说明算法越稳定,由图中对比可以看出,冒泡排序,简单插入排序,归并排序,基数排序,计数排序是稳定的排序算法,另外,由于桶排序所用桶内的排序方法,所以桶排序也是稳定的,而简单选择排序,快速排序不稳定。

效果展示

img

img

img

img

img

img

源文件下载

点击下载代码文件和运行文件

以下为源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<assert.h>
#include<math.h>
#include<algorithm>
using namespace std; //调用sort函数对数据次序进行调整
#define maxkey 32767 //定义计数排序最大关键字
struct node { //定义桶排序和基数排序所需链表结构
int x;
struct node* next;
};
typedef struct node* list;
struct Node { //定义基数排序所需链表结构
list head, tail;
};
typedef struct Node* space;
int a[1000000]; //定义排序所需数组
int n; //存储数组大小
double consumetime; //存储排序所需时间
clock_t START, END; //定义记录系统时间的变量
void check(int* a); //检验排序结果函数

int* Arraycopy(int* a); //数组拷贝函数

void Bubblesort(int* a); //冒泡排序

void Simpleselectionsort(int* a);//简单选择排序

void Simpleinsertsort(int* a); //简单插入排序

void Mergesort(int* a);
void MergeSort(int* a, int low, int high, int* b);
void Merge(int* a, int low, int m, int high, int* b);//归并排序所需函数

void Quicksort(int* a);
void QuickSort(int* a, int low, int high);
int QuickPass(int* a, int low, int high);//快速排序所需函数

void Countsort(int* a);
void CountSort(int* a, int n,int *b,int max,int *c);//计数排序所需函数

void Bucketsort(int* a);
void BucketSort(int* a, int n, int m);
void insert(list p, int y); //桶排序所需函数

void Cardinalsort(int* a);
void CardinalSort(int* a, int n, int Base, int m);
void Insert(space p, int y); //基数排序所需函数

int main() {
int i;
srand((unsigned)time(NULL));//设置生成随机数种子
for (i = 0; i < 1000000; i++) {
a[i] = rand(); //生成0~32767随机数作为数组元素
}
int k = 2;
while (k--) { //无序数组排序,几乎有序数组排序,共两次循环
n = 100;
while (n <= 1000000) {
if (k == 1)
printf("当无序数组大小为%d时:\n\n", n);
else
printf("当几乎有序数组大小为%d时:\n\n", n);
Bubblesort(a);
Simpleselectionsort(a);
Simpleinsertsort(a);
Mergesort(a);
Quicksort(a);
Countsort(a);
Bucketsort(a);
Cardinalsort(a); //以上调用排序函数
n *= 10;
}
int i;
sort(a, a + 1000000); //将无序数组变为几乎有序数组
for (i = 0; i < 10000; ++i) {
a[i * 100] = rand();
}
}
return 0;
}
void check(int* a) { //检验函数定义
int i;
for (i = 0; i < n - 1; ++i) {
if (a[i] > a[i + 1])break;
}
if (i == n - 1) {
printf("排序结果正确\n");
}
else {
printf("排序结果错误\n");
}
}
int* Arraycopy(int* a) { //数组拷贝函数定义
int i;
int* b = (int*)malloc(sizeof(int) * n);
for (i = 0; i < n; i++) {
b[i] = a[i];
}
return b;
}
void Bubblesort(int* a) { //冒泡排序函数定义
printf("冒泡排序:\n");
int *b= Arraycopy(a); //调用拷贝函数,以下同此处
clock_t halfway; //定时中途时间变量,用于检验是否超时,以下同此处
START = clock(); //调用系统时间函数记录排序开始时间,以下同此处
int i, j, temp;
for (i = 0; i < n-1; ++i) {
for (j = 0; j < n - i - 1; ++j) {
if (b[j + 1] < b[j]) {
temp = b[j + 1];
b[j + 1] = b[j];
b[j] = temp;
}
}
halfway = clock(); //即时检验是否超时
if ((((double)halfway - (double)START) / CLOCKS_PER_SEC) >= 300) {
printf("超过5分钟\n\n");
free(b);
return;
}
}
END = clock(); //记录排序结束时间
check(b); //检验结果正确性
free(b);
consumetime = ((double)END -(double)START ) / CLOCKS_PER_SEC;
printf("耗费时间: %fseconds\n\n", consumetime);//计算并打印耗费时间
}
void Simpleselectionsort(int* a) {//简单选择排序函数定义
printf("简单选择排序:\n");
int* b = Arraycopy(a);
clock_t halfway;
START = clock();
int i, j, l,temp;
for (i = 0; i < n-1; ++i){
l = i;
for (j = i + 1; j < n; ++j) {
if (b[j] < b[l]) {
l = j;
}
}
temp = b[i];
b[i] = b[l];
b[l] = temp;
halfway = clock();
if ((((double)halfway - (double)START) / CLOCKS_PER_SEC )>= 300) {
printf("超过5分钟\n\n");
delete[] b;
return;
}
}
END = clock();
check(b);
free(b);
consumetime = ((double)END - (double)START) / CLOCKS_PER_SEC;
printf("耗费时间: %fseconds\n\n",consumetime);

}
void Simpleinsertsort(int* a) { //简单插入排序函数定义
printf("简单插入排序:\n");
int* b = Arraycopy(a);
clock_t halfway;
START= clock();
int i, j,x;
for (i = 1; i < n; ++i) {
x = b[i];
j = i - 1;
while (j >= 0 && x < b[j]) {
b[j + 1] = b[j];
--j;
}
b[j + 1] = x;
halfway = clock();
if ((((double)halfway - (double)START) / CLOCKS_PER_SEC) >= 300) {
printf("超过5分钟\n\n");
free(b);
return;
}
}
END = clock();
check(b);
free(b);
consumetime = ((double)END - (double)START) / CLOCKS_PER_SEC;
printf("耗费时间: %fseconds\n\n",consumetime);
}
void Mergesort(int* a) { //归并排序函数定义
printf("归并排序:\n");
int* b = Arraycopy(a);
int* c = (int*)malloc(sizeof(int) * n); //定义辅助数组,以下同此处
START = clock();
MergeSort(b, 0, n-1, c);
END = clock();
check(b);
delete[] b;
delete[] c;
consumetime = ((double)END - (double)START) / CLOCKS_PER_SEC;
printf("耗费时间: %fseconds\n\n", consumetime);
if (consumetime >= 300) {
printf("超过五分钟\n\n");
return;
}
}
void MergeSort(int* a, int low, int high, int* b) {//归并排序
if (low >= high) {
return;
}
int m = (low + high) / 2;
MergeSort(a, low, m, b);
MergeSort(a, m+1, high, b); //递归调用
Merge(a, low, m, high, b); //调用函数合并数组
int i;
for (i = low; i <= high; ++i) {
a[i] = b[i];
} //元素转移至原数组
}
void Merge(int* a, int low, int m, int high, int* b) {//合并数组函数
int i = low;
int j = m + 1;
int k = i;
while (i <= m && j <= high) {
if (a[i] <= a[j]) {
b[k++] = a[i++];
}
else {
b[k++] = a[j++];
}
}
while (i <= m) {
b[k++] = a[i++];
}
while (j <= high) {
b[k++] = a[j++];
}
}
void Quicksort(int* a) { //快速排序定义
printf("快速排序:\n");
int* b = Arraycopy(a);
int* c = new int[n];
START = clock();
QuickSort(b, 0, n - 1);
END = clock();
check(b);
free(b);
free(c);
consumetime = ((double)END - (double)START) / CLOCKS_PER_SEC;
printf("耗费时间: %fseconds\n\n", consumetime);
if (consumetime >= 300) {
printf("超过五分钟\n\n");
return;
}
}
void QuickSort(int* a, int low, int high) {//快速排序
if (low >= high) {
return;
}
int p = QuickPass(a, low, high); //调用划分函数同时取枢轴元素的位置
QuickSort(a, low, p - 1);
QuickSort(a, p + 1, high); //划分并递归调用
}
int QuickPass(int* a, int low, int high) {//划分函数
int x = a[low];
while (low < high) {
while (low < high && x <= a[high]) {//从右往左,保留大于等于枢轴元素的所有元素位置不变
--high;
}
if (low == high) {
break;
}
a[low++] = a[high]; //右边较小元素移动到左边空位
while (low < high && x >= a[low]){ //从左往右,保留小于等于枢轴元素的所有元素位置不变
++low;
}
if (low == high) {
break;
}
a[high--] = a[low]; //左边较大元素移动到右边空位
}
a[low] = x; //枢轴元素放回空余位置
return low; //返回枢轴元素所在位置
}
void Countsort(int* a) {
printf("计数排序:\n");
int* b = Arraycopy(a);
int* c =(int*)malloc(sizeof(int)*n);
int* d = (int*)malloc(sizeof(int) * maxkey);
START = clock();
CountSort(b, n , d, maxkey, c);
END = clock();
check(c);
free(b);
consumetime = ((double)END - (double)START) / CLOCKS_PER_SEC;
printf("耗费时间: %fseconds\n\n", consumetime);
if (consumetime >= 300) {
printf("超过五分钟\n\n");
return;
}
}
void CountSort(int* a, int n, int* b, int max, int* c) {//计数排序函数定义
int i,key;
for (key = 0; key <= maxkey; ++key) { //初始化
b[key] = 0;
}
for (i = 0; i < n; ++i) { //相同关键字计数
++b[a[i]];
}
int iStartPos = 0;
int iNextPos;
for (key = 0; key <= maxkey; ++key) {
iNextPos = iStartPos + b[key]; //计算下一个key起始下标
b[key] = iStartPos; //设置存放key起始下标
iStartPos = iNextPos; //调整下一个key起始下标
}
assert(iStartPos == n);
for (i = 0; i < n; ++i) {
c[b[a[i]]++] = a[i]; //存入后调整位置
}
}
void Bucketsort(int* a) { //桶排序函数定义
printf("桶排序:\n");
int* b = Arraycopy(a);
int t[3];
t[0] = (int)sqrt(n);
t[1] = n / 2;
t[2] = n;
int i;
for (i = 0; i < 3; i++) {
START = clock();
BucketSort(b, n, t[i]);
END = clock();
check(b);
consumetime = ((double)END - (double)START) / CLOCKS_PER_SEC;
printf("耗费时间: %fseconds\n(桶的数量为%d)\n\n", consumetime,t[i]);
if (consumetime >= 300) {
printf("超过五分钟\n\n");
return;
}
}
delete[] b;
}
void BucketSort(int* a, int n, int m) {
int i;
list* bucket = (list*)malloc((sizeof(list)) * m);//用链表实习桶
for (i = 0; i < m; ++i) { //初始化
bucket[i] = (list)malloc(sizeof(struct node));
bucket[i]->next=NULL ;
}
double h = (double)35000/ m; //定义桶的容量
int d = (int)h + 1; //确保包含所有元素
for (i = 0; i < n; ++i) { //元素入桶
insert(bucket[a[i] / d], a[i]); //插入同时保证有序(必须排序)
}
int k=0;
for (i = 0; i < m; ++i) { //元素出桶
list p = bucket[i]->next;
while (p != NULL) {
a[k++] = p->x;
p = p->next;
}
}
}
void insert(list p, int y) { //有序插入函数
list q = (list)malloc(sizeof(struct node));
q->x = y;
while (p->next != NULL && y > p->next->x) {
p = p->next;
}
q->next = p->next;
p->next = q;
}
void Cardinalsort(int* a) { //基数排序定义
printf("基数排序:\n");
printf("(基数为整数各位上的数)\n");
int* b = Arraycopy(a);
START = clock();
CardinalSort(b, n, 10,5);
END = clock();
check(b);
delete[] b;
consumetime = ((double)END - (double)START) / CLOCKS_PER_SEC;
printf("耗费时间: %fseconds\n\n", consumetime);
}
void CardinalSort(int* a, int n, int Base, int m) {//基数排序
int j;
int x = 10; //用于取对应位关键字
for (j = 1; j <= m; ++j) { //根据关键字个数循环(关键字为数据各位上数字)
space* bucket = (space*)malloc((sizeof(space))*Base);//用链表实现桶
int i;
for (i = 0; i < Base; ++i) { //初始化
bucket[i] = (space)malloc(sizeof(struct Node));
bucket[i]->head = bucket[i]->tail = NULL;
}
for (i = 0; i < n; ++i) { //元素入桶
int k = (a[i] % x)/(x/10); //取关键字
Insert(bucket[k], a[i]); //无序插入,更快(无须排序)
}
x *= 10;
int l;
int t = 0;
for (l = 0; l < Base; ++l) { //元素出桶
list p = bucket[l]->head;
while (p != NULL) {
a[t++] = p->x;
p = p->next;
}
free(bucket[l]);
}
free(bucket);
}
}
void Insert(space p, int y) { //无序插入函数
list q = (list)malloc(sizeof(struct node));
q->x = y;
q->next = NULL;
if (p->head== NULL) {
p->head = p->tail = q;
return;
}
list s = p->tail;
s->next = q;
p->tail = q;
}