給定NN個(長整型范圍內的)整數,要求輸出從小到大排序后的結果。
本題旨在測試各種不同的排序算法在各種數據情況下的表現。各組測試數據特點如下:
- 數據1:只有1個元素;
- 數據2:11個不相同的整數,測試基本正確性;
- 數據3:103個隨機整數;
- 數據4:104個隨機整數;
- 數據5:105個隨機整數;
- 數據6:105個順序整數;
- 數據7:105個逆序整數;
- 數據8:105個基本有序的整數;
- 數據9:105個隨機正整數,每個數字不超過1000。
輸入格式:
輸入第一行給出正整數NN(\le 10^5≤105),隨后一行給出NN個(長整型范圍內的)整數,其間以空格分隔。
輸出格式:
在一行中輸出從小到大排序后的結果,數字間以1個空格分隔,行末不得有多余空格。
輸入樣例:
11 4 981 10 -17 0 -20 29 50 8 43 -5
輸出樣例:
-20 -17 -5 0 4 8 10 29 43 50 981
-
下面試驗了各種排序算法的的表現
-
算法/時間復雜度
10^3的隨機整數
10^4個隨機整數
10^5個隨機整數
10^5個順序整數
10^5個逆序整數
10^5個基本有序的整數
10^5個隨機正整數,每個數不超過1000
冒泡排序
4ms
228ms
>10s
88ms
>10s
650ms
>10s
插入排序
3ms
35ms
4784ms
82ms
9206ms
115ms
4499ms
選擇排序
5ms
332ms
>10s
>10s
>10s
>10s
>10s
歸並排序(遞歸版本)
4ms
12ms
131ms
82ms
127ms
83ms
75ms
堆排序
3ms
10ms
103ms
89ms
102ms
126ms
94ms
希爾排序
3ms
25ms
128ms
119ms
125ms
117ms
116ms
歸並排序(循環版本)
3ms
24ms
125ms
78ms
99ms
77ms
93ms
快速排序(pivot取中位數)
3ms
10ms
122ms
76ms
112ms
76ms
69ms
/* 冒泡排序 * 1.最好情況 已經有序了O(n) * 2.最壞情況 逆序 O(n^2) * 3.平均情況 O(n^2) */ void bubble_sort(int a[],int n) { for (int i = n - 1; i > 0; i--) { int flag = 0; for (int j = 0; j < i; j++) { if (a[j] > a[j + 1]) { int temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; flag = 1; } } if (flag == 0) break; } }
/* * 插入排序(對於基本有序的數組排序有較好的表現) * 1.最好情況 有序 O(n) * 2.最壞情況 逆序 o(n^2) * 3.平均情況 O(n^2) */ void insertion_sort(int a[],int n) { int i, j; for (i = 1; i < n; i++) { int temp = a[i]; /* 當前要插入的數 */ for (j = i - 1; j >= 0; j--) { if (temp >= a[j]) break; a[j + 1] = a[j]; } a[j + 1] = temp; } }
/* * 希爾排序(不穩定) * 1.時間復雜度跟取得序列有關系 * 2.取 n/2,n/2^2,...,1序列時 最壞情況下時間復雜度為O(n^2) * 3.sedgewick序列時 最壞: O(n^3/2) 平均:O(n^5/4) */ void shell_sort(int a[],int n) { int i, j; int sedgewick[] = { 929,505,209,41,19,5,1,0 }; for (i = 0; sedgewick[i] >= n; i++); for(int d=sedgewick[i];d>0;d=sedgewick[++i]) for (int p = d; p < n; p++) { int temp = a[p]; for (j = p; j >= d&&a[j - d] > temp; j -= d) a[j] = a[j - d]; a[j] = temp; } }
/* * 選擇排序(不穩定 應該是最差的排序算法了吧) * 最好 最壞 平均 時間復雜度都是O(n^2) */ void selection_sort(int a[],int n) { for (int i = 0; i < n-1; i++) { int min = i; for (int j = i + 1; j < n; j++) { if (a[j] < a[min]) { min = j; } } if (min != i) { int temp = a[min]; a[min] = a[i]; a[i] = temp; } } }
/* * 歸並排序(遞歸版本) 在外排序中使用較多 * 1.時間復雜度 最好 最壞 平均 都是O(n*log n). * 2.空間復雜度 是 O(n). */ void merge1(int a[],int temp[],int left,int right,int rightEnd) { int l = left; int leftEnd = right -1; int r = right; int index = rightEnd - left + 1; int x = left; while (l <= leftEnd && r <= rightEnd) { if (a[l] <= a[r]) { temp[x++] = a[l++]; } else temp[x++] = a[r++]; } while (l <= leftEnd) temp[x++] = a[l++]; while (r <= rightEnd) temp[x++] = a[r++]; for (int i=rightEnd; index > 0; index--,i--) a[i] = temp[i]; } void mSort1(int a[],int temp[],int left,int right) { if (left < right) { int mid = (left + right) / 2; mSort1(a, temp, left, mid); mSort1(a, temp, mid + 1, right); merge1(a, temp, left, mid + 1, right); } } void merge_sort1(int a[],int n) { int* temp = (int*)malloc(sizeof(int)*n); if (temp != NULL ) { mSort1(a, temp, 0, n-1); free(temp); } else { cout << "內存不足" << endl; } }
/* * 歸並排序循環版本 * 1. 時間復雜度 最好 最壞 平均 都為O(n * log n) * 2. 空間復雜度O(n) */ void merge2(int a[], int temp[], int left, int right, int rightEnd) { int l = left; int leftEnd = right - 1; int r = right; int index = rightEnd - left + 1; int x = left; while (l <= leftEnd && r <= rightEnd) { if (a[l] <= a[r]) { temp[x++] = a[l++]; } else temp[x++] = a[r++]; } while (l <= leftEnd) temp[x++] = a[l++]; while (r <= rightEnd) temp[x++] = a[r++]; } void mergePass(int a[],int temp[],int n,int length) { int i; for (i = 0; i + 2 * length <= n; i += 2 * length) { merge2(a, temp, i, i + length, i + 2 * length - 1); } if (i + length < n) { merge2(a, temp, i, i + length, n - 1); } else for (int j = i; j < n; j++) temp[j] = a[j]; } void merge_sort2(int a[],int n) { int* temp = (int*)malloc(n * sizeof(int)); if (temp != NULL) { int length = 1; while (length < n) { mergePass(a, temp, n, length); length *= 2; mergePass(temp, a, n, length); length *= 2; } free(temp); } else { cout << "內存不足" << endl; } }
/* * 堆排序(不穩定) * 最好 最壞 平均 時間復雜度 O(n*log n). */ void adjust(int a[],int i, int n) { int parent, child; int temp = a[i]; for (parent = i; parent * 2 < n - 1; parent = child) { child = parent * 2 + 1; /* 先指向左孩子 */ if (child != n - 1 && a[child+1] > a[child]) { child++; /* 右孩子較大則指向右孩子 */ } if (temp >= a[child]) break; else a[parent] = a[child]; } a[parent] = temp; } void heap_sort(int a[], int n) { for (int i = (n-1) / 2; i >= 0; i--) adjust(a,i,n); /* 構建最大堆 */ for (int i = n - 1; i > 0; i--) { int temp = a[i]; a[i] = a[0]; a[0] = temp; adjust(a, 0, i); } }
/* * 快速排序 (不穩定) * 1.最壞情況和主元的選取有一定的關系 如果選首位為主元O(n^2) * 2.最好 平均 O(n * log n) * 3.當待排元素較少時 快排效率會急速下降 此時可采用插入排序 */ void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } int median3(int a[],int left,int right) { int center = (left + right) / 2; if (a[left] > a[center]) { swap(&a[left], &a[center]); } if (a[left] > a[right]) { swap(&a[left], &a[right]); } if (a[center] > a[right]) { swap(&a[center], &a[right]); } swap(&a[center], &a[right-1]); /* 將基准放在數組右端 */ return a[right-1]; } void qSort(int a[],int left,int right) { int cutoff = 100; int low, high, pivot; if (right - left >= cutoff) { pivot = median3(a, left, right); low = left; high = right - 1; while (1) { while (a[++low] < pivot); while (a[--high] > pivot); if (low < high) swap(&a[low], &a[high]); else break; } swap(&a[low], &a[right - 1]); qSort(a, left, low - 1); qSort(a, low + 1, right); } else insertion_sort(a+left,right-left+1); } void quick_sort(int a[],int n) { qSort(a,0,n-1); }
算法/時間復雜度 |
10^3的隨機整數 |
10^4個隨機整數 |
10^5個隨機整數 |
10^5個順序整數 |
10^5個逆序整數 |
10^5個基本有序的整數 |
10^5個隨機正整數,每個數不超過1000 |
冒泡排序 |
4ms |
228ms |
>10s |
88ms |
>10s |
650ms |
>10s |
插入排序 |
3ms |
35ms |
4784ms |
82ms |
9206ms |
115ms |
4499ms |
選擇排序 |
5ms |
332ms |
>10s |
>10s |
>10s |
>10s |
>10s |
歸並排序(遞歸版本) |
4ms |
12ms |
131ms |
82ms |
127ms |
83ms |
75ms |
堆排序 |
3ms |
10ms |
103ms |
89ms |
102ms |
126ms |
94ms |
希爾排序 |
3ms |
25ms |
128ms |
119ms |
125ms |
117ms |
116ms |
歸並排序(循環版本) |
3ms |
24ms |
125ms |
78ms |
99ms |
77ms |
93ms |
快速排序(pivot取中位數) |
3ms |
10ms |
122ms |
76ms |
112ms |
76ms |
69ms |
基數排序 |
|
|
|
|
|
|