C语言——冒泡排序的实现(含优化版)

冒泡排序介绍

冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。——来自百度百科

图文解析

我们举一个简答的例子,现在有如下五个方块,需要将将它们从低到高升序排序。
在这里插入图片描述
我们现在详细演示一遍第一趟的内容:
在这里插入图片描述
在这里插入图片描述
第三步结束后:
在这里插入图片描述
第四步过后,第一轮结束:
在这里插入图片描述

总结规律:

1.每一轮结束后,最大的方块会移动到最右边,即可以将一块方块归位。
2.对n个数据进行冒泡排序,需要排序n-1轮
3.每次完成一轮后,下一轮需要比较的数据减少1。(比如我们这里,第一轮完成后,最大的数据就会道达右边,下一轮就可以少比较一次)
每一轮的结果演示:
第一轮:
在这里插入图片描述
第二轮:
在这里插入图片描述
排序完成!

可视化演示

71,114,105,62,44,47,93,80,56,121这十个数通过冒泡排序进行升序排序:
在这里插入图片描述

冒泡排序C语言实现(一般方法)

最简单的方法,遍历数组,满足条件则替换。

代码

#include <stdio.h>
void bubble_sort(int arr[], int sz)
{
	//进行sz-1轮排序
	for (int i = 0; i < sz - 1; i++)
	{
		//每一轮比较sz-1-i次(i就是已经完成的轮数)
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}
int main()
{
	int arr[10] = { 71,114,105,62,44,47,93,80,56,121};
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前: ");
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	bubble_sort(arr, sz);
	printf("\n排序后(升序): ");
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

程序运行效果:
在这里插入图片描述

思考一下优化方案

我们现在代码的缺点:
1.可能还没有完全循环完就已经排序好了,就想我们上面的图解,只进行了两轮就排序好了,于是我们通过自己的判断让排序停止了。但是我们写的程序不会这样做,所以我们第一步优化方案就是加一个标记来标记是否已经排序完毕,这里我们的逻辑是:如果进行了交换,则没有排序完毕,否则就代表已经排序完成
2.很难想到的一点,我在参考了一位大佬的做法后,总结一下。请看上方我们第一轮结束时的图片:
在这里插入图片描述
第二轮,需要比较三次((n-1-i)=(5-1-1))但是我们实际只需比较一次即可,因为右方的4,5已经有序了。
所以我们有了第二个优化方案:每一轮结束后,标记最后一次交换的位置,其右侧为有序,左侧为无序。我们只需要判断无序的位置即可。

优化后代码:

#include <stdio.h>
void bubble_sort(int arr[], int sz)
{
	//有序数的边界(我们只需判断其左侧的无序数)
	int limit = sz - 1;
	//标记每一轮最后一次交换的位置
	int last_change = 0;
	//进行sz-1轮排序
	for (int i = 0; i < sz - 1; i++)
	{
		//假设没有进行替换(数组已经有序)
		int flag = 0;
		//每一轮比较limit次,即只比较无序的数
		for (int j = 0; j < limit; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				//交换
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				//如果交换了,则标记数组无序
				flag = 1;
				//记录最后一次交换的位置
				last_change = j;
			}
		}
		//每一轮结束后,更新有序数的边界,其边界就是上一轮最后一次交换的位置
		limit = last_change;
		//如果没有交换,则数组已经有序,直接跳出循环
		if (0 == flag)
		{
			break;
		}
	}
}
int main()
{
	int arr[10] = { 71,114,105,62,44,47,93,80,56,121 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前: ");
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	bubble_sort(arr, sz);
	printf("\n排序后(升序): ");
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

程序运行效果:
在这里插入图片描述

总结

冒泡排序是一个稳定的算法,也是比较简单的算法,希望大家能够尽早掌握。本篇博客主要介绍了冒泡排序的一般形式和优化方法,希望对你有所帮助!
文章如果有问题请大家积极在评论区讨论,一起讨论一起进步!
那我们下期再见吧!
在这里插入图片描述

  • 8
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值