一些常见的排序方法
插入排序: 时间复杂度O(n^2), 辅助存储空间O(1), 稳定排序
插入排序
#include <stdio.h> #include <stdlib.h> int A[10000]; void insertsort(int a[], int p, int r) { int i, j; for (i = 2; i <= r; ++i) { a[0] = a[i]; // 作为元素的备份和起到监视哨的作用 for (j = i-1; a[0] < a[j]; --j) { a[j+1] = a[j]; } a[j+1] = a[0]; } } int main() { int N; while (1) { printf("请输入要排序的元素个数:"); scanf("%d", &N); for (int i = 1; i <= N; ++i) { scanf("%d", &A[i]); } insertsort(A, 1, N); for (int i = 1; i <= N; ++i) { printf("%d ", A[i]); } puts(""); } }
快速排序: 时间复杂度O(nlogn), 辅助存储空间O(logn), 非稳定排序
快速排序
#include <stdio.h> #include <stdlib.h> int A[10000]; int patition(int a[], int p, int r) { int i = p-1; for (int j = p; j <= r-1; ++j) { if (a[j] < a[r]) { ++i; int t = a[i]; a[i] = a[j]; a[j] = t; } } int t = a[i+1]; a[i+1] = a[r]; a[r] = t; return i+1; } void quicksort(int a[], int p, int r) { if (p < r) { int q = patition(a, p, r); quicksort(a, p, q-1); quicksort(a, q+1, r); } } int main() { int N; while (1) { printf("请输入要排序的元素个数:"); scanf("%d", &N); for (int i = 1; i <= N; ++i) { scanf("%d", &A[i]); } quicksort(A, 1, N); for (int i = 1; i <= N; ++i) { printf("%d ", A[i]); } puts(""); } return 0; }
树形选择排序: 时间复杂度O(nlogn), 辅助存储空间O(n), 稳定排序
树形选择排序
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #define INF 0x3f3f3f3f int N, seq[5000]; int min(int x, int y) { return x < y ? x : y; } int modify(int x) { int lch = x<<1, rch = x<<1|1; if (seq[lch] == INF && seq[rch] == INF) { return seq[x] = INF; // 下面已经没有了节点 } if (seq[lch] == seq[x]) { // 如果已经输出的节点来自左边的子树 seq[x] = min(modify(lch), seq[rch]); } else { seq[x] = min(modify(rch), seq[lch]); } return seq[x]; } int main() { while (1) { memset(seq, 0x3f, sizeof (seq)); printf("请输入要排序的元素个数:"); scanf("%d", &N); printf("请输入%d个元素,以空格隔开:\n", N); int deep = int (ceil(log2(1.*N))); // deep 表示要到达第deep+1层,才可以容纳下N个元素 int sta = int (pow(2, deep)); for (int i = sta, j = 0; j < N; ++i, ++j) { scanf("%d", &seq[i]); } for (int i = sta-1; i >= 1; --i) { int lch = i<<1, rch = i<<1|1; // 相当于 lch = i*2, rch = i*2+1 seq[i] = min(seq[lch], seq[rch]); } while (seq[1] != INF) { printf("%d ", seq[1]); seq[1] = modify(1); } puts(""); } return 0; }
堆排序: 时间复杂度O(nlogn), 辅助存储空间O(1), 非稳定排序
堆排序
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> int N, seq[5000]; void swap(int a, int b) { int t = seq[a]; seq[a] = seq[b]; seq[b] = t; } void down(int p) { // down操作是用来完成使得以节点p为根的子树保持堆的性质 int lch = p<<1, rch = p<<1|1; if (lch <= N && seq[p] > seq[lch]) { swap(p, lch); down(lch); } if (rch <= N && seq[p] > seq[rch]) { swap(p, rch); down(rch); } } void build() { for (int i = N/2; i >= 1; --i) { int lch = i<<1, rch = i<<1|1; if (lch <= N && seq[i] > seq[lch]) { swap(i, lch); down(lch); } if (rch <= N && seq[i] > seq[rch]) { swap(i, rch); down(rch); } } } int main() { while (1) { printf("请输入要排序的元素个数:"); scanf("%d", &N); printf("请输入%d个元素,以空格隔开:\n", N); for (int i = 1; i <= N; ++i) { scanf("%d", seq+i); } build(); while(N) { printf("%d ", seq[1]); swap(1, N--); // 将第一个元素与最后一个元素交换,元素个数减1 down(1); } puts(""); } return 0; }
归并排序: 时间复杂度O(nlogn), 辅助存储空间O(n), 稳定排序
归并排序
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> int N, seq[5000], temp[5000]; void Merge_Sort(int l, int r) { if (l >= r) return; // 如果只有一个元素或者没有元素 int mid = (l + r) >> 1; // 右移一位相当 (l + r) / 2 Merge_Sort(l, mid); // 对两个部分进行一个排序 Merge_Sort(mid+1, r); // 下面的合并操作一般来说是分治方法里面的难点 int k = 0, i = l, j = mid+1; // k表示将要合并到的数组的下标, i表示左半部分下标, j表示右半部分下标 while (i <= mid && j <= r) { if (seq[i] < seq[j]) { temp[k++] = seq[i++]; } else { temp[k++] = seq[j++]; } } while (i <= mid) temp[k++] = seq[i++]; while (j <= r) temp[k++] = seq[j++]; for (i = 0; i < k; ++i) { seq[l + i] = temp[i]; } } int main() { while (1) { memset(seq, 0x3f, sizeof (seq)); printf("请输入要排序的元素个数:"); scanf("%d", &N); printf("请输入%d个元素,以空格隔开:\n", N); for (int i = 1; i <= N; ++i) { scanf("%d", seq+i); } Merge_Sort(1, N); for (int i = 1; i <= N; ++i) { printf("%d ", seq[i]); } } return 0; }
当然还有冒泡和选择许多... 就写这么几种,够用了. 到最后还是调用的库函数sort.