冒泡排序几乎是我们学习的第一个排序算法,它的思想很简单,在一串数字里面,两两依次比较出较大的或者较小的,当比较到最后一个元素的时候,最大或者最小的那个一个数字就找到了,我们把它放在当前末尾位置,然后重复此操作,每次比较的元素个数减一,因为我们每次都会找到一个次大或者次小的元素后,就会把它固定在最终位置。冒泡的实现有好几种,但思想都是一样的。但是在我们比较的过程中,有一种特别的情况,就是数组已经是有序的了,而简单的冒泡排序就没有考虑到这个问题,还在傻傻的对有序序列进行比较,这显然是不理想的。那么怎么判断序列是否有序,判断是否交换就行,如果一轮冒泡结束了还没有交换,那么我们就认为它已经有序,我们就直接退出排序操作,代码中实现只需声明一个变量标记一下是否有进行交换这个操作就行。
普通版冒泡排序代码(冒泡有很多写法我这里提供其中的一种):
#include <stdio.h>
// 交换两个整数的值
void Swap(int* a, int* b) {
*a = *a + *b; // 步骤1: 将 *a 和 *b 的和赋值给 *a
*b = *a - *b; // 步骤2: 将 *a 减去原 *b 的值,得到原 *a 的值,赋值给 *b
*a = *a - *b; // 步骤3: 将 *a 减去原 *b 的值,得到原 *b 的值,赋值给 *a
}
// 冒泡排序函数
void BubbleSort(int Array[], int len) {
// 外层循环: 遍历整个数组的轮次
for (int i = 0; i < len - 1; i++) {
// 内层循环: 进行相邻元素的比较和交换
for (int j = len - 1; j > i; j--) {
// 如果前一个元素大于后一个元素,则交换它们
if (Array[j - 1] > Array[j]) {
Swap(&Array[j - 1], &Array[j]);
}
}
}
}
int main() {
// 初始化待排序的数组
int Array[10] = { 50, 26, 38, 80, 70, 90, 8, 30, 40, 20 };
// 调用冒泡排序函数,对数组进行排序
BubbleSort(Array, 10);
// 打印排序后的数组元素,以 "->" 连接每个元素
for (int i = 0; i < 10; i++) {
printf("%d->", Array[i]);
}
printf("\n"); // 打印换行符,以结束输出
return 0; // 程序正常结束
}
运行结果:
优化版冒泡排序代码:
#include <stdio.h>
#define bool int
#define true 1
#define false 0
// 交换两个整数的值
void Swap(int* a, int* b) {
*a = *a + *b; // 步骤1: *a 加上 *b
*b = *a - *b; // 步骤2: *b 赋值为原 *a
*a = *a - *b; // 步骤3: *a 赋值为原 *b
}
// 冒泡排序函数
void BubbleSort(int Array[], int n) {
// 外层循环: 遍历整个数组,逐步将最大值"冒泡"到数组的末尾
for (int i = 0; i < n - 1; i++) {
bool flag = false; // 标记当前一趟排序是否发生了交换
// 内层循环: 对当前未排序的部分进行比较和交换
for (int j = n - 1; j > i; j--) {
// 如果前一个元素大于后一个元素,交换它们
if (Array[j - 1] > Array[j]) {
Swap(&Array[j - 1], &Array[j]);
flag = true; // 发生了交换
}
}
// 如果在当前趟排序中没有发生交换,说明数组已经有序,可以提前退出
if (!flag) return;
}
}
int main() {
// 初始化待排序的数组
int Array[10] = { 50, 26, 38, 80, 70, 90, 8, 30, 40, 20 };
// 调用冒泡排序函数,对数组进行排序
BubbleSort(Array, 10);
// 打印排序后的数组元素
for (int i = 0; i < 10; i++) {
printf("%d->", Array[i]);
}
printf("\n"); // 打印换行符,以结束输出
return 0;
}
运行结果: