经典排序算法

import java.util.Arrays;

/**
 * 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
 * 不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
 * 时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
 * 空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。
 */
public class Sort {
    /**
     * 选择排序
     * <p>
     * 时间复杂度(平均):O(n^2)
     * 时间复杂度(最好):O(n^2)
     * 时间复杂度(最坏):O(n^2)
     * 空间复杂度:O(1)
     * 稳定性:不稳定
     *
     * @param arr
     */
    public static void selectionSort(int[] arr) {
        for (int i = 0, len = arr.length - 1; i < len; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {//选择最小的数
                if (arr[j] < arr[i]) {
                    minIndex = j;
                }
            }
            if (minIndex != i) {
                swap(arr, i, minIndex);
            }
        }
    }

    /**
     * 冒泡排序
     * <p>
     * 时间复杂度(平均):O(n^2)
     * 时间复杂度(最好):O(n^2)
     * 时间复杂度(最坏):O(n^2)
     * 空间复杂度:O(1)
     * 稳定性:稳定
     *
     * @param arr
     */
    public static void bubbleSort(int arr[]) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0, len = arr.length - i - 1; j < len; j++) {
                if (arr[j + 1] < arr[j]) {
                    swap(arr,j+1,j);
                }
            }
        }
    }

    /**
     * 快速排序
     * <p>
     * 时间复杂度(平均):O(nlogn)
     * 时间复杂度(最好):O(nlogn)
     * 时间复杂度(最坏):O(n^2)
     * 空间复杂度:O(nlogn)
     * 稳定性:不稳定
     *
     * @param arr
     */
    public static void QuickSort(int[] arr) {

        QuickSort(arr, 0, arr.length - 1);
    }

    public static void QuickSort(int[] arr, int start, int end) {
        if (start >= end) {
            return;
        }
        int k = arr[start];
        int l = start, r = end;
        //使k左边的值小于等于k,k右边的值大于等于k
        while (l < r) {
            while (l < r && arr[r] >= k) r--;

            arr[l] = arr[r];

            while (l < r && arr[l] <= k) l++;

            arr[r] = arr[l];
        }
        arr[l] = k;
        QuickSort(arr, start, l - 1);
        QuickSort(arr, l + 1, end);
    }

    /**
     * 归并排序
     * <p>
     * 时间复杂度(平均):O(nlogn)
     * 时间复杂度(最好):O(nlogn)
     * 时间复杂度(最坏):O(nlogn)
     * 空间复杂度:O(n)
     * 稳定性:稳定
     *
     * @param arr
     */
    public static void mergeSort(int[] arr) {
        mergeSort(arr, new int[arr.length], 0, arr.length - 1);
    }

    public static void mergeSort(int[] arr, int[] temp, int start, int end) {
        if (start < end) {
            int mid = (start + end) >> 1;
            mergeSort(arr, temp, start, mid);
            mergeSort(arr, temp, mid + 1, end);
            merge(arr, temp, start, mid, end);
        }
    }

    /**
     * 合并
     *
     * @param arr
     * @param temp
     * @param start
     * @param mid
     * @param end
     */
    private static void merge(int[] arr, int[] temp, int start, int mid, int end) {
        int i = start;
        int j = mid + 1;
        int t = 0;
        while (i <= mid && j <= end) {
            if (arr[i] < arr[j]) {
                temp[t++] = arr[i++];
            } else {
                temp[t++] = arr[j++];
            }
        }
        //剩余的数,直接赋值
        while (i <= mid) temp[t++] = arr[i++];
        while (j <= end) temp[t++] = arr[j++];

        System.arraycopy(temp, 0, arr, start, end - start + 1);
    }

    /**
     * 插入排序
     * <p>
     * 时间复杂度(平均):O(n^2)
     * 时间复杂度(最好):O(n)
     * 时间复杂度(最坏):O(n^2)
     * 空间复杂度:O(1)
     * 稳定性:稳定
     *
     * @param arr
     */
    public static void insertSort(int[] arr) {
        for (int i = 0, len = arr.length - 1; i < len; i++) {
            int current = arr[i + 1];
            int j = i;
            while (j >= 0 && arr[j] > current) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = current;
        }
    }

    /**
     * 堆排序
     * <p>
     * 时间复杂度(平均):O(nlogn)
     * 时间复杂度(最好):O(nlogn)
     * 时间复杂度(最坏):O(nlogn)
     * 空间复杂度:O(1)
     * 稳定性:不稳定
     *
     * @param arr
     */
    public static void heapSort(int[] arr) {
        //从堆的第一个非叶子节点(位置:(arr.length - 1)/2)开始从右至左,从下到上,构建大顶堆
        for (int i = (arr.length - 1) >> 1; i >= 0; i--) {
            buildMaxHeap(arr, i, arr.length - 1);
        }

        for (int i = arr.length - 1; i >= 0; i--) {
            swap(arr, i, 0);//将大顶堆的根,交换到堆的末尾
            buildMaxHeap(arr, 0, i - 1);//构建新的大顶堆
        }
    }

    private static void buildMaxHeap(int[] arr, int index, int len) {
        int max = (index << 1) + 1;//2*index+1
        if (max > len) {
            return;
        }
        int right = max + 1;
        //有右节点,且比左节点大
        if (right <= len && arr[right] > arr[max]) {
            max++;
        }

        if (arr[max] > arr[index]) {
            swap(arr, max, index);
            buildMaxHeap(arr, max, len);//对被置换的原父节点重新构建大顶堆
        }
    }

    public static void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值