1.简介
希尔排序(Shellsort),也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
- 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率
- 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位
希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。
2.java代码
public static void main(String[] args) {
int[] numArray = {7,6,9,3,1};
System.out.println(arrayToString(numArray));
shellSort(numArray);
}
/**
* <一句话功能简述> 将比较的全部元素分为多组,注意每组之间的元素都有一个固定的步长(分组数),分别对每组元素
* 进行排序逐渐缩小分组数,并对每个分组进行排序,直至为1,最后就全部排好序了;之所以分组,是为了解决元素过多
* 时,插入排序每次向前移动速度过慢的问题
* author: zhanggw
* 创建时间: 2022/10/15
*/
private static void shellSort(int[] numArray) {
if(numArray.length < 2){
return;
}
// 第一次分为numArray.length/2组,步长也是numArray.length/2,每次缩减为原来的一半
for(int group=numArray.length/2; group>0;){
groupSort(numArray, group);
group /= 2;
}
}
// 希尔排序对分组后的每组进行排序
private static void groupSort(int[] numArray, int group) {
// 对分组后的每一组元素进行排序
for(int i=0; i<group; i++){
insertSortInner(numArray, group, i);
}
}
// 希尔排序内部使用的插入排序
private static void insertSortInner(int[] numArray, int group, int groupIndex) {
System.out.println("开始排序,分组数:" + group + ",开始第" + (groupIndex+1) + "组排序");
// 插入排序,注意步长
for(int i=groupIndex+group; i<numArray.length;){
for(int k=i; k>=0;){
if(k - group < 0){
break;
}
if(numArray[k] < numArray[k-group]){
int tmp = numArray[k];
numArray[k] = numArray[k-group];
numArray[k-group] = tmp;
}else{
break;
}
k -= group;
}
i += group;
}
System.out.println("排序后:"+arrayToString(numArray));
}
执行结果:
7,6,9,3,1
开始排序,分组数:2,开始第1组排序
排序后:1,6,7,3,9
开始排序,分组数:2,开始第2组排序
排序后:1,3,7,6,9
开始排序,分组数:1,开始第1组排序
排序后:1,3,6,7,9