Java实现冒泡排序以及优化冒泡排序的一些小技巧
约定声明:
为了更加简洁明了的说明算法的思想而不是仅仅局限于算法实现,本文假定:
1、 要排序的数据都是整数
2、 数据存储在数组中(正文中成为序列)
3、 排序后的数据以升序排列
备注:本文为我个人学习后总结的一些学习笔记,难免有错误或是不足之处,还望大家见谅!
一:冒泡排序
对于含有N个元素的序列,冒泡排序在最坏情况下需要N-1次遍历。在每次遍历中,比较连续相邻的两个元素,如果某一对元素是降序的,则互换他们的值;否则保持不变。每次遍历需要比较N- i次比较(i为第几次遍历的序号)。
冒泡排序能够在一次排序比较后找出序列中的最值(升序时为最大值,降序时为最小值)。
冒泡排序过程说明:
例如对序列[3,9,5,4,8,2]进行冒泡排序。共有6个元素一共需要遍历5次
第一次遍历时:
① 首先比较第一对元素:(3,9)这两个数原本就是升序的,不做任何操作。
这时序列为:[3,9,5,4,8,2]
② 接着比较(9,5)因为9大于5,呈现降序状态,所以交换两者的位置(5,9)
这时序列为:[3,5,9,4,8,2]
③ 接着比较(9,4),同②一样也需要交换连个元素的位置
这时序列为:[3,5,4,9,8,2]
④ 接着比较(9,8)
这时序列为:[3,5,4,8,9,2]
⑤ 接着比较(9,2)
这时序列为:[3,5,4,8,2,9] 最大值已经排在正确的位置上
第二次遍历:因为第一次遍历时序列的最后一个元素已经有序了,所以可以少比较一组元素
……
第五次遍历……
五次遍历后序列变为:[2,3,4,5,8,9]
普通代码实现:
for(int i = 0; i < array.length - 1;i++){ //遍历次数为 N-1次
for(intj = 0; j < array.length – i; j++){ // 第i次遍历需要比较N – i次
if(array[j] > array[j + 1]){ // 如果呈现降序状态,交换两个元素
array[j]^= array[j + 1]; // 交换算法有三种方式,此处采用效率最高的位运算
array[j+ 1] ^= array[j];
array[j]^= array[j + 1];
}
}
}
----两个元素的交换算法常见的一共有三种,这三种算法实现也是面试题和笔试题中常见的
Eg:交换a和b两个元素的值
方法一: 借助临时变量
int temp = a;
a = b;
b = temp;
方法二:不借助临时变量采用加减运算
a = a + b;
b = a - b;
a = a - b;
方法三:同上代码实现采用位运算,效率三者中最高的,因为直接操作的是底层寄存器
冒泡排序算法的优化:
① :使用效率较高的位运算方式进行元素的交换
② :如果在某次遍历中没有发生交换,说明序列现在已经是有序的了,那么就不必进行下一次遍历啦!这时可以在算法实现中添加一个标志位用于监视序列的状态。
优化的算法实现:
public void double(int[] array){
booleanisNeedNext = true; // 设置监视哨,第一次遍历总是必须的
for(inti = 0; i < array.length – 1 && isNeedNext; i++){
isNeedNext = false; // 将监视哨设置为false
for(int j = 0; j < array.length – i;j++){
if (array[j] > array[j + 1]){
array[j] ^= array[j + 1];
array[j + 1] ^= array[j];
array[j] ^= array[j + 1];
isNeedNext= true; // 发生了交换操作就将监视哨设置为 ture
}
}
}
}
冒泡排序的时间复杂度
最佳情况下序列原本就是有序的,这是只需要O(n)
最坏情况下,冒泡排序算法需要进行N-1次遍历,每一次遍历需要比较 N – i次比较(i为第几次遍历的序号),因此最差情况下,时间复杂度为O(n*n)
冒泡排序的平均时间复杂度为O(n*n)