1、希尔排序是对直接插入排序的改进,加入了分组的思想,分完组后进行直接插入排序。分组依据是增量gap,初始值是数组长度/2, 增量变化:gap/=2。gap也可以代表组数。
2、编程思路:嵌套3个循环,第一循环控制分组次数,第二个循环从下标为gap的元素开始循环,依次扫描数组,通过下标j=i-gap可以找到对应分组的元素。
3、直接插入排序的代码可以对比着插入排序法改写
for (int gap = arr.length/2; gap > 0 ; gap /= 2) { //gap既代表增量,又代表组数
for (int i = gap; i < arr.length; i++) {//arr[i]经过以下代码插入到arr[i]所属分组的有序子表中
//记录要进行插入的元素和它的下标
int j = i - gap;//插入的位置
int temp = arr[i];//待插入的元素
if(temp < arr[j]){
while(j >= 0 && temp < arr[j]){ //j >= 0是为了防止数组越界
arr[j + gap] = arr[j];//arr[j]后移
j -= gap;//j以gap为间隔不断向左移动
}
}
//程序执行到此说明找到插入的位置
arr[j+gap] = temp;
}
}
public class shellSort {
public static void main(String[] args) {
int[] arr = new int[80000];
for (int i = 0; i < 80000; i++) {
arr[i] = (int)(Math.random()*80000);
}
Date date1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1Str = simpleDateFormat.format(date1);
System.out.println(date1Str);
shellSort(arr);//大约10s
// shellSort2(arr);//大约0s
Date date2 = new Date();
String date2Str = simpleDateFormat.format(date2);
System.out.println(date2Str);
// System.out.println(Arrays.toString(arr));
}
//交换式希尔排序
private static void shellSort(int[] arr){//交换式希尔排序,分组后的冒泡排序,从后往前冒泡
for (int gap = arr.length/2; gap > 0 ; gap /= 2) {//控制分组次数
for (int i = gap; i < arr.length ; i++) {//arr[i]与它前面同一分组的元素进行冒泡排序,从后向前冒泡,把小的往前交换
for (int j = i - gap; j >= 0 ; j -= gap) {//j指向arr[i]前面统一分组的元素
if(arr[j+gap] < arr[j] ){//arr[j+gap] 与 arr[j]进行交换
int temp = arr[j];
arr[j] = arr[j+gap];
arr[j+gap] = temp;
}
}
}
}
}
//移动式希尔排序
private static void shellSort2(int[] arr){//移动式希尔排序,分组后,再用直接插入排序法
for (int gap = arr.length/2; gap > 0 ; gap /= 2) { //gap既代表增量,又代表组数
for (int i = gap; i < arr.length; i++) {//arr[i]经过以下代码插入到arr[i]所属分组的有序子表中
//记录要进行插入的元素和它的下标
int j = i - gap;//插入的位置
int temp = arr[i];//待插入的元素
if(temp < arr[j]){
while(j >= 0 && temp < arr[j]){ //j >= 0是为了防止数组越界
arr[j + gap] = arr[j];//arr[j]后移
j -= gap;//j以gap为间隔不断向左移动
}
}
//程序执行到此说明找到插入的位置
arr[j+gap] = temp;
}
}
}
}