引言

排序是最基础的算法之一。本文全面讲解常见排序算法的原理和实现。

一、基础排序算法

1.1 冒泡排序

1
2
3
4
5
6
7
8
9
10
public void bubbleSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1);
}
}
}
}

1.2 选择排序

1
2
3
4
5
6
7
8
9
10
11
12
public void selectionSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
int minIdx = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIdx]) {
minIdx = j;
}
}
swap(arr, i, minIdx);
}
}

1.3 插入排序

1
2
3
4
5
6
7
8
9
10
11
12
13
public void insertionSort(int[] arr) {
int n = arr.length;
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;
}
}

二、高级排序算法

2.1 快速排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public void quickSort(int[] arr, int left, int right) {
if (left < right) {
int pivot = partition(arr, left, right);
quickSort(arr, left, pivot - 1);
quickSort(arr, pivot + 1, right);
}
}

private int partition(int[] arr, int left, int right) {
int pivot = arr[right];
int i = left - 1;

for (int j = left; j < right; j++) {
if (arr[j] < pivot) {
i++;
swap(arr, i, j);
}
}

swap(arr, i + 1, right);
return i + 1;
}

2.2 归并排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public 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 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);
}

2.3 堆排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public void heapSort(int[] arr) {
int n = arr.length;

// 建堆
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}

// 排序
for (int i = n - 1; i > 0; i--) {
swap(arr, 0, i);
heapify(arr, i, 0);
}
}

private 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, largest);
heapify(arr, n, largest);
}
}

三、复杂度对比

算法 平均 最好 最坏 空间 稳定性
冒泡 O(n²) O(n) O(n²) O(1) 稳定
选择 O(n²) O(n²) O(n²) O(1) 不稳定
插入 O(n²) O(n) O(n²) O(1) 稳定
快排 O(n log n) O(n log n) O(n²) O(log n) 不稳定
归并 O(n log n) O(n log n) O(n log n) O(n) 稳定
堆排序 O(n log n) O(n log n) O(n log n) O(1) 不稳定

总结

排序算法核心:

  1. 基础算法:冒泡、选择、插入
  2. 高级算法:快排、归并、堆排序
  3. 选择依据:时间、空间、稳定性

参考资料