思路
假设有一个长度为
n
n
n 的数组
a
a
a 。
冒泡排序的执行过程如下:
首先,设 r = n − 1 r=n-1 r=n−1 。
- 遍历一遍 a 0 ⋯ a r a_0\cdots a_{r} a0⋯ar 比较相邻的两个数( a i , a i − 1 ( 0 ≤ i < r ) a_i,a_{i-1}(0\le i< r) ai,ai−1(0≤i<r)),若 a i > a i + 1 a_i>a_{i+1} ai>ai+1 则交换 a i a_i ai 与 a i + 1 a_{i+1} ai+1。
- 做完 1. 后,最大值肯定在最后面,下次遍历不用管,所以 r r r 减少 1 1 1。
- 每次都对越来越少需要操作的元素进行操作,直到没有需要操作的元素为止。
代码
#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;
}
优化
假如从 a x a_x ax 之后的区间是有序的,那么再去对该区间做冒泡是没有意义的,应当立即退出。可以维护布尔变量 b b b,假如发生了交换(说明后面的数组可能无序)直接退出。
#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) (
a
a
a已经是有序的)。
最坏复杂度仍是
O
(
n
2
)
O(n^2)
O(n2) (
a
a
a 是逆序的)。