希尔排序
希尔排序也是一种插入排序,不过,它在进行比较和交换位置的时候,不是相邻元素之间的比较,而是具有一定的间隔之间的元素进行比较。这个间隔是多少呢?一般刚开始排序的时候,是数组长度的1/2. 比如有一个长度是13的数组,那么间隔是13/2,就是6. 比较的时候,由于是插入排序,它是间隔索引后面的元素和间隔索引前面的元素进行比较,索引6处的元素与索引0处的元素进行比较,索引7处的元素和索引1处的元素进行比较,索引8处的元素和索引2处元素地进行比较,索引9处的元素和索引3处元素地进行比较,索引10处的元素和索引4处元素地进行比较,索引11处的元素和索引5处元素地进行比较,索引12处的元素和索引6处元素地进行比较,由于索引6和索引0是一个间隔,所以索引12和索引6的元素比较完了以后,还要和索引0处的元素进行比较。相同间隔的元素进行比较,[0, 6, 12]进行比较,[1, 7]进行比较,还有[2, 8], [3, 9], [4, 10], [5, 11], 也可以说,间隔把数组分了子数组,在子数组中进行插入排序。
在各个子数组中,执行比较和位置交换
执行完一轮排序后,第二次进行排序时,间隔是数组的长度/4, 也就是13/4, 等于3,这也就意味着,索引3和索引0进行比较,索引4和索引1进行比较,索引5和索引2,索引6和索引3,然后再和索引0,依次类推
在相应的子数组中实现比较和和位置交换
再进行一次,间隔是数组的长度/8,也就是13/8,等于1,间隔是1,也就没有必要再分子数组了,直接对整个数组来一次插入排序。如要数组的长度是N,那么问隔的选取依次是N/2, N/4, N/8 .... 直到1,每一次都是原来的1/2.
对于希尔排序来说,首先是间隔的循环,假设数组的长度为N
for(int interval = N/2; interval > 0; interval /=2){}
获取到间隔后,间隔后的元素要和间隔前的元素进行比较,假设数组是arr, 那就arr[interval], arr[interval +1], arr[interval + 2], 从inteval开始,依次取出数组的元素,这又是一个循环
// 从interval 开始,依次取出数组中的元素 for (int i = interval; i < n ; i++) { int temp = arr[i]; }
获取到元素后,要和 i - interval处的元素进行比较,像[0, 6, 12], 6处的元素和0进行比较,正好相差inteval。但就像[0, 6, 12]一样,索引12处的元素要和索引6处的元素进行比较,还要和索引0处元素进行比较,相当于i-和i - interval, 再和 i - interval- interval, 如果在比较程中有不符合排序顺序,就交换位置。这也是一个循环,把i赋值为j,以interval进行递减,结束条件是j>= interval, 因为j -interval 要大于0,数组元素的索引要大于0.
int j; // 取出的元素和前面interval处的元素进行比较 for (j = i; j >= interval && (arr[j - interval] > temp); j -= interval) { // 如果前面的数比后面的大,前面的数赋值给后面的数 arr[j] = arr[j - interval]; } // 循环完毕后,如果位置有移动,j的位置就是temp的位置 arr[j] = temp;
整个排序如下
import java.util.Arrays; class ArraySort { public static void shellSort(int[] arr, int n) { for (int interval = n / 2; interval > 0; interval /= 2) { // 从interval 开始递增,循环 for (int i = interval; i < n; i++) { // 依次取出数组中的元素 int temp = arr[i]; int j; // 取出的元素和前面interval处的元素进行比较 for (j = i; j >= interval && (arr[j - interval] > temp); j -= interval) { // 如果前面的数比后面的大,前面的数赋值给后面的数 arr[j] = arr[j - interval]; } // 循环完毕后,如果位置有移动,j的位置就是temp的位置 arr[j] = temp; } } } public static void main(String[] args) { int[] arr = {10, 16, 11, 4, 15, 3, 9, 6, 1, 17, 8, 12, 7}; shellSort(arr, arr.length); System.out.println(Arrays.toString(arr)); } }