排序算法(四):希尔排序
一、排序原理
希尔排序是插入排序的一种,又称为‘缩小增量排序’,是插入排序算法的一种更高效的改进版本。
1. 选定一个增长量h,按照增长量h对数据进行分组。
2. 对分好的每一组数据完成插入排序。
3. 减少增长量,最小减为1,重复第二步操作。
增长量h的确定规则:增长量h的值为一固定的规则,我们采用以下规则:
int h = 1; while(h<数组的长度/2) { h = 2h+1; } //h的减小规则为: h = h/2;
二、代码实现
import java.util.Arrays; /** * 希尔排序 */ public class ShellSort { public static void main(String[] args) { Integer[] arr = {4, 5, 3, 9, 2, 1}; sort(arr); System.out.println(Arrays.asList(arr).toString()); } public static void sort(Comparable[] a) { /** * int h = 1; * while(h<数组的长度/2) { * h = 2h+1; * } * //h的减小规则为: * h = h/2; */ // 根据数组a的长度,确定增长量h的初始值 int h = 1; while (h < a.length / 2) { h = 2 * h + 1; } // 进行希尔排序 while (h >= 1) { // 找到待插入的元素,并把待插入的元素插入到有序数列中 for (int i = 0; i < a.length; i++) { for (int j = i; j > h; j -= h) { // 待插入的元素为a[j],比较a[j]和a[j-h] if (greater(a[j - h], a[j])) { // 交换元素 exch(a, j - h, j); } else { // 已经找到合适的位置 } } } // 减少h的值 h = h / 2; } for (int i = 0; i < a.length; i++) { for (int j = i; j > 0; j--) { // 比较索引j处的值和索引j-1处的值,如果j-1处的值比j处的值大,则交换。如果不大,则证明找到合适的位置了,退出本次循环 if (greater(a[j - 1], a[j])) { exch(a, j, j - 1); } else { break; } } } } private static boolean greater(Comparable i, Comparable j) { return i.compareTo(j) > 0; } public static void exch(Comparable[] a, int i, int j) { Comparable temp = a[i]; a[i] = a[j]; a[j] = temp; } }
运行结果:
[1, 2, 3, 4, 5, 9]
三、时间复杂度分析
1、希尔排序的优化点
希尔排序是插入排序的优化版本,利用的是插入排序的两个特点:
1).在大多数元素已经有序的情况下,插入排序的工作量较小
这个结论很明显,如果一个数组大部分元素都有序,那么数组中的元素自然不需要频繁地进行比较和交换。
2).在元素数量较少的情况下,插入排序的工作量较小
这个结论更加显而易见,插入排序的工作量和n的平方成正比,如果n比较小,那么排序的工作量自然要小得多。
2、希尔排序的时间复杂度
时间复杂度为:O(n^(1.3—2))
空间复杂度:O(1)
稳定性:不稳定

浙公网安备 33010602011771号