排序算法的实现(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也没有进去过的,也就是不需要再进行排序了。

这样的修改,才是较为不错的。以上就是给各位带来的第一个排序算法—冒泡排序,码字不易,看到这里不妨给博主点一个关注,点一个赞吧,希望这个排序算法的实现和优化能让你们学到一点东西。我会坚持更新的。

如有错误,请联系修改。

参考资料:

冒泡排序_百度百科 (baidu.com)

冒泡排序动图 - 国内版 Bing images

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值