美文网首页
希尔排序(shell sort)

希尔排序(shell sort)

作者: 水中的蓝天 | 来源:发表于2022-08-20 15:02 被阅读0次
    10大排序算法.png

    希尔排序在1959年由唐纳德-希尔提出
    希尔排序把序列看作是一个矩阵,分成m列逐列进行排序

    • m从某个整数逐渐减为1
    • 当m为1时,整个序列将完全有序
      因此希尔排序也被称之为递减增量排序(Diminishing Increment Sort)
      矩阵的列数取决于步长序列
    • 比如 步序列为{1,5,19,41,109...} 就代表依次分成109列、41列、19列、5列、1列
    • 不同的步长序列,执行效率也不同

    希尔排序也可看做是对快速排序的一种改进

    
    //步长序列数组
    List<Integer> stepSequence = shellStepSequence();
    for(Integer step: stepSequence) {
     //取出步长序列进行排序
      sort(step);
    }
    
    //分成step列进行排序
    private void sort(int step) {
         //col:第几列 column的简称
        for(int col = 0;col < step;col++) {//对第col列进行排序
            //col 、col+step、 col+2*step..
           for(int begin = col+step;begin < list.length;begin+=step) {//快排逻辑
                  int cur = begin;
                  while(cur > col && cmp(cur,cur-step) < 0) {//当前元素小于前一个,就交换
                      swap(cur,cur-step);
                      cur -= step;
                  }
           }
    
        }
    
    }
    
    //计算步长  希尔给出的公式:n/2^k 
    private List<Integer> shellStepSequence() {
         List<Integer> stepSequence = new ArrayList();
         int step = array.length;
         while((step>>=1) > 0) {
            stepSequence.add(step);
         }
         return stepSequence;
    }
    
    

    希尔本人会给出的步长序列,最坏情况时间复杂度是:O(n^2)

    //计算步长  希尔给出的公式:n/2^k 
    private List<Integer> shellStepSequence() {
         List<Integer> stepSequence = new ArrayList();
         int step = array.length;
         while((step>>=1) > 0) {
            stepSequence.add(step);
         }
         return stepSequence;
    }
    

    目前已知的最好步长序列,最坏情况时间复杂度是O(n^4/3),1986年由Robert Sedgewick提出

    新的步长序列公式.png
    • k even: 当k为偶数时
    • k odd: 当k为奇数时
    //计算步长序列 
    
    private List<Integer> sedgewickStepSequence() {
    
           List<Integer> stepSequence = new LinkedList():
           int k = 0, step = 0;
           while(true) {
                if(k%2==0) { //偶数
                    int pow = (int)Math.pow(2,k>>1);
                    step = 1+9*(pow*pow-pow);
                }else {//奇数
                     int pow1 = (int)Math.pow(2,(k-1)>>1);
                     int pow2 = (int)Math.pow(2,(k+1)>>1);
                     step = 1 + 8*pow1*pow2 - 6*pow2;
                 }
                 //超出就结束循环
                 if(step >= list.length) break;
                 //由于要倒序存储,所以每次加到0的位置
                 stepSequence.add(0,step;);
                 k++;
          }
        return stepSequence;
    }
    
    

    相关文章

      网友评论

          本文标题:希尔排序(shell sort)

          本文链接:https://www.haomeiwen.com/subject/lgdfirtx.html