排序 - 希尔排序

希尔排序的概念:


希尔排序(Shell Sort)是插入排序的一种,是针对直接插入排序的算法的改进。


该方法又称缩小增量排序。


那么什么是缩小增量排序呢?


首先,我们再来理解下直接插入排序,我们在使用它时,是循环它的第二个数值和它后面的属于与它前面的数值进行比较。


如果小于前面的数值,则将当前数值保存为一临时变量,将将大于当前值的数值往后挪一位,至少前面没有数值比当前值大时,则停止循环,并将中间变量赋值到最后一个挪动位置的数值的原始位置。


直接插入排序的时间复杂度是O(n的p平方)


而希尔排序,就是比它更加优秀的排序方法,它利用增量,把数据分割称几段,分别排序,然后递减增量,重新分组,再次排序,直到增量为1时,进行最后一次排序,如此便可完成排序。


上面提到的分别排序,其实也用的是插入排序,具体见算法



下面给出C代码:

 

 

void ShellSort(SqList *L)
{
    int i,j;
    int increment = L->length;
    do{
         increment = increment/3+1;
         for(i=increment+1;i<L->length;i++){
             if(L->r[i]<L->r[i-increment]){
                L->r[0] = L->r[i];
                for(j=i-increment;j>0&&L->r[0]<L->[j];j-=increment){
                     L->r[j+increment] = L->r[j];
                }
                L->r[j+increment] = L->r[0];
             }
         }

       
     }while(increment>1)


}

 


上面的例子中,首先我们定义了三个变量,


i用于最外层循环,它的起始位置是增量值,结束位置是数组最大长度


j用于内层循环,保存当前位置-增量值 ,也就是和要比较数据的位置。


increment 用于设置增量,在上面的例子中,我们首先将数组分成三组,这样数据的增量就位4,


如此,我们得到如下的分组,假设我们的数据是{0,10,2,36,12,1,25,42,13,21,11}


那么分组情况如下


10,2,36,12

1,25,42,13

21,11


如上所示,我们将数组分成三组,然后我们将每列的数组进行排序,得到如下结果


1,2,36,12

10,11,42,13

21,25


我们在看下上面的算法,首先i等于增量值+1,因为数组0位置为交换变量,


然后,与当前位置-增量位置的数据进行比较,在第一次循环中,i=5,值为1,i-increment=1,值位10,


因为当前值比前面的值小,所以,开始交换它们的位置,


首先,将当前值赋值给中间变量r[0],然后,开始移动前面一个增量值的位置,直到找不到比当前值大的数据,


最后,将中间变量赋值给最后移动的值,就是r[1],


如此反复,最终结果如上图所示


接着,increment 变为2,则数据分组如下


1,2

36,12,

10,11,

42,13,

21,25


进行排序后,它们的顺序如下


1,2

10,11

21,12

36,13

42,25


接着increment变为1,数组分组如下


1

2

10

11

21

12

36

13

42

25


如此,进行最后一次排序,我们将数据横过来,是不是就是直接插入排序呢?


对了,如此,可以确保,排序是正确的。


下面在给出java版实现

 

 

package com.fortune.test;

/**
 * Created with IntelliJ IDEA.
 * User: liupeng
 * Date: 12-7-10
 * Time: 下午3:19
 */
public class TestShellSort {
    public static void main(String args[]) {
        int i;
        int a[] = {10, 2, 36, 12, 1, 25, 42, 13, 11};
        for (i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }
        System.out.println("");
        int increment = a.length;
        do {
            increment = increment / 3 + 1;
            sort(a, increment);

        } while (increment > 1);
        for (i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }
        System.out.println("");
    }

    public static void sort(int arr[], int d) {
        for (int i = d; i < arr.length; i++) {
            if (arr[i] < arr[i - d]) {
                int temp = arr[i];
                int j;
                j = i - d;
                do {
                    arr[j + d] = arr[j];
                    j = j - d;
                } while (j > 0 && temp < arr[j]);
                arr[j + d] = temp;
            }
        }
    }
}
 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值