排序算法 | 平均时间复杂度 | 最差时间复杂度 | 空间复杂度 | 数据对象稳定性 |
---|---|---|---|---|
冒泡排序 | O(n2) | O(n2) | O(1) | 稳定 |
选择排序 | O(n2) | O(n2) | O(1) | 数组不稳定、链表稳定 |
插入排序 | O(n2) | O(n2) | O(1) | 稳定 |
快速排序 | O(n*log2n) | O(n2) | O(log2n) (递归的原因),如果每次一半都没有元素,最坏O(n) | 不稳定 |
堆排序 | O(n*log2n) | O(n*log2n) | O(1) | 不稳定 |
归并排序 | O(n*log2n) | O(n*log2n) | O(n) | 稳定 |
希尔排序 | O(n*log2n) | O(n2) | O(1) | 不稳定 |
计数排序 | O(n+m) | O(n+m) | O(n+m) | 稳定 |
桶排序 | O(n) | O(n) | O(m) | 稳定 |
基数排序 | O(k*n) | O(n2) | 稳定 |
以下是一些实现
冒泡
void sort(int *arr, int len) {
for (int i = 0; i < len; i++) {
int flag = false; // 是否发生交换
for (int j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) { // 相邻比较,交换
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
flag = true;
}
}
if (!flag) { // 没有发生交换,表示排序完毕
break;
}
}
}
选择
void sort(int *arr, int len) {
for (int i = 0; i < len; i++) {
int min = i;
for (int j = i; j < len; j++) {
if (arr[min] > arr[j]) {
min = j;
}
}
if(min != i) {
int tmp = arr[i];
arr[i] = arr[min];
arr[min] = tmp;
}
}
}
快速
void quick_sort(int *arr, int low, int high) {
if (low >= high) {
return;
}
int i = low, j = high, index = arr[low];
while (i < j) {
for (; i < j; j--) {
if (arr[j] < index) {
arr[i++] = arr[j];
break;
}
}
for (; i < j; i++) {
if (arr[i] > index) {
arr[j--] = arr[i];
break;
}
}
}
arr[i] = index;
quick_sort(arr, low, i - 1);
quick_sort(arr, i + 1, high);
}
插入
c
void insertion_sort(int arr[], int len) {
for (int i = 1; i != len; ++i) { // 第0个元素可以认为是排序好的,所以从1开始
int key = arr[i];
for (int j = i - 1; j >= 0; j--) {
if (arr[j] > key) {
arr[j + 1] = arr[j];
} else {
arr[j + 1] = key;
break;
}
}
}
}
归并
c
void merge_sort_recursive(int* arr, int* temp, int start, int end) {
if (start >= end)
return;
int len = end - start, mid = (len >> 1) + start;
int start1 = start, end1 = mid;
int start2 = mid + 1, end2 = end;
merge_sort_recursive(arr, temp, start1, end1);
merge_sort_recursive(arr, temp, start2, end2);
int k = start;
while (start1 <= end1 && start2 <= end2)
temp[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
while (start1 <= end1)
temp[k++] = arr[start1++];
while (start2 <= end2)
temp[k++] = arr[start2++];
for (k = start; k <= end; k++)
arr[k] = temp[k];
}
void merge_sort(int* arr, int len) {
int* temp = (int*)malloc(sizeof(int) * len);
merge_sort_recursive(arr, temp, 0, len - 1);
free(temp);
}
堆
c
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
void heapify(int* arr, int n, int i) {
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left] > arr[largest]){
largest = left;
}
if (right < n && arr[right] > arr[largest]){
largest = right;
}
if (largest != i) { // 如果最大不是根
swap(&arr[i], &arr[largest]);
heapify(arr, n, largest); // 递归地定义子堆
}
}
void heap_sort(int* arr, int n) {
for (int i = n / 2 - 1; i >= 0; i--) { // 从最后一个非叶子节点开始,构建堆
heapify(arr, n, i);
}
for (int i = n - 1; i > 0; i--) {
swap(&arr[0], &arr[i]); // 移动当前根到最后
heapify(arr, i, 0); // 在减小的堆上调用 max heapify
}
}
希尔排序
c
void shell_sort(int* arr, int len) {
int temp;
for (int step = len / 2; step > 0; step /= 2) {
for (int i = step; i < len; i++) {
temp = arr[i];
int j = i - step;
while (j >= 0 && arr[j] > temp) {
arr[j + step] = arr[j];
j -= step;
}
arr[j + step] = temp;
}
}
}
计数排序
C
void counting_sort(const int *ini_arr, int *sorted_arr, const int n, const int max_val) {
int *count_arr = (int *) calloc(max_val, sizeof(int));
for (int i = 0; i < n; i++)
count_arr[ini_arr[i]]++; // 计数
for (int i = 1; i < max_val; i++)
count_arr[i] += count_arr[i - 1]; // 定位
for (int i = n; i > 0; i--)
sorted_arr[--count_arr[ini_arr[i - 1]]] = ini_arr[i - 1];
free(count_arr);
}
桶排序
基数排序
多路归并排序
跳跃表排序
红黑树排序