先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。该方法实质上是一种分组插入方法。
2、图示
3、Java代码实现
package com.leiht.sort; /** * 希尔排序算法简单实现 * @author Leiht * */ public class ShellSort { public static void main(String[] args) { int[] numbers = { 56, 45, 78, 67, 99, 13, 34, 49, 55, 34, 12, 77, 1 }; System.out.println("排序之前:"); for (int i = 0; i < numbers.length; i++) { System.out.print(numbers[i] + " "); } //执行排序算法 new ShellSort().sort(numbers); System.out.println(); System.out.println("排序之后:"); for (int i = 0; i < numbers.length; i++) { System.out.print(numbers[i] + " "); } } /** * 排序方法 * * @param numbers */ public void sort(int[] numbers) { //定义分组1 d2 d3 ....dn dn= numbers.length / 2; //目前效率较高的d的定义为 1,3 ,5. ... 2的K次方-1 int d = numbers.length / 2; while (true) { //每次 d = d /2 d = d / 2; //第一次循环次数为0到d 代表总共分组的组数(一共有多少组) for (int index = 0; index < d;index++) { //循环第一组,增量为d,即【第i个,i+d, i+2d, i+3d....】为一组 //并按照直接插入排序对第一组进行排序,直到d=1,即对其完成直接排序 for (int i = index + d; i < numbers.length; i = i + d) { int temp = numbers[i]; int j; //循环从当前数据的前一个开始(如大于当前数据则向后移动一位即if(numbers[j] > temp) numbers[j + d] = numbers[j];) //到有小于或等于当前数据止,跳出循环,将当前数据放到该位置即numbers[j + d] = temp; for (j = i - d; j >= 0; j = j - d) { if(numbers[j] > temp) { numbers[j + d] = numbers[j]; }else { break; } } numbers[j + d] = temp; } } if (d == 1) { break; } } } }
4、分析
前面分析过插入排序是稳定的,但经过多次插入排序后相同的元素的位置已经发生移动,最后稳定性会被打乱,所以希尔排序算法的实现是不稳定的。