数据结构与算法------插入排序

插入排序

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

排序思想

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

图解

在这里插入图片描述

举个例子,上面的图数据太长,我们来个简单的例子,加入有个数组是[17,3,25,14,20,9]

插入排序怎么排序呢?

首先第一个元素17看成是有序表,那么剩下的就是无序表

第一次插入:插入3,跟有序表比较,比17小,按照我们的从小到大规则,插入到17前面

成为 [(3,17) 25,14,20,9]

第二次插入:插入25,跟有序表[3,17]比较,比我们17大,放在17后面

成为 [(3,17,25) 14,20,9]

第三次插入:插入14,跟有序表(3,17,25)比较,比25小,往前找,比17小再往前,比3大,介于3,17之间。插入成为 [(3,14,17,25) 20,9]

依次类推,直至无序表没有数据

共要进行n-1次插入

请听题:

科大有一宿舍学生,成绩分别是:101,34,119,1

请用插入排序,将他们的成绩从小到大排列

代码实现

package com.wang.sort;

import java.util.Arrays;

/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/24 16:05
 * @Description TODO
 * @pojectname 插入排序算法
 */
public class InsertSort {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    101,34,119,1};
        insertSort(arr);
    }
    //插入排序
    //逐步推到
    //第一次插入101,34,119,1====>34,101,119,1
    public static void insertSort(int[] arr){
    
    
        //定义待插入的数   34是下标为0的元素
        int insertValue = arr[1];
        int insertIndex = 1-1;//跟谁比较,跟前面的数比较
        //给insertValue找到插入位置
        while (insertIndex >=0 && insertValue <arr[insertIndex]){
    
    
            //insertIndex >=0保证我们找位置的时候不越界
            //insertValue <arr[insertIndex]==》说明我们还没找到位置
            //没有找到位置,说明我们的insertIndex代表的值大,往后面走
            arr[insertIndex+1] = arr[insertIndex];
            //数组变成了 101,101,119,1
            //我们的34被保存到了insertValue中
            insertIndex--;
        }
        //当退出while循环时,位置找到
        arr[insertIndex+1] = insertValue;
        System.out.println("第一次插入后的数组:"+ Arrays.toString(arr
        ));
        //第二轮
        insertValue = arr[2];
        insertIndex = 2-1;
        while (insertIndex >=0 && insertValue <arr[insertIndex]){
    
    
            //insertIndex >=0保证我们找位置的时候不越界
            //insertValue <arr[insertIndex]==》说明我们还没找到位置
            //没有找到位置,说明我们的insertIndex代表的值大,往后面走
            arr[insertIndex+1] = arr[insertIndex];
            //数组变成了 34,101,119,1
            //我们的34被保存到了insertValue中
            insertIndex--;
        }
        //当退出while循环时,位置找到
        arr[insertIndex+1] = insertValue;
        System.out.println("第二次插入后的数组:"+ Arrays.toString(arr));
        //第三轮
        insertValue = arr[3];
        insertIndex = 3-1;
        while (insertIndex >=0 && insertValue <arr[insertIndex]){
    
    
            //insertIndex >=0保证我们找位置的时候不越界
            //insertValue <arr[insertIndex]==》说明我们还没找到位置
            //没有找到位置,说明我们的insertIndex代表的值大,往后面走
            arr[insertIndex+1] = arr[insertIndex];
            //我们的34被保存到了insertValue中
            insertIndex--;
        }
        //当退出while循环时,位置找到
        arr[insertIndex+1] = insertValue;
        System.out.println("第三次插入后的数组:"+ Arrays.toString(arr));
    }

}

为什么退出的时候,我们的insertIndex要+1呢?因为我们一开始定义这个insertIndex的时候减去了一个1,跟我们的图解差不多

图解中,每插入一个元素的时候,我们发现有一个绿色的标记,那个就是我们的insertIndex所处的位置,好比243,排序3,我先跟谁比较?这个时候3的下标是2,他要先跟4比较也就是下标为1的元素,那我们insertIndex就是2-1正好是4,比较发现小,那么我们进入while循环,数组变成244,insertIndex变成了0,再去判断循环,这个时候的insertValue >arr[insertIndex],现在的insertIndex就是绿色柱子2,我们3比绿色数字要大,当时比刚才那个有小,所以我们插入的位置就在insertIndex+1的位置

插入排序算法

/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/24 16:05
 * @Description TODO
 * @pojectname 插入排序算法
 */
public class InsertSort {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    101,34,119,1};
        insertSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void insertSort(int[] arr){
    
    
        for (int i = 1; i <arr.length; i++) {
    
    
            //从1个元素开始,不需要减一,减一的话我们的最后一个元素就不插入了
            int insertValue = arr[i];
            int insertIndex = i-1;//跟谁比较,跟前面的数比较
            //给insertValue找到插入位置
            while (insertIndex >=0 && insertValue <arr[insertIndex]){
    
    
                //insertIndex >=0保证我们找位置的时候不越界
                //insertValue <arr[insertIndex]==》说明我们还没找到位置
                //没有找到位置,说明我们的insertIndex代表的值大,往后面走
                arr[insertIndex+1] = arr[insertIndex];
                //数组变成了 101,101,119,1
                //我们的34被保存到了insertValue中
                insertIndex--;
            }
            arr[insertIndex+1] = insertValue;
        }
    }
}

外层for循环控制我从从那个位置开始准备插入,起始位置是arr[1],因为arr[0]我们当成了有序列表

那么外层循环就是arr[1],找位置arr[2]找位置……

内层while循环是用来找位置的,判断是不是我们要插入的位置,也就是我们推导过程说的那样
当然有人会问,我们的arr[insertIndex+1] = insertValue;地方如果恰好是相等的,不用交换呢?你可以加一个if去判断,但是这个优化,效果不大

问题

我们看简单的插入排序可能存在的问题.
数组arr = {2,3,4,5,6,1}这时需要插入的数1(最小),这样的过程是:
{2,3,4,5,6, 6}
{2,3,4,5,5, 6}
{2,3,4,4,5, 6}
{2,3,3,4,5, 6}
{2,2,3,4,5, 6}
{1,2,3,4,5, 6}
结论:当需要插入的数是较小的数时,后移的次数明显增多,对效率有影响.

那么如何优化插入排序呢?=====>希尔排序

这就是插入排序(直接插入排序),有什么地方说错了,说的不好,大家可以交流下

猜你喜欢

转载自blog.csdn.net/qq_22155255/article/details/111639169