改进插入如排序
- 普通插入排序
- 使用二分查找实现插入排序
- 希尔排序
工具类
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级别