Java常用算法——插入排序

来源:互联网 发布:聚类算法分类电子表格 编辑:程序博客网 时间:2024/06/07 07:09

插入排序
时间复杂度:O(n^2)
空间复杂度:O(1)
插入排序是稳定的

思路:

插入排序

第一趟插入:将第2个元素插入到前面的有序子序列,此时前面只有一个元素,当然是有序的
第二趟插入:将第3个元素插入到前面的有序子序列,前面两个元素是有序的

第n-1趟插入:将第n个元素插入到前面的有序子序列,前面n-1个元素是有序的

代码:

生成随机数组的工具类:

package com.algorithm.utils;import java.util.Random;public class ArraysUtil {    private static Random rand = new Random();    /**     * 返回长度为size,并且数组中元素的大小范围为[begin, end)的int数组     */    public static int[] makeIntArray(int begin, int end, int size) {        int[] nums = new int[size];        for(int i = 0; i < size; i++) {            nums[i] = begin + rand.nextInt(end - begin);        }        return nums;    }}

插入排序代码:

package com.algorithm.sort;import java.util.Arrays;import com.algorithm.utils.ArraysUtil;/** * 思路: * 第一趟插入:将第2个元素插入到前面的有序子序列,此时前面只有一个元素,当然是有序的 * 第二趟插入:将第3个元素插入到前面的有序子序列,前面两个元素是有序的 * ... * 第n-1趟插入:将第n个元素插入到前面的有序子序列,前面n-1个元素是有序的 */public class S03_InsertionSort {    private static final int SIZE = 10;    /*     * 插入排序的时间效率并不高,在最坏的情况下,所有元素的比较次数总和为:     * 0 + 1 + ... + (n-1)     * 故时间复杂度为O(n^2)     */    public static void insertionSort(int[] nums) {        int i, j, temp;        for(i = 1; i < nums.length; i++) {            temp = nums[i];            j = i - 1;            // 整体后移一格            while(j >= 0 && temp < nums[j]) {                nums[j+1] = nums[j];                j--;            }            // 把 temp的值插入合适的位置            nums[j+1] = temp;            System.out.print("第" + i + "步的排序结果为:");            System.out.println(Arrays.toString(nums));        }    }    /*     * 上面的方法存在的问题:     * 第n-1趟插入需要把第n个元素插入到前面[0, n-1]个元素中     * 而每次总是从第n-1个元素开始逐个比较,直到找到合适的位置     * 这显然没有利用前面[0, n-1]个数已经有序的特点     * 改进:利用折半查找的思想     * 1.计算[0, n-1]的中间点,把第i索引处的元素和第(0+n-1)/2索引处的元素进行比较     * 如果i索引处的元素大,就在[(0+n-1)/2, n-1]范围     * 内查找,反之在[0,(0+n-1)/2]范围内查找     * 2.在半个范围内进行搜索时,在按照1步的方法进行折半查找,总是不断的折半,     * 这样就可以把搜索范围缩小到1/2, 1/4, 1/8...从来快速确定第i个元素的插入位置     * 3.确定第i个元素的插入位置后,把该位置以后的元素整体后移一位,把第i个元素放入该位     * 置     */    public static void insertionSortOptimize(int[] nums) {        int i, j, temp;        for(i = 1; i < nums.length; i++) {            temp = nums[i];            int low = 0;            int high = i - 1;            while(low <= high) {                int mid = (low + high)/2;                if(temp > nums[mid]) {                    low = mid + 1;                }else {                    high = mid - 1;                }            }            // 将[low, i)处的所有元素向后整体移一位            for(j = i; j > low; j--) {                nums[j] = nums[j-1];            }            // 把 temp的值插入合适的位置            nums[low] = temp;            System.out.print("第" + i + "步的排序结果为:");            System.out.println(Arrays.toString(nums));        }    }    public static void main(String[] args) {        int[] nums = ArraysUtil.makeIntArray(10, 100, SIZE);        System.out.print("排序前的数组为:");        System.out.println(Arrays.toString(nums));//      insertionSort(nums);        insertionSortOptimize(nums);        System.out.print("排序后的数组为:");        System.out.println(Arrays.toString(nums));    }}

结果:

排序前的数组为:[76, 13, 53, 94, 25, 31, 23, 95, 89, 30]第1步的排序结果为:[13, 76, 53, 94, 25, 31, 23, 95, 89, 30]第2步的排序结果为:[13, 53, 76, 94, 25, 31, 23, 95, 89, 30]第3步的排序结果为:[13, 53, 76, 94, 25, 31, 23, 95, 89, 30]第4步的排序结果为:[13, 25, 53, 76, 94, 31, 23, 95, 89, 30]第5步的排序结果为:[13, 25, 31, 53, 76, 94, 23, 95, 89, 30]第6步的排序结果为:[13, 23, 25, 31, 53, 76, 94, 95, 89, 30]第7步的排序结果为:[13, 23, 25, 31, 53, 76, 94, 95, 89, 30]第8步的排序结果为:[13, 23, 25, 31, 53, 76, 89, 94, 95, 30]第9步的排序结果为:[13, 23, 25, 30, 31, 53, 76, 89, 94, 95]排序后的数组为:[13, 23, 25, 30, 31, 53, 76, 89, 94, 95]
原创粉丝点击