图解希尔排序的交换法和移位法
②从每组的第二个元素开始,依次和前面的所有元素比较大小, 和下标为0的元素同组的第二个元素的下标为0+增量(这里用gap表示),所以从gap开始:
③这里第一组的元素分别为8和3,不满足顺序,进行交换,然后gap后移,直到遍历完所有元素,此时每个组内的元素有序:
④缩小增量为原来的一半,5/2=2,重新进行分组:
⑤重复②③步骤,使每个组内的元素有序:
⑥再次缩小增量为原来的一半,2/2=1,重新分组,此时所有的元素都在一个组内
⑦从第二个元素开始依次和前面的元素比较,不满足顺序则交换,当所有元素交换完后,即排序完成,如下图:
代码实现:
public static int[] transShellSort(int[] arr) {int tmp = 0;int len = arr.length;//增量从数组长度/2开始,之后每次都/2,只要得到的增量大于0,就一直循环for (int gap = len / 2; gap > 0; gap /= 2) {//从每组的第二个元素开始,依次和前面的所有元素比较大小,// 和下标为0的元素同组的第二个元素的下标为0+gap,所以从gap开始for (int i = gap; i < arr.length; i++) {//j从i的前一个元素开始,直到遍历i前面的所有同组元素for (int j = i - gap; j >= 0; j -= gap) {//这里虽然定义j=i-gap,但这只是初始j的值,当j-=gap后这个等式便不再成立,// 所以交换时不能直接将arr[j]和arr[i]的值交换if (arr[j] > arr[j + gap]) {tmp = arr[j];arr[j] = arr[j + gap];arr[j + gap] = tmp;}}}}return arr;}
和交换法相比,移位法是对每个组直接进行插入排序。还是采用上面那组元素:
我们以增量缩小为2时举例,此时所有元素分为两组,分别为[3,1,0,9,7] 和 [5,6,8,4,2]
分别对两组元素直接进行插入排序,具体流程可以看《》中关于插入排序的讲解。
同样,当所有的元素分到一个组,即增量为1时,进行排序后的结果就是最终的排序结果。
代码实现:
public static int[] moveShellSort(int[] arr) {int tmp = 0;int len = arr.length;for (int gap = len / 2; gap > 0; gap /= 2) {//从第gap个元素开始,逐个对其所在的组进行直接插入排序for (int i = gap; i < len; i++) {int j = i;//这里的tmp就相当于插入排序中的insertVal,而j-gap就相当于insertIndextmp = arr[j];//gap所在的组,前面的数如果大于待插入的数,那么表示没有找到插入位置,// 其中arr[j]和arr[j-gap]为同组相邻的两个数if (arr[j] < arr[j - gap]) {while (j - gap >= 0 && arr[j - gap] > tmp) {arr[j] = arr[j - gap];//下标前移量为步长j -= gap;}//当跳出while循环时,表示找到了插入位置//当j-gap小于0时,tmp的位置下标就是j-gap+gap=jarr[j] = tmp;}}}return arr;}
