希尔排序
希尔排序
基本思想
希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。
实现步骤
-
先将数组分为n/2组对每一组进行简单的插入排序
-
再将数组分为n/2/2组,对每一组进行简单的插入排序
-
同上……
-
直到只剩余一组时,执行最后一次排序,算法终止
注意:分组是,每组的元素不是连续的,第一组是以n/2为步长分组,其余的以此类推,不断除以2,直至为1进行最后一次排序
分类:希尔排序分为两种,交换法(不推荐),移位法(更优)
建议:先看懂插入排序再看希尔排序,
代码实现
//移位式希尔排序
public static int[] sortRemove(int[] arr){
int n=arr.length/2;
while(n>=1){
for(int i=n;i< arr.length;i++){//起始为每组的第二个数
int index=i-n;//待插入下标,初始值为前部分有序列表的最后一个值
int insertValue=arr[i];//待插入值
while(index>=0 && insertValue<arr[index]){//找出待插入值的位置
arr[index+n]=arr[index];
index-=n;
}
arr[index+n]=insertValue;//index+n是由于上面循环的最后index-n;
}
n/=2;
}
return arr;
}
//交换式希尔排序
public static int[] sortXi(int[] arr){
int n=arr.length/2;
while(n>=1){
for(int i=n;i< arr.length;i++){//起始为每组的第二个数
for(int j=i-n;j>=0;j-=n){//起始为每组的第一个数;内部实现类似于选择排序,将最小的数不断向前放,但全都遍历
if(arr[j]>arr[j+n]){
arr[j]=arr[j]^arr[j+n];
arr[j+n]=arr[j+n]^arr[j];
arr[j]=arr[j]^arr[j+n];
}
}
}
n/=2;
}
return arr;
}
复杂度与稳定性
稳定性:若数组中出现重复元素,若排序后重复元素还按照源数组中的先后顺序排列,则称之为稳定,否则为不稳定
in-place:不占用额外内存
n:数据规模
排序算法 | 平均时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 | 排序方式 | 稳定性 |
---|---|---|---|---|---|---|
希尔排序 | O(n log n) | O(n log^2 n) | O(n log^2 n) | O(1) | in-place | 稳定 |