目录
1.冒泡排序算法:
2.算法优化分析:
2.1优化外层循环
2.2优化内层循环
2.3同时优化内层和外层循环
3.时间复杂度分析:
3.1优化前
3.2优化后
4.空间复杂度分析:
原理:以N个元素数组的升序为例。相邻元素两两比较,大的往后放,第一轮完毕,最大值出现在了最大索引处,即数组最右侧。每一轮都从头开始执行,总共执行 N-1 轮。
代码书写分析:需要两层循环。第一层表示轮次,从第一个元素开始,相邻元素两两比较,大的往后放。每遍历一轮,进入第二层循环,在此从头开始,确定最大值后放在最大索引处,每遍历一轮最大索引值 -1。直到排序完成。
public class BubbleSort {
public static void swap(int[] arr,int i,int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
/**
* 冒泡排序:
* isAsc:true 升序 ;false 降序
* @param arr
* @param isAsc
*/
public static void bubbleSort(int[] arr,boolean isAsc) {
for(int i=0;iarr[j+1]) {
swap(arr,j,j+1);
}
}
}
}
}
}
正常情况下,冒泡排序算法的外层循环需要进行N-1轮,但如果在某一轮结束后数组排序完成,这个时候就可以提前退出外层循环,这就是冒泡排序外层循环优化的基本思路,如下所示:
原始数组 2 1 3 5 6 4
一轮循环 1 2 3 5 4 6
二轮循环 1 2 3 4 5 6
正常情况下,数组需要进行5轮外层循环,但两轮就已经排序完成。因此可以在第三轮未发生交换的情况下,设置一个标志。作为结束外层循环的标志。
public class BubbleSort_Opt {
public static void swap(int[] arr,int i,int j) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void bubbleSort(int[] arr) {
for(int i=0 ; i0 ; j--) {
//以升序为例
if(arr[j]
冒泡排序算法是相邻元素两两比较,经过一轮就可以将最大的元素防止数组尾部。但是如果相邻元素有序的话则不发生交换。因此在最后交换位置前面为无序区,需要继续循环比较;而最后交换位置后面则为有序区,下一轮可以只遍历无序区即可。因此可以将最后交换位置的索引值赋给一个变量,作为内层循环结束的标志,这样可以提前结束内层循环。具体原理如下所示:
原始数组 3 2 1 4 6 7
一轮交换 2 1 3 4 6 7
二轮交换 1 2 3 4 6 7
public class BubbleSort_Opt {
public static void swap(int[] arr,int i,int j) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void bubbleSort(int[] arr) {
int pos = 0;
int temp = arr.length-1;
for(int i=0 ; iarr[j+1]) {
swap(arr,j,j+1);
pos = j ; //记录最后的交换位置,换分有序区与无序区
}
}
temp = pos; //将最后的交换位置作为内层循环结束标志
}
}
}
public class BubbleSort_Opt {
public static void swap(int[] arr,int i,int j) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void bubbleSort(int[] arr) {
int pos = 0;
int temp = arr.length-1;
for(int i=0 ; iarr[j+1]) {
swap(arr,j,j+1);
flag = 1; //发生交换则对标志变量重新赋值
pos = j ;
}
}
//将最后交换位置作为内层循环结束的标志
temp = pos;
//内层循环完成后,判断上一轮是否发生元素交换。未交换元素,则表示排序完成,提前退出外层循环。
if(flag == 0) {
return;
}
}
}
}
对于元素个数为N的数组:
1.第一轮从第一个元素开始,相邻元素进行对比,需要比较 (N-1) 次,考虑均交换的情况是 3(N-1),之后最值放在最大索引处,同时维护最大索引值(最大索引值-1);
2.第二轮从也第一个元素开始,相邻元素进行对比,需要比较 (N-2) 次,考虑均交换的情况是 3(N-2),之后最值放在最大索引处,同时维护最大索引值(最大索引值-1);
......
3.总共循环 (N-1)轮
注:复杂度与数组是否有序无关,每轮都需要遍历才能找到最大/最小值,最好,最坏或平均时间复杂度均为O(N^2)
对于近乎有序的数组,优化后的冒泡排序会提前结束循环。因此它的时间复杂度会降低很多。
1.对于有序数组,它在进行一轮遍历后就会提前结束,最佳的时间复杂度为O(N);
2.对于逆序数组,它需要进行N-1轮的遍历,因此最差的时间复杂度为O(N^2);
3.平均的时间复杂度为O(N^2);
冒泡排序属于原位排序,无论是否进行优化,其需要的临时变量都在个位数以内。因此冒泡排序算法的空间复杂度为 O(1)