void insert_sort(int x[], int n) { int i, j; for (i=1; i<n; i++) { /*循环不变式:x[0...i-1]有序。每次迭代开始前,x[0...i-1]有序, 循环结束后i=n,x[0...n-1]有序*/ int key = x[i]; for (j=i; j>0 && x[j-1]>key; j--) { x[j] = x[j-1]; } x[j] = key; } }
希尔排序内部调用插入排序来实现,通过对N/2,N/4...1阶分别排序,最后得到整体的有序。
void shell_sort(int a[], int n) { for (int gap=n/2; gap>0; gap /=2) { for (int i=gap; i<n; i++) { int key = a[i], j; for (j=i; j>=gap && key<a[j-gap]; j -= gap) { a[j] = a[j-gap]; } a[j] = key; } } }
void select_sort(int x[], int n) { int i, j, min, tmp; for (i=0; i<n-1; i++) { min = i; for (j=i+1; j<n; j++) { if (x[j] < x[min]) min = j; } if (min != i) tmp = x[i], x[i] = x[min], x[min] = tmp;//交换x[i]和x[min] } }
void bubble_sort(int x[], int n) { int tmp; for (int i=0; i<n; i++) { for (int j = n-1; j>=i+1; j--) { if (x[j] < x[j-1]) tmp = x[j], x[j] = x[j-1], x[j-1] = tmp; } } }循环不变式:在循环开始迭代前,子数组x[0...i-1]包含了数组x[0..n-1]的i-1个最小值,且是排好序的。
void bubble_sort_better(int x[], int n) { int tmp; for (int i=0; i<n; i++) { int sorted = 1; for (int j = n-1; j>=i+1; j--) { if (x[j] < x[j-1]) { tmp = x[j], x[j] = x[j-1], x[j-1] = tmp; sorted = 0; } } if (sorted) return ; } }
const int N = 5; //数字个数 int b[N+1]; void count_sort(int a[], int n, int k) //k为数组最大数字 { int c[k+1]; //辅助数组 for (int i=0; i<=k; i++) c[i] = 0; for (int j=0; j<n; j++) c[a[j]] = c[a[j]] + 1; //C[i]包含等于i的元素个数 for (int i=1; i<=k; i++) c[i] = c[i] + c[i-1]; //C[i]包含小于等于i的元素个数 for (int j=n-1; j>=0; j--) { b[c[a[j]]-1] = a[j]; //结果存在B[0...N-1]中 c[a[j]] = c[a[j]] - 1; } }
归并排序通过分治算法,先排序好两个子数组,然后将两个子数组归并。时间复杂度为O(NlgN)。代码如下:
/*归并排序代码*/ void merge_sort(int a[], int p, int r) { if (p < r) { int q = p+(r-p)/2; merge_sort(a, p, q); merge_sort(a, q + 1, r); merge(a, p, q, r); } } void merge(int a[], int start, int mid, int end) { int n1 = mid - start + 1; int n2 = end - mid; int left[n1], right[n2]; int i, j; for (i = 0; i < n1; i++) /* left holds a[start..mid] */ left[i] = a[start + i]; for (j = 0; j < n2; j++) /* right holds a[mid+1..end] */ right[j] = a[mid + 1 + j]; i = j = 0; int k = start; while (i < n1 && j < n2) { if (left[i] < right[j]) a[k++] = left[i++]; else a[k++] = right[j++]; } while (i < n1) /* left[] is not exhausted */ a[k++] = left[i++]; while (j < n2) /* right[] is not exhausted */ a[k++] = right[j++]; }
扩展:归并排序的非递归实现怎么做?
归并排序的非递归实现其实是最自然的方式,先两两合并,而后再四四合并等,就是从底向上的一个过程。代码如下:
void merge_sort(int a[], int n) { int s=2,i; while(s<=n){ i=0; while(i+s<=n){ merge(a, i, i+s/2-1, i+s-1); i+=s; } //处理末尾残余部分 merge(a, i, i+s/2-1, n-1); s*=2; } //最后再从头到尾处理一遍 merge(a, 0, s/2-1, n-1); }