希尔排序算法分析实现
希尔排序分为希尔交换排序和希尔移位排序两种方式,其中希尔移位排序的方法会有更高的效率
以排序8个为例
算法思路是首先将数组元素个数/2(8/2=4)得到增量值4(若元素个数为奇数其实也不要紧,这里是向下取整,若是9个元素即9/2=4),定义两个指针,位置一个是在arr[0],一个是在arr[0+4],将这两个对应的元素看作一组进行内排序。随后这两个指针位置分别向后移一位,进行下一次的判断操作,直至后面的指针指向数组末尾。
然后将之前的到的增量值再除2,得到下一次的增量(2),同样的,将arr[0]与arr[0+2]分为一组,进行排序,排序后指针再次依次后移,直至数组末尾。
如果数组较大可能会进行多次改变增量的操作,最后直至增量为1时,即将数组从头到尾依次排序,得到了排好序的数组
交换法与移位法
两个方法的主要区别是在定义好需要排序的两元素之后对其进行排序的方式。
交换法类似于冒泡排序,利用一个中间变量储存前面的值,将两位置值调换,然后再把中间变量储存的值赋给后面的位置。
移位法主要在这个过程中使用了插入排序的方式,将后面的元素的值与前面的所有值依次比较,插入到合适的位置,插入排序本身就是比较高效的方法,配合希尔排序的分组操作,减少了需要判断的次数,大大提高了效率。
交换法代码
1 //希尔排序--交换法 2 public static void shellSort(int[] arr) { 3 int temp = 0; 4 for (int gap = arr.length / 2; gap > 0; gap /= 2) { 5 //第一轮排序将分成arr.length/2组 6 for (int i = gap; i < arr.length; i++) { 7 //遍历各组中所有的元素(共gap组,每组有2个元素),步长为gap 8 for (int j = i - gap; j >= 0; j -= gap) { 9 //如果当前元素大于加上步长后的哪个元素,说明交换 10 //此步骤并没有采用插入式排序的思想,因而会花费大量时间 11 if (arr[j] > arr[j + gap]) { 12 temp = arr[j]; 13 arr[j] = arr[j + gap]; 14 arr[j + gap] = temp; 15 } 16 } 17 } 18 } 19 }
移位法代码
1 //对交换式希尔排序进行优化->移位法 2 public static void optiShellSort(int[] arr) { 3 //设置增量gap,并逐步缩小增量 4 for (int gap = arr.length / 2; gap > 0; gap /= 2) { 5 //从第gap个元素,逐个对其所在的组进行直接插入排序 6 for (int i = gap; i < arr.length; i++) { 7 int j = i; 8 int temp = arr[j]; 9 while (j - gap >= 0 && temp < arr[j - gap]) { 10 arr[j] = arr[j - gap]; 11 j -= gap; 12 } 13 //退出while循环后,说明temp找到了插入位置 14 arr[j] = temp; 15 } 16 } 17 }