十大排序方法

十大排序方法

在这里插入图片描述

1、冒泡排序

/**
 * @author Honey
 * @date 2021/8/8
 */
public class BubbleSort {

    public static void main(String[] args) {
        int[] a = {1, 6, 5, 3, 13, 7, 11, 9};
        // 接下来三个方法任选一个来进行排序,要注掉两个
        sort(a);
        sortArray(a,a.length-1,1);
        goodSort(a);

        System.out.println(Arrays.toString(a));
    }

    /**
     * 非递归
     * @param arr 排序的数组
     */
    private static void sort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - i - 1; j++) {
                if (arr[j + 1] < arr[j]) {
                    int temp = arr[j + 1];
                    arr[j + 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }

    /**
     * 递归实现
     * @param array 需要排序的数组
     * @param m array.length - 1      递减
     * @param n 从 1 开始到 m         递增
     */
    public static void sortArray(int[] array, int m, int n) {
        if (m > 0) {
            if (array[n] < array[n - 1]) {
                int temp = array[n];
                array[n] = array[n - 1];
                array[n - 1] = temp;
            }
            if (n >= m) {
                sortArray(array,m - 1,1);
            } else {
                sortArray(array,m,n + 1);
            }
        }
    }


    /**
     * 冒泡排序的优化,如果在排的过程中有序,则会立即返回
     * @param arr 排序的数组
     */
    public static void goodSort(int[] arr) {
        boolean flag;

        for (int i = 0; i < arr.length - 1; i++) {
            System.out.println("第" + (i + 1) + "轮");
            flag = true;
            for (int j = 0; j < arr.length - i - 1; j++) {
                if (arr[j + 1] < arr[j]) {
                    int temp = arr[j + 1];
                    arr[j + 1] = arr[j];
                    arr[j] = temp;
                    flag = false;
                }
            }
            if (flag) {
                return;
            }
        }
    }

}

2、选择排序

时间复杂度和冒泡一样,但是排序的时间要比冒泡快

/**
 * @author Honey
 * @date 2021/8/8
 */
public class SelectSort {

    public static void main(String[] args) {
        int[] a = {1, 6, 5, 3, 13, 7, 11, 9};
        selectSort(a);
        goodSelectSort(a);
        System.out.println(Arrays.toString(a));
    }

    /**
     * 选择排序
     * @param array 排序数组
     */
    public static void selectSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            // 找到未排序数的最小值
            for (int j = i; j < array.length; j++) {
                if (array[j] < array[minIndex]) {
                    minIndex = j;
                }
            }
            // 让最小值跟第 i 个值交换,第 i 个前面的值是已排好顺序的。
            int temp1 = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp1;
        }
    }
    
    /**
     * 选择排序优化,双向选择排序
     * @param array 排序数组
     */
    public static void goodSelectSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            int maxIndex = array.length - 1 - i;
            // 找到未排序数的最小值
            for (int j = i; j < array.length - 1 - i; j++) {
                if (array[j] < array[minIndex]) {
                    minIndex = j;
                }
                if (array[j] > array[maxIndex]) {
                    maxIndex = j;
                }
            }
            // 让最小值跟第 i 个值交换,第 i 个前面的值是已排好顺序的。
            int temp1 = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp1;

            int temp2 = array[maxIndex];
            array[maxIndex] = array[array.length - 1 - i];
            array[array.length - 1 - i] = temp2;
        }
    }
}

3、插入排序

/**
 * @author Honey
 * @date 2021/8/8
 */
public class InsertionSort {

    public static void main(String[] args) {
        int[] a = {1, 6, 5, 3, 13, 7, 11, 9};
        insertionSort(a);
        System.out.println(Arrays.toString(a));
    }

    /**
     * 插入排序
     * @param array 排序的数组
     */
    public static void insertionSort(int[] array) {
        int currenrt;
        for (int i = 0; i < array.length - 1; i++) {
            currenrt = array[i + 1];
            int preIndex = i;
            // 把大于current的值往后挪一位,再把current的值插入进去
            while (preIndex >= 0 && currenrt < array[preIndex]) {
                array[preIndex + 1] = array[preIndex];
                preIndex--;
            }
            array[preIndex + 1] = currenrt;
        }
    }
    
}

4、希尔排序

/**
 * @author Honey
 * @date 2021/8/8
 */
public class ShellSort {


    public static void main(String[] args) {
        int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
        sort(array);
        System.out.println(Arrays.toString(array));
    }

    /**
     * 排序的方法
     * @param array 排序的数组
     */
    public static void sort(int[] array) {
        List<Integer> integers = shellStepSequence(array);
        for (Integer integer : integers) {
            shellSort(integer,array);
        }
    }

    /**
     * 通过出入的步长序列值的数组,进行排序
     * @param step 步长序列的值
     * @param array 排序数组
     */
    private static void shellSort(int step,int[] array) {
        for (int i = 0; i < step; i++) {
            for (int begin = i + step; begin < array.length; begin += step) {
                int cur = begin;
                while (cur > i && array[cur] < array[cur - step]) {
                    int temp = array[cur];
                    array[cur] = array[cur - step];
                    array[cur - step] = temp;
                    cur -= step;
                }
            }
        }
    }

