插入排序之折半插入排序、希尔排序

本文介绍了两种优化的插入排序算法:折半插入排序和希尔排序。折半插入排序利用折半查找确定插入位置,减少了比较次数。希尔排序通过设定不同步长进行插入排序,提高效率。实验表明,折半插入排序在无序数据上优于直接插入排序,希尔排序则在效率上显著高于两者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.折半插入排序:

  • 折半插入排序实际上是对直接插入排序的优化,通过折半查找来找到要插入的位置,再搬移元素,最后插入即可。
  • 思路分析:
  • 定义low为有序部分的第一个位置,high为有序部分的最后一个位置,通过折半查找的方法,不断更新low和high的位置,直到 low>high,此时high+1即为我们要插入的位置。
  • 直接插入排序是在每一次比较时,就进行数据的搬移;而折半插入排序是在找到插入位置后,通过循环一次性将high+1位置的元素到有序部分的最后一个元素j进行搬移,最后插入本次的value值到high+1位置。
  • 代码实现如下:
package www.first;

import java.util.Scanner;

public class HalfInsertSort {
    public static void halfInsertSort(int[] arr){
        if(arr.length<=1||arr==null){
            return;
        }else{
            //i为无序部分的第一个元素位置
            for(int i = 1;i<arr.length;i++){
                //存储无序元素的值,方便比较
                int value = arr[i];
                //有序部分的第一个元素位置
                int low = 0;
                //有序部分的最后一个元素位置
                int high = i-1;
                while(low<=high){
                    int mid =(low+high)/2;
                    if(value<arr[mid]){
                        high = mid-1;
                    }else{
                        low = mid+1;
                    }
                }
                //此时已经找到插入位置,为high+1,开始搬移元素
                //将high+1~j位置的元素都往后搬移一位
                int j = i-1;
                for(;j>high;j--){
                    arr[j+1] = arr[j];
                }
                //循环之后,此时的j为high
                //将high+1位置赋值为我们的value
                arr[j+1] = value;
            }
        }
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String str = scanner.nextLine();
        String[] s = str.split(" ");
        int[] array = new int[s.length];
        for(int i = 0;i<s.length;i++){
            array[i] = Integer.parseInt(s[i]);
        }
        halfInsertSort(array);
        for(int i:array){
            System.out.print(i+" ");
        }
    }
}

结果如下:
在这里插入图片描述

  • 折半插入排序的时间复杂度,空间复杂度都与直接插入排序相同;也是一个稳定的排序算法。
  • 折半插入排序与直接插入排序的比较:
    我随机生成了10万条有序数据和10万条无序数据,我们来看看结果:
    在这里插入图片描述
    在这里插入图片描述
    可以看出,折半插入排序在无序的情况下要优于直接插入排序;但是在近乎有序的情况下,直接插入排序要比折半插入排序好一点,因为直接插入只用比较一次。

2.希尔排序:

  • 思路分析:希尔排序通过将数据分成不同的组,先对每一组进行排序,此时的数据已经大部分有序,然后再对所有元素进行一次插入排序,以减少数据交换和移动的次数
  • 代码实现:
public class ShellSort {
    public static void shellSort(int[] arr){
        if(arr.length<=1||arr==null){
            return;
        }else{
            int step = arr.length/2;
            while(step>=1){
                for(int i = step;i<arr.length;i++){
                    int value = arr[i];
                    int j = i-step;
                    for(;j>=0;j-=step){
                        if(value<arr[j]){
                            arr[j+step] = arr[j];
                        }else{
                            break;
                        }
                    }
                    arr[j+step] = value;
                }
                step/=2;
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = new int[]{1,2,5,6,8,2,3,5,2};
        shellSort(arr);
        for(int i:arr){
            System.out.print(i+" ");
        }
    }
}

结果如下:
在这里插入图片描述

  • 希尔排序是按照不同步长对元素进行插入排序,当刚开始元素无序的时候,步长最大,插入排序的元素个数很少;当步长为1时,元素基本有序了,再进行插入排序就会大大提高效率。
  • 希尔排序的时间复杂度为O(nlogn),空间复杂度为O(1),但不是一种稳定的排序算法,因为相同的元素可能在各自的插入排序中移动。
  • 希尔排序与直接插入排序、折半插入排序的对比:
    随机生成10万条数据分别进行三种方式的排序,结果如下:
    在这里插入图片描述
    可见,希尔排序的效率远远高于直接插入排序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值