zoukankan      html  css  js  c++  java
  • JAVA排序算法

    1.选择排序

    import java.util.Arrays;
    
    public class SelectSort {
        // 选择排序:每一轮选择最小元素交换到未排定部分的开头
        public int[] sortArray(int[] nums) {
            int len = nums.length;
            for (int i = 0; i < len - 1; i++) {
                int minIndex = i;
                for (int j = i + 1; j < len; j++) {
                    if (nums[j] < nums[minIndex]) {
                        minIndex = j;
                    }
                }
                swap(nums, i, minIndex);
    
            }
            return nums;
        }
    
        private void swap(int[] nums, int index1, int index2) {
            int temp = nums[index1];
            nums[index1] = nums[index2];
            nums[index2] = temp;
    
        }
    
        public static void main(String[] args) {
            int[] nums= {5,1,9,6,2,7,3,8};
            SelectSort solution = new SelectSort();
            int[] res = solution.sortArray(nums);
            System.out.println(Arrays.toString(res));
    
        }
    }
    

    2.插入排序

    public class InsertSort{
    public int[] sortArray(int[] nums) {
            int len = nums.length;
            // 循环不变量:将 nums[i] 插入到区间 [0, i) 使之成为有序数组
            for (int i = 1; i < len; i++) {
                // 先暂存这个元素,然后之前元素逐个后移,留出空位
                int temp = nums[i];
                int j = i;
                // 注意边界 j > 0
                while (j > 0 && nums[j - 1] > temp) {
                    nums[j] = nums[j - 1];
                    j--;
                }
                nums[j] = temp;
            }
            return nums;
        }
    }
    

    3.归并排序

    算法思想:分而治之。

    public class Solution {
        // 归并排序
    
        /**
         * 列表大小等于或小于该大小,将优先于 mergeSort 使用插入排序
         */
        private static final int INSERTION_SORT_THRESHOLD = 7;
    
        public int[] sortArray(int[] nums) {
            int len = nums.length;
            int[] temp = new int[len];
            mergeSort(nums, 0, len - 1, temp);
            return nums;
        }
    
        /**
         * 对数组 nums 的子区间 [left, right] 进行归并排序
         *
         * @param nums
         * @param left
         * @param right
         * @param temp  用于合并两个有序数组的辅助数组,全局使用一份,避免多次创建和销毁
         */
        private void mergeSort(int[] nums, int left, int right, int[] temp) {
            // 小区间使用插入排序
            if (right - left <= INSERTION_SORT_THRESHOLD) {
                insertionSort(nums, left, right);
                return;
            }
    
            int mid = left + (right - left) / 2;
            // Java 里有更优的写法,在 left 和 right 都是大整数时,即使溢出,结论依然正确
            // int mid = (left + right) >>> 1;
    
            mergeSort(nums, left, mid, temp);
            mergeSort(nums, mid + 1, right, temp);
            // 如果数组的这个子区间本身有序,无需合并
            if (nums[mid] <= nums[mid + 1]) {
                return;
            }
            mergeOfTwoSortedArray(nums, left, mid, right, temp);
        }
    
        /**
         * 对数组 arr 的子区间 [left, right] 使用插入排序
         *
         * @param arr   给定数组
         * @param left  左边界,能取到
         * @param right 右边界,能取到
         */
        private void insertionSort(int[] arr, int left, int right) {
            for (int i = left + 1; i <= right; i++) {
                int temp = arr[i];
                int j = i;
                while (j > left && arr[j - 1] > temp) {
                    arr[j] = arr[j - 1];
                    j--;
                }
                arr[j] = temp;
            }
        }
    
        /**
         * 合并两个有序数组:先把值复制到临时数组,再合并回去
         *
         * @param nums
         * @param left
         * @param mid   [left, mid] 有序,[mid + 1, right] 有序
         * @param right
         * @param temp  全局使用的临时数组
         */
        private void mergeOfTwoSortedArray(int[] nums, int left, int mid, int right, int[] temp) {
            System.arraycopy(nums, left, temp, left, right + 1 - left);
    
            int i = left;
            int j = mid + 1;
    
            for (int k = left; k <= right; k++) {
                if (i == mid + 1) {
                    nums[k] = temp[j];
                    j++;
                } else if (j == right + 1) {
                    nums[k] = temp[i];
                    i++;
                } else if (temp[i] <= temp[j]) {
                    // 注意写成 < 就丢失了稳定性(相同元素原来靠前的排序以后依然靠前)
                    nums[k] = temp[i];
                    i++;
                } else {
                    // temp[i] > temp[j]
                    nums[k] = temp[j];
                    j++;
                }
            }
        }
    }
    
    

    3.快速排序

    import java.util.Random;
    
    public class Solution {
    
        // 快速排序 1:基本快速排序
    
        /**
         * 列表大小等于或小于该大小,将优先于 quickSort 使用插入排序
         */
        private static final int INSERTION_SORT_THRESHOLD = 7;
    
        private static final Random RANDOM = new Random();
    
    
        public int[] sortArray(int[] nums) {
            int len = nums.length;
            quickSort(nums, 0, len - 1);
            return nums;
        }
    
        private void quickSort(int[] nums, int left, int right) {
            // 小区间使用插入排序
            if (right - left <= INSERTION_SORT_THRESHOLD) {
                insertionSort(nums, left, right);
                return;
            }
    
            int pIndex = partition(nums, left, right);
            quickSort(nums, left, pIndex - 1);
            quickSort(nums, pIndex + 1, right);
        }
    
        /**
         * 对数组 nums 的子区间 [left, right] 使用插入排序
         *
         * @param nums  给定数组
         * @param left  左边界,能取到
         * @param right 右边界,能取到
         */
        private void insertionSort(int[] nums, int left, int right) {
            for (int i = left + 1; i <= right; i++) {
                int temp = nums[i];
                int j = i;
                while (j > left && nums[j - 1] > temp) {
                    nums[j] = nums[j - 1];
                    j--;
                }
                nums[j] = temp;
            }
        }
    
        private int partition(int[] nums, int left, int right) {
            int randomIndex = RANDOM.nextInt(right - left + 1) + left;
            swap(nums, left, randomIndex);
    
            // 基准值
            int pivot = nums[left];
            int lt = left;
            // 循环不变量:
            // all in [left + 1, lt] < pivot
            // all in [lt + 1, i) >= pivot
            for (int i = left + 1; i <= right; i++) {
                if (nums[i] < pivot) {
                    lt++;
                    swap(nums, i, lt);
                }
            }
            swap(nums, left, lt);
            return lt;
        }
    
        private void swap(int[] nums, int index1, int index2) {
            int temp = nums[index1];
            nums[index1] = nums[index2];
            nums[index2] = temp;
        }
    }
    
    
  • 相关阅读:
    PHP之Trait详解
    PHP中__call()方法与重载解析
    PHP Closure(闭包)类详解
    PHP 核心特性
    回调函数
    php的各种 I/O流 以及用法
    关于php的buffer(缓冲区)
    php的运行原理、cgi对比fastcgi以及php-cgi和php-fpm之间的联系区别
    低功耗设计入门(一)——低功耗设计目的与功耗的类型
    从CMOS到触发器(一)
  • 原文地址:https://www.cnblogs.com/gongcheng-/p/12683388.html
Copyright © 2011-2022 走看看