冒泡排序
冒泡排序的核心思想非常直观,就像水中的气泡一样,较轻(小)的元素会逐渐上浮到水面(列表前端),而较重(大)的元素会逐渐下沉到底部(列表后端)。
其具体工作流程如下:
比较相邻元素:从列表的第一个元素开始,比较每一对相邻的两个元素。
交换位置:如果前一个元素比后一个元素大(在升序排序中),就交换它们的位置。
一轮遍历结束 :对列表中所有相邻元素对重复上述步骤,直到处理完最后一对。此时,列表中最大 的元素就会被移动到列表的最后位置。
重复过程:针对剩余的、未排序的元素(不包含上一轮已经就位的最大元素),重复执行步骤1-3。
这个过程会持续进行,每一轮都会将一个未排序部分的最大值放到正确的位置,直到整个列表有序
算法排序过程:
以数组 [38, 27, 43, 3, 9, 82, 10] 进行升序排序为例,其前两轮的详细过程如下:
第一轮遍历:
- 比较 38 和 27:38 > 27 → 交换 →
[27, 38, 43, 3, 9, 82, 10] - 比较 38 和 43:38 < 43 → 不交换 →
[27, 38, 43, 3, 9, 82, 10] - 比较 43 和 3:43 > 3 → 交换 →
[27, 38, 3, 43, 9, 82, 10] - 比较 43 和 9:43 > 9 → 交换 →
[27, 38, 3, 9, 43, 82, 10] - 比较 43 和 82:43 < 82 → 不交换 →
[27, 38, 3, 9, 43, 82, 10] - 比较 82 和 10:82 > 10 → 交换 →
[27, 38, 3, 9, 43, 10, 82] - 结果 :最大元素
82已经移动到正确位置。
第二轮遍历:
- 比较 27 和 38:27 < 38 → 不交换 →
[27, 38, 3, 9, 43, 10, 82] - 比较 38 和 3:38 > 3 → 交换 →
[27, 3, 38, 9, 43, 10, 82] - 比较 38 和 9:38 > 9 → 交换 →
[27, 3, 9, 38, 43, 10, 82] - 比较 38 和 43:38 < 43 → 不交换 →
[27, 3, 9, 38, 43, 10, 82] - 比较 43 和 10:43 > 10 → 交换 →
[27, 3, 9, 38, 10, 43, 82] - 结果 :第二大元素
43已经就位。
后续轮次继续此过程,直到所有元素有序。如果在某一轮遍历中没有发生任何交换,说明列表已经完全有序,可以提前结束算法。
算法分析:
冒泡排序虽然实现简单,易于理解,但其效率并不高,尤其在处理大量数据时。
时间复杂度
最坏情况 O(n²):当输入的列表完全逆序时,需要进行 n-1 轮遍历,每轮都要进行大量的比较和交换。
平均情况 O(n²):在处理随机顺序的列表时,其时间复杂度也是平方级别的。
最好情况 O(n):当输入的列表已经有序时,经过优化的冒泡排序只需进行一轮遍历(没有发生任何交换)即可完成,时间复杂度为线性。
空间复杂度
O(1) :冒泡排序只需要常数级别的额外空间来存储临时变量(用于交换元素),是一种原地排序算法。
稳定性
稳定 :冒泡排序是一种稳定排序算法。因为只有当相邻两个元素前大于后时才会交换,如果两个元素相等,它们的相对位置不会改变。
cpp
#include <stdio.h>
// 冒泡排序函数
void bubbleSort(int arr[], int n) {
// 外层循环控制排序轮数 (n-1 轮即可保证全部有序)
for (int i = 0; i < n - 1; i++) {
int swapped = 0; // 标志位,记录本轮是否发生交换
// 内层循环进行相邻元素比较
// 每经过一轮,最大的元素会"冒泡"到末尾,所以 j 的范围是 n-i-1
for (int j = 0; j < n - i - 1; j++) {
// 如果前一个元素大于后一个元素,则交换
if (arr[j] > arr[j + 1]) {
// 执行交换操作
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = 1; // 标记发生了交换
}
}
// 如果本轮没有发生任何交换,说明数组已经有序,可以提前结束
if (!swapped) {
break;
}
}
}
// 打印数组的辅助函数
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// 主函数,用于测试
int main() {
int data[] = {38, 27, 43, 3, 9, 82, 10};
int n = sizeof(data) / sizeof(data[0]); // 计算数组长度
printf("排序前: ");
printArray(data, n);
bubbleSort(data, n);
printf("排序后: ");
printArray(data, n);
return 0;
}