算法——希尔插入排序

来源:互联网 发布:linux rpm 位置 编辑:程序博客网 时间:2024/04/27 13:21

    上篇说到插入排序,现在来说下插入排序的优化——希尔排序。

    希尔排序是插入排序的一种,它和其他的优化排序一样,例如堆排序,二路归并排序,是对原有基础排序方法的优化,把要排序的数列进行分组排序。每个组使用插入排序方法就行排序。然后在进行下一趟分组排序。

    学习的难点:1、怎么分组?2、分组的重点是哪?3、怎么排序?

    其实学好插入排序后,希尔排序就好理解了。

    一、减半增量排序。选取下标为i,i+d,i+2d......的数组元素为一组。即i+2d的前一位置为i+d,i+d的前一位置为i。类似基础的直接插入排序。

   二、对数组按组进行直接插入排序。注意每组的前一位置。

   三、直到d=1时,进行最后一次排序。如果d=1,就相当与把数组分为了一组,这就和直接插入排序一模一样了。整个排序也就到此为止了。

   

    看数组元素在数组位置的移动

    

    因为直接插入元素的增量为1,而希尔排序的增量为d,所以这里的上图数据移动位置为依次为d。

    

<span style="font-size:24px;"><span style="font-family:KaiTi_GB2312;font-size:18px;">#include <stdio.h>#include <stdlib.h>//希尔排序void shell(int array[],int n,int dk ){    int i,j,temp;    //插入排序核心代码//    for (i=1;i<10;i++)//        {//            temp=array[i];//            j=i-1;//                while(temp<array[j]&&j>0)//                {//                    array[j+1]=array[j];//                    j--;//                }//                if(j!=i-1)//                    array[j]=temp;////        }    //希尔排序核心代码    for (i=dk;i<n;i++)    {       temp=array[i]; //temp为临时变量       j=i-dk;       while( j>=0 && j<n && temp<array[j])  //要确保下标j不超过长度n,不小于0       {            array[j+dk]=array[j];   //j位置的后一位置为j+dk,dk为增量            j-=dk;       }       if(j!=i-dk)       {        array[j+dk]=temp;       }    }}void shellpaixu(){    int i,j,k;    int array[10000];    for(i=0;i<10000;i++)        array[i]=10000-i;    for(i=10000/2;i>=1;i=i/2)        shell(array,10000,i);     for(i=0;i<10000;i++)        printf("%d,",array[i]);}void main(){    shellpaixu();}</span></span>

    通过比较上面直接插入和希尔排序的核心代码。很容易的看出来,直接插入和希尔排序的相同点。他们简直就是一个。


分析过程:由于采用了C语言的写法(在VB,C#可能不会出现问题,没试过)编译的时候遇到了问题:

    问题一:在c语言中,下面的两行代码是不一样的。

<span style="font-size:24px;">while( j>=0 && temp<array[j] ) //先判断下标是否越界,然后比较 while( temp<array[j] && j>=0)  先比较,然后判断下标是否越界</span>




     小编原先写的是第二行,所以就不断的程序崩溃,还好小编没有崩溃,经过无数次的验证,推理。终于找到了自己代码的小bug。得出一个非常严重的教训。

     主要的判断,控制按优先级的顺序写,这样能防止一定的错误。就向方法的判null一样,把最优先的判断放在前面。

    上面的两行代码,小数据量不会出错 <5000。大数据量就会崩溃了。为什么大数据量就会崩溃呢?

    因为在C语言中是可以获取超出数组元素范围的值的,所以小数据量是还是可以获取array【-10】的值的。所以程序不崩。

   当数据量大时,那么可能获取了array【-9999】的值。可能超出地址范围太大了。就崩溃了

参考网址希尔排序


    

    

    

0 0
原创粉丝点击