希尔排序算法思想
希尔排序的实质就是分组插入排序,该方法又称缩小增量排序.
基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。
代码
要求
对于一个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 hereif(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 hereif(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 hereif(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 白话经典算法系列之三 希尔排序的实现