常见排序算法小结

最近温习了一下之前学的七七八八的常见排序算法

快速排序

    // 快速排序  时间复杂度O(nlogn) 稳定性:不稳定
    public static int[] quickSort(int[] nums, int start, int end) {
        if (start < end) {
            int i = start;
            int j = end;
            int temp = nums[start]; // 基准值 (优化点 可先取mid位子处的元素和start位子互换再开始快排)

            while (i < j) {
                while (i < j && nums[j] > temp) {
                    j--;
                }
                if (i < j)
                    nums[i++] = nums[j];
                while (i < j && nums[i] < temp) {
                    i++;
                }
                if (i < j) {
                    nums[j--] = nums[i];
                }
            }
            nums[i] = temp;
            quickSort(nums, start, i - 1);
            quickSort(nums, i + 1, end);
        }
        return nums;
    }

归并排序

    // 归并排序  时间复杂度O(nlogn) 稳定性: 稳定
    public static void mergeSort(int[] nums, int i, int j) {
        if (i < j) {
            int mid = i + ((j - i) >> 1);
            mergeSort(nums, i, mid);
            mergeSort(nums, mid + 1, j);
            merge(nums, i, mid, j);
        }
    }

    private static void merge(int[] nums, int i, int mid, int j) {

        int[] arr = new int[j - i + 1];
        int x = i;
        int y = mid + 1;
        for (int a = 0; a < arr.length; a++) {
            if (x > mid) {
                arr[a] = nums[y++];
            } else if (y > j) {
                arr[a] = nums[x++];
            } else if (nums[x] <= nums[y]) {
                arr[a] = nums[x++];
            } else
                arr[a] = nums[y++];
        }


        for (int b = 0; b < arr.length; b++) {
            nums[i + b] = arr[b];
        }
    }

插入排序

    // 插入排序 时间复杂度 O(n^2) 稳定性:稳定
    public static void insertSort(int[] nums) {
        // 思路是 在已有序 序列基础上 继续添加元素 // 即在第一个元素后 遍历要添加的元素
        // 从右到左依次比较有序序列 将要添加的元素插入合适的位子
        for (int i = 1; i < nums.length; i++) {
            int target = nums[i];
            int pre = i - 1;
            while (pre >= 0 && nums[pre] > target) {
                nums[pre + 1] = nums[pre];
                pre--;
            }
            nums[pre + 1] = target;
        }
    }

希尔排序

    // 希尔排序是对插入排序的更高效的优化 插入排序即为gap为1的特殊场景 时间复杂度 O(nlog^2 n) 稳定性不稳定
    //由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元 素的相对顺序,
    // 但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱;
    public static void shellSort(int[] nums) {
        int length = nums.length;
        for (int gap = length >> 1; gap > 0; gap = gap >> 1) {
            for (int i = gap; i < length; i++) {
                insertSortByGap(nums, gap, i);
            }
        }
    }

    private static void insertSortByGap(int[] nums, int gap, int i) {
        int current = nums[i];
        int pre = i - gap;
        while (pre >= 0 && nums[pre] > current) {
            nums[pre + gap] = nums[pre];
            pre -= gap;
        }
        nums[pre + gap] = current;
    }

堆排序

    // 借助优先队列 (堆)进行排序 时间复杂度O(nlogn) 稳定性 不稳定
    public static void heapSort(int[] nums) {
        PriorityQueue queue = new PriorityQueue<>(nums.length);
        for (int i = 0; i < nums.length; i++) {
            queue.offer(nums[i]);
        }

        for (int i = 0; i < nums.length; i++) {
            nums[i] = queue.poll();
        }
    }

位图排序

    // 位图排序 利用底层1字节8个bit位 来进行0,1设置
    // 使用场景为:内存限制较大,数据不重复,知道数组中的最大值
    public static int[] bitSort(int[] nums, int max) {
        BitSet bitSet = new BitSet(max + 1);
        for (int i = 0; i < nums.length; i++) {
            bitSet.set(nums[i]);
        }
        return bitSet.stream().toArray();
    }

冒泡排序

    // 冒泡排序 时间复杂度度O(n^2) 稳定性:稳定
    public static void bubbleSort(int[] nums) {
        for (int i = nums.length - 1; i > 0; i--) {
            boolean isSwap = true;
            for (int j = 0; j < i; j++) {
                if (nums[j] > nums[j + 1]) {
                    swap(nums, j, j + 1);
                }
                isSwap = false;
            }

            if (isSwap)
                break;
        }
    }

选择排序

    // 选择排序 时间复杂度度O(n^2) 稳定性:不稳定
    public static void selectSort(int[] nums) {

        for (int i = nums.length - 1; i > 0; i--) {
            int maxIndex = i;
            for (int j = 0; j < i; j++) {
                if (nums[j] > nums[maxIndex]) {
                    maxIndex = j;
                }
            }
            if (i != maxIndex)
                swap(nums, i, maxIndex);
        }
    }

计数排序

    // 计数排序 时间复杂度: 当输入的元素是 n 个 0到 k 之间的整数时,时间复杂度是O(n+k)
    public static void countingSort(int[] nums, int max) {
        int[] counting = new int[max + 1];

        for (int i = 0; i < nums.length; i++) {
            counting[nums[i]] += 1;
        }

        int x = 0;
        for (int i = 0; i < counting.length; i++) {
            if (counting[i] != 0) {
                for (int j = 0; j < counting[i]; j++) {
                    nums[x++] = i;
                }
            }
        }
    }
 private static void swap(int[] array, int x, int y) {
        int temp = array[x];
        array[x] = array[y];
        array[y] = temp;
    }

你可能感兴趣的:(常见排序算法小结)