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語言描述》