插入排序

插入排序

排序步骤(有n个数需要排序)

1、从第一个数开始,被认为是有序的

2、取出下一个数,在已经排好数的序列之中插入当前数

3、将之后的数后移

4、重复取数,直到数列取完

解析说明(n个数字需要升序排列)

插入排序的最好情况:序列已经是升序数列,所要进行的比较次数最小,比较次数为n-1次

插入排序的最差情况:序列降序排列,此时需要比较的次数为1+2+3+ ... + (n-1) + n = n(n-1)/2

平均来说插入排序算法时间复杂度为O(N^2)

最优的空间复杂度为开始元素已排序,则空间复杂度为 0;

最差的空间复杂度为开始元素为逆排序,则空间复杂度最坏时为 O(N);

平均的空间复杂度为O(1)

public static int[] insertSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {//外层循环控制从1开始取数
            int temp = arr[i];//当i所在位置的数字向前移动时,arr[i]会被arr[i-1]位置上的数字替代,因此需要有一个变量存储arr[i]上的值
            for (int j = i - 1; j >= 0; j--) {//内层循环控制遍历已排序的序列,寻找合适的位置插入arr[i]
                if (temp < arr[j]) {
                    arr[j+1] = arr[j];
                }else{//找到合适的位置后退出
                    break;
                }
                arr[j] = temp;//插入
            }
        }
        return arr;
    }

优化

优化查找效率:采用二分插入排序的方式。通过二分查找不断确定数的范围,直到确定为两个数的中间。时间复杂度降至O(NlogN)

二分查找:在已经排好序的一组数中(这里设定为从小到大),取出最中间的数字 arr[middle] ,比较它与所要查找的数字 arr[i] 的大小。如果 arr[i] < arr[middle] ,那么 arr[i] 所在的位置在0~middle之间;如果 arr[i] < arr[middle] ,那么 arr[i] 所在的位置在middle~n-1之间。以此类推,不断二分,最终能够确定 arr[i] 位于两个数之间

二分查找停止情况分析:程序通过left和right来确认 arr[i] 的位置范围;如果 left < right ,说明此时还未确认 arr[i] 的位置;如果 left > right ,如下图所示,left即为查找的数插入的位置

 举个栗子:

//优化一:二分查找
    public static int[] insertSort1(int[] arr) {
        int left, right, middle, target, t = 0;//target为所需要查找的数,具体作用同temp相同;t记录最终target所在数组的位置的索引
        for (int i = 1; i < arr.length; i++) {
            target = arr[i];
            left = 0;
            right = i - 1;
            //查找数的位置
            while (left <= right) {
                middle = (left + right) / 2;
                if (target < arr[middle]) {
                    right = middle - 1;
                } else{
                    left = middle + 1;
                }

                t = left;
            }

            //插入数的位置
            for (int j = i - 1; j >= t; j--) {//仅堆插入位置之后的数进行位移
                //未优化的方法在此处范围为大于等于0是因为还有大小判断限制,能够break跳出循环
                arr[j + 1] = arr[j];
            }
            arr[t] = target;
        }
        return arr;
    }

插入排序代码

import org.junit.Test;

public class InsertSort {
    @Test
    public void test() {
        int[] arr = new int[]{12, 15, 4, 5, 8, 35};
        insertSort1(arr);
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }

    public static int[] insertSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {//外层循环控制从1开始取数
            int temp = arr[i];//当i所在位置的数字向前移动时,arr[i]会被arr[i-1]位置上的数字替代,因此需要有一个变量存储arr[i]上的值
            for (int j = i - 1; j >= 0; j--) {//内层循环控制遍历已排序的序列,寻找合适的位置插入arr[i]
                if (temp < arr[j]) {
                    arr[j + 1] = arr[j];
                } else {//找到合适的位置后退出
                    break;
                }
                arr[j] = temp;//插入
            }
        }
        return arr;
    }

    //优化一:二分查找
    public static int[] insertSort1(int[] arr) {
        int left, right, middle, target, t = 0;//target为所需要查找的数,具体作用同temp相同;t记录最终target所在数组的位置的索引
        for (int i = 1; i < arr.length; i++) {
            target = arr[i];
            left = 0;
            right = i - 1;
            //查找数的位置
            while (left <= right) {
                middle = (left + right) / 2;
                if (target < arr[middle]) {
                    right = middle - 1;
                } else{
                    left = middle + 1;
                }

                t = left;
            }

            //插入数的位置
            for (int j = i - 1; j >= t; j--) {//仅堆插入位置之后的数进行位移
                //未优化的方法在此处范围为大于等于0是因为还有大小判断限制,能够break跳出循环
                arr[j + 1] = arr[j];
            }
            arr[t] = target;
        }
        return arr;
    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值