标签:style class blog code color strong
5. 归并排序 (Merge Sort)
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void print(int arr[], int n) { 5 int i; 6 for (i = 0; i < n; i++) { 7 printf("%d ", arr[i]); 8 } 9 printf("\n"); 10 } 11 12 void merge(int arr[], int s, int n) { 13 int* L = (int*)malloc(s * sizeof(int)); 14 int* R = (int*)malloc((n-s) * sizeof(int)); 15 int i, j, k, t = n - s; 16 for (i = 0; i < s; i++) { 17 L[i] = arr[i]; 18 } 19 for (j = 0; i < n; i++, j++) { 20 R[j] = arr[i]; 21 } 22 i = j = k = 0; 23 while (i < s && j < t) { 24 if (L[i] <= R[j]) { 25 arr[k++] = L[i++]; 26 } else { 27 arr[k++] = R[j++]; 28 } 29 } 30 while (i < s) { 31 arr[k++] = L[i++]; 32 } 33 while (j < t) { 34 arr[k++] = R[j++]; 35 } 36 free(L), free(R); 37 } 38 39 void merge_sort(int arr[], int n) { 40 if (n > 1) { 41 int s = n / 2, t = (n+1) / 2; 42 merge_sort(arr, s); 43 merge_sort(arr+s, t); 44 merge(arr, s, n); // [0, s) & [s, n) 45 } 46 } 47 48 int main() { 49 int arr[10] = {1, 4, 2, 8, 5, 7, 9, 3, 0, 6}; 50 int n = 10; 51 merge_sort(arr, n); 52 print(arr, n); 53 return 0; 54 }
上面程序中,merge_sort 的时间复杂度为 O(nlgn), 空间复杂度为 O(nlgn)。
下面给出一种原地归并排序的C语言代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void print(int arr[], int n) { 5 int i; 6 for (i = 0; i < n; i++) { 7 printf("%d ", arr[i]); 8 } 9 printf("\n"); 10 } 11 12 void reverse(int arr[], int n) { 13 int i = 0, j = n-1; 14 while (i < j) { 15 int t = arr[i]; 16 arr[i] = arr[j]; 17 arr[j] = t; 18 i++, j--; 19 } 20 } 21 22 void rotate(int arr[], int n, int k) { 23 reverse(arr, n-k); 24 reverse(arr+n-k, k); 25 reverse(arr, n); 26 } 27 28 void merge(int arr[], int s, int n) { 29 int i = 0, j = s, k = s; 30 while (j < n) { 31 while (i < j && arr[i] <= arr[j]) i++; 32 if (i == j) break; 33 while (j < n && arr[j] < arr[i]) j++; 34 rotate(arr+i, j-i, j-k); 35 i += j-k, k = j; 36 } 37 } 38 39 void merge_sort(int arr[], int n) { 40 if (n > 1) { 41 int s = n / 2, t = (n+1) / 2; 42 merge_sort(arr, s); 43 merge_sort(arr+s, t); 44 merge(arr, s, n); // [0, s) & [s, n) 45 } 46 } 47 48 int main() { 49 int arr[10] = {1, 4, 2, 8, 5, 7, 9, 3, 0, 6}; 50 int n = 10; 51 merge_sort(arr, n); 52 print(arr, n); 53 return 0; 54 }
6. 冒泡排序 (Bubble Sort)
1 void bubble_sort(int arr[], int n) { 2 int i, j; 3 for (i = 0; i < n; i++) { 4 for (j = n-1; j > i; j--) { 5 if (arr[j] < arr[j-1]) { 6 int tmp = arr[j]; 7 arr[j] = arr[j-1]; 8 arr[j-1] = tmp; 9 } 10 } 11 } 12 }
对其做一点小的优化,使得最好情况下时间复杂度为 O(n),平均情况下执行时间有所减少,但是不会改变平均情况和最坏情况下渐近复杂度的上界 O(n^2)。
1 void bubble_sort(int arr[], int n) { 2 int i, j; 3 for (i = 0; i < n; i++) { 4 int flag = 0; 5 for (j = n-1; j > i; j--) { 6 if (arr[j] < arr[j-1]) { 7 int tmp = arr[j]; 8 arr[j] = arr[j-1]; 9 arr[j-1] = tmp; 10 flag = 1; 11 } 12 } 13 if (flag == 0) break; 14 } 15 }
7. 选择排序 (Selection Sort)
1 void what_sort(int arr[], int n) { 2 int i, j; 3 for (i = 0; i < n; i++) { 4 for (j = i+1; j < n; j++) { 5 if (arr[i] > arr[j]) { 6 int tmp = arr[i]; 7 arr[i] = arr[j]; 8 arr[j] = tmp; 9 } 10 } 11 } 12 } 13 14 void selection_sort(int arr[], int n) { 15 int i, j; 16 for (i = 0; i < n; i++) { 17 int mini = i, tmp = arr[i]; 18 for(j = i+1; j < n; j++) { 19 if (arr[j] < arr[mini]) { 20 mini = j; 21 } 22 } 23 arr[i] = arr[mini]; 24 arr[mini] = tmp; 25 } 26 }
what_sort 其实也是一种选择排序,但是它在性能上比 selection_sort 差一些。
8. 逆序对 (Inversions)
在一个序列 A[0 .. n-1] 中,对任意 i, j, 若 i < j 且 A[i] > A[j], 那么 A[i] 和 A[j] 构成一个逆序对。
求序列的逆序对数的最简单的方法就是枚举,时间复杂度为 O(n^2)。
1 int count_inversions(int arr[], int n) { 2 int inversions = 0; 3 int i, j; 4 for (i = 0; i < n; i++) { 5 for (j = i+1; j < n; j++) { 6 if (arr[i] > arr[j]) inversions++; 7 } 8 } 9 return inversions; 10 }
在合并排序的基础上做一些修改,我们能得到一个时间复杂度为O(nlgn)的算法:
1 void reverse(int arr[], int n) { 2 int i = 0, j = n-1; 3 while (i < j) { 4 int t = arr[i]; 5 arr[i] = arr[j]; 6 arr[j] = t; 7 i++, j--; 8 } 9 } 10 11 void rotate(int arr[], int n, int k) { 12 reverse(arr, n-k); 13 reverse(arr+n-k, k); 14 reverse(arr, n); 15 } 16 17 int merge(int arr[], int s, int n) { 18 int inversions = 0; 19 int i = 0, j = s, k = s; 20 while (j < n) { 21 while (i < j && arr[i] <= arr[j]) i++; 22 if (i == j) break; 23 while (j < n && arr[j] < arr[i]) j++; 24 rotate(arr+i, j-i, j-k); 25 inversions += (j-k) * (k-i); 26 i += j-k, k = j; 27 } 28 return inversions; 29 } 30 31 int count_inversions(int arr[], int n) { 32 int inversions = 0; 33 if (n > 1) { 34 int s = n / 2, t = (n + 1) / 2; 35 inversions += count_inversions(arr, s); 36 inversions += count_inversions(arr+s, t); 37 inversions += merge(arr, s, n); 38 } 39 return inversions; 40 }
* 最后,顺便提一下,本文所介绍的三种排序算法都是稳定的。
《算法导论》(CLRS)第三版 第1、2章总结(二),布布扣,bubuko.com
标签:style class blog code color strong
原文地址:http://www.cnblogs.com/bestofme/p/3787590.html