1.1 动画展示

冒泡.gif
示例
image.png

1.2 思路分析

冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就像水底下的气泡一样逐渐向. 上冒。
优化:因为排序的过程中,各元素不断接近自己的位置,如果-趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志flag判断元素是否进行过交换。从而减少不必要的比较。(这里说的优化,可以在冒泡排序写好后,在进行)

1.3演示冒泡排序的例子(图解)

image.png
小结上面的图解过程:(1)一共进行数组的大小-1次大的循环
(2)每一趟排序的次数在逐渐的减少
(3)如果我们发现在某趟排序中,没有发生一次交换,可以提前结束冒泡排序。这个就是优化

1.4 复杂度分析

1.不管原始数组是否有序,时间复杂度都是O(n2),
因为没一个数都要与其他数比较一次,(n-1)2次,分解:n2-2n+1, 去掉低次幂和常数,剩下n2,所以最后的时间复杂度是n2
2.空间复杂度是O(1),因为只定义了两个辅助变量,与n的大小无关,所以空间复杂度为O(1)

1.5 java代码实现

最近看的
初始优化,若发现没有有一轮没发生交换,则退出循环

  1. public static void Bubble2(int[] arr){
  2. for (int i = 0; i <arr.length-1 ; i++) {
  3. boolean swapped=false;//是否发生了交换
  4. //注意:swapped 在第一层for循环里定义,如果在外层for循环,后面还要多加一个判断
  5. //如在下下面的优化
  6. for (int j = 0; j <arr.length-i-1 ; j++) {
  7. System.out.println((j+1)+"次");
  8. if (arr[j]>arr[j+1]){
  9. swap(arr,j,j+1);
  10. swapped =true;
  11. }
  12. }
  13. System.out.println(Arrays.toString(arr));
  14. //一轮都没有进行交换过,说明数组排序完,则终止循环
  15. if (!swapped){
  16. break;
  17. }
  18. }
  19. }

二次优化
记录最后交换的位置,直到最后交换的位置为0,交换结束。

  1. public static void Bubble(int[] arr){
  2. int n = arr.length-1;//需要比较的最后一个索引
  3. while (true){
  4. int last = 0;//记录最后交换的位置
  5. for (int i = 0; i < n; i++) {
  6. System.out.println("比较次数:"+(i+1));
  7. if (arr[i]>arr[i+1]){
  8. swap(arr,i,i+1);
  9. last=i;//更新最后交换的位置
  10. }
  11. }
  12. n =last;//更新最后需要比较的索引,n其实就是要比较的次数
  13. System.out.println("第轮冒泡"+Arrays.toString(arr));
  14. if (n==0){
  15. break;
  16. }
  17. }
  18. }

之前看的
未优化

  1. public class BubbleSort {
  2. public static void main(String[] args) {
  3. int arr[] = new int[]{1,2,3,4,5,0};
  4. //冒泡排序时间复杂度为O(n^2),给80000个数据,测试
  5. //创建80000个随机的数组
  6. // int[] arr =new int[80000];
  7. // for (int i=0;i<80000;i++){
  8. // arr[i] = (int) (Math.random() * 8000000);//生成一个[0,8000000)数
  9. // }
  10. // Date date1 = new Date();
  11. // SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  12. // String date1Str = simpleDateFormat.format(date1);
  13. // System.out.println("排序前的时间是="+date1Str);
  14. //
  15. System.out.println("排序前:");
  16. System.out.println(Arrays.toString(arr));
  17. System.out.println("进行冒泡排序:");
  18. BubbleSort2(arr);
  19. // Date date2 = new Date();
  20. // String date1Str2 = simpleDateFormat.format(date2);
  21. // System.out.println("排序前的时间是="+date1Str2);
  22. // System.out.println(Arrays.toString(arr));
  23. }
  24. }
  25. /**
  26. * 未优化
  27. * @param arr
  28. */
  29. public static void BubbleSort(int[] arr){
  30. int temp=0;
  31. for (int i = 0; i<arr.length-1;i++){
  32. for (int j=0 ;j<arr.length-1-i;j++){
  33. if (arr[j]>arr[j+1]) { //逆序则改变该处符号即可
  34. temp = arr[j];
  35. arr[j] = arr[j + 1];
  36. arr[j + 1] = temp;
  37. }
  38. }
  39. // System.out.println("第"+(i+1)+"次冒泡排序");
  40. // System.out.println(Arrays.toString(arr));
  41. }
  42. }
  43. }

优化代码:

  1. /**
  2. * 优化后,如果有一次未发生交换则停止排序
  3. * @param arr
  4. */
  5. public static void BubbleSort2(int[] arr){
  6. int temp=0;
  7. boolean flag = false;//标识变量,表示是否交换过 true表示发生过交换
  8. for (int i = 0; i<arr.length-1;i++){ //需要进行arr.length-1趟冒泡
  9. for (int j=0 ;j<arr.length-1-i;j++){ //每一趟找最后的最大值。
  10. if (arr[j]>arr[j+1]) { //逆序则改变该处符号即可
  11. flag = true;
  12. temp = arr[j];
  13. arr[j] = arr[j + 1];
  14. arr[j + 1] = temp;
  15. }
  16. }
  17. // System.out.println("第"+(i+1)+"次冒泡排序");
  18. // System.out.println(Arrays.toString(arr));
  19. if (!flag){
  20. break;//在一趟排序中,一次交换也没发生,则说明是有序,排序完毕,终止循环
  21. }else {
  22. flag = false;//重置flag!!!,进行下次判断,如果没加这句,flag的设置相当于无效
  23. }
  24. }
  25. }

推导

  1. /*
  2. // 第二趟排序,就是将第二大的数排在倒数第二位
  3. for (int j = 0; j < arr.length - 1 - 1 ; j++) {
  4. // 如果前面的数比后面的数大,则交换
  5. if (arr[j] > arr[j + 1]) {
  6. temp = arr[j];
  7. arr[j] = arr[j + 1];
  8. arr[j + 1] = temp;
  9. }
  10. }
  11. System.out.println("第二趟排序后的数组");
  12. System.out.println(Arrays.toString(arr));
  13. // 第三趟排序,就是将第三大的数排在倒数第三位
  14. for (int j = 0; j < arr.length - 1 - 2; j++) {
  15. // 如果前面的数比后面的数大,则交换
  16. if (arr[j] > arr[j + 1]) {
  17. temp = arr[j];
  18. arr[j] = arr[j + 1];
  19. arr[j + 1] = temp;
  20. }
  21. }
  22. System.out.println("第三趟排序后的数组");
  23. System.out.println(Arrays.toString(arr));
  24. // 第四趟排序,就是将第4大的数排在倒数第4位
  25. for (int j = 0; j < arr.length - 1 - 3; j++) {
  26. // 如果前面的数比后面的数大,则交换
  27. if (arr[j] > arr[j + 1]) {
  28. temp = arr[j];
  29. arr[j] = arr[j + 1];
  30. arr[j + 1] = temp;
  31. }
  32. }
  33. System.out.println("第四趟排序后的数组");
  34. System.out.println(Arrays.toString(arr)); */
  35. }

运行截图
image.png