冒泡排序作为算法的入门程序,就好比编程语言里面的hello world。
核心思想就是将相邻的两个元素进行比较,如果顺序错误就进行交换。
给定一组数据:9,7,3,5,8,2,1。
从第一个数字9开始,将他与前面的数字7进行比较,大于7,然后两个就交换位置,然后在用9去跟3做比较,大于3,同样交换位置,依此类推,最终9放在了最后一个位置,也就是说,经过第一趟排序后,最大的数字移动到了最后一位上面。
一:7 3 5 8 2 1 9;
同理:第二次循环则只用考虑前面的7到1这六个数了。这次会筛选出第二大的数字。
二:3 5 7 2 1 8 9
依此类推:
三:3 5 2 1 7 8 9
四:3 2 1 5 7 8 9
五:2 1 3 5 7 8 9
六:1 2 3 5 7 8 9。
至此我们可以写出程序。
public class BubbleSort {
public int[] sort(int[] arr){
int len = arr.length;
for (int i=0; i<len-1; i++){
for (int j=0; j<len-i-1; j++){
if (arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
return arr;
}
}
由于每次都要比较所有未排序的元素,而且要比较n-1次,所以冒泡排序的时间复杂度是 O(n²).
优化一:如果在某一次排序后,数组已经有序,后面就不用再比较了。这时我们只需在每趟循环之前初始化一个标志位,如果这趟排序没有元素交换,则证明数组已经有序,则直接返回即可。
public class BubbleSortImprove {
public int[] sort(int[] arr){
int len = arr.length;
int flag = 0;
for (int i=0; i<len-1; i++){
flag = 1;
for (int j=0; j<len-i-1; j++){
if (arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = 0;
}
}
if (flag == 1){
break;
}
}
return arr;
}
}
优化二:如果数组arr[0] 到arr[i]已经有序,上次扫描最后一次数据交换的位置为lastPoss,则下次扫描的范围可以缩减到lastPoss到len
public class BubbleSortImprove1 {
public int[] sort(int[] arr){
int len = arr.length;
int lastPoss = 0;
int lastTemp = 0;
for (int i=0; i<len-1; i++){
lastPoss = lastTemp;
for (int j=len-1; j>lastPoss; j--){
if (arr[j-1] > arr[j]){
int temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
lastTemp = j;
}
}
if (lastPoss == lastTemp){
break;
}
}
return arr;
}
}
分别对这三个方法进行测试
public class Test {
public static void main(String[] args) throws Exception{
int[] arr = CreateRandomArray.getRandmonArray(1000,5000000,20000);
CreateRandomArray.print(arr);
BubbleSort bubbleSort = new BubbleSort();
// BubbleSortImprove bubbleSort = new BubbleSortImprove();
// BubbleSortImprove1 bubbleSort = new BubbleSortImprove1();
bubbleSort.sort(arr);
System.out.println();
CreateRandomArray.print(arr);
System.out.println();
MethodUtils.getMethodTime(bubbleSort.getClass(),arr);
}
}
其中未经改进的冒泡排序BubbleSort所花费的时间是500毫秒左右
而经过改进的另外两个则是只有几毫秒