排序——希尔排序
一、基本介绍
? 希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更加高效的版本,也称为缩小增量排序。
? 在排序过程中,把待排序数据按照一定增量分组,对每组数据使用直接插入排序算法进行排序;随着增量的减小,每组的数据越来越多;当增量减少为 1 时,整个数据被分为一组,算法终止,排序完成。
二、图解过程
对数组[ 8, 9, 1 , 7, 6 , 5 , 3 , 4 , 2 , 0 ] 从小到大排序过程如下:
初试时共有 10 个元素
第一次排序
初始步长设置为 10 / 2 = 5,分为 5 个组。即 [8 , 5],[9 , 3],[1 , 4],[7 , 2],[6 , 0],如下图所示,相同颜色为一组,然后同一组数据进行直接插入排序,排序后数组为[5 , 3 , 1 , 2 , 0 , 8 , 9 , 4 , 7 , 6]。
第二次排序
步长设置为 5 / 2 = 2,分为 2 个组。即[5 , 1 , 0 , 9 , 7],[3 , 2 , 8 , 4 , 6],如下图所示,相同颜色为一组,然后同一组数据进行直接插入排序,排序后为 [0 , 2 , 1 , 3 , 5 , 4 , 7 , 6 , 9 ,8]。
第三次排序
步长设置为 2 / 2 = 1,分为一个组,最后对着组数据进行插入排序即可获得最终排序完成的结果。
从以上分析可知,希尔排序的排序次数是当增量为 1 时结束。每一次分组之后在组内在此进行排序,直到最终排序完成。
三、代码实现
? 希尔排序实现排序时,对于每一组的数排序可以采用交换法,或者是移动法插入。因为交换法的效率并不高,所以下面代码仅展示移动法。
public static void shellSort(int[] arr) { if (arr == null || arr.length < 2) {//数组为空或者长度为1直接返回 return; } for (int gap = arr.length / 2; gap > 0; gap /= 2) {//初始步长(增量)为数组长度的一半 //创建一个循环,对每一个组的元素进行排序 for (int i = gap; i < arr.length; i++) { int j = i;//待插入位置的索引 int temp = arr[j];//临时保存待插入元素值 if (arr[j] < arr[j - gap]) {//如果当前元素的数小于其前一位的数,需要插入排序 while (j - gap >= 0 && temp < arr[j - gap]) {//循环移位找出插入该元素的位置 arr[j] = arr[j - gap];//移位 j -= gap; } arr[j] = temp;//插入元素 } } } }