    /**
     * 通过传入的数组判断需要的步长序列
     * 希尔本人给出的步长序列算法 n/2的k次方
     * @param array 传入需要排序的数组
     * @return 返回一个步长序列集合List<Integer>
     */
    private static List<Integer> shellStepSequence(int[] array) {
        List<Integer> stepSequence = new ArrayList<>();
        int step = array.length;
        while ((step >>= 1) > 0) {
            stepSequence.add(step);
        }
        return stepSequence;
    }
}

优化后计算步长序列的方法:

在这里插入图片描述

/**
     * 优化后计算步长序列的公式
     * @param count 传入需要排序的数组的长度
     * @return 返回一个步长序列集合List<Integer>
     */
    private static List<Integer> sedgewickStepSequence(int count) {
        List<Integer> stepSequence = new ArrayList<>();
        int k = 0;
        int step = 0;
        while (true) {
            if (k % 2 == 0) {
                int pow = (int)Math.pow(2,k >> 1);
                step = 1 + 9 * (pow * pow - pow);
            } else {
                int pow1 = (int) Math.pow(2, (k - 1) >> 1);
                int pow2 = (int) Math.pow(2, (k + 1) >> 1);
                step = 1 + 8 * pow1 * pow2 - 6 * pow2;
            }
            if (step >= count) {
                break;
            }
            stepSequence.add(0,step);
            k++;
        }
        return stepSequence;
    }

5、归并排序

/**
 * @author Honey
 * @date 2021/9/20
 */
public class MergeSort {

    public static void main(String[] args) {
        int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
        int[] ints = MergeSort(array);
        System.out.println(Arrays.toString(ints));
    }

    public static int[] MergeSort(int[] array) {
        if (array.length < 2) {
            return array;
        }
        int mid = array.length >> 1;
        int[] left = Arrays.copyOfRange(array, 0, mid);
        int[] right = Arrays.copyOfRange(array, mid, array.length);
        return merge(MergeSort(left), MergeSort(right));
    }
    /**
     * 归并排序——将两段排序好的数组结合成一个排序数组
     * @param left
     * @param right
     * @return
     */
    public static int[] merge(int[] left, int[] right) {
        int[] result = new int[left.length + right.length];
        for (int index = 0, i = 0, j = 0; index < result.length; index++) {
            if (i >= left.length) {
                result[index] = right[j++];
            } else if (j >= right.length) {
                result[index] = left[i++];
            } else if (left[i] > right[j]) {
                result[index] = right[j++];
            } else {
                result[index] = left[i++];
            }
        }
        return result;
    }

}

6、快速排序

/**
 * @author Honey
 * @date 2021/9/20
 */
public class QuickSort {

    private static int[] array = {1, 6, 5, 3, 13, 7, 11, 9};

    public static void main(String[] args) {
        sort(0,array.length);
        System.out.println(Arrays.toString(array));
    }
    public static void sort(int begin, int end) {
        if (end - begin < 2) {
            return;
        }
        // 确定轴点位置
        int mid = pivotIndex(begin, end);
        // 对子序列进行快速排序
        sort(begin,mid);
        sort(mid + 1,end);
    }

    /**
     * 确定 [begin,end) 的轴点位置
     * @return 轴点元素的最终位置
     */
    private static int pivotIndex(int begin, int end) {
        // 备份begin位置的元素
        int pivot = array[begin];
        // end要指向最后一个元素
        end--;
        while (begin < end) {
            while (begin < end) {
                // 从右往左
                if (pivot < array[end]) {
                    // 右边元素 > 轴点元素
                    end--;
                } else {
                    // 右边元素 < 轴点元素
                    array[begin++] = array[end];
                    break;
                }
            }
            while (begin < end) {
                // 从左往右
                if (pivot > array[begin]) {
                    begin++;
                } else {
                    array[end--] = array[begin];
                    break;
                }
            }
        }
        // 将轴点元素放入最终的位置
        array[begin] = pivot;
        // 返回轴点的位置
        return begin;
    }
}

7、堆排序

/**
 * @author Honey
 * @date 2021/9/20
 */
public class HeapSort {

    public static void main(String[] args) {
        int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
        HeapSort(array);
        System.out.println(Arrays.toString(array));
    }

    //声明全局变量,用于记录数组array的长度;
    static int len;
    /**
     * 堆排序算法
     *
     * @param array
     * @return
     */
    public static void HeapSort(int[] array) {
        len = array.length;
        if (len < 1) {
            return;
        }
        //1.构建一个最大堆
        buildMaxHeap(array);
        //2.循环将堆首位(最大值)与末位交换,然后在重新调整最大堆
        while (len > 0) {
            swap(array, 0, len - 1);
            len--;
            adjustHeap(array, 0);
        }
        return;
    }

