排序算法
插入排序(Insertion Sort):
原址排序,具有稳定性
时间复杂度:O(n*n),空间复杂度:O(1)
边界:逆序排序的数组花费最多的时间(n * n),排序好的数组花费最少的时间(n)

/* normal version */ void insertSort(int *array, int n) { int key, i, j; for (i = 1; i < n; i++) { key = array[i]; j = i - 1; while (j >= 0 && array[j] > key) { array[j + 1] = array[j]; --j; } array[j + 1] = key; } } /*
Binary version is using binary search approch to find the insert position.
In normal insertion, sort it takes O(i) (at ith iteration) in worst case. we can reduce it to O(logi) by using binary search.
*/ void binaryInsertSort(int * array, int n) { int key, i, j, pos; for (i = 1; i < n; i++) { key = array[i]; j = i - 1; pos = binarySearch(array, key, 0, j); while (j >= pos) { array[j + 1] = array[j]; j--; } array[j + 1] = key; } } int binarySearch(int * array, int key, int left, int right) { if (right > left) { int middle = (left + right) / 2; if (key == array[middle]) return middle + 1; if (key > array[middle]) return binarySearch(array, key, middle + 1, right); else return binarySearch(array, key, left, middle - 1); } return key >= array[left]? left + 1: left; }
希尔排序(Shell Sort):
原址排序,不具稳定性
时间复杂度:O(n2)
是对插入排序的改进,相对插入排序更优,减少因子:2
void shellSort(int *array, int n) { for (int gap = n / 2; gap > 0; gap /= 2) { for (int i = gap; i < n; i++) { int temp = array[i]; int j; for (j = i; j >= gap && array[j - gap] > temp; j -= gap) { array[j] = array[j - gap]; } array[j] = temp; } } }
选择排序(Selection Sort):
原址排序
时间复杂度:O(n2), 空间复杂度: O(1)
不超过O(n)次swap, 适合写内存耗费资源的情况
void selectionSort(int *array, int n) { int min_index; for (int i = 0; i < n - 1; i++) { min_index = i; for (int j = i + 1; j < n; j++) { if (array[j] < array[min_index]) min_index = j; } if (min_index != i) swap(&array[i], &array[min_index]); } }
圈排序(Cycle Sort):
时间复杂度:O(n2)
适合内存写操作耗费资源时排序数组
void cycleSort(int *array, int n) { for (int cycle_start = 0; cycle_start < n - 1; cycle_start++) { int item = array[cycle_start]; int pos = cycle_start; for (int i = cycle_start + 1; i < n; ++i) { if (array[i] < item) ++pos; } while (pos != cycle_start) { while (pos < n - 1 && array[pos] == item) ++pos; swap(&item, array + pos); pos = cycle_start; for (int i = cycle_start + 1; i < n; ++i) { if (array[i] < item) ++pos; } } if (array[cycle_start] != item) { array[cycle_start] = item; } } }
归并排序(Merge Sort):
非原址排序,具有稳定性
时间复杂度:Θn(nlgn),空间复杂度:O(n)
通常是顺序访问元素,适合与链表排序

void mergeSort(int * array, int left, int right) { if (left < right) { int middle = (left + right) / 2; mergeSort(array, left, middle); mergeSort(array, middle + 1, right); merge(array, left, middle, right); } } void merge(int * array, int left, int middle, int right) { int n1 = middle - left + 1; int n2 = right - middle; int *array1 = (int *)calloc(n1 + 1, sizeof(int)); int *array2 = (int *)calloc(n2 + 1, sizeof(int)); int i; for (i = 0; i < n1; i++) { array1[i] = array[left + i]; } for (i = 0; i < n2; i++) { array2[i] = array[middle + i + 1]; } array1[n1] = INT_MAX; array2[n2] = INT_MAX; int n = 0, m = 0; for (int k = left; k <= right; k++) { if (array1[n] < array2[m]) { array[k] = array1[n]; ++n; } else { array[k] = array2[m]; ++m; } } }
堆排序(Heap Sort):
原址排序,不具有稳定性(可改变)
构建堆的时间复杂度为 Θ(n)
时间复杂度:O(nLogn)
void heapSort(int * array, int n) { buildMaxHeap(array, n); for (int i = n - 1; i > 0; i--) { exchange(array, i, 0); --n; maxHeapify(array, n, 0); } } void buildMaxHeap(int * array, int n) { for (int i = (n >> 1) - 1; i >= 0; i--) { maxHeapify(array, n, i); } } void maxHeapify(int * array, int n, int key) { int left = (key << 1) + 1; int right = (key << 1) + 2; int largest; if (left < n && array[left] > array[key]) largest = left; else largest = key; if (right < n && array[right] > array[largest]) largest = right; if (largest != key) { exchange(array, key, largest); maxHeapify(array, n, largest); } }
冒泡排序(Bubble Sort):
原址排序,具有稳定性
时间复杂度:O(n2),空间复杂度:O(1)
边界:已排序数组花费最少时间,逆序数组花费最多时间

