算法 - 排序

Posted chenxianbin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法 - 排序相关的知识,希望对你有一定的参考价值。

冒泡排序

public static void bubbleSort(int[] arr) {
    if (arr == null || arr.length < 2) return;
    for (int i = arr.length - 1; i > 0; i--) {
        for (int j = 0; j < i; j++) {
            if (arr[j] > arr[j + 1]) {
                swap(arr, j);
            }
        }
    }
}

冒泡排序比较简单,但是容易出现冗余的循环,即使是一个已经排序的数组传入仍然需要遍历 O(n ^ 2)。

选择排序

public static void selectSort(int[] arr) {
    if (arr == null || arr.length < 2) return;
    for (int i = 0; i < arr.length - 1; i++) {
        int min = i;
        for (int j = i + 1; j < arr.length; j++) {
            if (arr[min] > arr[j]) {
                min = j;
            }
        }
        if (i != min) {
            swap(arr, i, min);
        }
    }
}

选择排序时间复杂度也是 O(n ^ 2)。

插入排序

public static void insertSort(int[] arr) {
    if (arr == null || arr.length < 2) return;
    for (int i = 1; i < arr.length; i++) {
        for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
            swap(arr, j, j + 1);
        }
    }
}

插入排序,有可能是 O(n) 也有可能是 O(n^2),和数据是否已经有序有关。

归并排序

public static void mergeSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }
    mergeSort(arr, 0, arr.length - 1);
}


public static void mergeSort(int[] arr, int l, int r) {
    if (l == r) {
        return;
    }
    int mid = l + ((r - l) >> 2);
    mergeSort(arr, l, mid);
    mergeSort(arr, mid + 1, r);
    merge(arr, l, mid, r);
}

public static void merge(int[] arr, int l, int m, int r) {
    //这个数组是临时生成的,使用过后又马上销毁,最大的长度为排序数组的长度,所以额外空间为 O(n)
    int[] helper = new int[r - l + 1];
    int i = 0;
    int p1 = l;
    int p2 = m + 1;
    while (p1 <= m && p2 <= r) {
        helper[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
    }
    //下面两个循环有且只有一个会执行
    while (p1 <= m) {
        helper[i++] = arr[p1++];
    }
    while (p2 <= r) {
        helper[i++] = arr[p2++];
    }
    //需要注意 l 为归并的左边界,不是定值 0
    for (int j = 0; j < helper.length; j++) {
        arr[l + j] = helper[j];
    }
}

归并排序使用了递归的方式,利用 master 公式可以分析分治思路算法的时间复杂度。关于 master 公式可以参看这篇文章。归并排序使用了额外的存储空间,时间复杂度为 O(n * logn),空间复杂度为 O(n)。

以上是关于算法 - 排序的主要内容,如果未能解决你的问题,请参考以下文章

算法排序之堆排序

快速排序-递归实现

从搜索文档中查找最小片段的算法?

在第6731次释放指针后双重免费或损坏

TimSort算法分析

以下代码片段的算法复杂度