12、冒泡排序和希尔排序

内容来自刘宇波老师算法与数据结构体系课

1、冒泡排序

/**
 * 冒泡排序:O(n^2)
 * 优化: 对完全有序的数组 O(n)
 * 每一轮都会减少逆序对, 当逆序对数量减为 0 时, 就有序了
 */
public class BubbleSort {

    private BubbleSort() {
    }

    /**
     * 冒泡排序
     */
    public static <E extends Comparable<E>> void sort1(E[] arr) {
        for (int tail = arr.length - 1; tail >= 1; tail--) {
            // 通过冒泡在 arr[tail] 放上合适的元素
            for (int i = 0; i + 1 <= tail; i++) {
                if (arr[i].compareTo(arr[i + 1]) > 0) swap(arr, i, i + 1);
            }
        }
    }

    /**
     * 冒泡排序优化 1
     */
    public static <E extends Comparable<E>> void sort2(E[] arr) {
        for (int tail = arr.length - 1; tail >= 1; tail--) {
            // 通过冒泡在 arr[tail] 放上合适的元素
            boolean isSwapped = false;
            for (int i = 0; i + 1 <= tail; i++) {
                if (arr[i].compareTo(arr[i + 1]) > 0) {
                    swap(arr, i, i + 1);
                    isSwapped = true;
                }
            }

            if (!isSwapped) return;
        }
    }

    /**
     * 冒泡排序优化 2
     */
    public static <E extends Comparable<E>> void sort3(E[] arr) {
        for (int tail = arr.length - 1; tail >= 1; ) {
            // 通过冒泡在 arr[tail] 放上合适的元素
            int nextTail = 0; // 如果一次都没 swap, 就应该退出
            for (int i = 0; i + 1 <= tail; i++) {
                if (arr[i].compareTo(arr[i + 1]) > 0) {
                    swap(arr, i, i + 1);
                    nextTail = i;
                }
            }

            tail = nextTail;
        }
    }

    private static <E> void swap(E[] arr, int a, int b) {
        E k = arr[a];
        arr[a] = arr[b];
        arr[b] = k;
    }
}

2、希尔排序

image

/**
 * 希尔排序
 * 复杂度: O(n^2 - n^2 / 2^logN), O(n^1.3) ~ O(n^1.5)
 */
public class ShellSort {

    private ShellSort() {
    }

    /**
     * 希尔排序
     */
    public static <E extends Comparable<E>> void sort1(E[] arr) {
        int h = arr.length / 2; // h = 间隔数 = 组数, 分母 = 每组的元素数
        while (h >= 1) {
            for (int start = 0; start < h; start++) {
                // 对 arr[start, start + h, start + 2h ...] 进行插入排序
                for (int i = start + h; i < arr.length; i += h) {
                    E k = arr[i];
                    int j;
                    for (j = i; j - h >= start && arr[j - h].compareTo(k) > 0; j -= h) {
                        arr[j] = arr[j - h];
                    }
                    arr[j] = k;
                }
            }
            h /= 2;
        }
    }

    /**
     * 代码优化
     */
    public static <E extends Comparable<E>> void sort2(E[] arr) {
        int h = arr.length / 2; // h = 间隔数 = 组数, 分母 = 每组的元素数
        while (h >= 1) {
            // 对 arr[h, n - 1] 进行插入排序
            for (int i = h; i < arr.length; i++) {
                E k = arr[i];
                int j;
                for (j = i; j - h >= 0 && arr[j - h].compareTo(k) > 0; j -= h) arr[j] = arr[j - h];
                arr[j] = k;
            }
            h /= 2;
        }
    }

    /**
     * 性能优化: 新的步长序列
     */
    public static <E extends Comparable<E>> void sort3(E[] arr) {
        int h = 1; // h = 间隔数 = 组数, 分母 = 每组的元素数
        while (h < arr.length) h = h * 3 + 1;
        // 1, 4, 13, 40 ...
        while (h >= 1) {
            // 对 arr[h, n - 1] 进行插入排序
            for (int i = h; i < arr.length; i++) {
                E k = arr[i];
                int j;
                for (j = i; j - h >= 0 && arr[j - h].compareTo(k) > 0; j -= h) arr[j] = arr[j - h];
                arr[j] = k;
            }
            h /= 3;
        }
    }
}
posted @ 2023-04-11 00:27  lidongdongdong~  阅读(23)  评论(0编辑  收藏  举报