交换排序之冒泡排序
参考博客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,以从小到大排序为例,主要分为以下几步:
- 从第一个数开始,比较前后相邻的元素,若a[i]>a[i+1]则发生交换,
- 就这样对数组的第0个数据到n-1个数据进行一次遍历后,最大的一个数据就冒泡到数组第n-1的位置。
- 就这样最后面数组的元素都是最大的和较大的,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;//发生了交换则记录之位置
}
}
}
}
冒泡排序毕竟是一种效率低下的排序方法,在数据规模很小时,可以采用。数据规模比较大时,最好用其它排序方法。