冒泡算法的简单优化

冒泡排序算法的原理如下:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

 

时间复杂度:

若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数 https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D12/sign=5e6ca6622c738bd4c021b633a08bb91b/b3b7d0a20cf431ad4f379a864936acaf2fdd98ac.jpg 和记录移动次数 https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D16/sign=c765e07cd5ca7bcb797bc329bf09e8ac/48540923dd54564e27333d86b1de9c82d1584f3f.jpg 均达到最小值:

 https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D84/sign=2cfb4bf49182d158bf8254b5810a024c/8326cffc1e178a8244f3b2bafb03738da877e8da.jpg , https://gss3.bdstatic.com/7Po3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D66/sign=1745c99097cad1c8d4bbff217e3e11cd/b21c8701a18b87d6007472a0050828381f30fd5f.jpg 。

所以,冒泡排序最好的时间复杂度为 https://gss3.bdstatic.com/7Po3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D33/sign=feddd1e257fbb2fb302b5e114e4a94f7/b58f8c5494eef01f9d1ac17ae2fe9925bc317d07.jpg 。
若初始文件是反序的,需要进行 https://gss3.bdstatic.com/7Po3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D32/sign=411c7ed7d309b3deefbfe26acdbf0492/8b82b9014a90f60364df45f83b12b31bb051ed26.jpg 趟排序。每趟排序要进行 https://gss3.bdstatic.com/7Po3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D30/sign=3af139940cf41bd5de53eef450da752f/503d269759ee3d6d1214597441166d224e4adebb.jpg 次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。

在这种情况下,比较和移动次数均达到最大值:

https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D171/sign=f38fc3a1bb389b503cffe455b434e5f1/838ba61ea8d3fd1f846a7b85324e251f95ca5f2a.jpg

https://gss2.bdstatic.com/9fo3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D188/sign=752dcc96713e6709ba0041f703c69fb8/34fae6cd7b899e51dd180aa54ca7d933c9950de8.jpg

冒泡排序的最坏时间复杂度为 https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D40/sign=17b28fa860d0f703e2b294dc09fa9d5c/e4dde71190ef76c63a4e22949f16fdfaae5167f5.jpg 。 

综上,因此冒泡排序总的平均时间复杂度为 https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D40/sign=17b28fa860d0f703e2b294dc09fa9d5c/e4dde71190ef76c63a4e22949f16fdfaae5167f5.jpg 。

算法稳定性

冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,是不会再交换的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

template<class Data>
class CSortingBubbling
{
public:
	CSortingBubbling();
	~CSortingBubbling();
public:
	void sorting(Data arr[], int length);
	void BubbleSort(Data arr[], int len);
	void swap(Data& a, Data& b);
};

template<class Data>
CSortingBubbling<Data>::CSortingBubbling() {

}

template<class Data>
CSortingBubbling<Data>::~CSortingBubbling()
{
}
/************************************************************************/
/* 它是一种较简单的排序算法。它会遍历若干次要排序的数列,每次遍历时,它都会从前往后依次的比较相邻两个数的大小;如果前者比后者大,则交换它们的位置。这样,一次遍历之后,最大的元素就在数列的末尾! 采用相同的方法再次遍历时,第二大的元素就被排列在最大元素之前。重复此操作,直到整个数列都有序为止 */
/************************************************************************/
template<class Data>
void CSortingBubbling<Data>::sorting(Data arr[], int length) {
	int max_index = length - 1;
	for (int i = 0;i < length;i++)
	{
		bool is_exchange = true;
		max_index = (length - i) > max_index ? max_index : (length - i);
		int _max_index = max_index;
		for (int j = 0;j < _max_index;j++)
		{
			if (arr[j] > arr[j+1])
			{
				is_exchange = false;
				swap(arr[j], arr[j + 1]);
				/************************************************************************/
				/* 记录最后交换,后面没有交换说明j后面的数字已经是有序的没必要没次都全部循环 */
				/************************************************************************/
				max_index = j;
			}
		}
		/************************************************************************/
		/*循环结束is_exchange为true说明本次循环发现数组已经有序不需要再次进行交换*/
		/************************************************************************/
		if (is_exchange)
			break;
	}
}
/************************************************************************/
/* 换个思路,每次找到最大值放到最后再查找最小值放到数组最前面*/
/************************************************************************/
template<class Data>
void CSortingBubbling<Data>::BubbleSort(Data arr[], int len)
{
	int i = 0;
	int j = 0;
	int n = 0;//同时找最大值的最小需要两个下标遍历
	bool flag = true;
	int pos = 0;//用来记录最后一次交换的位置
	int k = len - 1;
	for (i = 0; i < len - 1; i++)//确定排序趟数
	{
		pos = 0;
		flag = 0;
		//正向寻找最大值
		for (j = n; j < k; j++)//确定比较次数
		{
			if (arr[j] > arr[j + 1])
			{
				//交换
				swap(arr[j], arr[j + 1]);
				flag = false;//加入标记
				pos = j;//交换元素,记录最后一次交换的位置
			}
		}
		if (flag)//如果没有交换过元素,则已经有序,直接结束
			return;
		k = pos;//下一次比较到记录位置即可
				//反向寻找最小值
		for (j = k; j > n; j--)
		{
			if (arr[j] < arr[j - 1]) {
				swap(arr[j], arr[j - 1]);
				flag = false;
			}
		}
		n++;
		if (flag)//如果没有交换过元素,则已经有序,直接结束
			return;
	}
}

template<class Data>
void CSortingBubbling<Data>::swap(Data& a, Data& b)
{
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值