思路
假设有一个长度为 nnn 的数组 aaa 。
冒泡排序的执行过程如下:
首先,设 r=n−1r=n-1r=n−1 。
- 遍历一遍 a0⋯ara_0\cdots a_{r}a0⋯ar 比较相邻的两个数(ai,ai−1(0≤i<r)a_i,a_{i-1}(0\le i< r)ai,ai−1(0≤i<r)),若 ai>ai+1a_i>a_{i+1}ai>ai+1 则交换 aia_iai 与 ai+1a_{i+1}ai+1。
- 做完 1. 后,最大值肯定在最后面,下次遍历不用管,所以 rrr 减少 111。
- 每次都对越来越少需要操作的元素进行操作,直到没有需要操作的元素为止。
代码
#include <iostream>
using namespace std;
int a[int(1e7)];
void BubbleSort(int *a, int n) {
for (int i = 0; i < n - 1; ++i)
for (int j = 0; j < n - i - 1; ++j)
if (a[j] > a[j + 1]) swap(a[j], a[j + 1]);
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n; ++i) cin >> a[i];
BubbleSort(a, n);
for (int i = 0; i < n; ++i) cout << a[i] << ' ';
return 0;
}
优化
假如从 axa_xax 之后的区间是有序的,那么再去对该区间做冒泡是没有意义的,应当立即退出。可以维护布尔变量 bbb,假如发生了交换(说明后面的数组可能无序)直接退出。
#include <iostream>
using namespace std;
int a[int(1e7)];
void BubbleSort2(int *a, int n) {
for (int i = 0; i < n - 1; ++i) {
bool b = 0;
for (int j = 0; j < n - i - 1; ++j)
if (a[j] > a[j + 1]) {
swap(a[j], a[j + 1]);
b = 1; // 有交换说明后面的数组可能无序
}
if (!b) break; // 假如没有交换说明后面数组已经有序,再排序没有意义,直接退出
}
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n; ++i) cin >> a[i];
BubbleSort2(a, n);
for (int i = 0; i < n; ++i) cout << a[i] << ' ';
return 0;
}
优化之后,最好时间复杂度是 O(n)O(n)O(n) (aaa已经是有序的)。
最坏复杂度仍是 O(n2)O(n^2)O(n2) (aaa 是逆序的)。

本文介绍了冒泡排序的基本原理和优化方法。通过设置布尔变量检测是否发生交换,当数组已有序时可提前终止排序,从而在最佳情况下达到O(n)的时间复杂度。同时,讨论了冒泡排序的最坏情况时间复杂度为O(n^2)。
2万+

被折叠的 条评论
为什么被折叠?



