排序算法–希尔排序
一、学习资料:
一、希尔排序法介绍
希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序。
二、希尔排序法基本思想
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止
三、示例图:
四、代码
4.1、 希尔排序一(分组冒泡)
/**
* 希尔排序
* 根据步长的分组冒泡排序
*
* 100000个随机数花费时间(三次测试):34941ms 30509ms 31519ms
* 平均时间:32323ms
* @param arr
*/
public static void shellSort1(int[] arr) {
//遍历步长,每遍历一轮步长除2,直到小于等于0跳出循环
for (int d = arr.length/2;d>0;d/=2){
//遍历每个元素
for (int i = d;i<arr.length;i++){
//遍历本步长组中的元素
for (int j=i-d;j>=0;j-=d ){
//将当前元素与加上步长的元素比对
//如果当前元素大就交换位置
if (arr[j]>arr[j+d]){
//交换位置
int temp = arr[j];
arr[j] = arr[j+d];
arr[j+d] = temp;
}
}
}
}
}
4.2、希尔排序二(分组插入优化)
/**
* 希尔排序优化
* 根据步长的分组插入排序
* 此方法加入了同组插入优化,不需要每次都是同组冒泡排序
* 100000个随机数花费时间(三次测试):31ms 40ms 35ms
* 平均时间:35ms
* @num
*/
public static void shellSort2(int[] num){
//获取num数组的长度
int length=num.length;
//遍历步长
for(int d=length/2;d>0;d/=2){
//分组比较
for(int i=d;i<length;i++){
//获取当前的下标
int j=i;
//获取当前值
int temp=num[j];
//同组中如果这个数前面还有数并且比这个数小说明还没有找到位置
//此时将同组中这个数后移步长d位,直到找到要插入的位置
while(j-d>=0&&temp<num[j-d]){
//同组这个数向后移
num[j]=num[j-d];
//再向前搜索
j-=d;
}
//循环完后就可以得到插入的位置了(并且要移动了才有插入操作)
if(j!=i){
num[j]=temp;
}
}
}
}
4.3、测试代码
package com.lxf.sort;
import java.util.Arrays;
import java.util.Random;
public class XiErSort {
public static void main(String[] args) {
//测试
//获取一个数字字符串
StringBuilder stringBuilder = new StringBuilder();
Random random = new Random();
for (int i = 0; i < 100000; i++) {
stringBuilder.append(random.nextInt(500)+",");
}
//去掉最后一个,
stringBuilder.setLength(stringBuilder.length()-1);
//获取整数数组
String[] splits= stringBuilder.toString().split(",");
int[] nums = Arrays.stream(splits).mapToInt(Integer::valueOf).toArray();
//获取开始时间
long start = System.currentTimeMillis();
System.out.println("start = " + start);
//希尔排序
//shellSort1(nums);
shellSort2(nums);
//获取执行完的时间
long end = System.currentTimeMillis();
System.out.println("end = " + end);
//计算执行时间
long sub=end-start;
System.out.println("花费时间="+sub);
}
}