void bubbleSort(int * array, int n) { int swapped; for (int i = 0; i < n - 1; i++) { swapped = 0; for (int j = 1; j < n - i; j++) { if (array[j - 1] > array[j]) { int temp = array[j - 1]; array[j - 1] = array[j]; array[j] = temp; swapped = 1; } } if (swapped == 0) break; } }
梳排序(Comb Sort):
时间复杂度:O(n2)
是对冒泡排序的改进,相对较优,缩减因子为1.3
void combSort(int *array, int n) { int gap = n; while (gap != 1) { gap = (gap * 10) / 13; if (gap < 1) { gap = 1; } for (int i = 0; i < n - gap; i++) { if (array[i] > array[i + gap]) { swap(array + i, array + i + gap); } } } }
快速排序(Quick Sort):
原址排序
T(n) = T(k) + T(n-k-1) +
(n)
1、最坏情况:
T(n) = T(n-1) +
(n)
数组已排好序、按逆序排列、所有元素具有相同的值,则时间复杂度为 (n2)。通过随机选择pivot,尽量避免此情况的发生。
2、最佳情况:
T(n) = 2T(n/2) +
(n)
每次所选key为中间值,时间复杂度为 (nLogn)
可考虑子数组使用插入排序法进行排序

void quickSort(int * array, int left, int right) { if (left < right) { int middle = partition(array, left, right); quickSort(array, left, middle - 1); quickSort(array, middle + 1, right); } } int partition(int *array, int left, int right) { int i, j, key; /* random version */ int k = rand() % (right - left) + left; if (k != right) exchange(array, k, right); key = array[right]; j = left - 1; for (i = left; i < right; i++) { if (array[i] < key) { ++j; exchange(array, i, j); } } ++j; exchange(array, j, right); return j; } /* iterativity version */ void quickSortIterative(int *array, int left, int right) { int *stack; int top = -1; int middle; stack = calloc(right - left + 1, sizeof(int)); stack[++top] = left; stack[++top] = right; while (top >= 0) { right = stack[top--]; left = stack[top--]; middle = partition(array, left, right); if (middle - 1 > left) { stack[++top] = left; stack[++top] = middle - 1; } if (middle + 1 < right) { stack[++top] = middle + 1; stack[++top] = right; } } }
计数排序(Counting Sort):
非原址排序
时间复杂度:O(n+max),空间复杂度:O(n+max)
假设输入数据属于一个小的区间
void countingSort(int * array, int n, int max) { int *count = (int *)calloc(max, sizeof(int)); int *temp = (int *)calloc(n, sizeof(int)); int i; for (i = 0; i < n; i++) { temp[i] = array[i]; count[array[i]]++; } for (i = 1; i < max; i++) { count[i] += count[i - 1]; } for (i = 0; i < n; i++) { array[count[temp[i]] - 1] = temp[i]; count[temp[i]]--; } }
基数排序(Radix Sort):
非原址排序
时间复杂度:O(d*(n+b)),b是基数,d是有效数字位(logbn) //使用计数排序作为子过程
从低位开始分别就位进行稳定性排序
/* base is 10 */ void countingSort(int * array, int n, int exp) { int *count = (int *)calloc(10, sizeof(int)); int *temp = (int *)calloc(n, sizeof(int)); int i; for (i = 0; i < n; i++) { temp[i] = array[i]; count[array[i] / exp % 10]++; } for (i = 1; i < 10; i++) { count[i] += count[i - 1]; } for (i = 0; i < n; i++) { array[count[temp[i] / exp % 10] - 1] = temp[i]; count[temp[i] / exp % 10]--; } } void radixSort(int *array, int n) { int max = array[0]; int exp; for (int i = 1; i < n; i++) { if (array[i] > max) max = array[i]; } for (exp = 1; max / exp > 0; exp *= 10) { countingSort(array, n, exp); } }
桶排序(Bucket Sort):
非原址排序
时间复杂度:Θ(n) + ∑Ο(n2)
假设输入数据服从均匀分布且为小数,每个桶可用插入排序法

void bucketSort(float *array, int n) { vector<float> *buckets; buckets = new vector<float> [n]; for (int i = 0; i < n; i++) { int index = n * array[i]; buckets[index].push_back(array[i]); } for (int i = 0; i < n; i++) { sort(buckets[i].begin(), buckets[i].end()); } int k = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < buckets[i].size(); j++) { array[k++] = buckets[i][j]; } } }
鸽巢排序(Pigeonhole Sort):
时间复制度:O(n + Range)
适合于排序数组元素的值与索引大体相同,当range大于n时,bucket排序更有效率
void pigeonholeSort(int *array, int n) { int min, max; min = max = array[0]; for (int i = 0; i < n; i++) { if (array[i] < min) min = array[i]; if (array[i] > max) max = array[i]; } int range = max - min + 1; vector<int> *holes = new vector<int> [range]; for (int i = 0; i < n; i++) { holes[array[i] - min].push_back(array[i]); } int index = 0; for (int i = 0; i < range; i++) { vector<int>::iterator it; for (it = holes[i].begin(); it != holes[i].end(); ++it) array[index++] = *it; } }

浙公网安备 33010602011771号