冒泡排序的最优算法

来源:互联网 发布:拜耳驱虫药淘宝哪里买 编辑:程序博客网 时间:2024/06/08 18:35

冒泡排序是一种交换类排序的算法,比较常用,这里讨论下算法的优化。

 //  待排序数组,升序排序 int[] arr = {2,6,4,5,3,7,8,11,14}; 

算法一

这是最简单也是最容易的写法,两层for循环,前后比较,大的交换。若数组长度为n,总共需要比较n*(n-1)/2次。

public static void bubbleSort1(int[] arr) {        int count = 0;        for (int i = 0; i < arr.length-1; i++) {            for (int j = 0; j < arr.length-i-1; j++) {                // 前面比后面大,则进行交换                if(arr[j] > arr[j+1]) {                     arr[j] = arr[j] + arr[j+1];                    arr[j+1] = arr[j] - arr[j+1];                    arr[j] = arr[j] - arr[j+1];                }                count++;            }        }        System.out.println("比较" + count + "次");    }

运行结果:
这里写图片描述


算法二

这里我们根据算法一中的思路进行下优化,我们注意到上述arr数组中后四个数7,8,11,14是已排好序的,我们遍历比较一次就已经没有必要再去比较了。因此,在排序过程中,我们可能会重复的去多次比较已排好的序列,这样就造成了冗余,当数据量大时,会明显的耗时。
为解决这个问题,我们在这里添加一个lastIndex索引,用于标记最后一次交换的位置(注意,这里是交换不是比较),当交换到arr数组中7之前,也就是下标为4的时候,不再交换,说明后面的已经有序,下次就直接比较到下标为4的位置,后面的不再比较。
另外,如果是倒序排正序,则没有优化,比较n*(n-1)/2次。

int[] arr = {-1,2,6,4,5,3,7,8,11,14};
public static void bubbleSort2(int[] arr) {    int i = arr.length-1;    int count = 0; // 计数    while(i>1){        int lastChange = 1; // 记录最后一次交换位置        for (int j = 1; j < i; j++) {            // 前面比后面大,则进行交换            if(arr[j]>arr[j+1]){                arr[j] = arr[j] + arr[j+1];                arr[j+1] = arr[j] - arr[j+1];                arr[j] = arr[j] - arr[j+1];                lastChange = j; // 每交换一次更新一次            }            count++;        }        i = lastChange;    }    System.out.println(count);}

运行结果:
这里写图片描述
很明显,比较的次数减少了。
注意:存放数据时从数组下标为1的位置开始放,该算法不比较下标为0位置的数。另外,对于不同的数组,排序比较的次数可能会不同,比较次数一定满足count<=n*(n-1)/2。


算法三

最后,这里再提供一种一层for循环实现的冒泡排序。原理就是在for循环内部动态改变下标 i 的值,让其反复循环。并没有什么性能上的优化,只是换了一种形式而已。

public static void bubbleSort3(int[] arr) {        int count = 0;        int t = arr.length-1;        for (int i = 0; i < t; i++) {            // 前面比后面大,则进行交换            if(arr[i] > arr[i+1]) {                arr[i] = arr[i] + arr[i+1];                arr[i+1] = arr[i] - arr[i+1];                arr[i] = arr[i] - arr[i+1];            }            count++;            if(i == t-1){                i = -1;                t--;            }        }        System.out.println("比较" + count + "次");    }

运行结果:
这里写图片描述