前言:
正如我标题所言,冒泡排序是C语言中比较重要的算法之一(还有快速排序等等许多【排序方法,现在先讲冒泡排序)锕,大家一定要掌握好冒牌排序算法的实现,这个是C语言中比较重要的一个部分,下面不多废话直接进入正题:
目录:
1.冒泡排序实现的逻辑
2.冒泡排序的代码实现
3.冒泡排序的优化
4.代码展现
正文:
1.冒泡排序实现的逻辑
在讲述冒泡排序的逻辑之前,可能有些读者朋友并不知道冒牌排序是干什么的,我在这里简单的说一下,冒牌排序就是一个对你所选择的数组进行升序排序的,假如你想要个升序数组,那么冒泡排序是一个可以帮助你的不错的算法(后期我会将qosrt函数,这个是更加好用的,读者们敬请期待)
首先我们需要设置一个数组,对于数组的内容可以自己定义,可以自己设置一个固定的,也可以用scanf设置一个自己可以改变的数组,之后我们便进入了正题,如何做到升序排列呢,这里我拿十个元素进行举例,我们可以相邻的元素两两比较, 如果前者大于后者,那么我们就对数组元素进行交换,之后我们在让第二个元素和后面的元素进行比较,如此循环下去可以讲比较大的放在后面,结束完这一轮循环以后我们在进入下个循环,此时内部的循环可以减少两两比较一次,因为最后一个数已经是最大的了,在和它比较没意义,再将最大的数放在倒数第二位,如此大循环九次以后,我们便可以完成数的交换,数组里面的元素便会升序排放,下面光说逻辑不加入代码是不好理解的,下面来进入代码实现环节。
2.冒泡排序的代码实现
首先我们需要先输入数组的内容,接下来我将会用10个元素的数组为例·,可以先往里面输入十个数,下面是代码实现:
int arr[10] = {0}
int i = 0;
for(i = 0 ; i < 10 ; i++)
{
scanf("%d",arr + i); //这里为什么可以这么写我在上一篇文章已经解释过了,想要了解的可以看上一篇博客
}
在我们进行完输入函数以后,接下来进入我们的重点环节:如何进行数的排列,我将排序写到了一个函数里面,从而减少主函数的复杂程度,名字我定义的"my_paopao",注意,再传函数的时候一定要把数组的个数传递过去(我在上一篇指针传参的实质重点强调过,如果不加数,传过去的仅仅就是数组第一个元素的地址,并不是整体数组)下面是代码展现:
void my_paopao(int arr[10],int sz)
{
int i = 0;
}
此时函数已经创建完毕,之后通过我在逻辑写的,我们要先循环九次比较作为外层(因为某次都是从前九个开始进行循环的),然后我们内部要再次设置一个循环,这一层循环实现的是两两比较,我们循环的次数随着外部循环的减少而减少,所以在设置最大循环的时候要记得减去i代表着减少循环次数,然后对于两两大小的比较,我们用到了我们的老朋友,if语句来进行判断,如果前者大于后者,那么会实现两两交换,对于两两交换如何实现我相信大家都会做(不会的话我后期可能会出一篇博文来写这个) ,我光口头说大家可能听不懂,下面来放置代码如何进行实现:
void my_paopao(int arr[10], int sz) //这里的sz指的是十个元素个数,对于完整代码下面会展示
{
int i = 0;
for (i = 0; i < sz - 1; i++) //这个是外层循环,最后一个元素是不用比较大,所以我们选择循环9次
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++) //这时候就开始两两数的比较了,这个次数随着外层的减少而减少,因为后几个数已经比较好了就不需要比较了
{
if (arr[j] > arr[j + 1]) //如果前者大于后者就进行交换
{
int tmo = 0;
tmo = arr[j];
arr[j] = arr[j + 1]; //这一部分是进行两个数的交换的算法实现
arr[j + 1] = tmo;
}
count++; //这个不用写,我在这里用count主要是为了后续文章的展开的
}
}
}
上面便是我的语言转代码实现,具体内容我已经标记在代码里面了,我就不多追溯了,下面来看看此代码可不可以正常实现:
可以很清楚的看见我们成功将数组进行升序了,证明此算法已经完全实现了,可能有些读者朋友会疑惑,我为什么会在上面的代码中写个count?这个到底有什么作用?
其实,这里我是为了展现此代码的不足的, 就拿我们上面的输入举例,因为上面的式子是完全降序的,所以我们会完整的循环45次,可能读者朋友们会觉着这样是完全没问题的,但如果我输入一个完全升序的一串数呢?下面来看看结果:
我们发现同样也循环了45次,这样会让代码运行的时间大大增大,所以我们能不能减少循环次数呢?答案是肯定的,下面来进入代码优化过程:
3.冒泡排序的优化:
我们在前文已经说了,此代码的缺点是循环的次数是固定的,所以我们可以设置一个flag的变量,我们可以通过它的改变来判断两者是否需要再次进行外部循环,我们可以在函数循环外部设置它,然后如果内层循环进行了,那么flag的值让它改变,如果flag没有改变,证明并没有发生两个数的交换,此时我们可以直接结束循环,这样可以让循环次数减少,减少代码的运行速度,下面是代码的呈现(加了flag的):
int count = 0;
void my_paopao(int arr[10], int sz)
{
int i = 0;
int flag = 1;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int tmo = 0;
tmo = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmo;
flag = 0;
}
if (flag == 1)
break;
count++;
}
}
}
上面的图片可以看出,当我们是完全是一串升序的数的时候,此时并没有进行循环,成功的对代码进行优化了,我想要讲的都说完了,下面来呈现完整的代码:
4.代码展现
4.1.主函数
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
int i = 0;
for (i = 0; i < 10; i++)
{
scanf("%d", arr + i);
}
int sz = sizeof(arr) / sizeof(arr[0]);
my_paopao(arr, sz);
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
printf("%d", count);
return 0;
}
函数部分:
int count = 0;
void my_paopao(int arr[10], int sz)
{
int i = 0;
int flag = 1;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int tmo = 0;
tmo = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmo;
flag = 0;
}
if (flag == 1)
break;
count++;
}
}
}
总结:
今天的博客内容很短,因为今天的课程比较多,小编目前是大一学生,所以我特定的写了一篇比较短的干货满满的博客,希望读者朋友们要好好掌握冒泡排序的使用,还是那句话,如果文章有错误的话,请您在评论区指出,希望大家多多点赞,那么我们下一篇见啦!