Java排序算法之希尔排序

来源:互联网 发布:cad软件下载什么版本 编辑:程序博客网 时间:2024/05/20 23:07

Java排序算法之希尔排序

希尔排序(Shell Sort)又称为“缩小增量排序”。是1959年由D.L.Shell提出来的。它也是一种属于插入排序类的排序方法,是一种对直接插入排序的改进,但在时间效率上却有较大的改进。

基本思想

希尔排序的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。
通俗来讲是首先将待排序的元素分为多个子序列,使得每个子序列的元素个数相对较少,对各个子序列分别进行直接插入排序,待整个待排序序列“基本有序”后,再对所有元素进行一次直接插入排序。
因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比直接插入方法有较大提高。

算法原理

 取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量d2 < d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。 理解该算法的关键是:该方法实质上是一种分组插入方法,但是分组并不是直接连起来的,而是以d1为间隔的间隔取值组成一个逻辑上的分组。
例如,当d[0]=6时,共分了6个小组,每个小组两个数据,在每个小组内按直接插入算法排序。

源码

package com.algorithm.sorting;/** * 希尔排序 *  * @author Administrator * */public class ShellSort {    public static void shell_sort(int array[]) {        System.out.print("要排序的数组:");        for (int a = 0; a < array.length; a++) {            System.out.print(array[a] + "\t");        }        System.out.println("");        int temp = 0;        int incre = array.length;        while (true) {            incre = incre / 2;//增量分子            for (int k = 0; k < incre; k++) { // 根据增量分为若干子序列                for (int i = k + incre; i < array.length; i += incre) {//将子序列中的数组元素排序。                    for (int j = i; j > k; j -= incre) {                        if (array[j] < array[j - incre]) {                            temp = array[j - incre];                            array[j - incre] = array[j];                            array[j] = temp;                        } else {                            break;                        }                    }                }                System.out.print("第" + (k + 1) + "次排序结果:");                for (int a = 0; a < array.length; a++) {                    System.out.print(array[a] + "\t");                }                System.out.println("");            }            if (incre == 1) {                break;            }        }        System.out.print("最终排序结果:");        for (int a = 0; a < array.length; a++) {            System.out.print(array[a] + "\t");        }    }    public static void main(String[] args) {        int array[] = { 100, 99, 53, -1, 33, 20 };        shell_sort(array);    }}

源码解析

源码结果

要排序的数组:100  99  53  -1  33  20  第1次排序结果:-1  99  53  100 33  20  ①第2次排序结果:-1  33  53  100 99  20  ②第3次排序结果:-1  33  20  100 99  53  ③第1次排序结果:-1  20  33  53  99  100 ④最终排序结果:-1   20  33  53  99  100 

从排序结果中可以看出,增量分子为3,将数组分为两部份,a[0]与a[3],a[1]与a[4],a[2]与a[5]进行增量插入排序,如①②③;最后再对所有元素进行一次直接插入排序如④。

效率分析

空间效率:仅使用一个辅存单元。
时间效率:从对直接插入排序的分析中知道,虽然直接插入排序的时间复杂度为O(n 2 ),但是在待排序元素序列有序时,其时间复杂度可提高至O(n)。由此可知在待排序元素基本有序时,直接插入排序的效率可以大大提高。从另一方面看,由于直接插入排序方法简单,则在n值较小时效率也较高。希尔排序正是从这两点出发,对直接插入排序进行改进而得到的一种排序方法。

总结

通过前面的分析,从直观上我们可以预见希尔排序的效率会较直接插入排序要高,然而对希尔排序的时间复杂度分析是一个复杂的问题,因为希尔排序的时间复杂度与增量序列的选取密切相关,如何选择增量序列才能使得希尔排序的时间复杂度达到最佳,这还是一个有待解决的问题。
写博客是为了帮助开发者学习使用技术,同时巩固自己所学技术。如果此篇博客有助于您的学习,那是我的荣幸!如果此篇博客有任何瑕疵,请多多指教!在此感谢您的学习和指教!

原创粉丝点击