希尔排序使插入排序的一种,又称"缩小增量排序",是一种更加高效的插入排序
- 在学习插入排序的时候,如果前面的一组元素都排好序,如{2,3,5,6},后面一组未排序的元素为:{1,0},那么下一个待插入的元素为1,我们需要将1和前面排好序的元素依次进行交换位置,才能完成插入。
- 因此希尔排序是为了解决插入排序插入的数据比前面已排序的元素都小,需要前面元素逐个向后移动的问题。
- 核心:对若干个数据进行分组并实现插入排序,分组的长度由数组的长度确定,每次遍历分组长度都要除2,直到分组量比1小。
- 使用希尔排序,要确定一个分组的长度,这个长度取决于数组的长度
如上图,我们要把1插入前面有序的序列,需要逐个向前插入,原有的元素需要逐个向后移动,显然这样就很麻烦。
我们将元素进行分组,每次对一组进行排序,一次遍历之后,分组长就减小
在希尔排序中,分组长的确定公式:
//1.根据数组的长度,确定分组长度h的值
int h = 1;
while (h<arr.length/2){
h = h*2+1;
}
每一次遍历,分组长都要减小:
//减小h的值
h/=2; //直到小于1
代码实现:
public static void main(String[] args) {
int arr[] = new int[10];
System.out.println("排序前:");
for (int i = 0; i < arr.length; i++) {
arr[i] = new Random().nextInt(10);
System.out.print(arr[i]+"\t");
}
System.out.println("\n排序后:");
//1.根据数组的长度,确定分组长度h的值
int h = 1;
while (h < arr.length/2){
h = h * 2 + 1;
}
//2.进行希尔排序
while (h >= 1){
//排序
//先找到待插入的元素
for (int i = h; i < arr.length; i++) {
//把待插入的元素插入到有序数列中
for (int j = i; j >= h ; j-=h) { //每一组进行插入排序
if(arr[j]<arr[j-h]){
int temp = arr[j];
arr[j] = arr[j-h];
arr[j-h] = temp;
}
else{
break;
}
}
}
//减小h的值
h/=2;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+"\t");
}
}
运行结果: