美文网首页
交换排序—冒泡排序(Bubble Sort)

交换排序—冒泡排序(Bubble Sort)

作者: JavaEdge | 来源:发表于2022-02-08 21:27 被阅读0次

    1 思想

    待排序的一组数中,对当前还未排序的范围内的全部数,自上而下对相邻两数依次进行:

    • 比较
    • 调整

    让较大数往下沉,较小往上冒,故名冒泡排序。

    即每当两相邻的数比较后,发现它们的排序与排序要求相反时,就互换。


    冒泡排序的示例

    2 实现

    package com.sss;
    
    import java.util.Arrays;
    
    /**
     * @author JavaEdge
     */
    public class BubbleSort {
    
        public static void bubbleSort(int[] arr) {
            if (arr == null || arr.length < 2) {
                return;
            }
            for (int e = arr.length - 1; e > 0; e--) {
                for (int i = 0; i < e; i++) {
                    if (arr[i] > arr[i + 1]) {
                        swap(arr, i, i + 1);
                    }
                }
            }
        }
    
        public static void swap(int[] arr, int i, int j) {
            arr[i] = arr[i] ^ arr[j];
            arr[j] = arr[i] ^ arr[j];
            arr[i] = arr[i] ^ arr[j];
        }
    
        // for test
        public static void comparator(int[] arr) {
            Arrays.sort(arr);
        }
    
        // for test
        public static int[] generateRandomArray(int maxSize, int maxValue) {
            int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
            for (int i = 0; i < arr.length; i++) {
                arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
            }
            return arr;
        }
    
        // for test
        public static int[] copyArray(int[] arr) {
            if (arr == null) {
                return null;
            }
            int[] res = new int[arr.length];
            for (int i = 0; i < arr.length; i++) {
                res[i] = arr[i];
            }
            return res;
        }
    
        // for test
        public static boolean isEqual(int[] arr1, int[] arr2) {
            if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
                return false;
            }
            if (arr1 == null && arr2 == null) {
                return true;
            }
            if (arr1.length != arr2.length) {
                return false;
            }
            for (int i = 0; i < arr1.length; i++) {
                if (arr1[i] != arr2[i]) {
                    return false;
                }
            }
            return true;
        }
    
        // for test
        public static void printArray(int[] arr) {
            if (arr == null) {
                return;
            }
            for (int i = 0; i < arr.length; i++) {
                System.out.print(arr[i] + " ");
            }
            System.out.println();
        }
    
        // for test
        public static void main(String[] args) {
            int testTime = 500000;
            int maxSize = 100;
            int maxValue = 100;
            boolean succeed = true;
            for (int i = 0; i < testTime; i++) {
                int[] arr1 = generateRandomArray(maxSize, maxValue);
                int[] arr2 = copyArray(arr1);
                bubbleSort(arr1);
                comparator(arr2);
                if (!isEqual(arr1, arr2)) {
                    succeed = false;
                    break;
                }
            }
            System.out.println(succeed ? "Nice!" : "Fucking fucked!");
    
            int[] arr = generateRandomArray(maxSize, maxValue);
            printArray(arr);
            bubbleSort(arr);
            printArray(arr);
        }
    
    }
    
    

    3 改进

    3.1 标志变量flag

    标志某趟排序过程中,是否有数据交换。若某趟排序时并无数据交换,则说明数据已排好,可提前结束排序,避免后续多余的比较过程。

    private void bubbleSort1(int[] arr) {
      int length = arr.length;
      boolean flag;
      for (int i = 0; i < length - 1; i++) {
        exchange = false;
        for (int j = 0; j < length - i - 1; j++) {
          if (arr[j] > arr[j + 1]) {
            flag = true;
            int tmp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = tmp;
          }
        }
        // 若本次循环无任何数据交换,则跳出循环
        if (!flag) {
          break;
        }
      }
    }
    

    3.2 标志变量pos

    记录每趟排序中最后一次进行交换的位置。

    由于pos位置后的记录均已排序到位,所以执行下一趟排序时,只要扫描到pos位置即可!

    void bubbleSort2(int[] arr) {
      int length = arr.length;
      // 初始时,最后位置保持不变
      int i = length - 1;
      while (i > 0) {
        // 每趟开始时,无记录交换
        int pos = 0;
        for (int j = 0; j < i; j++) {
          if (arr[j] > arr[j + 1]) {
            // 记录交换的位置
            pos = j;
            int tmp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = tmp;
          }
        }
        // 为下一趟排序作准备
        i = pos;
      }
    }
    

    3.3 正向和反向两遍冒泡

    传统冒泡排序中每一趟排序操作只能找到一个max或min,考虑利用在每趟排序中进行正向和反向两遍冒泡的方法,一次便可得到max和min , 从而使排序趟数几乎减少一半。

    void bubbleSort3(int[] arr) {
      int length = arr.length;
      // 设置变量初始值
      int low = 0;
      int high = length - 1;
      int tmp, j;
      while (low < high) {
        // 正向冒泡,找到max
        for (j = low; j < high; ++j) {
          if (arr[j] > arr[j + 1]) {
            tmp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = tmp;
          }
        }
        // 修改high值, 前移一位
        --high;
        // 反向冒泡,找到min
        for (j = high; j > low; --j) {
          if (arr[j] < arr[j - 1]) {
            tmp = arr[j];
            arr[j] = arr[j - 1];
            arr[j - 1] = tmp;
          }
        }
        // 修改low值,后移一位
        ++low;
      }
    }
    

    相邻值相同时不交换情况下,可以保持稳定性。

    相关文章

      网友评论

          本文标题:交换排序—冒泡排序(Bubble Sort)

          本文链接:https://www.haomeiwen.com/subject/cmdikrtx.html