算法与数据结构】--希尔排序

什么是希尔排序?

希尔排序,也是插入排序的一种,又称“缩小增量排序”。插入排序是非稳定排序,希尔排序也是非稳定排序。

希尔排序的实现:

通过将数据根据增量序列进行分组,分组的后的数据根据插入排序进行排序,当所有分组都排好序之后,再进行最后一次插入排序。这样显著减少了数据的交换次数,提高了效率。

这种思想需要一个增量序列,我们成为n - 增量。n表示的是进行排序时数据项之间的间隔。习惯上用 h 表示。为了很好的理解增量排序,我们看下面的示意图:
在这里插入图片描述

上图显示了增量为4时对10个数据项进行排序的示意图,一趟后0、4、8三个位置上的数据项已经排好序,接下来,算法向右移动一步,对1、5、9三个位置的数据进行排序,这个过程一直持续进行,直到所有数据项都完成了一次4-增量排序,然后缩小增量,再重复上面的过程,最后一次增量为1,对所有的数据项进行一次插入排序,从而完成了希尔排序的全部步骤。因为最后一趟都已经基本有序了,所有复杂度没有向普通插入排序那么大了。

##增量序列的两个特征:
1、最后增量序列必须为1,保证最后一趟是一次普通的插入排序。
2、应该尽量避免序列的值(尤其是相邻的值)互为倍数的情况。

代码示例中我们使用增量序列用h = 3 * h + 1来生成。h初值被赋予1,然后使用该公式生成序列1、4、13、40、364等等。当间隔大于数组大小的时候停止,使用序列的最大数组作为间隔开希尔排序的过程,然后每完成一次排序,用推到公式h = (h -1)/3 来减小间隔,保证最后一次h = 1;完成最后一次插入排序。

具体代码实现如下:

public class ShellSort {
       public static void shellSort(int[] arr){
            //定义增量序列
           int h = 1;
           while(h <= arr.length/3){
                h = h * 3 + 1;
           }
           while(h > 0){
                for(int i = h; i < arr.length; i++){
                    for(int j = i; j < arr.length; j+=h){
                        for(int k = j; (k - h >=0) && arr[k] < arr[k-h];k-=h){
                            int a = arr[k];
                            arr[k] = arr[k-h];
                            arr[k-h] = a;
                        }
                    }
                }
                h = (h - 1)/3;
           }
       }
}

猜你喜欢

转载自blog.csdn.net/taojin12/article/details/84230377