Java实现插入排序

本文介绍了三种经典的排序算法:直接插入排序、折半插入排序和希尔排序。直接插入排序在最好情况下时间复杂度为O(n),最坏情况下为O(n^2);折半插入排序减少了比较次数,但时间复杂度仍为O(n^2);希尔排序在特定范围内的平均时间复杂度约为O(n^1.3),最坏情况为O(n^2)。这些排序算法的空间复杂度均为O(1),属于原地排序。文章通过代码实现展示了三种排序算法的详细步骤,并提供了测试用例。
摘要由CSDN通过智能技术生成

直接插入排序

//直接插入查找
    static void InsertSort(int[] arr,int length){
        int i,j;
        //依次将arr[2]~arr[n]插入前面已排序序列
        for(i=2;i<=length;i++){
            //若arr[i]关键字小于其前驱,则将arr[i]插入有序表
            if(arr[i]<arr[i-1]){
                //复制为哨兵,arr[0]不存放元素
                arr[0]=arr[i];
                //从后往前查找待插入排序位置
                for (j=i-1;arr[0]<arr[j];--j){
                    //往后挪位
                    arr[j+1]=arr[j];
                }
                //复制到插入位置
                arr[j+1]=arr[0];
            }
        }
    }

空间效率:仅使用了常数个辅助单元,因而空间复杂度为O(1)。
时间效率:在排序过程中,向有序子表中逐个插入元素的的操作进行了n-1趟,每趟操作都分为比较关键字和移动元素,而比较次数和移动次数取决于待排序的初始状态。
在最好的情况下:表中的元素已经有序,此时没插入一个元素,都只需比较一次而不用移动元素,因而时间复杂度为O(n)。
最坏的情况下:表中的元素为逆序,总的比较次数达到最大,总的移动次数也达到最大。
因此直接插入排序算法的时间复杂度为O(n^2)。
算法比较稳定

折半插入排序

//折半查找
    static void InsertSort2(int[] arr,int length){
        int i,j,high,low,mid;
        //依次将arr[2]~arr[n]插入到前面的已排序序列
        for (i=2;i<=length;i++){
            //暂时存入当前元素于arr[0]
            arr[0]=arr[i];
            //设置折半查找的范围
            low=1;high=i-1;
            //折半查找
            while (low<=high){
                //确定中间点
                mid=(low+high)>>1;
                //查找左半子表
                if(arr[mid]>arr[0]){
                    high=mid-1;
                }
                //查找右半子表
                else {
                    low=mid+1;
                }
            }
            //统一后移元素,为插入元素腾位置
            for(j=i-1;j>=low;j--){
                arr[j+1]=arr[j];
            }
            //插入操作
            arr[low]=arr[0];
        }
    }

空间复杂度:O(1)
时间效率:折半插入排序比直接插入排序仅减少了比较次数,约为O(nlog2n),该比较次数与待排序序列的初始状态无关,仅取决于表中元素的个数n;而元素的移动次数并未改变,它依赖于表的初始状态。因此时间复杂度为O(n^2)。
算法比较稳定。

希尔排序

//希尔排序
    static void ShellSort(int[] arr,int length){
        int dk,i,j;
        //变化要比较两元素之间的距离
        for (dk=length>>1;dk>=1;dk=dk>>1 ){
            //依次往后分组,分组以两元素间隔距离为dk
            for (i=dk+1;i<=length;i++){
                //如果当前分组后者元素小于前者元素,则暂存后者元素于arr[0]
                if (arr[i]<arr[i-dk]){
                    arr[0]=arr[i];
                    //把前者元素后移,为后者元素提供插入位置
                    for (j=i-dk;j>0&&arr[0]<arr[j];j-=dk){
                        arr[j+dk]=arr[j];
                    }
                    //插入操作
                    arr[j+dk]=arr[0];
                }
            }
        }
    }

空间效率:O(1)
时间效率:由于希尔排序的时间复杂度依赖于增量序列的函数,这涉及数学上尚未解决的难题,所以时间复杂度比较难分析。当n在某个特定的范围时,希尔排序的时间复杂度约为O(n^1.3)。 在最坏情况下希尔排序的时间复杂度为O(n^2)。
算法不稳定。

最后写个main方法验证下

public static void main(String[] args) {
        int[] arr=new int[]{-1998857732,995773975,986263711,970050582,978672815,946770900,884642435,885254231,830140516,917959651,768122842,937296273,546931356,861262547,764532283,965184299,918973856,915272981,830623614,728999048,693597252,631219735,884688278,984427390,714012242,537616843,536343860,521612397,659978110,445747969,433183457,641532230,480363996,586696306,31693639,805374069,303753633,215386675,261627544,604354651,733048764,393354006,631784130,241316335,427529125,111935818,698504118,109686701,64838842,353487181,82447697,177571868,691252458,230964510,453463919,340316511,280992325,13701823,77481420,544069623,544526209,193715454,157540946,427514727,292446044,782703840,219297819,151485185,256184773,570872277,695760794,738644784,784607555,433518449,440403918,281397572,493886311,970466103,738026287,819959858,119093579,411203381,306242389,84356804,42607214,462370265,294497342,70309112,158982405,513023688,740856884,784337461,17092337,633020080,387052570,421701576,298738196,54807658,472147510,169670404};
        
        int[] arr2=new int[]{-1,5,4,3,2,1};
        //直接插入排序
//        InsertSort(arr,arr.length-1);
        //折半插入排序
//        InsertSort2(arr,arr.length-1);
        //希尔排序
        ShellSort(arr,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
}

注意arr[0]为暂存元素,不算最终排序,所以数组长度应为arr.length-1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值