算法--排序算法的介绍与总结(四)

上一篇文章介绍了堆排序,这篇文章介绍下shell排序算法。

2.7、Shell排序算法

在介绍shell排序算法之前,我们先回顾下直接插入排序算法的流程:

1、首先对数组的前两个数据进行从小到大的排序。
2、接着将第3个数据与排好序的两个数据比较,将第3个数据插入合适的位置。
3、然后将第4个数据插入已排好序的前3个数据中
4、不断重复上述过程,直到把最后一个数据插入合适的位置。最后便完成了对原始数组从小到大的排序。

由插入排序算法的流程我们可以知道:每次向已排好序的数据中插入一个新的数据时,新插入的数据都要跟已排好序的数据一一比较,直到找到自己的位置。如果数据量比较大,数据比较的次数较多影响效率。shell排序算法也用到了上面的直接插入排序算法,但是每一次使用直接插入排序算法时,数组中的数据已经是基本有序的了,这就大大提高了排序的效率。

实现思路:
1、将有n个元素的数组分成n/2个数字序列,第1个数据和第n/2+1个数据为一对,后面的一次类推(即分组)。
2、一次循环使每一个序列对排好顺序(使用直接排序算法)。
3、然后再变为n/4个序列(分组数目变少,每组中的数据变多),再排序。
4、不断重复上述过程,随着序列分组变成了一个,数据也完成了排序。

举一个例子来帮助大家理解:现在有一个10个元素的数组:int[] a = {4,6,7,1,2,5,3,9,8,0};

第一步:n=10,n=n/2=5,那也就是说10个元素分成5组,每组两个,组距为5。即4、5一组,6、3一组,7、9一组,1、8一组,2、0一组。
第二步:对这五组数据分别排序:
     4<5:不用交换。
     6>3:6与3交换(即a[1]=3,a[6] = 6)。
     7<9:不用交换。
     1<8:不用交换。
     2>0:交换(a[5]=0,a[9]=2)
     最后的结果为:4,3,7,1,0,5,6,9,8,2
第三步:n = n/2 = 5/2 = 2,将第二步的数组分为2组,每组5个数据,组距为2。即:
  第一组:4   7   0   6   8
  第二组:   3   1   5    9   2
对每一个分别排序,结果为:
  第一组0   4   6   7   8
  第二组:1   2   3    5   9
这一步完成后的记过为:0,1,4,2,6,3,7,5,8,9
第四步:n = n/2 = 2/2 = 1。将第三步的数据分成一组(已不用分了)
再对数据进行排序,结果为:0,1,2,3,4,5,6,7,8,9

上述分析过程对应的代码如下,代码可以直接运行,而且对每一步的中间结果都输出了,方便大家查看

/**
 * @author Mr0
 * describe:使用shell插入排序时,如果原数据已经是基本有序的,则排序的效率可以大大的提高。
 * 另外,对于数据量较小的序列使用直接插入排序,因需要移动的数据量较少,其效率也较高。
 * 因此shell排序算法具有比较高的排序效率。
 *
 */
public class P4_4_Insert_ShellSort {
static final int SIZE =10;

    /**
     * @return
     */
    static int geneNum(){
        int tempNum =(int)(Math.random()*100.0);
        return tempNum;
    }

    /**
     * @param a
     */
    static void shellSort(int[] a){
        int r;
        int x=0;
        for(r=a.length/2;r>=1;r/=2){                    //分组,r是组距,也是组数。
            for(int i=r;i<a.length;i++){            //在每一组内部利用插入算法排序
                int temp=a[i];
                int j=i-r;
                while(j>=0 && temp<a[j]){
                    a[j+r] = a[j];
                    j-=r;
                }
                a[j+r] = temp;
            }
            x++;
            System.out.print("第"+x+"步排序结果为:");
            for(int k=0;k<a.length;k++){
                System.out.print(a[k]+" ");
            }
            System.out.print("r=" + r);
            System.out.print("\n");

        }



    }
    public static void main(String[] args){
        //int[] array = new int[SIZE];

//      for(int i=0;i<10;i++){
//          array[i]= P4_4_Insert_ShellSort.geneNum();
//      }
        int[] array = {4,6,7,1,2,5,3,9,8,0};
        System.out.print("排序前的数组为:");
        for(int i=0;i<array.length;i++){
            System.out.print(array[i]+" ");
        }
        System.out.print("\n");
        P4_4_Insert_ShellSort.shellSort(array);

        System.out.print("排序后的数组为:");
        for(int i=0;i<array.length;i++){
            System.out.print(array[i]+" ");
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值