以下是典型的排序算法分类及对应的 Java 实现,包含时间复杂度、稳定性说明和核心代码示例:
一、比较类排序(通过元素比较)
1. 交换排序
① 冒泡排序
时间复杂度:O(n²)(优化后最优O(n))
稳定性:稳定
java
public static void bubbleSort(int[] arr) {
boolean swapped;
for (int i = 0; i < arr.length - 1; i++) {
swapped = false;
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}
if (!swapped) break; // 提前终止优化
}
}
② 快速排序
时间复杂度:平均 O(n log n),最差 O(n²)
稳定性:不稳定
java
public static void quickSort(int[] arr, int low, int high) {
if (low < high) {
int pivot = partition(arr, low, high);
quickSort(arr, low, pivot - 1);
quickSort(arr, pivot + 1, high);
}
}
private static int partition(int[] arr, int low, int high) {
int pivot = arr[high]; // 选择末尾为基准
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return i + 1;
}
2. 插入排序
① 直接插入排序
时间复杂度:O(n²)(最优O(n))
稳定性:稳定
java
public static void insertionSort(int[] arr) {
for (int i = 1; i < arr.length; 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;
}
}
3. 选择排序
① 简单选择排序
时间复杂度:O(n²)
稳定性:不稳定
java
public static void selectionSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minIdx = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIdx]) {
minIdx = j;
}
}
int temp = arr[minIdx];
arr[minIdx] = arr[i];
arr[i] = temp;
}
}
4. 归并排序
时间复杂度:O(n log n)
稳定性:稳定
java
public static void mergeSort(int[] arr, int left, int right) {
if (left < right) {
int mid = left + (right - left) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
}
private static void merge(int[] arr, int left, int mid, int right) {
int[] temp = new int[right - left + 1];
int i = left, j = mid + 1, k = 0;
while (i <= mid && j <= right) {
temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];
}
while (i <= mid) temp[k++] = arr[i++];
while (j <= right) temp[k++] = arr[j++];
System.arraycopy(temp, 0, arr, left, temp.length);
}
5. 堆排序
时间复杂度:O(n log n)
稳定性:不稳定
java
public static void heapSort(int[] arr) {
// 构建最大堆
for (int i = arr.length / 2 - 1; i >= 0; i--) {
heapify(arr, arr.length, i);
}
// 逐步提取堆顶元素
for (int i = arr.length - 1; i > 0; i--) {
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
heapify(arr, i, 0);
}
}
private static 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) {
int swap = arr[i];
arr[i] = arr[largest];
arr[largest] = swap;
heapify(arr, n, largest);
}
}
二、非比较类排序(利用数值特征)
1. 计数排序
时间复杂度:O(n + k)(k 为数据范围)
稳定性:稳定
适用场景:整数且范围较小
java
public static void countingSort(int[] arr) {
int max = Arrays.stream(arr).max().getAsInt();
int[] count = new int[max + 1];
for (int num : arr) count[num]++;
int idx = 0;
for (int i = 0; i <= max; i++) {
while (count[i]-- > 0) {
arr[idx++] = i;
}
}
}
2. 基数排序
时间复杂度:O(nk)(k 为最大位数)
稳定性:稳定
java
public static void radixSort(int[] arr) {
int max = Arrays.stream(arr).max().getAsInt();
for (int exp = 1; max / exp > 0; exp *= 10) {
countSortByDigit(arr, exp);
}
}
private static void countSortByDigit(int[] arr, int exp) {
int[] output = new int[arr.length];
int[] count = new int[10];
for (int num : arr) count[(num / exp) % 10]++;
for (int i = 1; i < 10; i++) count[i] += count[i - 1];
for (int i = arr.length - 1; i >= 0; i--) {
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}
System.arraycopy(output, 0, arr, 0, arr.length);
}
三、总结与选择建议
算法 | 平均时间复杂度 | 空间复杂度 | 稳定性 | 适用场景 |
---|---|---|---|---|
冒泡排序 | O(n²) | O(1) | 稳定 | 小数据、教学演示 |
快速排序 | O(n log n) | O(log n) | 不稳定 | 通用场景(优化后高效) |
归并排序 | O(n log n) | O(n) | 稳定 | 大数据、稳定排序需求 |
堆排序 | O(n log n) | O(1) | 不稳定 | 原地排序、内存敏感场景 |
计数排序 | O(n + k) | O(k) | 稳定 | 整数且数值范围小 |
基数排序 | O(nk) | O(n + k) | 稳定 | 多位数整数(如身份证号) |
实际建议:
- 小规模数据:插入排序或冒泡排序(简单实现)。
- 通用场景:优先选择快速排序(需优化基准选择)。
- 稳定排序需求:归并排序或基数排序。
- 特定数值特征:计数排序/基数排序效率碾压比较排序。