当前位置:   article > 正文

排序算法-冒泡排序_冒泡算法

冒泡算法

基本思路

遍历给定的数组,从左往右,两两比较,小的放在左边,大的放在右边,遍历完成,数组有序。

先来看一个冒泡排序的过程:

给定数组:[5,3,2,1,4]

排序结果:[1,2,3,4,5]

拆解步骤

1.第一轮从左往右循环,遍历前5个数:

(1) 来到5和3,5大于3  ==>  5和3交换 

 

(2) 来到5和2,5大于2 ==> 5和2交换

 (3) 来到5和1,5大于1 ==> 5和1交换

 (4) 来到5和4,5大于4 ==> 5和4交换

 第一轮遍历结束,最右侧的5是数组中最大的,不用动了。

 

2.第二轮从左往右循环,遍历前4个数

 (1) 来到3和2,3大于2 ==> 3和2交换

(2) 来到3和1,3大于1 ==> 3和1做交换 

 

 (3) 来到3和4,3小于4 ==> 不用交换

第二轮遍历结束,最右侧的4已经是待排序数中最大的,不用动。

……略

得出规律

依次类推,得出规律:

1.每一次遍历的都是左侧待排序的数,遍历完成后会将最大的数放到最右边。

2.一共需要数组长度次数的遍历,比如数组长度是5,就需要5次遍历。

代码实现

  1. public class BubbleSort {
  2. public static void main(String[] args) {
  3. int[] arr = {5, 3, 2, 1, 4};
  4. for (int i : arr) {
  5. System.out.print(i);
  6. System.out.print(" ");
  7. }
  8. System.out.println();
  9. bubbleSort(arr);
  10. System.out.println("冒泡排序后 ---->");
  11. for (int i : arr) {
  12. System.out.print(i);
  13. System.out.print(" ");
  14. }
  15. }
  16. /**
  17. * 冒泡排序
  18. *
  19. * @param arr 待排序的数组
  20. */
  21. public static void bubbleSort(int[] arr) {
  22. if (arr == null || arr.length < 2) {
  23. return;
  24. }
  25. for (int i = 0; i < arr.length; i++) { // 数组长度是多少,就需要遍历多少次数组
  26. for (int j = 0; j < arr.length - i - 1; j++) { // 每次遍历的范围是 0 ~ len-i-1
  27. if (arr[j] > arr[j + 1]) {
  28. swap(arr, j, j + 1);
  29. }
  30. }
  31. }
  32. }
  33. /**
  34. * 数组交换
  35. *
  36. * @param arr 数组
  37. * @param index1 下标1
  38. * @param index2 下标2
  39. */
  40. public static void swap(int[] arr, int index1, int index2) {
  41. arr[index1] = arr[index1] + arr[index2];
  42. arr[index2] = arr[index1] - arr[index2];
  43. arr[index1] = arr[index1] - arr[index2];
  44. }
  45. }

对数器验证

  1. import cn.hutool.core.util.RandomUtil;
  2. import java.util.Arrays;
  3. public class BubbleSortTest {
  4. public static void main(String[] args) {
  5. int[] arr1 = new int[1000];
  6. for (int i = 0; i < arr1.length; i++) {
  7. arr1[i] = RandomUtil.randomInt(0, 10000);
  8. }
  9. final int[] arr2 = Arrays.copyOf(arr1, arr1.length);
  10. System.out.println("拷贝的数组arr2是否等于arr1:" + equals(arr1, arr2));
  11. print(arr1);
  12. Arrays.sort(arr1);
  13. System.out.println("使用系统的排序算法排序后的数组 ------->");
  14. print(arr1);
  15. BubbleSort.bubbleSort(arr2);
  16. System.out.println("使用冒泡排序算法排序后的数组 ------->");
  17. print(arr2);
  18. System.out.println("冒泡排序算法结果与系统内置排序算法结果是否一致:" + equals(arr1, arr2));
  19. }
  20. public static void print(int[] arr){
  21. for (int i : arr) {
  22. System.out.print(i);
  23. System.out.print(" ");
  24. }
  25. System.out.println();
  26. }
  27. public static boolean equals(int[] arr1, int[] arr2){
  28. if(arr1 == null && arr2 == null){
  29. return true;
  30. }
  31. if(arr1 == null || arr2 == null){
  32. return false;
  33. }
  34. if(arr1.length != arr2.length){
  35. return false;
  36. }
  37. for (int i = 0; i < arr1.length; i++) {
  38. if(arr1[i] != arr2[i]){
  39. return false;
  40. }
  41. }
  42. return true;
  43. }
  44. }

 优化

思路:如果在一次遍历中,发现所有的元素都不需要交换,那么说明这个数组已经是有序数组了。

比如一个数组:[1,2,3,4,5],其冒泡排序过程如下:

 

 对于这种有序数组,其实只需要遍历一次就可以了。我们可以在每次循环的时候记录当前循环是否发生了交换操作,如果没有发生,就提前结束排序操作,因为数组已经是有序了。

需要优化的核心代码:

  1. /**
  2. * 冒泡排序
  3. *
  4. * @param arr 待排序的数组
  5. */
  6. public static void bubbleSort(int[] arr) {
  7. if (arr == null || arr.length < 2) {
  8. return;
  9. }
  10. for (int i = 0; i < arr.length; i++) { // 数组长度是多少,就需要遍历多少次数组
  11. boolean swaped = false; // 用来记录是否交换的变量
  12. for (int j = 0; j < arr.length - i - 1; j++) { // 每次遍历的范围是 0 ~ len-i-1
  13. if (arr[j] > arr[j + 1]) {
  14. swaped = true; // 如果发生了交换,就记为true
  15. swap(arr, j, j + 1);
  16. }
  17. }
  18. if(!swaped){
  19. // 如果一次交换都没有发生,就是数组已经有序了
  20. return;
  21. }
  22. }
  23. }

其他定论

1.冒泡排序在排序期间没有申请其他的内存空间,它的空间复杂度是O(1),所以是原地排序算法

2.冒泡排序对于相同数值的元素来说,每次排序后所在的位置不变,因此冒泡排序是稳定的排序算法

3.冒泡排序的时间复杂度是O(n^2)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/891820
推荐阅读
相关标签
  

闽ICP备14008679号