概述
问题: 原来插入排序的问题
如果最后一个数是最小的数, 需要后移的次数增多, 对效率有影响
解决: 希尔排序 / 缩小增量排序
代码实现
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class insertSortPlus {
//static int[] arr = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
//static int[] arr = {8, 3, 2, 1, 7, 4, 6, 5};
static int[] arr = new int[80000];
public static void main(String[] args) {
for (int i = 0; i < 80000; i++) {
arr[i] = (int) (Math.random() * 8000000); // 生成一个[0, 8000000) 数
}
System.out.println("排序前");
Date data1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("ss");
String date1Str = simpleDateFormat.format(data1);
System.out.println("排序前的时间是=" + date1Str);
/*
int gap = arr.length / 2; // 折半
while (gap >= 1){ // 判断偏移量
for (int t = 0; t < gap; t++) {
//由于单独传入gap 只是规定了一组的偏移量, 通过传入 t 表示由于折半分组对每组都进行排序
//例如: gap = 10; 第一次折半 分成 5 = 5 gap 组, 而且偏移量 也是 5 = 5 gap,
// t < 5 则对 0 到 4 这五组进行偏移量为 5 的排序
sort2(gap, t);
}
gap = gap / 2;
}
*/
int gap = arr.length / 2;
while (gap >= 1){
sort(gap);
gap = gap / 2;
}
Date data2 = new Date();
String date2Str = simpleDateFormat.format(data2);
System.out.println("排序前的时间是=" + date2Str);
/*
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
*/
}
//插入法.
public static void sort(int n){
int insertVal = 0;
int insertIndex = 0;
//使用for循环来把代码简化
for(int i = n; i < arr.length; i = i + n) {
//定义待插入的数
insertVal = arr[i];
insertIndex = i - n;
while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
arr[insertIndex + n] = arr[insertIndex];
insertIndex = insertIndex - n;
}
// 当退出while循环时,说明插入的位置找到, insertIndex + n
if(insertIndex + n != i) {
arr[insertIndex + n] = insertVal;
}
//System.out.println("第"+i+"轮插入");
//System.out.println(Arrays.toString(arr));
}
}
//交换法
public static void sort2(int n, int t){ // n为偏移量, t代表第几组,
// t 为几刚好对应第几组的开头所在的下标
int j;
int temp;
// n + t 代表 偏移量 + 第几组的开头;
// i + t + n 中 (i + n)代表每次要比较的值在上个值的位置, 加 t 代表标明是第几组的偏移
// 采用从后往前比较方式
for (int i = n + t; i < arr.length; i = i + t + n) {
j = i - n; // 和原来插入排序思想一样, 插入的数据的下一位数据下标相差为他们的偏移量 -> i - j = n;
if (arr[i] < arr[j]){// 判断插入数据和前一个数据是否相同
// 交换
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
while (j > n){ // 如果 j - n > 0 说明目前下标的前一个数据还没到数组头, 可以继续和前一个数据比较
if (arr[j - n] > arr[j]){
temp = arr[j-n];
arr[j-n] = arr[j];
arr[j] = temp;
j = j - n;
}else break;
}
}
/*for (int k = 0; k < arr.length; k++) {
System.out.print(arr[k]);
}*/
}
//System.out.println(arr[arr.length-1]);
}
}