排序算法 | 平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 稳定性 | 适用场景 |
---|---|---|---|---|---|
冒泡排序 | O(n²) | O(n²) | O(1) | 稳定 | 小数据量 |
选择排序 | O(n²) | O(n²) | O(1) | 不稳定 | 简单实现 |
插入排序 | O(n²) | O(n²) | O(1) | 稳定 | 部分有序 |
希尔排序 | O(n log n) | O(n²) | O(1) | 不稳定 | 中等规模 |
快速排序 | O(n log n) | O(n²) | O(log n) | 不稳定 | 通用排序 |
归并排序 | O(n log n) | O(n log n) | O(n) | 稳定 | 大数据量 |
堆排序 | O(n log n) | O(n log n) | O(1) | 不稳定 | 内存受限 |
计数排序 | O(n + k) | O(n + k) | O(k) | 稳定 | 整数小范围 |
桶排序 | O(n + k) | O(n²) | O(n + k) | 稳定 | 均匀分布 |
基数排序 | O(d(n + k)) | O(d(n + k)) | O(n + k) | 稳定 | 多关键字 |
原理:通过相邻元素比较交换,使最大元素逐渐上浮到右侧
步骤:
特点:
void bubbleSort(int arr[], int n) {
for(int i = 0; i < n-1; ++i) {
bool swapped = false;
for(int j = 0; j < n-i-1; ++j) {
if(arr[j] > arr[j+1]) {
swap(arr[j], arr[j+1]);
swapped = true;
}
}
if(!swapped) break; // 提前终止优化
}
}
原理:每次从未排序序列中选择最小元素放到已排序序列末尾
步骤:
特点:
void selectionSort(int arr[], int n) {
for(int i = 0; i < n-1; ++i) {
int minIndex = i;
for(int j = i+1; j < n; ++j)
if(arr[j] < arr[minIndex])
minIndex = j;
swap(arr[i], arr[minIndex]);
}
}
原理:将未排序元素逐个插入已排序序列的合适位置
步骤:
特点:
void insertionSort(int arr[], int n) {
for(int i = 1; i < n; ++i) {
int key = arr[i];
int j = i-1;
while(j >= 0 && arr[j] > key) {
arr[j+1] = arr[j];
--j;
}
arr[j+1] = key;
}
}
原理:改进的插入排序,通过分组进行插入排序
步骤:
特点:
void shellSort(int arr[], int n) {
for(int gap = n/2; gap > 0; gap /= 2) {
for(int i = gap; i < n; ++i) {
int temp = arr[i];
int j;
for(j = i; j >= gap && arr[j-gap] > temp; j -= gap)
arr[j] = arr[j-gap];
arr[j] = temp;
}
}
}
原理:分治法选取基准元素进行分区排序
步骤:
特点:
void quickSort(int array[], int l, int r) {
if(l >= r) return;
int p = array[l + r >> 1], i = l - 1, j = r + 1;
while(i < j) {
while(array[++i] < p);
while(array[--j] > p);
if(i < j) swap(array[i], array[j]);
}
quickSort(array, l, j);
quiclSort(array, j + 1, r);
}
原理:分治法将数组分为两半分别排序后合并
步骤:
特点:
void mergeSort(int array[], int l, int r) {
if(l >= r) return;
int mid = l + r >> 1;
mergeSort(array, l, mid);
mergeSort(array, mid + 1, r);
int k = 0, i = l, j = mid + 1;
int temp[r - l + 1];
while(i <= mid && j <= r) {
if(array[i] <= array[j]) temp[k++] = array[i++];
else temp[k++] = array[j++];
}
while(i <= mid) temp[k++] = array[i++];
while(j <= r) temp[k++] = array[j++];
for(i = l, j = 0; i <= r; i++, j++) array[i] = temp[j];
}
原理:利用堆数据结构进行排序
步骤:
特点:
void down(int array[], int si, int u) {
int t = u;
if(u * 2 + 1 < si && array[u * 2 + 1] > h[t]) t = u * 2 + 1;
if(u * 2 + 2 < si && array[u * 2 + 2] > h[t]) t = u * 2 + 2;
if(u != t) {
swap(array[t], array[u]);
down(array, si, t);
}
}
void heapSort(int array[], int n) {
for(int i = n / 2 - 1; ~i; i--) down(i);
for(int i = n - 1; i; i--) {
swap(array[0], array[i]);
down(array, i, 0);
}
}
原理:将数据分到有限数量的桶中,各桶分别排序
适用条件:均匀分布的数据
步骤:
void bucketSort(vector<int> arr[], int bucketSize) {
// 1. 确定数据范围
int minVal = *min_element(arr.begin(), arr.end());
int maxVal = *max_element(arr.begin(), arr.end());
// 2. 计算桶的数量
int bucketCount = (maxVal - minVal) / bucketSize + 1;
vector<vector<int>> buckets(bucketCount);
// 3. 元素分桶
for (int num : arr) {
int bucketIdx = (num - minVal) / bucketSize;
buckets[bucketIdx].push_back(num);
}
// 4. 排序每个桶并合并
int index = 0;
for (auto& bucket : buckets) {
sort(bucket.begin(), bucket.end()); // 使用快速排序
for (int num : bucket) {
arr[index++] = num;
}
}
}
【算法系列】基数排序-CSDN博客
十大排序算法——计数排序-CSDN博客
原理:使用一个额外的数组C,其中第i个元素是待排序数组A中值等于i的元素的个数。然后根据数组C来将A中的元素排到正确的位置。它只能对整数进行排序。
适用条件:整数排序,数据范围较小
步骤:
特点:
参考:DeepSeek