1.插入排序
稳定空间复杂度O(1) 时间复杂度O(n^2) 最差情况:反序,需要移动n*(n-1)/2个元素最好情况:正序,不需要移动元素
void insertsort(int a[], int n) { int i, j; int tmp;
for (i = 1; i < n; i++) { tmp = a[i]; for (j = i - 1; j >= 0 && a[j] > tmp; j--) a[j + 1] = a[j]; a[j + 1] = tmp; } }
2.冒泡排序
稳定空间复杂度O(1) 时间复杂度O(n^2) 最差情况:反序,需要交换n*(n-1)/2个元素最好情况:正序,不需要交换元素
void bubblesort(int a[], int n) { int i, j; int tmp;
for (i = n - 1; i > 0; i--) for (j = 0; j < i; j++) { if (a[j] > a[j + 1]) { tmp = a[j]; a[j] = a[j + 1]; a[j + 1] = tmp; } } }
3.选择排序
不稳定空间复杂度O(1) 时间复杂度O(n^2) 最差情况:第一个元素为最大元素,其余元素正序,需要交换n-1个元素(例如:4 3 2 1)最好情况:正序,不需要交换元素
void selectsort(int a[], int n) { int i, j, k; int tmp;
for (i = 0; i < n - 1; i++) { k = i; for (j = i + 1; j < n; j++) { if (a[j] < a[k]) k = j; } if (k != i) { tmp = a[i]; a[i] = a[k]; a[k] = tmp; } } }
4.希尔排序(缩小增量排序)
不稳定空间复杂度O(1) 时间复杂度优于插入排序,最坏情况下O(n^2) 最差情况:有n=2^k个元素,偶数位置上有n/2个同为最大的元素,奇数位置上有n/2个同为最小的元素,此时最优最后一趟进行插入排序(例如:1 5 2 6 3 7 4 8)最好情况:正序,不需要移动元素
void shellsort(int a[], int n) { int i, j, increment; int tmp; for (increment = n / 2; increment > 0; increment /= 2) { for (i = increment; i < n; i++) { tmp = a[i]; for (j = i - increment; j >= 0 && tmp < a[j]; j -= increment) { a[j + increment] = a[j]; } a[j + increment] = tmp; } } }
5.堆排序
不稳定空间复杂度O(1) 时间复杂度O(nlogn)
#define leftchild(i) (2 * (i) + 1)
void percdown(int a[], int i, int n) { int child; int tmp;
for (tmp = a[i]; leftchild(i) < n; i = child) { child = leftchild(i); if (child != n - 1 && a[child + 1] > a[child]) child++; if (tmp < a[child]) a[i] = a[child]; else break; } a[i] = tmp; }
void heapsort(int a[], int n) { int i; int tmp;
for (i = n / 2; i >= 0; i--) { percdown(a, i, n); } for (i = n - 1; i > 0; i--) { tmp = a[0]; a[0] = a[i]; a[i] = tmp; percdown(a, 0, i); } }
6.归并排序
稳定空间复杂度O(n) 时间复杂度O(nlogn)
void merge(int a[], int tmparray[], int lpos, int rpos, int rightend) { int i, leftend, numelements, tmppos;
leftend = rpos - 1; tmppos = lpos; numelements = rightend - lpos + 1;
while (lpos <= leftend && rpos <= rightend) { if (a[lpos] <= a[rpos]) tmparray[tmppos++] = a[lpos++]; else tmparray[tmppos++] = a[rpos++]; }
while (lpos <= leftend) tmparray[tmppos++] = a[lpos++]; while (rpos <= rightend) tmparray[tmppos++] = a[rpos++];
for (i = 0; i < numelements; i++, rightend--) a[rightend] = tmparray[rightend]; }
void msort(int a[], int tmparray[], int left, int right) { int center;
if (left < right) { center = (left + right) / 2; msort(a, tmparray, left, center); msort(a, tmparray, center + 1, right); merge(a, tmparray, left, center + 1, right); } }
void mergesort(int a[], int n) { int *tmparray;
tmparray = (int*)malloc(n * sizeof(int)); if (tmparray != NULL) { msort(a, tmparray, 0, n - 1); free(tmparray); } else printf("No space for tmp array!!!/n"); }
7.快速排序(当小于4个元素时,用到插入排序)
不稳定空间复杂度O(1) 时间复杂度O(nlogn) 最差情况:要排序的数组基本有序,枢纽每次取最大(小)元素,退化为冒泡算法最好情况:枢纽两边元素个数基本相同
#define cutoff (3)
void swap(int *a, int *b) { int tmp; tmp = *a; *a = *b; *b = tmp; }
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 i, j; int pivot;
if (left + cutoff <= right) { pivot = median3(a, left, right); i = left; j = right - 1; for ( ; ; ) { while (a[++i] < pivot) {} while (a[--j] > pivot) {} if (i < j) swap(&a[i], &a[j]); else break; } swap(&a[i], &a[right - 1]);
qsort(a, left, i - 1); qsort(a, i + 1, right); } else insertsort(a + left, right - left + 1); }
void quicksort(int a[], int n) { qsort(a, 0, n - 1); }
参考资料:
《排序算法归总》
《数据结构与算法分析—C语言描述》