冒泡排序

来自姬鸿昌的知识库
跳到导航 跳到搜索

https://www.bilibili.com/video/BV1tW4y1i7Mo

算法描述

  1. 首先从未排序数组的首位开始,和后面相邻的数字进行比较,如果前面一个比后面一个大,那么则进行交换。
  2. 接下来再将第二个位置的数字和后面相邻的数字进行比较,如果大,那么则进行交换,直到将最大的数字交换到数组的尾部
  3. 然后再从排序的数组的首位开始,重复前面两步,将最大的数组交换到未排序数组的尾部(交换到尾部的数字是已经排好序的)。
  4. 如此反复,直到排序完毕。

比如:

排序前的原始数组

8 6 12 7 2 5 4 1 9

第1个元素和第2个元素比较,如果第1个元素比第2个元素大的话,它们就会交换位置,这里8>6,所以交换位置,变成:

6 8 12 7 2 5 4 1 9

接下来,再以第2个元素和第3个元素进行比较,8<12,不变;

接下来,再使用第3个元素和第4个元素进行比较,12>7,进行交换:

6 8 7 12 2 5 4 1 9

……,就这样一直进行比较交换,把值最大的元素一直往后面移,直到值最大的元素被交换到数组的尾部:

6 8 7 2 5 4 1 9 12


算法实现

分解1:将第一个数字和后面相邻的数字进行比较,如果大则进行交换

public class Test {

    public static void main(String[] args) {
        int[] arr = {8,6,12,7,2,5,4,1,9};

        //比较两个元素
        if (arr[0] > arr[1]) {
            int tmp = arr[0];
            arr[0] = arr[1];
            arr[1] = tmp;
        }

        if (arr[1] > arr[2]) {
            int tmp = arr[1];
            arr[1] = arr[2];
            arr[2] = tmp;
        }

        if (arr[2] > arr[3]) {
            int tmp = arr[2];
            arr[2] = arr[3];
            arr[3] = tmp;
        }

        //……
    }

}


分解2:用循环实现比较、交换的过程

public class Test {

    public static void main(String[] args) {
        int[] arr = {8, 6, 12, 7, 2, 5, 4, 1, 9};

        for (int i = 0; i < arr.length; i++) {

            if (arr[i] > arr[i + 1]) {
                int tmp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = tmp;
            }

        }
    }

}

会发现抛出异常:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 9
	at bubblesort.Test.main(Test.java:10)

这是因为当 i 为 arr.length-1 时,arr[i+1] 发生了数组下标越界,而且实际上,对于 n 个元素的数组,我们也只需要进行 n - 1 次的比较大小的判断,

比如本例中有9个元素,每两个位置之间进行比较,就需要进行8次比较(像五根手指四个缝O(∩_∩)O哈哈~),arr.length-1就是8,“i=0;i<8;i++”,就将循环i值为“0,1,2,3,4,5,6,7”8个值。

于是修正成:

public class Test {

    public static void main(String[] args) {
        int[] arr = {8, 6, 12, 7, 2, 5, 4, 1, 9};

        for (int i = 0; i < arr.length - 1; i++) {

            if (arr[i] > arr[i + 1]) {
                int tmp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = tmp;
            }

        }// end for

    }//end main

}

到这里,我们完成了第一轮的冒泡,整个数组可以看成两部分,左边是未排序的,右表是已排序的(数组中的最大值),


分解3:多轮冒泡

public class Test {

    public static void main(String[] args) {
        int[] arr = {8, 6, 12, 7, 2, 5, 4, 1, 9};

        //第一轮,最大值到最后
        for (int i = 0; i < arr.length - 1; i++) {

            if (arr[i] > arr[i + 1]) {
                int tmp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = tmp;
            }

        }

        //第二轮,次大的值到倒数第2个位置
        for (int i = 0; i < arr.length - 2; i++) {

            if (arr[i] > arr[i + 1]) {
                int tmp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = tmp;
            }

        }

        //第三轮
        for (int i = 0; i < arr.length - 3; i++) {

            if (arr[i] > arr[i + 1]) {
                int tmp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = tmp;
            }

        }
        //……



    }

}

双层循环代替:




完整实现

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--) {// 0 ~ e

            boolean swapped = false;

            for (int i = 0; i < e; i++) {

                if (arr[i] > arr[i + 1]) {

                    swap(arr, i, i + 1);

                    swapped = true;

                }

            }//end for

            if (!swapped) {
                break;
            }

        }//end for

    }//end bubbleSort

    /**
     * 交换 arr 的 i 和 j 位置上的值
     * 相较于:
     * int tmp = arr[i];
     * arr[i] = arr[j];
     * arr[j] = tmp;
     * 的写法,节省了一个额外的空间
     * @param arr
     * @param i
     * @param j
     */
    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];
    }

    public static void main(String[] args) {
        int[] arr = new int[]{6, 8, 4, 3, 9, 7};
        SelectionSort.selectionSort(arr);
        System.out.print(arr[0]);
        for(int i = 1; i < arr.length; i++){
            System.out.print(", " + arr[i]);
        }
    }
}
public class Test {

    public static void main(String[] args) {

        int[] arr = {8, 6, 12, 7, 2, 5, 4, 1, 9};

        for(int i = 1; i < arr.length;i++){

            boolean swapped = false;

            for (int j = 0; j < arr.length - i; j++){

                if (arr[i] > arr[i+1]) {

                    arr[i] = arr[i] ^ arr[i+1];
                    arr[i+1] = arr[i] ^ arr[i+1];
                    arr[i] = arr[i] ^ arr[i+1];

                    swapped = true;

                }

            }//end for

            if (!swapped) {
                break;
            }

        }//end for
    }

}