数据结构之起泡排序

写在前面

看了b站上清华老师邓俊辉邓老师的视频,把代码写下来自己记录记录,方便记忆和理解。

起泡排序算法

bubbleSort.1

这是个很简单也很容易理解的起泡排序算法。
算法开始逐行扫描,每次能找到最大者然后放在最后。因此需要的扫描的次数逐行递减,最后排序完成。
代码如下

void bubblesort ( int A[], int n ) { //起泡排序算法(版本0):0 <= n
    while ( n-- ) { //在尚未确认已全局排序之前,逐趟进行扫描交换
       for ( int i = 0; i < n; i++ ) { //自左向右逐对检查当前范围A[0, n)内的各相邻元素
          if ( A[i] > A[i+1] ) { //一旦A[i]与A[i+1]逆序,则
             swap ( A[i], A[i+1] ); //交换之,并
          }
       }
    }
 } //蛮力算法,不能及时提前退出,总是必须做n-1趟扫描交换

算法的正确性:
1.经过k趟扫描交换后,最大的k个元素必然就位。
2.经过k趟扫描后,问题规模缩减至n-k。
3.至多经过n-1趟,算法必然终止,且给出正确答案。
4.时间效率在最好最坏情况下都是O(n^2)

显然,我们有更好的策略改进这个算法。
可能出现这种情况,当机器经过某次扫描后可能剩下的都是有序的,这个时候我们就想可不可以提前终止这个算法,显然,是可以的。

bubbleSort.2

while版本

void bubblesort1A ( int A[], int n ) { //起泡排序算法(版本1A):0 <= n
    bool sorted = false; //整体排序标志,首先假定尚未排序
    while ( !sorted ) { //在尚未确认已全局排序之前,逐趟进行扫描交换
       sorted = true; //假定已经排序
       for ( int i = 1; i < n; i++ ) { //自左向右逐对检查当前范围A[0, n)内的各相邻元素
          if ( A[i - 1] > A[i] ) { //一旦A[i - 1]与A[i]逆序,则
             swap ( A[i - 1], A[i] ); //交换之,并
             sorted = false; //因整体排序不能保证,需要清除排序标志
          }
       }
       n--; //至此末元素必然就位,故可以缩短待排序序列的有效长度
    }
 } //

for循环版本

void bubbleSort(int A[],int n){
	for(bool sorted=false;sorted=!sorted;n--){
		for(int i=0;i<n-1;i++){
			if(A[i]>A[i+1]){
				swap(A[i],A[i+1]);
				sorted=false;
			}
		}
	}
}

注意while和for版本的区别,在while版本中,我们的i起始位置是1,for版本起始位置是0;
我们可能经常是让i从0开始(例如上面的bubbleSort.1),所以要注意两者之间的区别。
当i从0开始时,我们需要在i<n-1时跳出内层循环,不然可能会造成A[n-1]和A[n]比较并交换数据,造成结果错误;当i从1时,我们则需进行A[i-1]和A[i]的比较,在i<n时跳出内层循环。

在bubbleSort.2中我们借助布尔型标志位sorted,可及时提前退出,而不致总是蛮力地做n - 1趟扫描交换。不过,如果我们在完成某次扫描就位后,可能会发现这种情况:
在这里插入图片描述
在这里发现hi前面的一段元素是就位好了的,我们就发现可以让遍历次数大幅度的减小,让n=last,
这样就可以减少我们扫描时比较的次数。于是,有了下面的版本。

bubbleSort.3

void bubbleSort(int A[],int n){
	for(int m;1<n;n=m){//在尚未确认已全局排序之前,逐趟进行扫描交换
		for(int i=m=0;i<n-1;i++){ //自左向右逐对检查当前范围A[0, m)内的各相邻元素
			if(A[i]>A[i+1]){//一旦A[i-1]与A[i]逆序,则
				swap(A[i],A[i+1]);//交换之,并
				m=i+1;//更新待排序区间的长度
			}
		}
	}
} 

我们让m=i+1,也就是此趟扫描最后交换元素的秩,直接让n=m,就能跳过Last到hi之间排序正确的元素,省略了在bubbleSort.2版本中下一趟需要比较的次数。
特点:
**1.对尾部有序(或接近有序)的输入,算法收敛的速度大大提高
2.元素交换的次数仅取决于输入序列
分析:
该算法在输入数据都是顺序时时间效率最好,为O(n),即为算遍历比较一遍然后退出。
输入数据是逆序排列时时间效率最坏,为O(n^2),即为每次都就位最大的元素,重复n-1次。
同时,该算法也是稳定的。**如下图所示:稳定性
在上图中,有三个值相同但下标有序的数,当我们排序为7a,7b,7c时,我们认为它是稳定的。
显然,bubbleSort算法的三个版本都是稳定的,因为只有前一个元素严格大于后一个元素(A[i]>A[i+1])时,我们才执行swap语句。

写在后面

排序算法有很多种,选择排序、归并排序以及还可能学习的堆排序、快速排序。
不过,起泡排序就值得我们多多练习,多多思考。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一章 绪论作业答案(共50分) 一、分析如下程序中 (1)~ (10)各语句的频度。(每个1分,共10分) Ex( ) { int i , j , t ; (1) for( i=1 ; i<10 ; i++) //n = (2) printf(“\n %d” , i ); //n = (3) for(i=1; i<=2; i++) //n = (4) printf(“\n”); //n = (5) for(i=1; i<=9; i++) //n = { (6) for(j=1; j <= i ; j++) //n = { (7) t = i * j ; //n = (8) printf(“]”,t); //n = } (9) for(j=1; j 0) { if(x > 100) {x -= 10 ; y -- ;} else x ++ ; } 问if 语句执行了多少次?(2分) y--执行了多少次?(2分) x ++执行了多少次?(2分) 三、回答问题(共25分) 书中16页的起泡排序如下: void bubble_sort(int a[],int n){ //将a中整数序列重新排列成自小至大有序的整数序列。 for(i=n-1,change=TRUE;i>=1&&change;--i){ change=FALSE; for(j=0;ja[j+1]{a[j]<-->a[j+1];change=TRUE; } } }//bubble_sort 1.(共15分)分析该算法的最佳情况 ,最坏情况和平均情况下各自的时间复杂度(给出分析思路与过程)。 (1) 最佳情况的时间复杂度分析(5分): (2) 最坏情况的时间复杂度分析(5分): (3) 平均情况的时间复杂度分析(5分): 2.(共10分)比较与C语言书中的起泡排序异同,并从时空效率角度说明谁更优。 四、完成如下选择题(每3分,共9分)。 1. 设f为原操作,则如下算法的时间复杂度是( )。 for (i = 1; i*i=1;i--) for(j=1;jA[j+1]) A[j]与A[j+1]对换; 其中n为正整数,则算法在最坏情况下的时间复杂度为( )。 A.O(n) B.O(nlog2n) C. O(n3) D. O(n2)

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值