希尔排序法。Java实现希尔排序
前言基础:
1、因为希尔排序法的步长选取不是固定的,不同的步长会对应不同的复杂度,但是综合起来希尔排序法的时间复杂度是在O(nlogn)~O(n2)之间,近似为O(n的1.3次幂)。空间复杂度为O(1)是一种不稳定的排序算法。
2、希尔排序法最适合用于数据量不是特别大,而且数据近乎有序的数组。因为希尔排序法可以说是插入排序法的一个改进版。
3、当数据量不是很大(近乎一百万以内时)希尔排序法的排序效率还会率高于时间复杂度为O(nlogn)的快排和归并排序法。
排序原理
由于插入排序的的在数组近乎有序的情况下性能最佳,而且又借助冒泡排序每轮循环结束之后逆序对数就会减少使数组变得更加有序,因此出现了希尔排序法。 希尔排序法的核心就是每次让数组的有序程度变高。 冒泡排序每次只能交换两个相近的元素,即每次循环元素只能移动一个位置。如果有一个特别小的元素在数组的最后,就需要进行好多次循环才能将该小元素交换到数组的最前面。希尔排序就是要每次将数组进行分割成多个小数组,然后在分别对小数组进行插入排序
1、对于下面这个数组,起初以n/2为一个间隔分割数组,相同元素为一组,两两比较。
第一轮循环结束之后数组是这样的:
2、之后我们以n/4为间隔继续对数组进行划分比较:此时分为了两组
第二轮结束之后是这样的:保证了蓝色和棕色的数组都是分别有序的
3、第三轮以n/8进行比较,即n=1了,所以相当于对这种近乎有序的数组进行插入排序
代码实现:
希尔排序法内部的插入排序法写法就是将之前的j-1全部替换为j-间隔。
public class ShellSort { public ShellSort() { } public static <E extends Comparable<E>> void sort(E arr[]) { int interval = arr.length / 2; while (interval >= 1) { for (int i = 0; i < arr.length; i++) { E tmp = arr[i]; int j; for (j = i; j - interval >= 0 && tmp.compareTo(arr[j - interval]) < 0; j -= interval) { arr[j] = arr[j - interval]; } arr[j] = tmp; } interval /= 2; } } public static void main(String[] args) { Integer[] arr = Util.getRandomArr(); ShellSort.sort2(arr); Util.Traverse(arr); } }