在本篇文章中,我们将通过实操一个小题目,来理解与运用冒泡排序
冒泡排序是什么,怎么工作的?
冒泡排序是一种排序算法,它可以将一堆无序/乱序的元素,排列成有序的元素。
它的工作方式就和在水底吐泡泡一样:一次吐一个泡泡,泡泡吐出来后向上冒,而当这个泡泡向上冒的运动结束时,它的位置处于当前水的最高处(水面)。
如图:
我们每一次冒泡的过程中,都会从第一个数开始,不断地向后进行比较。
以排升序(从小到大排)为列:
有数列 4 3 2 1
第一趟冒泡(本趟冒泡排序中,共要执行 n - 1次冒泡,n为元素的个数):
4 和 3比, 4 大,则4冒上来。数列变为 3 4 2 1
然后4 再与 2比较,4 大, 4再冒上来。数列变为 3 2 4 1
然后4 再与 1比较,4 大, 4再冒上来。数列变为 3 2 1 4
此时第一趟冒泡走完,数列的最后一个数已经是数列中最大的元素。
再进行第二趟冒泡排序,此时水面下下降一个元素,本次排序只需执行 n - 1 -1 次。(因为最后一个元素已经排序完成,无需再进行比较)。
以此下去,一共要执行n - 1趟冒泡。(因为最后一个元素已经被动地放在了它该在地地方,无需排序)。
运用:
我们刚刚已经学会了冒泡排序地工作原理,现在我们运用冒泡排序来解一个小题目,来加深冒泡排序地理解。
题目描述:
输入4个整数,要求按由小到大的顺序输出。
解题思路:
直接运用冒泡排序算法,进行升序的重新排列。
代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
#define SIZE 4
//冒泡排序
void Bubble_sort(int* const p, int num)
{
assert(p);
int i = 0;//控制总冒泡的次数
int j = 0;//控制每一次冒泡时,需要操作的元素数量
int tem = 0;//进行交换时的临时变量
int flag = 0;//标志位,记录是否发生元素交换
//num个元素,即需要进行num - 1次冒泡
for (i = 0; i < num - 1; i++)
{
//每次进入循环,标志位重置为0
flag = 0;
//每次减少1个数(每次冒泡完成,即有1个数已被排序完成)
//
//j不能等于数组的最后一个元素
//所以结束条件为: num - i - 1
//因为:
// 1.j为最大下标时, 执行*(action + j + 1),会造成越界访问
// 2.j不是最大下标时,*(action + j + 1)已经被排序结束,无需再进行比较
for (j = 0; j < num - i - 1; j++)
{
if (j != num - i - 1)
{
//如果前面的数大于后面的数,则需要替换
if (*(p + j) > *(p + j + 1))
{
tem = *(p + j);
*(p + j) = *(p + j + 1);
*(p + j + 1) = tem;
//发生交换,更新标志位
flag = 1;
}
}
}
//如果一轮中为发生任何排序,说明排序已经完成,可提前结束排序
if (!flag)
{
break;
}
}
}
int main()
{
int arr[SIZE] = { 0 };
int i = 0;
//录入元素
for (i = 0; i < SIZE; i++)
{
scanf("%d", &arr[i]);
}
//进行排序
Bubble_sort(arr, SIZE);
//输出排序好的数列
for (i = 0; i < SIZE; i++)
{
printf("%d ", arr[i]);
}
return 0;
}