原理:冒泡排序可就是通过冒泡泡的方式,每一趟把最大的数字通过冒泡泡的方式放到最后。也就是如果有n个数字,一趟排序完成后,最大的数字就在最后,那么接下来就只用对前边的n-1项数字进行排序
算法描述:
1)如果有n个数要进行排序,那么只需要进行n-1趟排序
2)第一趟排序:通过相邻数字进行两两比较,如果前一个数比后一个数大,就进行交换。这一趟排序完成后,最大的数就在最后一位,接下来只需要对他的前n-1项进行排序。
3)第二趟排序:对前n-1项进行排序,两两比较,如果前一个数比后一个数大交换两数的位置,这一趟排序完成后,最大的数就排在倒数第二的位置上。,接下来就对前边n-2项进行排序
4)直到还有一个元素的时候就说明排序完了,
基本方法:用两层循环,外层决定排序的趟数,内层决定每层里面比较的次数,然后如果前一个数比后一个数大,就进行交换
举例子:
原始数组:3, 9, -1, 10, 20
第一趟排序
(1) 3, 9, -1, 10, 2 // 如果相邻的元素逆序就交换
(2) 3, -1, 9, 10, 2
(3) 3, -1, 9, 10, 2
(4) 3, -1, 9 , 2, 10
第二趟排序
(1) -1, 3, 9, 2, 10 //交换
(2) -1, 3, 9, 10, 20
(3) -1, 3, 2, 9, 10
第三趟排序
(1) -1, 2, 3, 9, 10
(2) -1, 2, 3, 9, 10
第四趟排序
(1) -1, 2, 3, 9, 10 ----- >有序
冒泡排序规则
(1) 一共进行 数组的大小-1 次 大的循环
(2)每一趟排序的次数在逐渐的减少
(3) 如果我们发现在某趟排序中,没有发生一次交换, 可以提前结束冒泡排序。这个就是优化
public static void bubbleSort(int[] arr,int len) {
for(int i=0;i<len-1;i++){//外部循环
for(int j=0;j<len-i-1;j++){//内部循环
if(arr[j]>arr[j+1]) {//如果前一个数比后一个数大的话就进行交换
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j+1]=tmp;
}
}
}
}
优化方法1:添加标记flag,来判断有没有进行交换,如果一趟下来都没有进行交换,那么说明元素都已经有序了,就不需要进行排序了。它减少了多余的排序次数
public static void bubbleSort2(int[] arr,int len) {
for(int i=0;i<len-1;i++){//外部循环
int flag=0;//添加的标记
for(int j=0;j<len-i-1;j++){//内部循环
if(arr[j]>arr[j+1]) {//如果前一个数比后一个数大的话就进行交换
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j+1]=tmp;
flag=1;//如果交换了,就把标记修改为1
}
}
if(flag==0){//如果没有进行交换,就说明排序已经完成
break;
}
}
}
优化方法2:记录交换的位置,如果交换位置为0的时候就说明排序完成
public static void bubbleSort3(int[] arr,int len) {
for(int i=0;i<len-1;i++){//外部循环
int pos=0;//记录最开始的交换位置
for(int j=0;j<len-i-1;j++){//内部循环
if(arr[j]>arr[j+1]) {//如果前一个数比后一个数大的话就进行交换
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j+1]=tmp;
pos=j;//如果交换了,就把交换位置修改为j
}
}
if(pos==0){//如果pos==0,就说明排序已经完成
break;
}
}
}
优化方案3:每一趟不仅可以把最大的数冒泡泡到最后相应的位置,也可以把最小的数冒泡泡到前边对应的位置,也就是同时排序,它是减少了排序的趟数
public static void bubbleSort4(int[] arr,int len) {
for(int i=0;i<len-1;i++){//外部循环
int flag=0;//添加的标记
for(int j=0;j<len-i-1;j++){//内部循环
if(arr[j]>arr[j+1]) {//如果前一个数比后一个数大的话就进行交换
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j+1]=tmp;
flag=1;//如果交换了,就把标记修改为1
}
}
for(int z=0;z<len-i-1;z++){
if(arr[z+1]<arr[z]) {//如果后一个数比前一个数小的话就进行交换
int tmp = arr[z];
arr[z] = arr[z + 1];
arr[z+1]=tmp;
flag=1;//如果交换了,就把标记修改为1
}
}
if(flag==0){//如果flag==0,就说明排序已经完成
break;
}
}
}
时间复杂度:
冒泡排序的的平均和最坏的情况下时间复杂度都为O(n2),最好的情况下为O(n),也就是本身是有序的
空间复杂度:O(1)
稳定性:因为冒泡排序它是把大的往后调,或者把小的往前调,所以都是相邻之间的元素进行比较,交换也发生在相邻的元素之间,如果相邻的元素不满足交换的条件,他们就不会进行交换,所以即使相同元素,他们之间的顺序都不会发改变。