冒泡排序及3个优化

本文详细介绍了冒泡排序的基本思想及四种优化版本,包括基本冒泡排序、通过标记减少比较轮数的优化、利用实际有序集长度减少比较次数的优化以及采用鸡尾酒法的双向比较优化。

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

目录

 

冒泡排序基本思想(默认从小到大):

版本1 基本的冒泡排序

版本2:纵向优化(通过标记是否交换,减少不必要的比较轮数)

V3 横向优化(优化有序集,用实际有续集减少不必要的比较)

v4 鸡尾酒法(左右比较优化以下情况)


 

冒泡排序基本思想(默认从小到大):

每轮比较相邻的两个数进行交换操作,每一轮完毕,无序集里最大的数都会排在有续集里。

若每轮从左到右进行比较,则有续集在右边,每轮的最大数在右边有序集中冒泡。

若每轮从右到左进行比较,则有续集在左边,每轮的zuix最小数在左边有序集中冒泡。

与选择排序不同,选择排序初始最左边最小,在剩下的里面逐个比较选择选择更小的替换此位置上的值,知道一轮完毕,选出最小的替换在最左边。如此进行第二轮。冒泡排序则每一轮进行相邻的数比较排序,最大的数逐渐被替换到最右边,得到第一轮有序集,如此进行第二轮。

版本1 基本的冒泡排序

没有任何优化,eg 5 6 7 3 9 2 1 8

6轮之后 1 2 3 4 5 6 7 8后面两轮在做无用功

//冒泡排序  时间复杂度仍未n^2但是有效
void BubbleSortV1(int arrey[], int len)//顺序比较,顺序集合在后
{
	int temp;
	for (int i = 0; i < len; i++)
	{
		for (int j = 0; j < len - i -1; j++)//有序集长度为i即比较的轮数,有序集没必要比较
		{
			if (arrey[j] > arrey[j+1])
			{
				temp = arrey[j];
				arrey[j] = arrey[j+1];
				arrey[j+1] = temp;
			}
		}
	}
}

 

版本2:纵向优化(通过标记是否交换,减少不必要的比较轮数)

通过引入exchange标记每一轮是否发生交换,若发生交换则说明并未排好序,继续下一轮,否则排好序退出循环。

//冒泡排序 exchange 标记优化 时间复杂度仍未n^2但是有效
void BubbleSortV2(int arrey[], int len)//顺序比较,顺序集合在后
{
	int temp;
	int exchange = 1;//交换标记 0 没发生交换集合已经顺序 否则发生交换排序未完成
	for (int i = 0; i < len&&exchange ==1; i++)
	{
		exchange = 0;//每一趟默认排序好 若此趟已经排序好 则下一趟exchange 为0排序结束循环结束
		for (int j = 0; j < len - i -1; j++)//有序集长度为i即比较的轮数,有序集没必要比较
		{
			if (arrey[j] > arrey[j+1])
			{
				temp = arrey[j];
				arrey[j] = arrey[j+1];
				arrey[j+1] = temp;
				exchange = 1;//发生交换
			}
		}
	}
}

 

V3 横向优化(优化有序集,用实际有续集减少不必要的比较)

//优化Bubble,实际中有序集长度可能大于算法有序集
//eg 3 2 1 4 5 6 7 8 第一轮比较算法有序集为0,但第一轮比较两次之后
//是 3 2交换后 2 1交换 2 1 3 4 5 6 7 8 3后面已经是实际有序,但算法有续集为0
//故后面得比较5次无用的 
//优化 记录最后一次交换的位置即为实际的有序集Border
void BubbleSortV3(int arrey[], int len)
{
	int tmp = 0;
	int lastexIndex = 0;
	int Border = len - 1;
	int exchange = 1;
	for (int i = 0; i < len && (exchange); i++)
	{
		exchange = 0;//每一轮默认不交换 证明排序好 若此轮已经排序好 则下一轮exchange 为0排序结束循环结束
		for (int j = 0; j < Border; j++)
		{
			if (arrey[j] > arrey[j + 1])
			{
				tmp = arrey[j];
				arrey[j] = arrey[j + 1];
				arrey[j + 1] = tmp;
				exchange = 1;
				lastexIndex = j;//记录实际有序集的边界,即最后一次交换的j
			}
		}
		Border = lastexIndex;//记录最后发生交换的位置,即实际有序集边界
	}
}

 

v4 鸡尾酒法(左右比较优化以下情况)

//2 3 4 5 6 7 1 8
//若按照之前的排序方法从左到右 得8轮排序但是只有1位置不对
//从右到左排序只需要1轮
//通用性:先从左到右在从右到左,则可以避免这种问题 需要两个边界,两轮
//鸡尾酒排序
void BubbleSortV4(int arrey[], int len)
{
	int tmp = 0;
	int lastexLeftIndex = 0;
	int lastexRightIndex = 0;
	int BorderLeft = 0;
	int BorderRight = len - 1;
	int exchange = 1;
	for (int i = 0; i < len/2 -1 && (exchange); i++)//每一轮进行左右冒泡则每轮有序集增加2个,轮次减半
	{
		exchange = 0;//每一轮默认不交换 证明排序好 若此轮已经排序好 则下一轮exchange 为0排序结束循环结束
	 //奇数轮次 从左到右 左右都有有序集故左边起始为i(有序集边界) BorderLeft
		for (int j = BorderLeft; j < BorderRight; j++)
		{
			if (arrey[j] > arrey[j + 1])
			{
				tmp = arrey[j];
				arrey[j] = arrey[j + 1];
				arrey[j + 1] = tmp;
				exchange = 1;
				lastexRightIndex = j;//记录实际有序集的边界,即最后一次交换的j
			}
		}
		BorderRight = lastexRightIndex;//记录最后发生交换的位置,即实际有序集边界

	 //偶数轮次 从右到左 左右都有有序集故右边起始为j(有序集边界)BorderRight
		for (int j = BorderRight; j >BorderLeft ; j--)
		{
			if (arrey[j] < arrey[j - 1])
			{
				tmp = arrey[j];
				arrey[j] = arrey[j - 1];
				arrey[j - 1] = tmp;
				exchange = 1;
				lastexLeftIndex = j;//记录实际有序集的边界,即最后一次交换的j
			}
		}
		BorderLeft = lastexRightIndex;//记录最后发生交换的位置,即实际有序集边界
	}
}

 

好困啊,昨晚实验室任务阶段性完成,如释重负,农药打到晚上3点,上个钻石(菜鸟级别)哎,早上起不来,标记以下,希望后面能够自律一点。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值