基本思想
冒泡排序的基本思想是对比相邻的元素值,如果满足条件就交换元素值,把较小的元素移动到数组前面,把大的元素移动到数组后面(交换两个元素的位置)。
算法分析
冒泡算法由双层循环实现。其外层循环用于控制排序轮数,即(i=arr.length)。而内层循环主要用于对比数组中每个相邻元素大小,以确定是否交换位置,对比和交换次数随排序轮数而减少,及(j=arr.length-1-i)。
时间复杂度
因此冒泡排序总的平均时间复杂度为:
代码示例:
/*** 通过第三个临时变量方式,普通排序* @param arr*/public static void sort(int[] arr) {int temp = 0;for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - 1 - i; j++) {if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}}/*** 两个数原地交换,不借助于第三个变量,实现两数交换* @param arr* @return*/public static void subtractSort(int[] arr) {// 判断数组边界条件if (arr==null||arr.length<2) return;for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - 1 - i; j++) {if (arr[j] > arr[j + 1]) {arr[j] += arr[j + 1];arr[j + 1] = arr[j] - arr[j + 1];arr[j] -= arr[j + 1];}}}}/*** 按位异或方法,实现两数交换(效率更高推荐*****)* 算法一定要尽可能高效,因为这是高频操作, 因此采用位运算;* @param arr*/public static void xorSort(int[] arr) {// 判断数组边界条件if (arr == null || arr.length < 2) return;for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - 1 - 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];}}}}
优化问题
- 针对问题:
数据的顺序排好之后,冒泡算法仍然会继续进行下一轮的比较,直到arr.length-1次,后面的比较没有意义的。
- 方案:
设置标志位flag,如果发生了交换flag设置为true;如果没有交换就设置为false。
这样当一轮比较结束后如果flag仍为false,即:这一轮没有发生交换,说明数据的顺序已经排好,没有必要继续进行下去。
/*** 优化过后的冒泡排序* @param arr*/public static void fastSort(int[] arr) {// 判断数组边界条件if (arr == null || arr.length < 2) return;boolean flag = false;// 标识变量:记录是否交换for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - 1 - i; j++) {if (arr[j] > arr[j + 1]) {flag = true;arr[j] = arr[j] ^ arr[j + 1];arr[j + 1] = arr[j] ^ arr[j + 1];arr[j] = arr[j] ^ arr[j + 1];}}if (!flag) break;else flag = false;//*****置为false}}
