引言

冒泡排序是我在上大一学习C语言过程中授课老师给我们讲的第一个算法,也是我在编程道路上学会的第一个算法。

原理解释

冒泡排序就和它的名字一样,像水中的气泡一样从最底下往上升。较小的元素会逐渐向序列的一端“漂浮”或“冒泡”起来,而较大的元素则沉到另一端。每一轮遍历都会确保至少有一个元素(通常是最后一个未排序的元素)到达其最终的正确位置。

其基本思想是重复地遍历需要排序的数列,每次遍历时通过两两比较相邻元素,如果他们的顺序错误(即前一个比后一个大或相反),就交换这两个元素的位置。这个过程会一直持续到没有更多的元素需要交换为止,也就是数列已经排序完成。

附一张原理图

基本步骤

  1. 初始化:选择一个方向(升序或降序),并从序列的第一个元素开始。
  2. 比较与交换:比较相邻的元素。如果第一个比第二个大(对于升序排序),则交换它们;反之亦然。
  3. 继续遍历:继续对每一对相邻元素执行步骤2,直到列表的末尾。
  4. 重复:重复步骤2和3,但是每次遍历都忽略已正确排序的部分(通常是序列的尾部)。
  5. 终止条件:当没有更多的交换发生时,排序完成

代码实现

#include <stdio.h>
int main() {
	int arr[10];
	int temp;
	for (int i = 0; i < 10; i++) {
		scanf("%d", &arr[i]);
	}
	for (int i = 0; i < 10; i++) {
		for (int j = 0; j < 9 - i; j++) {
			if (arr[j] > arr[j + 1]) {
				temp = arr[j];         
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
	for (int i = 0; i < 10; i++) {
		printf("%d", arr[i]);
	}
	return 0;
}

效果

Tips

在代码中第二层for循环中”j<9-i"的原因是在每轮遍历中,最后一个元素(或称当前轮次的最后一个未排序元素)会被放置到它应该处于的正确位置。随着遍历的进行,每一轮都会将一个元素放到它的最终位置上,因此下一轮就不需要再考虑这个元素了。

以升序排序为例:

  • 第一轮:需要进行 n-1 次比较,将最大的元素移到数组的最后。
  • 第二轮:需要进行 n-2 次比较,将次大的元素移到倒数第二个位置。
  • 第三轮:需要进行 n-3 次比较,将第三大的元素移到倒数第三个位置。
  • ...
  • 最后一轮:需要进行 1 次比较,将仅剩的两个元素进行比较并排序。

总结来说,每轮遍历的比较次数如下表所示:

轮次比较次数
1n - 1
2n - 2
......
n-11

总结

冒泡排序虽然简单易懂,但由于其较高的时间复杂度,在实际应用中通常只适用于小型数据集或教学演示。对于大规模数据的排序,更高效的算法如快速排序、归并排序等通常更加合适。