冒泡排序算法的实现(Java 版)
-
Java 的八大基本数据类型中,有六个是用来存储数值的。
-
其中,
整数
用byte(1 字节)、short(2 字节)、int(4 字节)、long(8 字节)
来存储。 -
小数
用float(4 字节)、double(8 字节)
来存储。 -
大于八个字节的数值
用类对象 BigInteger(大整数)、BigDecimal(大小数)
来存储。
原理
-
比较相邻的元素,如果前者大于(小于)后者,就交换两者
。 -
从第一对(0 和 1)到最后一对(n-2 和 n-1),
重复比较
;交换完到最后一对时,最后一个元素应该是最大(最小)的数
。 -
剔除上一次循环归位的元素后,重复以上的步骤
,继续循环。 -
直到
剩余数据只有一位
;此时排序完成。或者,在当前循环中检测到所有元素都已归位
,此时结束当前循环后,排序结束
。 -
上一篇:常用的排序方法
图示
- 原理看上一篇文章常用的排序方法
代码
-
常用
六种基本数据类型(byte、short、int、long、float、double)
来存储数据,故主要写这六种数据类型的排序算法
。 -
大数值就是用来
运算大数据
和运算精密小数
的,故没有写对应的排序算法。 -
Arrays.sort(longs1);
是 Java 提供的排序方法,可以用来比较看看有没有成功。 -
升序、降序就是比较上有区别,其他无不同。
-
以
int[] 数组
的算法为例
public class BubbleSort {
/**
* 将 int[] 进行排序(整数排序)
* <p>
* 升序
*
* @param a int[]
*
* @return int[]
*/
private static int[] sortAsc(int[] a) {
boolean hasChange = false;
// 第一重循环用来表示要循环多少次
for(int i = 0; i < a.length; i++) {
// 每一次循环都会将一个待排序元素中最大的元素放到后面
for(int j = 0; j < a.length - i - 1; j++) {
if(a[j] > a[j + 1]) {
exchange(a, j, j + 1);
// 为什么直接赋值,而不是用 if 判断赋值,因为 基本数据类型的赋值一定比 if 判断快
hasChange = true;
}
}
// 在某次循环时发现,数组元素排序好了,就直接结束循环
if(!hasChange) {
break;
}
}
return a;
}
/**
* 将 int[] 进行排序(整数排序)
* <p>
* 降序
*
* @param a int[]
*
* @return int[]
*/
private static int[] sortDesc(int[] a) {
boolean hasChange = false;
for(int i = 0; i < a.length; i++) {
for(int j = 0; j < a.length - i - 1; j++) {
if(a[j] < a[j + 1]) {
exchange(a, j, j + 1);
hasChange = true;
}
}
if(!hasChange) {
break;
}
}
return a;
}
/**
* 交换方法,交换 int 数组中的元素(基本数据类型)
*
* @param array 数组
* @param a 下标一
* @param b 下标二
*/
private static void exchange(int[] array, int a, int b) {
int tmp = array[a];
array[a] = array[b];
array[b] = tmp;
}
}
-
第一次优化:添加
数据交换标志位 hasChange
,当这轮循环没有数据交换时,数据已归位,可以提前结束算法了
。 -
第二次优化:在第一次循环的基础上,添加
最后一次数据交换的信息记录位
,每次循环可以归位多个元素,可以减少比较的次数
。(以 long[] 升序为例)
public class BubbleSort {
/**
* 将 long[] 进行排序(整数排序)
* <p>
* 升序
*
* @param a long[]
*
* @return long[]
*/
private static long[] sortAsc(long[] a) {
// pos 用来表示某次循环时,最后交换的元素的下标
int size = a.length - 1, pos = 0;
boolean hasChange = false;
for(int i = 0; i < a.length; i++) {
// 不在用传统的逐位归位方式
for(int j = 0; j < size; j++) {
if(a[j] > a[j + 1]) {
exchange(a, j, j + 1);
hasChange = true;
// 取前一个,交换是邻位交换,每次记录都当成是当前循环中的最后一次交换,而后一个已经归位了
pos = j;
}
}
// 将每次循环中,最后交换位置(前一个)作为待排序区末尾
size = pos;
if(!hasChange) {
break;
}
}
return a;
}
}