排序算法——插入排序——希尔排序


发布于 2016-07-21 / 24 阅读 / 0 评论 /
希尔排序是时间复杂度最优的插入排序算法。

1.希尔排序的由来

希尔排序是直接插入排序的改良品种,尽管不是最快的,但是时间复杂度比O(N^2)要好。

希尔排序是Donald Shell在1959年设计的。

在直接插入排序中,元素的移动都是向后移动一位。如果一个结点与它正确的位置想差很远,则需要移动多次才能到达正确的位置上。这就造成了直接插入排序的高代价。

二分插入排序通过减少比较次数来提升排序效率。

希尔排序通过减少移动次数来提升排序效率。

2.希尔排序算法过程

希尔排序的想法是:先比较那些离得较远的元素,如果稍远的两个元素违反了次序,则进行交换。然后再比较那些离得较近的元素,两个元素的距离是一个递减序列。

算法过程如下:

(1)设计一个增量序列{h1, h2, ……, hn}

(2)对数组a进行间隔为hn的排序

a[0]、a[hn]、a[2hn]……为一组进行排序

a[1]、a[hn + 1]、a[2hn + 1]……为一组进行排序

……

a[hn - 1]、a[2hn - 1]、a[3hn - 1]……为一组进行排序

(3)依次对数组a进行间隔为hn到h1的排序。

(4)完成间隔为h1的排序后,最终得到一个有序数组。

代码如下所示:

    void shellSort(Comparable[] arr) {
        int j;
        for (int gap = arr.length / 2; gap >  0; gap /= 2) {
            for (int i = gap; i < arr.length; i++) {
                Comparable tmp = arr[i];
                for (j = i; j >= gap && tmp.compareTo(arr[j - gap]) < 0; j -= gap) {
                    arr[j] = arr[j - gap];
                }
                arr[j] = tmp;
            }
        }
    }

3.希尔排序性能

希尔排序的增量序列可有多种不同的取法,但是最后一个间隔必须为1,即h1 = 1。

D.E.Knuth利用大量实验统计资料得出:当待排序数组元素个数N很大时,元素的移动次数大约为N^1.25~1.6*N^1.25

4.希尔排序案例

例如以下数组,增量序列为{1,3,5},则排序过程如下图所示:

(1)间隔为5,分别对以下序列进行排序

(2)间隔为5,分别对以下序列进行排序

(3)间隔为1,对整个序列排序

排序完成