All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feingto.cloud.kit.SortAlgorithm Maven / Gradle / Ivy

There is a newer version: 2.5.2.RELEASE
Show newest version
package com.feingto.cloud.kit;

import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;

/**
 * 排序算法
 *
 * @author longfei
 */
@Slf4j
public class SortAlgorithm {
    /**
     * 插入排序:直接插入排序-稳定
     */
    public static void insertSort(int[] data) {
        for (int i = 1; i < data.length; i++) {
            int j;
            int tmp = data[i];
            for (j = i; j > 0 && tmp < data[j - 1]; j--) {
                data[j] = data[j - 1];
            }
            data[j] = tmp;
        }
    }

    /**
     * 插入排序:希尔排序-不稳定
     */
    public static void shellSort(int[] data) {
        int gap = data.length;
        while (gap >= 1) {
            gap = gap / 2;
            for (int i = gap; i < data.length; i++) {
                if (data[i] < data[i - gap]) {
                    int j;
                    int tmp = data[i];
                    data[i] = data[i - gap];
                    for (j = i - gap; j >= 0 && tmp < data[j]; j = j - gap) {
                        data[j + gap] = data[j];
                    }
                    data[j + gap] = tmp;
                }
            }
        }
    }

    /**
     * 交换位置
     */
    private static void swap(int[] data, int i, int j) {
        if (i == j) return;
        data[i] = data[i] + data[j];
        data[j] = data[i] - data[j];
        data[i] = data[i] - data[j];
    }

    /**
     * 选择排序:简单选择排序-不稳定
     */
    public static void selectSort(int[] data) {
        for (int i = 0; i < data.length; i++) {
            int k = i;
            for (int j = i + 1; j < data.length; j++) {
                if (data[k] > data[j]) {
                    k = j;
                }
            }
            swap(data, k, i);
        }
    }

    /**
     * 选择排序:堆排序-不稳定
     */
    public static void heapSort(int[] data) {
        for (int i = 0; i < data.length; i++) {
            // 创建小顶堆:每次循环完,二叉树的根节点都是最小值,所以与此时的未排好部分最后一个值交换位置
            createLittleHeap(data, data.length - 1 - i);
            swap(data, 0, data.length - 1 - i);
        }
    }

    /**
     * 创建小顶堆:双亲节点小于子节点的值。从叶子节点开始,直到根节点
     */
    private static void createLittleHeap(int[] data, int last) {
        for (int i = last; i > 0; i--) {
            int parent = (i - 1) / 2;// 当前节点的双亲节点
            if (data[parent] < data[i])
                swap(data, parent, i);
        }
    }

    /**
     * 交换排序:冒泡排序-稳定
     */
    public static void bubbleSort(int data[]) {
        for (int i = 0; i < data.length - 1; i++) {
            for (int j = 0; j < data.length - 1 - i; j++) {
                if (data[j] > data[j + 1]) {
                    swap(data, j, j + 1);
                }
            }
        }
    }

    /**
     * 交换排序:快速排序-不稳定
     */
    public static void quickSort(int[] data) {
        int pivot = data.length - 1;
        int middle = getMiddle(data, 0, pivot);
        quickSort(data, 0, middle - 1);// 递归对低子表递归排序
        quickSort(data, middle + 1, pivot);// 递归对高子表递归排序
    }

    private static void quickSort(int[] data, int low, int high) {
        if (low < high) {
            int middle = getMiddle(data, low, high);
            quickSort(data, 0, middle - 1);
            quickSort(data, middle + 1, high);
        }
    }

    private static int getMiddle(int[] data, int low, int high) {
        int key = data[low];// 基准元素(空出来的位置)
        while (low < high) {
            while (low < high && data[high] >= key) {// 从high开始找比基准小的,与low换位置
                high--;
            }
            data[low] = data[high];
            while (low < high && data[low] <= key) {// 从low开始找比基准大,放到之前high空出来的位置上
                low++;
            }
            data[high] = data[low];
        }
        data[low] = key;// low=high 是基准元素的位置(空出来的位置)
        return low;

    }

    /**
     * 归并排序-稳定
     */
    public static void mergeSort(int[] data) {
        mergeSort(data, 0, data.length - 1);
    }

    private static void mergeSort(int[] data, int left, int right) {
        if (left >= right)
            return;
        // 找出中间索引
        int center = (left + right) / 2;
        // 对左边数组进行递归
        mergeSort(data, left, center);
        // 对右边数组进行递归
        mergeSort(data, center + 1, right);
        // 合并
        mergeSort(data, left, center, right);
    }

