插入排序思考

改进插入如排序

  1. 普通插入排序
  2. 使用二分查找实现插入排序
  3. 希尔排序

工具类

ArrayUtils

import java.util.Random;

public class ArrayUtils {

    /**
     * 随机生成数组
     * @param min 最小值
     * @param max 最大值
     * @param number 数组的长度
     * @return T[]
     */
    public static Integer[] generateIntegerArray(int min,int max,int number){
        Random random = new Random();
        Integer[] array = new Integer[number];
        for(int i=0;i<number;i++){
            array[i]=min+random.nextInt(max-min+1);
        }
        return array;
    }

}

主类

InsertionSort


/**
    插入排序的几种形式(由小到大对元素进行排序)
 */
public class InsertionSort<T extends Comparable<T>> {
    //待排序数组
    T []array;

    public InsertionSort(T []array){
        this.array = array;
    }

    /**
     * 基本判断操作,所有排序函数均使用
     * @return
     */
    private boolean directReturn(){
        if(array == null||array.length == 0)return true;
        if(array.length == 1)return true;
        return false;
    }
    /**
     * 判断排序后的数组是否是升序
     * @return
     */
    public boolean isAscending(){
        for (int i=0;i<array.length-1;i++){
            if(array[i].compareTo(array[i+1])>0){
                System.out.println("error..........");
                System.out.println("出错位置为:"+i+"和"+(i+1));
                return false;
            }
        }
        System.out.println("success...............");
        return true;
    }

    /**
     * 最原始的插入排序
     * @return 排序后的数组
     */
    public T [] commonSort(){
        /*
            从第二个元素开始,遍历数组,每次取出一个元素,记为array[i]
                确定array[i]的插入位置j
                    从i位置依次向前遍历数组的有序区,如果后面的元素比前面小,当前元素位置前移
                将array[i]插入到j位置

         */
        if(this.directReturn())return this.array;

        for(int i=1;i<array.length;i++){

            T temp=array[i];
            int j=i;
            for(;j-1>=0&&temp.compareTo(array[j-1])<0;j--){
                array[j]=array[j-1];
            }
            //待插入的位置即是j
            array[j]=temp;
        }
        return array;
    }
    /**
     * 将二分搜索的思想运用到排序当中,因为数组前半部分是有序数组
     * @return
     */
    public T[]binarySort(){
        /*
            从第二个元素开始,遍历数组,每次取出一个元素,记为array[i]
                确定array[i]的插入位置index
                    在[0,i]位置使用二分搜索的方式查找插入位置(找到大于array[i]的最小值的位置即是待插入的位置)
                    从index到i之间的元素统一向后移一位
                将array[i]插入到index位置

         */
        if(this.directReturn())return this.array;

        for(int i=1;i<array.length;i++){

            T temp=array[i];
            int index=this.binarySearch(array,i,temp);
            if(index!=-1){
                for(int j=i;j-1>=index;j--){
                    array[j]=array[j-1];
                }
            }else{
                throw new RuntimeException("error, can't find the correct disposition");
            }
            array[index]=temp;
        }
        return array;
    }

    /**
     * 在array中找到大于或等于target的最小值的位置,并且返回;理论值为[0,right]
     */
    private int binarySearch(T[]array,int right,T target){
        int l=0;
        int r=right;
        
        while(l<r){
            int mid=l+(r-l)/2;
            if(array[mid].compareTo(target)==0)return mid;
            if(array[mid].compareTo(target)<0)l=mid+1;
            if(array[mid].compareTo(target) >0)r=mid;
        }
        return l;
    }

    /**
     * 进一步改进插入排序,实现希尔排序,调整步长
     */
    public T []shellSort(){
        /*
            分区间进行比较
                分组量packageNumber=array.length/2
                对每一个分组进行插入排序
                例如分成5组,每组4个数
                   则0,4,8,12一组
                    1,5,9,13一组
                    2,6,10,14一组
         */

        if(this.directReturn())return this.array;
        int packageNumber=array.length/2;
        while(packageNumber>0){
            //每一组起始位置为i,步长为packageLength
            //即将插入排序当中的加1改为加packageLength
            for(int i=0;i<packageNumber;i++){

                for(int j=i+packageNumber;j<array.length;j+=packageNumber){
                    //确定待插入的位置index
                    int index=j;
                    T temp=array[index];
                    for(;index-packageNumber>=i&&temp.compareTo(array[index-packageNumber])<0;index-=packageNumber){
                        array[index]=array[index-packageNumber];
                    }
                    array[index]=temp;
                }
            }
            packageNumber/=2;
        }
        return array;
    }
}

测试类

Test

import java.util.Arrays;

public class Test {

    public static void main(String[] args) {

        int min=1;
        int max=Integer.MAX_VALUE;
        int number=100_000;
        Integer[] integerArray = ArrayUtils.generateIntegerArray(min, max, number);
        InsertionSort<Integer> array = new InsertionSort<>(Arrays.copyOf(integerArray,integerArray.length));
        InsertionSort<Integer> array1 = new InsertionSort<>(Arrays.copyOf(integerArray,integerArray.length));
        InsertionSort<Integer> array2 = new InsertionSort<>(Arrays.copyOf(integerArray,integerArray.length));
        /*
            测试普通方法
         */
        //统计运行时间(单位为s)
        long start=0;
        long end=0;

        System.out.println("测试普通方法");
        start = System.currentTimeMillis();
        array.commonSort();
        end = System.currentTimeMillis();
        array.isAscending();
        System.out.println("数据量:"+number);
        System.out.println("排序时间为:"+(end-start)/1000.0+"s");

        /*
        测试使用二分查找改进的方法
         */
        //统计运行时间(单位为s)
        System.out.println("测试使用二分查找改进的方法");
        start = System.currentTimeMillis();
        array1.binarySort();
        end = System.currentTimeMillis();
        array1.isAscending();
        System.out.println("数据量:"+number);
        System.out.println("排序时间为:"+(end-start)/1000.0+"s");

        /*
        测试希尔排序
         */
        //统计运行时间(单位为s)
        System.out.println("测试希尔排序");
        start = System.currentTimeMillis();
        array2.shellSort();
        end = System.currentTimeMillis();
        array2.isAscending();
        System.out.println("数据量:"+number);
        System.out.println("排序时间为:"+(end-start)/1000.0+"s");
    }
}

测试结果

数据量为10000级别
在这里插入图片描述
数据量为100000级别
请添加图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值