希尔排序原理及Java实现

来源:互联网 发布:php正则匹配a标签href 编辑:程序博客网 时间:2024/04/29 19:44

java 算法基础之七希尔排序

希尔排序是插入排序的一种类型,也可以用一个形象的叫法缩小增量法。基本思想就是把一个数组分为好几个数组,有点像分治法,不过这里的划分是用一个常量d来控制。

这个0<d<n,n为数组的长度。这个算法有了插入排序的速度,也可以算是一个改进算法,在插入算法中,如果有一个最小的数在数组的最后面,用插入算法就会重最后一个

位置移动到第一个,这样就会浪费很大,使用这个改进的希尔排序可以实现数据元素的大跨度的移动。也就是这个算法的优越之处。

 

希尔排序过程图解:

数组:45,20,80,40,26,58,66,70

d=5时   分组为:45,58

               20,66

        80,70

排完后为: 45,20,70,40,26,58,66,80

d=3时 分组为:45,40,66

       20,26,80

       70,58

         40,66

         26,80

排完后为:40,20,58,45,26,70,66,80

d=1时 分组为:40,20,58,45,26,70,66,80

排序后直接得到结果:

20 26 40 45 58 66 70 80

实现的代码如下:

复制代码
class Shell {    public void shell_sort(int [] arrays){        for(int d=5;d>0;d=d-2){            for(int c=0;c<arrays.length-d;c++){                for(int i=c;i<arrays.length;i=i+d){                    for(int j=i;j>0;j=j-d){                        if(j<d)                            break;                        if(arrays[j]<arrays[j-d]){                            int tmp;                            tmp=arrays[j];                            arrays[j]=arrays[j-d];                            arrays[j-d]=tmp;                        }                    }                }                            }            snp(arrays);        }            }    public void snp(int[] arrays){        for(int i=0;i<arrays.length;i++){            System.out.print(arrays[i]+" ");        }        System.out.println();    }    public static void main(String[] args)     {        Shell s=new Shell();        int[] a={45,20,80,40,26,58,66,70};        s.shell_sort(a);    }}
复制代码

 

 

运行结果:

---------- java ----------45 20 70 40 26 58 66 80 40 20 58 45 26 70 66 80 20 26 40 45 58 66 70 80 输出完成 (耗时 0 秒) - 正常终止
另一种方法做希尔排序

上篇blog中介绍的直接插入排序,希尔排序就是对直接插入排序的一个优化。比如有这么一种情况:对一个无序数组进行从小到大的排序,但是数组的最后一个位置的数是最小的,我们要把它挪到第一个位置,其他位置的都要往后移动,要是这个数组非常大,那么直接插入排序的开销就非常大。

    现在有一个array,希尔排序就是设定一个增量incrementNum(0<incrementNum<array.length)。

    先从array[0]开始,以incrementNum为增量的进行直接插入排序,直到数组末尾,然后从array[1]开始重复:以incrementNum为增量的进行直接插入排序; 然后从array[1]开始重复......一直到array[n]。

    然后取一个小于上一步增量的新的增量(比如设置为incrementNum/2),对前一个步骤的结果array进行遍历,直接插入排序....

    再取小于上一步增量的新的增量,重复进行:遍历,直接插入排序

    直到新的增量小于1之后再退出循环

    步骤1:比如现在有数组{82 ,31 ,29 ,71, 72, 42, 64, 5,110}   第一次取增量设置为array.length/2 = 4    先从82开始以4为增量遍历直到末尾,得到(82,42) 排序得到{42 ,31 ,29 ,71, 72, 82, 64, 5,110}。 然后从第二个数31开始重复上一个步骤,得到(31,64) 排序得到{42 ,31 ,29 ,71, 72, 82, 64, 5,110}.......   以4为增量的遍历完数组之后,得到的结果是{42 ,31,5,71,72,82,64,29,110}

   然后重新区增量,这儿设定为incrementNum/2 = 2,对{42 ,31,5,71,72,82,64,29,110}重复步骤1。  完事之后,在取新的增量,重复步骤1。 直到取到的增量小于1,退出循环。

   java实现代码如下:

   

复制代码
    /**     * 希尔排序     * @param arrays 需要排序的序列     */    public static void sort(int[] arrays){        if(arrays == null || arrays.length <= 1){            return;        }        //增量        int incrementNum = arrays.length/2;        while(incrementNum >=1){            for(int i=0;i<arrays.length;i++){                //进行插入排序                for(int j=i;j<arrays.length-incrementNum;j=j+incrementNum){                    if(arrays[j]>arrays[j+incrementNum]){                        int temple = arrays[j];                        arrays[j] = arrays[j+incrementNum];                        arrays[j+incrementNum] = temple;                    }                }            }            //设置新的增量            incrementNum = incrementNum/2;        }    }

0 0
原创粉丝点击