    /**
     * 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序
     *
     * @param data   数组对象
     * @param left   左数组的第一个元素的索引
     * @param center 左数组的最后一个元素的索引,center+1是右数组第一个元素的索引
     * @param right  右数组最后一个元素的索引
     */
    private static void mergeSort(int[] data, int left, int center, int right) {
        // 临时数组
        int[] tmpArr = new int[data.length];
        // 右数组第一个元素索引
        int mid = center + 1;
        // third 记录临时数组的索引
        int third = left;
        // 缓存左数组第一个元素的索引
        int tmp = left;
        while (left <= center && mid <= right) {
            // 从两个数组中取出最小的放入临时数组
            if (data[left] <= data[mid]) {
                tmpArr[third++] = data[left++];
            } else {
                tmpArr[third++] = data[mid++];
            }
        }
        // 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)
        while (mid <= right) {
            tmpArr[third++] = data[mid++];
        }
        while (left <= center) {
            tmpArr[third++] = data[left++];
        }
        // 将临时数组中的内容拷贝回原数组中(原left-right范围的内容被复制回原数组)
        while (tmp <= right) {
            data[tmp] = tmpArr[tmp++];
        }
    }

    /**
     * 10进制基数排序-稳定
     */
    public static void radixSort(int[] data) {
        int max = Arrays.stream(data).max().getAsInt();// 计算最大数的位数
        radixSort(data, 10, String.valueOf(max).length());// 10进制数,有0~9一共10种情况
    }

    /**
     * 基数排序-稳定
     * 1.先循环数组中元素个位数上的数字,先根据个位数进行排序,使用二维数组进行数据存放
     * 2.再进行元素十位数上的数字排序
     *
     * @param data  数组
     * @param radix 基数 - 每位数字的范围(这里是10进制数,有0~9一共10种情况)
     * @param d     代表排序元素的位数
     */
    public static void radixSort(int[] data, int radix, int d) {
        // 临时数组
        int[] temp = new int[data.length];
        // count用于记录待排序元素的信息,用来表示该位是i的数的个数
        int[] count = new int[radix];

        int rate = 1;
        for (int i = 0; i < d; i++) {
            // 重置count数组
            Arrays.fill(count, 0);
            // 将data中的元素完全复制到temp数组中
            System.arraycopy(data, 0, temp, 0, data.length);

            // 计算每个待排序数据的子关键字
            for (int j = 0; j < data.length; j++) {
                int subKey = (temp[j] / rate) % radix;
                count[subKey]++;
            }
            // 统计count数组的前j位(包含j)共有多少个数
            for (int j = 1; j < radix; j++) {
                count[j] = count[j] + count[j - 1];
            }
            // 按子关键字对指定的数据进行排序
            for (int m = data.length - 1; m >= 0; m--) {
                int subKey = (temp[m] / rate) % radix;
                data[--count[subKey]] = temp[m];// 插入到第--count[subKey]位
            }
            rate *= radix;// 前进一位
        }
    }

    public static void main(String[] args) {
        int data[] = {3, 5, 1, 7, 2, 4, 9, 6, 10, 8, 93754, 199, 288, 32, 63754, 183, 12, 8903};
        log.debug("初始值:{}", Arrays.toString(data));
        int[] array = Arrays.copyOf(data, data.length);
        long start = System.currentTimeMillis();
        SortAlgorithm.insertSort(array);
        log.debug(">>> Execution time {}ms", System.currentTimeMillis() - start);
        log.debug("插入排序:直接插入排序:{}", Arrays.toString(array));

        array = Arrays.copyOf(data, data.length);
        start = System.currentTimeMillis();
        SortAlgorithm.shellSort(array);
        log.debug(">>> Execution time {}ms", System.currentTimeMillis() - start);
        log.debug("插入排序:希尔排序:{}", Arrays.toString(array));

        array = Arrays.copyOf(data, data.length);
        start = System.currentTimeMillis();
        SortAlgorithm.selectSort(array);
        log.debug(">>> Execution time {}ms", System.currentTimeMillis() - start);
        log.debug("选择排序:简单选择排序:{}", Arrays.toString(array));

        array = Arrays.copyOf(data, data.length);
        start = System.currentTimeMillis();
        SortAlgorithm.heapSort(array);
        log.debug(">>> Execution time {}ms", System.currentTimeMillis() - start);
        log.debug("选择排序:堆排序:{}", Arrays.toString(array));

        array = Arrays.copyOf(data, data.length);
        start = System.currentTimeMillis();
        SortAlgorithm.bubbleSort(array);
        log.debug(">>> Execution time {}ms", System.currentTimeMillis() - start);
        log.debug("交换排序:冒泡排序:{}", Arrays.toString(array));

        array = Arrays.copyOf(data, data.length);
        start = System.currentTimeMillis();
        SortAlgorithm.quickSort(array);
        log.debug(">>> Execution time {}ms", System.currentTimeMillis() - start);
        log.debug("交换排序:快速排序:{}", Arrays.toString(array));

        array = Arrays.copyOf(data, data.length);
        start = System.currentTimeMillis();
        SortAlgorithm.mergeSort(array);
        log.debug(">>> Execution time {}ms", System.currentTimeMillis() - start);
        log.debug("归并排序:{}", Arrays.toString(array));

        array = Arrays.copyOf(data, data.length);
        start = System.currentTimeMillis();
        SortAlgorithm.radixSort(array, 10, 5);
        log.debug(">>> Execution time {}ms", System.currentTimeMillis() - start);
        log.debug("基数排序:{}", Arrays.toString(array));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy