算法如其名,肯定是某个优秀的学者Shell提出了这种排序算法;
1.定义
是简单插入排序的改进版,它与插入排序不同之处在于:希尔排序会优先比较距离较远的元素。
希尔排序又称缩小增量排序,是对直接插入排序的优化;
2.基本思想
该方法实质上是一种分组插入方法
比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换;
(1)算法先将要排序的一组数按某个增量d分成若干组;
(2)每组中记录的下标相差d.对每组中全部元素进行排序
(3)然后再用一个较小的增量对它进行,在每组中再进行排序
(4)当增量减到1时,整个要排序的数被分成一组,排序完成。
3.下面的栗子看过来
3.1确定增量step
有以下两种方法,任选一种即可
(1)step = array.length/3+1
(2)step = array.length/2
3.2step = 6/2 = 3时,如下图所示,将数据元素分成了三组
对第一组元素进行排序,5>3,即array[0]>array[0+step];将元素5放到array[3],元素1放到array[0]的位置;
对第二组元素进行排序,4>3,即array[1]>array[1+step];将元素4放到array[4],元素3放到array[1]的位置;
对第三组元素进行排序,6>2,即array[2]>array[2+step];将元素4放到array[5],元素2放到array[2]的位置;
3.3step = 3/2 = 1时,如下图所示,将数据元素分成了一组
当step = 1,即就是直接插入排序(在上一篇博客哦);
插入排序后的结果是:
4.算法代码实现
4.1希尔排序代码实现
public static void shellSort(int[] array){
if(array.length <= 1){
return;
}else{
int step = array.length;
while (true){
//step的两种规定
step = step/2;
//step = step/3+1
insertSortWithStep(array,step);
//step=1就是直接插入排序
if (step == 1){
break;
}
}
}
}
private static void insertSortWithStep(int[] array, int step) {
for(int i = step;i < array.length;i++){
int value = array[i];
int j = i-step;
for(;j >= 0 && array[j] > value;j-=step){
array[j+step] = array[j];
}
array[j+step] = value;
}
}
4.2测试一下
public static void main(String[] args) {
int[] a = {2,5,1,7,3,6,9};
int[] b = a.clone();
shellSort(b);
System.out.println(Arrays.toString(b));
//通过Arrays.sort进行验证排序结果
int[] c = a.clone();
Arrays.sort(c);
System.out.println(Arrays.toString(c));
System.out.println(Arrays.equals(b,c));
//testSpeed();
}
看看结果吧:
bingo,正确哦
4.3接下来我们测一下速度
还是100000个数据
public static void testSpeed(){
Random random = new Random(20191019);
int[] a = new int[100000];
for (int i = 0;i < 100000;i++){
a[i] = random.nextInt(200000);
}
long begin = System.nanoTime();
shellSort(a);
long end = System.nanoTime();
double ms = (end-begin)/1000/1000;
System.out.printf("一共耗时:%.5f 毫秒%n",ms);
}
这次只用了49毫秒诶,比直接插入排序还厉害;
5.源代码
package sort.insertSort;
import java.util.Arrays;
import java.util.Random;
/**
* @Author:Star
* @Date:Created in 9:30 2019/10/19
* @Description:希尔排序算法
* 时间复杂度:最好:O(n)平均:O(n^1.3)最坏:O(n^2)
* 空间复杂度:O(1)(原地排序)
* 稳定性:不稳定(因为两个相同的数难以保证分到一个组里面去比较)
*/
public class ShellSort {
public static void shellSort(int[] array){
if(array.length <= 1){
return;
}else{
int step = array.length;
while (true){
//step的两种规定
step = step/2;
//step = step/3+1
insertSortWithStep(array,step);
//step=1就是直接插入排序
if (step == 1){
break;
}
}
}
}
private static void insertSortWithStep(int[] array, int step) {
for(int i = step;i < array.length;i++){
int value = array[i];
int j = i-step;
for(;j >= 0 && array[j] > value;j-=step){
array[j+step] = array[j];
}
array[j+step] = value;
}
}
public static void testSpeed(){
Random random = new Random(20191019);
int[] a = new int[100000];
for (int i = 0;i < 100000;i++){
a[i] = random.nextInt(200000);
}
long begin = System.nanoTime();
shellSort(a);
long end = System.nanoTime();
double ms = (end-begin)/1000/1000;
System.out.printf("一共耗时:%.5f 毫秒%n",ms);
}
public static void main(String[] args) {
// int[] a = {2,5,1,7,3,6,9};
//
// int[] b = a.clone();
// shellSort(b);
// System.out.println(Arrays.toString(b));
//
// //通过Arrays.sort进行验证排序结果
// int[] c = a.clone();
// Arrays.sort(c);
// System.out.println(Arrays.toString(c));
//
// System.out.println(Arrays.equals(b,c));
testSpeed();
}
}
期待留言和分享哦,哈哈哈
一起学习,一起进步哦