zoukankan      html  css  js  c++  java
  • 希尔排序

    在插入排序中,我们假设在即将进行排序的元素的左侧所有的元素已经是有序的,所以我们会将该元素与它左侧的元素逐个比较,如果左侧的元素大于该元素,则左侧的元素右移。然后,该元素继续与左侧的下一个元素比较。现在有一个问题:极端情况下,刚开始很小的元素放到了最右侧,那么它左侧所有的元素都要向右移动复制一次,这样效率是很低的,那么如何解决呢?可以考虑希尔排序。希尔排序是基于插入排序的,它通过加大插入排序中元素的间隔,从而使得元素能够大跨度的移动,这样能减少移动次数。经过一趟排序后,然后减小间隔再排序,直至最后一次排序的间隔为1,这最后一次的排序其实就是插入排序。这里,涉及到一个间隔h,一般情况下,我们使用h = 3*h+1。注意:颜色相同的元素都进行了排序。

    情景:对数组 int[] arr = {7,10,1,9,2,5,8,6,4 ,3}中的数据 从小到大排序。

    第一趟排序前:7   10   1   9   2   5   8   6   4   3     第一趟排序后:2   3     6   4   5     9     10       (h = 4)  

    第二趟排序前:2   3   1   6   4   5   8   9   7   10     第二趟排序后:1   2   3   4   5   6   7   8   9   10        (h = 1)

    代码:

    /**
     * 希尔排序
     * @author D N
     *
     */
    public class ShellSort {
        private long[] a; 
        private int nElems;
        
        public ShellSort(int max){
            a = new long[max];
            nElems = 0;
        }    
        
        public void insert(long value){
            a[nElems] = value;
            nElems++;
        }
        
        public void display(){
            for(int j=0;j<nElems;j++){
                System.out.print(a[j]+"   ");
            }
            System.out.println("");
        }
        
        
            //希尔排序算法 
            public void shellSort(){
                int inner,outer;
                long temp; // 临时变量
                
                int h = 1; //数据项之间的间隔,排序时按此间隔排序
                while(h <= nElems/3 ){
                    h = h*3+1;
                }
                
                while(h > 0){ //不断减少h,直至h = 1,此时排序成为了插入排序
                    for(outer = h;outer < nElems;outer++){
                        temp = a[outer];
                        inner = outer;
                        while(inner > h-1 && a[inner-h] >= temp){
                            a[inner] = a[inner-h];
                            inner -= h;
                        }
                        a[inner] = temp;
                    }
                    h = (h-1)/3;
                    display();
                }
                
            }
    }

    运行测试代码:

    public class SortTest {
        public static void main(String[] args) {
            int maxSize = 10;
            ShellSort arr = new ShellSort(maxSize);
            arr.insert(7);
            arr.insert(10);
            arr.insert(1);
            arr.insert(9);
            arr.insert(2);
            arr.insert(5);
            arr.insert(8);
            arr.insert(6);
            arr.insert(4);
            arr.insert(3);
            arr.display();
            System.out.println();
            arr.shellSort();
            System.out.println();
            arr.display();
        }
    }

    运行结果:

    7   10   1   9   2   5   8   6   4   3   
    
    2   3   1   6   4   5   8   9   7   10   
    1   2   3   4   5   6   7   8   9   10   
    
    1   2   3   4   5   6   7   8   9   10   

    效率分析:

    希尔排序效率比插入排序要高,在有几千个元素需要排序时,它的效率更容易显现出来。原因就是:当h大的时候,每一趟排序需要移动的元素个数很少,但是移动的距离很长,这很有效率。当h减少时,每一趟排序需要移动的次数增多,但是此时数组已经接近排序后最终的位置,当h=1时,希尔排序也就成为了插入排序。

  • 相关阅读:
    (多行)省略号隐藏超出范围的文本
    JSON.parse()和JSON.stringify()
    如何获取每个input的值
    禁止文字被选中
    javasctipt数据类型转换
    jq实现伸缩二级菜单
    table-layout 表格宽度不随文字改变
    VNC安装和配置
    HTML超连接的使用
    HTML图像标记
  • 原文地址:https://www.cnblogs.com/51life/p/10330407.html
Copyright © 2011-2022 走看看