引入:
昨天我们介绍了二分法(折半查找法)的使用和代码演示,该二分法存在一定的局限性,即只能在一个有序的数组中查找一个目标数target,为了消除此局限性,我们必须在使用二分法之前把该数组排序成一个有序数组,把一个无序数组变成一个有序数组的方法叫做--冒泡排序
正文:
冒泡排序实现原理(这里讲升序,假设该数组有10个元素):
取出一个无序数组中的第一个元素,把第一个元素和后面的一个元素进行比较如果第一个元素比后面的一个元素大则这两个元素进行交换,交换后第一个元素跑到了第二个元素的位置上面,然后又和第三个元素进行交换,如果此次比较发现,第一个元素比第三个元素的值小那么不交换,说明第一个元素小于第三个元素,此时我们就把第三元素和第四个元素进行比较,以此类推我们就可以在本次循环中把本数组中的元素最大值放在数组的最后一个位置上面完成后,第一趟比较结束;我们发现第一趟比较了9次,然后进行下一趟比较。
我们此时就来到了第二趟的比较,经过上一趟的比较后,可知该数组的最后一个元素为此数组中的最大值,为此此趟排序中就不考虑最后一个元素,所以第二趟相比于第一趟的比较次数要少一次,即为9-1=8次,以此类推可以知道第三趟比较7次、第四趟比较6次、第五趟比较5次.....此时我们就要确定趟数的次数了,我们知道一趟排序就把一个元素的位置确定下来了,该数组有10个元素,按理说需要10趟,但假设我们已经完成了8趟排序,已经有8个元素“安顿下来了”此时还有两个元素的位置还没有确定下来,那么我们仅需要一趟排序就可以把这两个元素“安顿”下来;所以我们需要总的趟数为数组元素个数10-1=9趟即可完成排序
综合上述例子我们可以知道,冒泡排序一个含有n个元素的的无序数组,需要进行n-1趟排序,而每趟排序比较的次数也在随趟数的增加而减少,即比较次数=n-1-已经完成的趟数。
上述冒泡排序后就可以实现一个无序数组的排序
实现代码演示如下:
#include<stdio.h>
int main()
{
int arr[] = { 1,3,5,7,9,2,4,6,8,10 };
int n = sizeof(arr) / sizeof(arr[0]);//计算数组元素个数
printf(" 冒泡排序前:");
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
//冒泡排序(升序)开始
//确定趟数n元素个数
for (int i = 0; i < n - 1; i++)//需要进行n-1趟
{
//确定比较次数,i的值是已经排序的总的趟数
for (int j = 0; j < n - 1 - i; j++)//比较次数=n-1-i
{
if (arr[j] > arr[j + 1])//如果前一个元素大于后一个元素则交换
{
//if的判断条件控制升序
int tem = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tem;
}
}
}
printf("冒泡排序升序后:");
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
//冒泡排序结束
//冒泡排序(降序)开始
//确定趟数n元素个数
for (int i = 0; i < n - 1; i++)//需要进行n-1趟
{
//确定比较次数,i的值是已经排序的总的趟数
for (int j = 0; j < n - 1 - i; j++)//比较次数=n-1-i
{
if (arr[j] < arr[j + 1])//如果前一个元素小于后一个元素则交换
{
//if的判断条件控制降序
int tem = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tem;
}
}
}
//冒泡排序结束
printf("冒泡排序降序后:");
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
代码运行结果如下:
结语:
该方法虽然可以实现无序数组的有序排序,但仍具有局限性,该局限性在于只能排一个整型数组,那么有没有一种方法可以实现字符数组,或者其他数组的元素的有序排序呢?明天将会和大家一起讨论对于任意类型的数组都可以实现冒泡排序的库函数qsort()以及模拟实现qsort()的原理的方法。
感谢大家的理解与支持。