冒泡排序及其改进

冒泡排序

1.排序思想
冒泡排序也是非常简单的排序算法,易于理解。
要点:(1)也把数组看作有序和无序部分,初始时将整个数组视为无序;
            (2)每次遍历数组中的无序部分,且两两比较,并将两者中较大的元素置于后面一位,则一趟遍历完成后,最大元素自然“沉到”无序部分的最后一位;
            (3)减小无序部分的长度,循环第二步,直到数组有序。
其思想与选择排序类似,所不同的是每一趟通过两两比较与交换得到最大值,同时交换到最后位置。

2.代码实现
       

//冒泡排序
void bubbleSort(int arr[], int len)
{
	for (int i=0; i<len-1; i++)  //外层n-1次循环,len-i代表了无序部分的最后一位元素,每循环一次,无序部分个数减1
	{
		for (int j=1; j<len-i; j++)  //内层n-i次循环,目的是将无序部分的最大值交换到len-i位置
		{
			if (arr[j-1] > arr[j])   //两两比较和交换
			{
				swap(arr[j-1], arr[j]);
			}
		}
	}
}


        从代码实现中可以看出外层循环中,len-i实际代表的是无序部分的最后一个元素的位置,外层循环每执行一次就找到无序部分的最大值并同时被交换到len-i的位置上。这样,无序部分元素减少一个,而有序部分个数增加一个。所以len-1趟之后,全部len个数据就拍好序了。
        但是如果数据是有序的或者后半部分有序,冒泡排序的效率将非常低,它依然会一趟一趟不折不扣的执行比较,而造成效率低下。所以,可以针对这种情况对冒泡排序进行改进,那就是引入一个空跑标志(将一趟遍历没有发生数据交换称之为空跑),用来代表该趟遍历是否有数据交换,如果没有,说明后面的数据已经有序(有序才不需要交换),则可以停止比较和交换了;如果有数据交换,则说明数据无序。
       

//冒泡排序的改进(引入空跑标志)
void bubbleSortImp(int arr[], int len)
{
	int flag = 0;                 //空跑标志,初始为0   0-未空跑 1-空跑
    int i = 0;
	while(!flag && i<len-1)          //加入上一趟是否空跑判断
	{
		flag = 1;                   //假设本趟空跑
		for (int j=1; j<len-i; j++)     //内层n-i次循环
		{
			if (arr[j-1] > arr[j])    //两两比较和交换
			{
				swap(arr[j-1], arr[j]);
				flag = 0;              //如果有交换则必然未空跑,否则空跑
			}
		}
		i++;
	}
}


        上述的改进算法主要针对的是数据后半部分有序时候的改进,如果前半部分的数据有序,而后半部分无序又该如何改进呢?这个问题留给读者思考,在文章的最后,我会给出参考链接。
3.性能分析
    时间复杂度:O(n^2)。
    由代码可以看出,相对于选择排序,它的数据移动次数明显增多,而比较次数相同,所以根据选择排序的性能分析,可以得知:无论最好情况、最坏情况和平均情况,比较次数都不变,所以选择排序的时间复杂度O(n^2)。
    空间复杂度:O(1)。
    特点:稳定的就地排序(稳定性与代码有关)。
    适用性:小规模数组排序。
    总结:在某本算法书中提到,冒泡排序的效率是非常糟糕的,如果不是因为它有一个形象易记的名字,可能根本不会有人注意它。
关于上述文章提到的冒泡排序的另一种改进方法,参考链接如下:

http://blog.csdn.net/morewindows/article/details/6657829
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值