【数据结构】八大排序之冒泡排序

本文详细解析冒泡排序算法,并提出三种优化策略:利用布尔变量判断是否已排序、记录最后一次交换位置以减少无效比较,及设定最新边界避免重复检查已排序部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

冒泡排序:(升序为例)

         利用两个for循环每次比较相邻的两个元素,如果前一个元素比后一个元素大则交换两个数。外层的for循环控制排序的总趟数,内层的for循环控制每一趟的相邻两个数的比较的次数

 

我们很轻易的看出:

      冒泡排序的时间复杂度最好情况为:

      冒泡排序的时间负责督最坏情况为

冒泡排序是稳定的排序

一.

下边我们以数组array[ ] = {5,8,6,3,9,2,1,7}为例,做升序排序

第一趟: 5 --> 8 --> 6 --> 3 --> 9 --> 2 --> 1 --> 7

               5 --> 6 --> 8 --> 3 --> 9 --> 2 --> 1 --> 7

               5 --> 6 --> 3 --> 8 --> 9 --> 2 --> 1 --> 7

               5 --> 6 --> 3 --> 8--> 2 --> 9 --> 1 --> 7  

               5 --> 6 --> 3 --> 8 --> 2 --> 1 --> 9 --> 7

               5 --> 6 --> 3 --> 8 --> 2 --> 1 --> 7 --> 9

第二躺: 5 --> 3 --> 6 --> 8 --> 2 --> 1 --> 7 --> 9

               5 --> 3 --> 6 --> 2 --> 8 --> 1 --> 7 --> 9

               5 --> 3 --> 6 --> 2 --> 1 --> 8 --> 7 --> 9

               5 --> 3 --> 6 --> 2 --> 1 --> 7 --> 8 --> 9

第三趟:

第四趟:

第五趟:

第六趟: 1 --> 2 --> 3 --> 5 --> 6 --> 7 --> 8 --> 9

第七躺:

第八躺:           

 

由于太多了,只能写出少部分,和特殊的,其中没写的都是重复以上动作

代码展示:

void BubbleSort(int array[],int sz)
{

	for (int i = 0; i < sz; i++)
	{

		for (int j = 0; j < sz - i - 1 ; j++)
		{
			if (array[j] > array[j + 1])
			{
				int temp = 0;
				temp = array[j + 1];
				array[j + 1] = array[j];
				array[j] = temp;
				isSoretd = false;

			}
		}


	}
}

二.

               我们可以看出,当我们不假思索的写出以上代码时,这个大部分人都可以搞定,这时候面试官肯定会问我们该去优化他

使得他效率更高。

            我们可以看到上面演示的过程中,在第六趟的时候,这个数组里的数据已经是有序的了,然而我们还多余的跑了两趟,大大的降低了代码的效率

解决方法:

      我们可以利用特殊的函数来标记当数据已经是有序的就可以跳出循环。这时候我们就可以利用boolean(布尔变量)isSorted作为标记。如果在本轮排序中没有元素交换就证明数据已经有序,直接跳出循环。

       布尔变量:

            是由两种逻辑状态的变量,他们分别为:true 和 false    常被用来作为标记

代码展示:

void BubbleSort(int array[],int sz)
{

	for (int i = 0; i < sz; i++)
	{
		boolean isSoretd = true;

		for (int j = 0; j < sz - i - 1 ; j++)
		{
			if (array[j] > array[j + 1])
			{
				int temp = 0;
				temp = array[j + 1];
				array[j + 1] = array[j];
				array[j] = temp;
				isSoretd = false;

			}
		}

		if (isSoretd)
		{
		break;
		}
	}
}

三.

这时候我们可以看到,代码在面对一些特殊情况时,效率上已经得到了极大的提升,但是这时候面试官可能觉得还不够,我们还必须去进一步优化。

来看以下情况:(升序)

我们选定一个新的数组 array[ ] ={3,4,2,1,5,6,7,8};

我们可以可到这个数组内前半部分是无序的(3,4,2,1)但是后边确实升序(5,6,7,8)

让我们来看一下按照以前的方法排序过程:

第一趟:3 --> 4 --> 2 --> 1 --> 5 --> 6 --> 7 --> 8

              3 --> 2 --> 4 --> 1 --> 5 --> 6 --> 7 --> 8

              3 --> 2 --> 1 --> 4 --> 5 --> 6 --> 7 --> 8

             。。。。。。。。

第二趟:2 --> 3 --> 1 --> 4 --> 5 --> 6 --> 7 --> 8

              2 --> 1 --> 3 --> 4 --> 5 --> 6 --> 7 --> 8

第三趟:1 --> 2 --> 3 --> 4 --> 5 --> 6 --> 7 --> 8

 

      从上边的过程我们可以看出,每趟的排序中在后边是已经有序的数据,但是在每一轮的排序中还会去做无用功,这又一次大大的降低了程序运行的效率。

       我们可以看到影响效率的问题关键是:对数列有序区的界定

为了解决这个问题我们可以在没一轮的循环中,记录数据最后一次交换的位置,则这个就是数列的有序的边界

代码展示:

void BubbleSort(int array[],int sz)
{

	//排序的最新边界
	int sortborder = sz - 1;
	//记录最后一次交换的位置
	int lastchange = 0;
	for (int i = 0; i < sz; i++)
	{
		boolean isSoretd = true;

		for (int j = 0; j < sortborder; j++)
		{
			if (array[j] > array[j + 1])
			{
				int temp = 0;
				temp = array[j + 1];
				array[j + 1] = array[j];
				array[j] = temp;
				isSoretd = false;

				lastchange = j;
			}
		}

		sortborder = lastchange;
		if (isSoretd)
		{
		break;
		}
	}
}

          以上就是本人自己想到的优化的地方,如果大家有什么可以进一步优化的地方麻烦留言告诉我一声,大家互相进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值