【引入】
我们都知道,一般情况下,气泡都会自动地从水下慢慢地往上浮。因此我们可以将要排序的数据都当成一个一个气泡,然后按照我们控制的条件使“气泡”们“自动”地浮到对应的位置。从整体上看,数据变得有序了。
【手工演示】
让我们从最坏的情况(一组数据是完全逆序的)来入手分析(假设数据都是int类型):
我们可以发现,趟数为元素个数减1(len-1)。每趟比较的次数随着趟数序数的变化而变化,明显成函数关系,并且它们的和与元素个数又成数学关系。
【代码实现】
然后将上述草稿转换为下面的代码:
void BubbleSort (int arr[], int len) //传参:要排序的数组以及数组元素的个数
{
int i=0;
for (i=0; i<len-1; i++) //外层循环控制排序的趟数
{
int j=0;
for (j=0; j<len-1-i; j++) //内层循环控制每趟排序的比较次数
{
if (arr[j] > arr[j+1]) //两个数据的交换条件(使数据升序或者降序)
{
int tmp = arr[j]; // 借助临时变量将两个数据交换
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
可以看到,前一趟被处理过的整数,已经排好并放在了后面,因此在后一趟中无须再次访问。
测试其它的用例,也能得到预期的结果。
那么如果存在多个数值相等的元素呢?
如果实际实现上面的代码,两个数值相等的元素在排序过程中会相互靠近,一旦它们处于相邻位置,那么后续的排序操作就不会对它们产生相对位置上的改变,因此冒泡排序算法是比较稳定的。
时间复杂度:
其实,不单单是int类型的数据,也可以是其他类型的数据:
void BubbleSort (elemType arr[], int len)
{
int i=0;
for (i=0; i<len-1; i++)
{
int j=0;
for (j=0; j<len-1-i; j++)
{
if (arr[j] > arr[j+1])
{
elemType tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
【运用举例】
比如按照学生的平均成绩来排序结构数组的元素:
void BubbleSort (struct data stu[], int len)
{
int i=0;
for (i = 0; i < len-1; i++)
{
int j=0;
for (j = 0; j < len-1-i; j++)
{
if (stu[j].average < stu[j + 1].average) //从大到小排序
{
struct data tmp = stu[j];
stu[j] = stu[j + 1];
stu[j + 1] = tmp;
}
}
}
}
或是按照学生名字(字符串)来排序结构数组的元素:将上面的if语句改为
if (strcmp(stu[j].name, stu[j + 1].name) > 0) 即可。
更多文章:
让你理解选择排序(C语言)