    /**
     * 建立最大堆
     * @param array
     */
    public static void buildMaxHeap(int[] array) {
        //从最后一个非叶子节点开始向上构造最大堆
        for (int i = (len/2 - 1); i >= 0; i--) {
            //感谢 @让我发会呆 网友的提醒,此处应该为 i = (len/2 - 1)
            adjustHeap(array, i);
        }
    }
    /**
     * 调整使之成为最大堆
     * @param array
     * @param i
     */
    public static void adjustHeap(int[] array, int i) {
        int maxIndex = i;
        //如果有左子树,且左子树大于父节点,则将最大指针指向左子树
        if (i * 2 < len && array[i * 2] > array[maxIndex]) {
            maxIndex = i * 2;
        }
        //如果有右子树,且右子树大于父节点,则将最大指针指向右子树
        if (i * 2 + 1 < len && array[i * 2 + 1] > array[maxIndex]) {
            maxIndex = i * 2 + 1;
        }
        //如果父节点不是最大值,则将父节点与最大值交换,并且递归调整与父节点交换的位置。
        if (maxIndex != i) {
            swap(array, maxIndex, i);
            adjustHeap(array, maxIndex);
        }
    }
    private static void swap(int[] array, int maxIndex, int i) {
        int temp = array[maxIndex];
        array[maxIndex] = array[i];
        array[i] = temp;
    }
}

8、计数排序

/**
 * 适合对一定范围的整数进行排序
 * 统计每个整数在序列中出现的次数,进而推导出每个整数在有序序列中的索引
 * @author Honey
 * @date 2021/9/20
 */
public class CountingSort {

    public static void main(String[] args) {
        int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
        CountingSort(array);
        System.out.println(Arrays.toString(array));
    }
    
    /**
     * 计数排序
     * @param array
     * @return
     */
    public static void CountingSort(int[] array) {
        if (array.length == 0) {
            return;
        }
        int bias, min = array[0], max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i] > max) {
                max = array[i];
            }
            if (array[i] < min) {
                min = array[i];
            }
        }
        bias = 0 - min;
        int[] bucket = new int[max - min + 1];
        Arrays.fill(bucket, 0);
        for (int i = 0; i < array.length; i++) {
            bucket[array[i] + bias]++;
        }
        int index = 0, i = 0;
        while (index < array.length) {
            if (bucket[i] != 0) {
                array[index] = i - bias;
                bucket[i]--;
                index++;
            } else {
                i++;
            }
        }
        return;
    }

}

9、桶排序

/**
 * @author Honey
 * @date 2021/9/20
 */
public class BucketSort {

    public static void main(String[] args) {
        int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
        bucketSort(array);
        System.out.println(Arrays.toString(array));

    }
    public static void bucketSort(int[] arr){
        // 计算最大值与最小值
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        for(int i = 0; i < arr.length; i++){
            max = Math.max(max, arr[i]);
            min = Math.min(min, arr[i]);
        }
        // 计算桶的数量
        int bucketNum = (max - min) / arr.length + 1;
        ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
        for(int i = 0; i < bucketNum; i++){
            bucketArr.add(new ArrayList<Integer>());
        }
        // 将每个元素放入桶
        for(int i = 0; i < arr.length; i++){
            int num = (arr[i] - min) / (arr.length);
            bucketArr.get(num).add(arr[i]);
        }
        // 对每个桶进行排序
        for(int i = 0; i < bucketArr.size(); i++){
            Collections.sort(bucketArr.get(i));
        }
        // 将桶中的元素赋值到原序列
        int index = 0;
        for(int i = 0; i < bucketArr.size(); i++){
            for(int j = 0; j < bucketArr.get(i).size(); j++){
                arr[index++] = bucketArr.get(i).get(j);
            }
        }
    }
}

10、基数排序

/**
 * 基数排序非常适合用于整数排序(尤其是非负整数)
 * 执行流程:依次对个位数、十位数、百位数、千位数、万位数。。。进行排序(从低到高)
 * @author Honey
 * @date 2021/9/20
 */
public class RadixSort {

    public static void main(String[] args) {

        int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
        RadixSort(array);
        System.out.println(Arrays.toString(array));
    }

    /**
     * 基数排序
     * @param array
     * @return
     */
    public static void RadixSort(int[] array) {
        if (array == null || array.length < 2) {
            return;
        }

        // 1.先算出最大数的位数;
        int max = array[0];
        for (int i = 1; i < array.length; i++) {
            max = Math.max(max, array[i]);
        }
        int maxDigit = 0;
        while (max != 0) {
            max /= 10;
            maxDigit++;
        }
        int mod = 10, div = 1;
        ArrayList<ArrayList<Integer>> bucketList = new ArrayList<ArrayList<Integer>>();
        for (int i = 0; i < 10; i++) {
            bucketList.add(new ArrayList<Integer>());
        }
        for (int i = 0; i < maxDigit; i++, mod *= 10, div *= 10) {
            for (int j = 0; j < array.length; j++) {
                int num = (array[j] % mod) / div;
                bucketList.get(num).add(array[j]);
            }
            int index = 0;
            for (int j = 0; j < bucketList.size(); j++) {
                for (int k = 0; k < bucketList.get(j).size(); k++) {
                    array[index++] = bucketList.get(j).get(k);
                }
                bucketList.get(j).clear();
            }
        }
        return;
    }
}
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值