排序算法-插入排序 及其优化-折半插入排序(java实现)

插入排序(Insertion Sort)

插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

算法描述

一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:

  • 从第一个元素开始,该元素可以认为已经被排序;
  • 取出下一个元素,在已经排序的元素序列中从后向前扫描;
  • 如果该元素(已排序)大于新元素,将该元素移到下一位置;
  • 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
  • 将新元素插入到该位置后;
  • 重复步骤2~5。

 动图演示

排序代码:

/**
     * 最佳时间复杂度:O(n) 平均时间复杂度:O(n²) 空间复杂度O(1)
     * @param array
     */
    public static void insertionSort(int[] array){
        if(array.length == 0){
            System.out.println("数组为空");
            return;
        }
        //记录插入的数据与前一个数的索引
        int current,preIndex;
        //0是只有一个数,默认有序
        for (int i=0;i<array.length-1;i++){
            //从第一个数开始插入
            current = array[i+1];
            preIndex = i;
            //从已排序的数据的右边开始找,找出小的数据
            while (preIndex >= 0 && current < array[preIndex]){
                //大的往后换
                array[preIndex+1] = array[preIndex];
                preIndex--;
            }
            //如果存在小的数,则插入
            if(preIndex != i){
                array[preIndex+1] = current;
            }
            System.out.println("第"+i+"次排序:"+Arrays.toString(array));
        }

    }

插入排序优化---折半插入排序:

/**
     * 折半插入排序 时间复杂度:O(n²) 最佳时间复杂度:O(n) 空间复杂度O(1)
     * @param array
     */
private static void binaryInsertSort(int[] array) {
        //从1开始,默认第0个是有序的
        for (int i = 1; i < array.length; i++) {
            //保留无序的数字
            int temp = array[i];
            //有序数组的第一个值的索引与最后一个值的索引
            int low = 0;
            int high = i - 1;
            //二分查找
            while (low <= high) {
                //有序数组中间值的索引
                int mid = (low + high) / 2;
                // >代表降序   <结果为升序
                if (temp < array[mid]) {
                    //有序数组中间值大于temp时,由于升序,前面可能存在小于temp的值,所以high前调,将中间值前的数再与temp比较
                    high = mid - 1;
                } else {
                    //有序数组中间值小于等于temp时,由于升序,后面可能存在大于temp的值,所以low后调,将中间值后的数再与temp比较
                    low = mid + 1;
                }
            }
            //上面的while循环结束表示,已经找到了插入位置low,然后将有序数组中low位置及之后的数据全部后移1位
            for (int j = i; j >= low + 1; j--) {
                array[j] = array[j - 1];
            }
            //将low位置值更新为temp
            array[low] = temp;
        }
    }

折半插入排序算法是一种稳定的排序算法,比直接插入排序算法明细减少了关键字比较的次数,因此速度比直接插入排序快,但是记录的移动次数没有变,所以折半插入排序时间复杂度仍然是O(n²),空间复杂度为O(1)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值