希尔排序算法思想

  • 希尔排序的实质就是分组插入排序,该方法又称缩小增量排序.

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

代码

要求

对于一个int数组,请编写一个希尔排序算法,对数组元素排序。
给定一个int数组A及数组的大小n,请返回排序后的数组。保证元素小于等于2000。

测试样例:

[1,2,3,5,2,3],6
[1,2,2,3,3,5]

程序一(好理解,但是比较麻烦)

class ShellSort {
public:
    int* shellSort(int* A, int n) {
        // write code here
        if(n<2){
            return A;
        }
        int count = 2, argument; //count:一个子序列中的元素数,argument:增量,也是子序列的数量
        while(count<=n){
            argument = n/count;
            for(int i=0;i<argument;i++){
                sortArgu(A,n,i,argument); //这里把一次插入排序过程抽出来
            }
            count *=2;
        }
        return A;
    }

private:
    void sortArgu(int* A, int n, int begin, int argu){
        int temp, last, current;  //begin:子序列的起始元素
        current = begin+argu;// current: 一次插入排序中,当前要排序的元素,也就是无序部分的第一个元素
        while(current<n){
            last = current;
             while(last-argu>=begin){
                if(A[last]<A[last-argu]){
                    temp = A[last];
                    A[last] = A[last-argu];
                    A[last-argu] = temp;
                }
                last -= argu;
            }
            current +=argu;
        }
    }
};

程序二

class ShellSort {
public:
    int* shellSort(int* A, int n) {
        // write code here
        if(n<2){
            return A;
        }
        int temp,j;
        for(int step=n/2; step>0; step/=2){ //这里控制增量,最小值时为1,也就是一次普通的插入排序
           for(int i=step; i<n; i++){ //重点是在这里!!!这里是对第一个增量后的元素进行插入排序(插入排序时起始有序序列为1),没有把一个子序列单独抽出来进行排序(区别程序一),而是依次对第一个增量后的元素在其所属的子序列中进行插入排序
               for(j=i; j>=step; j-=step){
                   if(A[j]<A[j-step]){
                       temp = A[j];   //这里还可以进一步优化,详见程序三
                       A[j] = A[j-step];
                       A[j-step] = temp;
                   }else{
                       break;
                   }
               }
           } 
        }
        return A;
    }

};

程序三

class ShellSort {
public:
    int* shellSort(int* A, int n) {
        // write code here
        if(n<2){
            return A;
        }
        int temp,j;
        for(int step=n/2; step>0; step/=2){
           for(int i=step; i<n; i++){   //思想:找到待排序元素在有序部分的位置,然后插入,而不是每一次都把待排序元素与前一个元素交换位置。
               temp = A[i];     //记录下待排序元素
               for(j=i; j>=step; j-=step){
                   if(temp<A[j-step]){  //有序部分的每一个元素都与待排序元素比较
                       A[j]=A[j-step];  //满足上述条件,则元素后移
                   }else{
                       break;
                   }
               }
               A[j]=temp;  //将待排序元素插入合适位置
           } 
        }
        return A;
    }

};

参考

1 白话经典算法系列之三 希尔排序的实现


jack2wang
753 声望27 粉丝