算法原理
1. 数组x,长度为n(n>1),即x[0],x[1], ..., x[n-1]。
2. 第k=1轮:处理范围x[0]~x[n-1]。
比较相邻的元素:如果x[0]>x[1],就交换他们两个。对每一对相邻元素做同样的处理,经过一轮交换后,最后的元素x[n-1]将会是数组中最大的元素。
3. 第k=2轮:处理范围x[0]~x[n-2],重复步骤2,x[n-2]将会是数组中第2大元素。
4. ...
4. 直到k=n-1时,没有任何一对数字需要比较,此时数组排序完成。
算法实现
package com.cjw.sort;
import java.util.Arrays;
/**
* 使用冒泡排序对整型数组进行排序
*
* Created by cjw on 2017/8/16 0016.
*/
public class BubbleSortUtil {
/**
* 交换数组x索引位置为a和b的值
*
* @param x 数组
* @param a 索引a
* @param b 索引b
*/
private static void swap(int[] x, int a, int b) {
int temp = x[a];
x[a] = x[b];
x[b] = temp;
}
/**
* 调试输出排序过程中数组中的数据
*
* @param time 排序次数
* @param x 数组
*/
private static void debugPrint(int time, int[] x) {
System.out.println("第" + time + "次排序结果:" + Arrays.toString(x));
}
/**
* 冒泡算法实现
*
* @param x 待排序的数组
*/
public static void sort(int[] x) {
if (x == null || x.length < 2) {
return;
}
int len = x.length;
for (int time = 1; time < len; time++) {
for (int i = 0; i < len-time; i++) {
if (x[i] > x[i+1]) {
swap(x, i, i+1);
}
}
debugPrint(time, x);
}
}
/**
* 冒泡算法的递归实现
*
* @param x 待排序的数组
* @param end 数组需要排序部分的最后元素的索引
*/
public static void recursionSort(int[] x, int end) {
//只剩下1个元素时,退出递归
if (end < 1) {
return;
}
for (int i = 0; i < end; i++) {
if (x[i] > x[i+1]) {
swap(x, i, i+1);
}
}
debugPrint((x.length - end), x);
recursionSort(x, --end);
}
public static void main(String[] args) {
int[] x = { 12, 87, 34, 39, 134, 4, 45, 8, 99 };
sort(x);
int[] y = { 12, 87, 34, 39, 134, 4, 45, 8, 99 };
recursionSort(y, y.length-1);
}
}
程序输出:
第1次排序结果:[12, 34, 39, 87, 4, 45, 8, 99, 134]
第2次排序结果:[12, 34, 39, 4, 45, 8, 87, 99, 134]
第3次排序结果:[12, 34, 4, 39, 8, 45, 87, 99, 134]
第4次排序结果:[12, 4, 34, 8, 39, 45, 87, 99, 134]
第5次排序结果:[4, 12, 8, 34, 39, 45, 87, 99, 134]
第6次排序结果:[4, 8, 12, 34, 39, 45, 87, 99, 134]
第7次排序结果:[4, 8, 12, 34, 39, 45, 87, 99, 134]
第8次排序结果:[4, 8, 12, 34, 39, 45, 87, 99, 134]
Process finished with exit code 0
我们发现在第7次开始就没有发生元素交换了,此时数组已经排序完成,但是上面的算法仍会继续进行排序。如果数组本身就是一个有序数组,上述算法仍然会进行8次排序。
程序改进:
/**
* 改进后的冒泡算法
*
* @param x 待排序的数组
*/
public static void optimizedSort(int[] x) {
if (x == null || x.length < 2) {
return;
}
int len = x.length;
for (int time = 1; time < len; time++) {
boolean isSwap = false;
for (int i = 0; i < len-time; i++) {
if (x[i] > x[i+1]) {
swap(x, i, i+1);
isSwap = true;
}
}
if (!isSwap) {
break;
}
debugPrint(time, x);
}
}
public static void main(String[] args) {
int[] x = { 4, 8, 12, 34, 39, 45, 87, 99, 134 };
System.out.println("===>普通:");
sort(x);
int[] y = { 4, 8, 12, 34, 39, 45, 87, 99, 134 };
System.out.println("===>优化:");
optimizedSort(y);
}
运行结果:
===>普通:
第1次排序结果:[4, 8, 12, 34, 39, 45, 87, 99, 134]
第2次排序结果:[4, 8, 12, 34, 39, 45, 87, 99, 134]
第3次排序结果:[4, 8, 12, 34, 39, 45, 87, 99, 134]
第4次排序结果:[4, 8, 12, 34, 39, 45, 87, 99, 134]
第5次排序结果:[4, 8, 12, 34, 39, 45, 87, 99, 134]
第6次排序结果:[4, 8, 12, 34, 39, 45, 87, 99, 134]
第7次排序结果:[4, 8, 12, 34, 39, 45, 87, 99, 134]
第8次排序结果:[4, 8, 12, 34, 39, 45, 87, 99, 134]
===>优化:
Process finished with exit code 0
优化后的冒泡排序在发现一轮比较中,如果没有发生元素交换,则该数组已经有序。对于已经是升序排列的数组,只进行一轮比较就可知道结果。