冒泡排序

本文深入探讨冒泡排序,从基本的交换函数到不同版本的实现,包括1.0、2.0和3.0版本。重点分析了2.0版本如何减少不必要的交换和移动次数,以及3.0版本如何优化无意义的循环。文章最后分析了冒泡排序的时间复杂度,指出在最好和最坏情况下的复杂度分别为O(n)和O(n^2)。

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

冒泡排序

本文参考自《大话数据结构》,这本书介绍的冒泡排序让我对之前学的冒泡有了更深的理解。

冒泡排序(Bubble Sort)一种交换排序,基本思想:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止

交换函数

/* 交换值 */
void swap(SqList* L, int i, int j){
    int temp = L->r[i];
    L->r[i] = L->r[j];
    L->r[j] = temp;
}

1.0版本

/* 顺序表L冒泡排序1.0 */
void BubbleSort1(SqList *L){
	int i, j;
	for(i=1;i<L->length;i++){	//交换的位置1
		for(j=i+1;j<=L->length;j++){	//交换的位置2
			if(L->r[i] > L->r[j])
				swap(L, i , j);	//交换值
		}
	}
}

2.0版本

/* 顺序表L冒泡排序2.0 */
void BubbleSort2(SqList *L){
	int i, j;
	for(i=1;i<L->length;i++){	//循环的次数=数组长度-1,因为最后一次只剩一个元素,不需要判断
		for(j=L->length-1;j>=i;j--){	//冒泡:每次都与后一个比较,如果当前的比后一个大,则交换。即小的放前面
			if(L->r[j] > L->r[j+1]
				swap(L, j, j+1);
		}
	}
}

1.0与2.0区别

1.0和2.0的区别在于:1.0不是真冒泡,它采用的是,每次拿去跟r[i] (i=1,2,…,n)做比较,这样做有什么问题呢?

比如,当序列为94563,i=1,2时,

  • 1.0排序的最终结果为:39564,34956,此时移动次数为:2,3;
  • 2.0排序的最终结果为:39456,34956,此时移动次数为:4,1;
  • 可以不一样的地方在于,如果序列本身是部分有序的,那么2.0版本的移动次数会少很多(第1次和第2次对比),而且2.0不会将已经部分排好序的序列再次打乱。

3.0版本

/* 顺序表L冒泡排序3.0 */
void BubbleSort3(SqList *L){
	int i, j;
	Status flag = TRUE;	//标记
	for(i=1;i<L->length && flag;i++){
		flag = FALSE;	//设置为false,代表没有发生数据交换,即后面的序列都是已经排好序的,后面可以跳出循环不用重复判断了
		for(j = L->length-1;j>=i;i--){
			if(L->r[j] > L->r[j+1]){
				swap(L, j, j+1);
				flag = TRUE;		//如果有数据交换,则flag为true
			}
		}
	}
}

3.0版本可以避免多次无意义的循环判断,比如序列为:123456,这种序列本身就已经排好序了,在i=1的时候就已经全部都知道了,只需遍历一次就行,后面的遍历都是没有意义的。

复杂度分析

按照3.0版本,最好的情况是表本身有序,那么比较的次数为n-1次,没有发生数据交换,时间复杂度O(n);最坏情况,排序表为逆序,此时需要比较n*(n-1)/2次,同时作等数量级的记录移动,此时时间复杂度为O(n^2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值