排序算法的实现(1)—冒泡排序(C语言)
上一篇博客上说了二分查找算法的条件,大家还记得吗?其中有一个条件就是数组是要有序的,那么,这篇博客给大家带来的就是对数组元素进行排序的一个算法—冒泡排序。
先上定义:
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中的二氧化碳气泡最终会上浮到顶端一样,故名“冒泡排序”。
冒泡排序的一个重要思想就是,将相邻的元素进行比较,并在必要时交换位置,从而实现排序的目的。
接下来是代码的实现
#include<stdio.h>
int main()
{
int arr[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
int sz = sizeof(arr) / sizeof(arr[0]);//这样会更具普遍性一些,而不是单纯只用看得出来的10,要考虑到数组是在变化的。
int i = 0;
printf("交换前:");
for (; i<sz; i++)//这里的这一段代码只是为了对比让读者能更清晰的看到排序的区别,如果只是为了排序,可以不要这段代码
{
printf("%d ", arr[i]);
}
for (i = 0; i<sz; i++)//这是要走的趟数
{
int j = 0;
for (j = 0; j<sz - 2; j++)//这里要注意一下,sz-2这个条件,下面数组要用到j+1,防止出现越界访问的现象。
{
if (arr[j]>arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
printf("\n");//换行一下,会让对比更明显一点
printf("交换后:");
for (i = 0; i<sz; i++)//这里的这一段代码只是为了对比让读者能更清晰的看到排序的区别,如果只是为了排序,可以不要这段代码
{
printf("%d ", arr[i]);
}
return 0;
}
但,你认为这样的代码就可以了吗?
大家想一想,如果我的数组一开始就不需要排序了呢?一开始的创建数组就是0,1,2,3,4,5,6,7,8,9,那就不需要排序了。但是,这个程序还是会一直闷声往下进行,进入循环,出循环,直到程序执行完毕。那么,应该如何优化这段代码,使得机器变得“聪明”起来,可以判断是不是需要排序呢?
接下来,我们就来实现一下这个过程,实际上也不是非常的难。
#include<stdio.h>
//int main()
//{
// int arr[] = {0,1,2,3,4,5,6,7,8,9};
// int sz = sizeof(arr) / sizeof(arr[0]);//这样会更具普遍性一些,而不是单纯只用看得出来的10,要考虑到数组是在变化的。
// int i = 0;
// printf("交换前:");
// for (; i<sz; i++)//这里的这一段代码只是为了对比让读者能更清晰的看到排序的区别,如果只是为了排序,可以不要这段代码
// {
// printf("%d ", arr[i]);
// }
// int flag = 1;//注意这个代码
// for (i = 0; i<sz; i++)//这是要走的趟数
// {
// int j = 0;
// for (j = 0; j<sz -1; j++)//这里要注意一下,sz-2这个条件,下面数组要用到j+1,防止出现越界访问的现象。
// {
// if (arr[j]>arr[j + 1])
// {
// int tmp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = tmp;
// flag = -flag;
// }
// }
// if (flag == 1)
// break;
// }
// printf("\n");
// printf("交换后:");
// for (i = 0; i<sz; i++)//这里的这一段代码只是为了对比让读者能更清晰的看到排序的区别,如果只是为了排序,可以不要这段代码
// {
// printf("%d ", arr[i]);
// }
// return 0;
//}
有了这个flag作为标志,我们就可以在第一次就不需要排序的时候直接跳出来,避免浪费时间。
然而,各位注意到了吗?我的措辞是第一次就不需要排序,那如果是刚好有一次需要排序偶数次,但flag是不是又变成了1?比如:5,3,4,2,1?又跳出来了,但我们的排序还没完成,这不是就错了吗?所以接下来,再进行优化,将情况思考周全
#include<stdio.h>
int main()
{
int arr[] = { 5,3,4,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);//这样会更具普遍性一些,而不是单纯只用看得出来的10,要考虑到数组是在变化的。
int i = 0;
printf("交换前:");
for (; i<sz; i++)//这里的这一段代码只是为了对比让读者能更清晰的看到排序的区别,如果只是为了排序,可以不要这段代码
{
printf("%d ", arr[i]);
}
int flag = 1, count = 0;//注意这个代码
for (i = 0; i<sz; i++)//这是要走的趟数
{
int j = 0;
for (j = 0; j<sz - 1; j++)//这里要注意一下,sz-2这个条件,下面数组要用到j+1,防止出现越界访问的现象。
{
if (arr[j]>arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = -flag;
count++;
}
}
if (flag == 1 && count % 2 != 0)
break;
}
printf("\n");
printf("交换后:");
for (i = 0; i<sz; i++)//这里的这一段代码只是为了对比让读者能更清晰的看到排序的区别,如果只是为了排序,可以不要这段代码
{
printf("%d ", arr[i]);
}
return 0;
}
加了一个count,用来记录一下次数,确保flag不是因为交换了偶次数而被重置为1,这样就可以说明,如果flag为1 的时候,是一次if也没有进去过的,也就是不需要再进行排序了。
这样的修改,才是较为不错的。以上就是给各位带来的第一个排序算法—冒泡排序,码字不易,看到这里不妨给博主点一个关注,点一个赞吧,希望这个排序算法的实现和优化能让你们学到一点东西。我会坚持更新的。
如有错误,请联系修改。
参考资料:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了