排序算法 - 插入排序(Insertion Sort)

插入排序

插入式排序属于内部排序法, 是对于欲排序的元素以插入的方式找寻该元素的适当位置, 以达到排序的目的。

插入排序的问题: 当需要排序的数组中小值越靠后, 就会循环判断次数越多
插入排序的演变过程(从小到大)

把 n 个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素, 无序表中包含有 n-1 个元素, 排序过程中每次从无序表中取出第一个元素, 把它的排序码依次与有序表元素的排序码进行比较, 将它插入到有序表中的适当位置, 使之成为新的有序表。

public class InsertSort {

	public static void main(String[] args) { 
		int[] arr = { 101, 34, 119, 1 };
		insertSort(arr);
	}

	// 插入排序
	public static void insertSort(int[] arr) {
		// 使用逐步推导的方式来讲解,便利理解
		// 第1轮 {101, 34, 119, 1}; => {34, 101, 119, 1}
		// {101, 34, 119, 1}; => {101,101,119,1}
		// 定义待插入的数
		int insertVal = arr[1];// 无序排序的第一个数
		// 有序排序的最后一个数
		int insertIndex = 1 - 1; // 即arr[1]的前面这个数的下标

		// 给insertVal 找到插入的位置
		// 说明
		// 1. insertIndex >= 0 保证在给insertVal 找插入位置,不越界
		// 2. insertVal < arr[insertIndex] 待插入的数,还没有找到插入位置
		// 3. 就需要将 arr[insertIndex] 后移
		while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
			arr[insertIndex + 1] = arr[insertIndex];// 往后移
			insertIndex--;
		}
		// 当退出while循环时,说明插入的位置找到, insertIndex + 1
		// 举例:理解不了,我们一会 debug
		arr[insertIndex + 1] = insertVal;

		System.out.println("第1轮插入");
		System.out.println(Arrays.toString(arr));

		// 第2轮
		insertVal = arr[2];
		insertIndex = 2 - 1;

		while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
			arr[insertIndex + 1] = arr[insertIndex];
			insertIndex--;
		}

		arr[insertIndex + 1] = insertVal;
		System.out.println("第2轮插入");
		System.out.println(Arrays.toString(arr));

		// 第3轮
		insertVal = arr[3];
		insertIndex = 3 - 1;

		while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
			arr[insertIndex + 1] = arr[insertIndex];
			insertIndex--;
		}

		arr[insertIndex + 1] = insertVal;
		System.out.println("第3轮插入");
		System.out.println(Arrays.toString(arr));

	}

}
/*
第1轮插入
[34, 101, 119, 1]
第2轮插入
[34, 101, 119, 1]
第3轮插入
[1, 34, 101, 119]
*/
插入排序实例代码
public class InsertionSortApp {
    public static int[] setArray(int capacity) {
        int[] arr = new int[capacity];
        for (int i =0; i < capacity;i++) {
            arr[i] = (int) (Math.random() * capacity);
        }
        return arr;
    }

    /** 插入排序方法
     * - 从无序表到有序表的转移过程*/
    public static void insertionSort(int[] arr) {
        /** 定义待插入的数值& 指定下标 -1, 也就是前一个元素下标
         * - 从第2个(1)元素开始与第一个元素(0)比较交换, 依次判断
         * */
        int insertValue = 0;
        int insertIndex = 0;
        for (int i = 1; i < arr.length; i++) {
            /** 定义待插入的数*/
            insertValue = arr[i];
            /** 待插入元素的下标 -1*/
            insertIndex = i - 1;

            /**
             * 1. 为了下标不越界 insertIndex >= 0
             * 2. 待插入的数(当前数: insertValue), 
             * 与原数组前一个数(下标-1的元素: arr[insertIndex])比
             * 较 insertValue < arr[insertIndex]
             * 3. 将 arr[insertIndex]值覆盖当前数的原数组
             * 位(arr[insertIndex + 1]), 也就是后移
             * */
            while (insertIndex >= 0 && insertValue < arr[insertIndex]) {
                arr[insertIndex + 1] = arr[insertIndex];
                insertIndex--;
            }

            /** 有在 while循环中处理过, 意味着 insertIndex下标递减过, 
            同时已锁定元素位, 所以可以将待插入的数(insertValue)插入到指
            定位置* */
            if (insertIndex + 1 != i) {
                arr[insertIndex + 1] = insertValue;
            }

            System.out.println("i=" + i + ": " + Arrays.toString(arr));
        }
    }

    public static void main(String[] args) {
        int arr[] = {9, 8, 7, 10, 2};
        System.out.println("排序前 " + Arrays.toString(arr));
        /** 开始插入排序*/
        insertionSort(arr);
    }
/*
输出:
> 排序前 [9, 8, 7, 10, 2]
* 8<9=true; arr[insertIndex + 1] = arr[insertIndex]; 89 交换
i=1: [8, 9, 7, 10, 2]
* 7比较9
* 7比较8
i=2: [7, 8, 9, 10, 2]
i=3: [7, 8, 9, 10, 2]
* 2比较10
* 2比较9
* 2比较8
* 2比较7
i=4: [2, 7, 8, 9, 10]
*/
插入排序效率(一般)
/** 生成长度为 100000的随机值数组, 用于与其它算法对比排序效率*/
int[] arr = setArray(100000);
System.out.println("开始时间 " + 
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));
/** 开始插入排序*/
insertionSort(arr);
System.out.println("结束时间 " + 
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));
/*
输出:
> 开始时间 2020-10-14 15:36:44
> 结束时间 2020-10-14 15:36:45
> */

你可能感兴趣的:(Java,数据结构与算法,算法,数据结构,java,排序算法,插入排序)