首页 > 代码库 > shell sort

shell sort

/**希尔排序的实质就是分组插入排序,该方法又称缩小增量排序,因DLShell1959年提出而得名。

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

*

 *n=10的一个数组49, 38, 65, 97, 26, 13, 27, 49, 55, 4为例

 

 第一次 gap = 10 / 2 = 5

 49   38   65   97   26   13   27   49   55    4

 

 1A                                1B

 

     2A                                  2B

 

           3A                                     3B

 

                 4A                                     4B

 

                      5A                                        5B

 1A,1B2A,2B等为分组标记,数字相同的表示在同一组,大写字母表示是该组的第几个元素,每次对同一组的数据进行直接插入排序。即分成了五组(49, 13) (38, 27) (65, 49)  (97, 55)  (26, 4)这样每组排序后就变成了(13, 49)  (27, 38)  (49, 65)  (55, 97)  (4, 26),下同。

 

 第二次 gap = 5 / 2 = 2

 

 排序后

 

 13   27   49   55   4    49   38   65   97   26

 

 1A         1B          1C          1D         1E

 

      2A          2B           2C           2D         2E

 

 第三次 gap = 2 / 2 = 1

 

 4   26   13   27   38    49   49   55   97   65

 

 1A  1B   1C   1D   1E    1F   1G   1H   1I   1J

 

 第四次 gap = 1 / 2 = 0 排序完成得到数组:

 

 4   13   26   27   38    49   49   55   65   97


*

*/


//下面给出严格按照定义来写的希尔排序  低级

void shell_sort_low(int unsorted[],int count)

{

//    int i, j, gap;

//    for (gap = count / 2; gap > 0; gap /= 2) { //步长

//        for (i = 0; i < gap; i++) {        //直接插入排序

//            for (j = i + gap; j < count; j += gap) {

//                if (unsorted[j] < unsorted[j - gap]) {

//                    int temp = unsorted[j];

//                    int k = j - gap;

//                    while (k >= 0 && unsorted[k] > temp) {

//                        unsorted[k + gap] = unsorted[k];

//                        k -= gap;

//                    }

//                    unsorted[k + gap] = temp;

//                }

//            }

//        }

//    }

    

    for (int gap = count/2; gap >0; gap /= 2) { //步长  //直接插入排序的次数

        for (int arrayCount =0; arrayCount < gap; arrayCount++) { //分组后数组的个数, (数组的个数 = gap)

            for (int index = arrayCount + gap; index < count; index += gap) {

                if (unsorted[index] < unsorted[index-gap]) {

                    int temp = unsorted[index];

                    int k = index - gap;

                    while (k >= 0 && unsorted[k] > temp) {

                        unsorted[k+gap] = unsorted[k];

                        k -= gap;

                    }

                    unsorted[k+gap] = temp;

                }

            }

        }

    }

    

}


//中级 进行改进和优化,以第二次排序为例,原来是每次从1A1E,从2A2E,可以改成从1B开始,先和1A比较,然后取2B2A比较,再取1C与前面自己组内的数据比较…….。这种每次从数组第gap个元素开始,每个元素与自己组内的数据进行直接插入排序显然也是正确的。

void shell_sort_middle(int unsorted[],int count)

{

    for (int gap = count /2; gap > 0; gap /= 2) {

        for (int j = gap; j < count; j++) { //从数组第gap个元素开始

            if (unsorted[j] < unsorted[j - gap]) {//每个元素与自己组内的数据进行直接插入排序

                int temp = unsorted[j];

                int k = j - gap;

                while (k >= 0 && unsorted[k] > temp) {

                    unsorted[k + gap] = unsorted[k];

                    k -= gap;

                }

                unsorted[k+gap] = temp;

            }

        }

    }

}


//高级

void shell_sort_high(int unsorted[],int count)

{

    for (int gap = count /2; gap > 0; gap /= 2) {

        for (int i = gap; i < count; i++) {

            for (int j = i - gap; j >=0 && unsorted[j] > unsorted[j + gap]; j -= gap) {

                swap(&unsorted[j], &unsorted[j + gap]);

            }

        }

    }

}


int main(int argc, const char * argv[])

{

    //int unsorted[] = { 6, 2, 4, 1, 5, 3, 7, 8, 9, 10, 11};

    //selection_sort(x, 11);

    

    //bubble_sort_low(unsorted, 11);

    //bubble_sort_middle(unsorted, 11);

    //bubble_sort_high(unsorted, 11);


    //insertion_sort_low(unsorted, 11);

    //insertion_sort_middle(unsorted, 11);

    //insertion_sort_high(unsorted, 11);


    int unsorted[] = {49,38, 65, 97,26, 13, 27,49, 55, 4};

    //shell_sort_low(unsorted, 10);

    //shell_sort_middle(unsorted, 10);

    shell_sort_high(unsorted, 10);


    for (int index =0; index<10; index++) {

        printf("%d ",unsorted[index]);

    }

    printf("\n");


}