排序之交换排序01冒泡排序以及改进

交换排序之冒泡排序

参考博客https://blog.csdn.net/MoreWindows/article/details/6657829

以及B站视频https://www.bilibili.com/read/cv3285768

复杂度

时间复杂度:

  • 最好情况:O(n)

  • 最坏情况:O(n^2)

  • 平均情况:O(n^2)

空间复杂度:O(1)

稳定性:稳定

主要思路:

设数组长度为n,以从小到大排序为例,主要分为以下几步:

  1. 从第一个数开始,比较前后相邻的元素,若a[i]>a[i+1]则发生交换,
  2. 就这样对数组的第0个数据到n-1个数据进行一次遍历后,最大的一个数据就冒泡到数组第n-1的位置。
  3. 就这样最后面数组的元素都是最大的和较大的,n--,直到n==0,排序完成

程序如下,

//冒泡排序
void bubbleA(int a[], int n){
	int i, j;
	for(i=0; i<n; i++){//i表示的第几趟冒泡排序 
		for(j=0; j<n-i; j++){
		//j始终是从0开始取的,由于第i趟冒泡已经将大的移动到了后面,所以后面不用排序 ,
		//只用到n-i即可 
			if(a[j]>a[j+1]) 
				swap(&a[j], &a[j+1]);
	}
//	skillA(a, n);
}
}

但是如果某一趟没有发生交换,则说明排序已经完成,这个时候就没有必要进行比较了,于是设置一个标志位flag,当发生交换时,flag = 1;每一次冒泡排序后都将其进行清零,代码如下:
 

//有标志位的冒泡排序 
void bubleAFlag(int a[], int n){
	int i, j;
	int flag = 1;
	for(i=0; i<n && flag==1; i++){//每一次排序开始前都判断一下flag,由此判断上次有无发生交换 
		flag = 0;//排序开始清零标志 
		for(j=0; j<n-i; j++){
			if(a[j]>a[j+1]){
				flag = 1;//发生了交换,置位标志位。 
				swap(&a[j], &a[j+1]);
			}
		}
	}
} 

还可以做进一步优化吗?假如有100个数组, 初始时,前面10个是无序的,但是后面90个都是排序好的,且大于前面10个,那么前90趟排序发生交换的位置必定限制在前10个里面,但是我们每趟的比较都是大于10的,所以可以设置一个标志记录一下一趟的交换排序的位置(因为某一趟的交换排序,最后发生交换的后面必定是有序的),避免多余比较。

//记录交换位置
void bubbleAFlag2(int a[], int n){
	int i, j;
	int flag = n;
	
	while(flag>1){//当flag标记到第二个元素的时候,也就是flag == 1 就说明已经排序好了 
		j = flag;//记录最后一次发生交换的位置(较大的那个元素),下一次排序到此为止 
		for(i=0; i<(j-1); i++){//比较是从0到记录位置之前的那个元素位置(j-1)冒泡 
			if(a[i]>a[i+1]){
				swap(&a[i], &a[i+1]);
				flag = i+1;//发生了交换则记录之位置
			} 
		}
		
	}
} 

冒泡排序毕竟是一种效率低下的排序方法,在数据规模很小时,可以采用。数据规模比较大时,最好用其它排序方法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值