1 实现原理和步骤
采用插入排序对arr这个数组进行排列,假如位置为0到10000的按照升序排好,将待插入数值a[10001]与a[10000]进行比较,如果a[10001]大于a[10000]时,则将带插入数据的位置为10001,即位置为0到10001已经排好序了。以此类推即可完成整个插入排序。问题来了,如果a[10001]的数值特别小呢?就可能要将这个数值从位置10000移动到位置0,大大提高算法的复杂度,因此插入排序在的时间复杂度仍为O(n^2)。
希尔排序基于插入排序并对上面提到的问题进行改良,大约需要O(n*(log n)^2)时间。原理是先把插入的间隔设为a.length/2, 再不断缩小直到为1,即为普通插入排序,减少小数值出现在右边的概率。
2 完整代码
public class ShellSort {
/**
* 希尔排序
* 基于插入排序进行改良
* @param arr
*/
public static void shellSort(int[] arr) {
int gap, temp, i, j;
for (gap = arr.length / 2; gap > 0; gap /= 2) { // 间隔不断缩小
for (i = gap; i < arr.length; i++) {
for (j = i - gap; j >= 0 && arr[j] > arr[j + gap]; j -= gap) { // 插入排序,当gap=1时,就是一个普通的插入排序
temp = arr[j];
arr[j] = arr[j + gap];
arr[j + gap] = temp;
}
}
// System.out.print("以间距为" + gap + "进行插入排序,结果为: " + Arrays.toString(arr));
System.out.print("以间距为" + gap + "进行插入排序,结果为: " );
display(arr);
}
}
/**
* 打印结果
*/
public static void display(int[] arr) {
StringBuilder str = new StringBuilder(); // 字符串拼接
str.append("[");
for (int i : arr) {
str.append(i + ", ");
}
str.replace(str.length() - 2, str.length() - 1, "]"); // 不包含起始值
System.out.println(str.toString());
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
// 初始化数组
int[] arr = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
// 希尔排序
shellSort(arr);
}
}
3 输出结果
4 参考文献
[1] Robert, Lafore., Java数据结构和算法.第2版 版. 2004: 中国电力出版社.[2] Sedgewick Robert与Wayne Kevin., 算法. 2012: 人民邮电出版社.