冒泡排序(C语言实现)
冒泡排序的基本思想:
冒泡排序(Bubble Sort):由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序。
冒泡排序流程:
- 比较相邻的元素。若前一个比后一个大,就交换它们两个(小数往前放,大数往后放)
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对
- 完成一次冒泡排序
- 针对所有的元素重复以上的步骤,除了最后一个
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
冒泡排序图解 :
首先,我们定义一个乱序排列的数组,需要将它升序排列
这里,我们定义了 一个降序排列的数组arr,这是一种最坏的情况

接下来我们开始第一趟冒泡排序,一趟冒泡排序可以使一个元素回归到正确位置
第一次比较

交换之后数组中的元素更新如下图,并进行下一次比较
第二次比较

同理,进行下一次比较
第三次比较

第四次比较

第五次比较

第六次比较

第七次比较

第八次比较

第九次比较
交换之后,数组中元素更新为下图

此时,已经进行完了一趟冒泡排序,一个元素(实际上是最大的元素)已经回归到了正确位置,在这一趟冒泡排序中,我们进行了九次比较
同理,在第二趟冒泡排序中,我们可以使次大元素回归到正确位置



为什么比较八次:因为第一趟冒泡排序之后,我们已经将最大数放到了最后的位置,次大数比较八次之后,没有必要再和最大数比较,此时的位置就是它的正确位置
八次比较并交换之后,数组更新为如下图:

同理,其他元素依次进行一趟冒泡排序,如下图

第九趟冒泡排序之后,最小数没有必要再进行比较,已经自动被挤到了它的正确位置
综上所述:
当一个数组有十个元素时,总共需要进行9趟冒泡排序,即元素个数减一
总结:一个有sz个元素的数组,冒泡排序需要进行sz-1趟
对于第一趟冒泡排序,需要比较交换9次;
对于第二趟冒泡排序,需要比较交换8次;
同理,对于第三趟冒泡排序,需要比较交换8次
... ...
对于第八趟冒泡排序,需要比较交换2次;
对于第九趟冒泡排序,只需要比较交换1次
每次比较交换的次数都是都是元素个数减一再依次减去0,1,2,... ... , sz-1
所以我们可以使用双层循环实现,外层循环一次进行一趟冒泡排序,内层循环实现比较交换
可以发现这些数字都是外层循环变量每次的取值
构造出双层循环的框架之后
我们可以发现一个小bug:当这个数组本身就是升序排列时,我们仍然需要不断地进入循环进行比较但是没有交换,这个操作是没有必要的,当一趟冒泡排序中没有交换操作时,就证明这个数组本身有序,没有必要进行下一趟冒泡排序,直接退出循环即可
因此我们可以定义一个标志变量flag,初始化为1,即假设这个数组有序
当我们有交换操作时,同时置falg为0,证明数组无序,需要进行下一趟冒泡排序
但是当我们内层循环结束时,判断flag仍然为1,即证明这一趟冒泡排序中没有交换操作,数组已经有序了,所以直接break退出循环
使用冒泡排序法将整形乱序数组升序排列:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void bubble_sort(int* arr, int sz)
{
int flag = 1;//假设已经有序
int i = 0;
//总共sz个数,进行sz-1趟排序
for (i = 0; i < sz-1; i++)
{
int j = 0;
//让第i个数到正确位置,一趟冒泡排序
for (j = 0; j <sz-i-1 ; j++)
{
if (arr[j] > arr[j + 1])
{
flag = 0;
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
//若程序运行至此flag的值为1,证明一趟冒泡排序进行时,发现该数组有序,跳出循环
if (flag == 1)
{
break;
}
}
}
int main()
{
int arr[] = { 10,9,8,7,6,5,4,3,2,1 };//定义一个乱序数组
int sz = sizeof(arr) / sizeof(arr[0]);//计算数组长度
bubble_sort(arr, sz);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)