一日一钱,千日一千。绳锯木断,水滴石穿。

冒泡排序、插入排序、选择排序

Posted on By TinyVampirePudge

冒泡排序、插入排序、选择排序

冒泡排序(Bubble Sort)

冒泡排序只会操作相邻的两个数据。两两比较,将较大的数换到后边。

代码如下:

    /**
     * 冒泡排序
     * 两两比较,将较大的数移到后边。
     *
     * @param a
     * @param n
     */
    public void bubbleSort(int[] a, int n) {
        if (n <= 1) return;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n - i - 1; j++) {
                // 交换条件
                if (a[j] > a[j + 1]) {
                    int tmp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = tmp;
                }
            }
        }
    }

这里我们还可以进行优化,如果某次冒泡之后已经没有数据可以交换时,说明已经达到完全有序,不用再继续执行后续的冒泡操作。代码如下:

    /**
     * 优化后的冒泡排序
     *
     * @param a
     * @param n
     */
    public void bubbleSortOptimize(int[] a, int n) {
        if (n <= 1) return;
        for (int i = 0; i < n; i++) {
            // 提前退出冒泡循环的标志位
            boolean flag = false;
            for (int j = 0; j < n - i - 1; j++) {
                if (a[j] > a[j + 1]) {
                    int tmp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = tmp;
                    flag = true;
                }
            }
            // 没有数据交换,提前退出
            if (!flag) break;
        }
    }

插入排序(Insertion Sort)

我们将待排序的数据分为两个区间,已排序区间和未排序区间。初始状态下,已排序区间为空。

插入算法的核心思想是取未排序区间的元素,在已排序区间中找到合适的位置插入,并保证已排序区间数据一直有序。重复这个过程,直到未排序区间中元素为空,算法结束。

代码如下:

    /**
     * 插入排序
     * 将数据插入到有序数组中。
     *
     * @param a
     * @param n
     */
    public void insertSort(int[] a, int n) {
        if (n <= 1) return;

        for (int i = 1; i < n; i++) {
            int value = a[i];
            int j = i - 1;
            // 查找插入的位置
            for (; j >= 0; j--) {
                if (a[j] > value) {
                    a[j + 1] = a[j];// 数据移动
                } else {
                    break;
                }
            }
            a[j + 1] = value;// 插入数据
        }
    }

选择排序(Selection Sort)

跟插入排序类似,选择排序也区分已排序区间和未排序区间。初始状态下,已排序区间为空。 选择排序的核心是每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。

代码如下:

    /**
     * 插入排序
     * 从未排序区间中找到最小元素,将其放到已排序区间的末尾。
     *
     * @param a
     * @param n
     */
    public void selectSort(int[] a, int n) {
        if (n <= 1) return;
        for (int i = 0; i < n - 1; i++) {
            // 查找最小值的角标
            int minIndex = i;
            for (int j = i + 1; j < n; j++) {
                if (a[j] < a[minIndex]) {
                    minIndex = j;
                }
            }

            // 减少无用的交换。
            if (minIndex == i) {
                continue;
            }

            // 交换
            int tmp = a[i];
            a[i] = a[minIndex];
            a[minIndex] = tmp;
        }
    }