走进数据结构之排序(二)---希尔排序

一、希尔排序算法分析

希尔排序基本思想就是分组的直接插入排序!

如何分组呢?希尔排序是以间距来分组的!

那间距又如何取呢?希尔排序是以传进来的数据序列的长度作为间距初始值的,每一趟排序都是将数据序列的一半作为间距来进行排序操作,直到间距取为1,停止排序。

有了间距又如何来排序呢?其实就是分组的直接插入排序,只是直接插入排序的间距是1,而希尔排序的间距为上述值。

二、代码实现

package top.einino.insertionsort;

public class ShellSort {

//升序排序
public static void shellSortAsc(int[] keys){
 for(int delta = keys.length/2; delta>0; delta/=2){
   for(int i=delta; i<keys.length; i++){
int temp = keys[i],j;
for(j=i-delta;j>=0&&temp<keys[j];j-=delta){
keys[j+delta] = keys[j];
}
keys[j+delta] = temp;
}
System.out.print("delta="+delta+" ");
print(keys);
}
}

//降序排序
public static void shellSortDesc(int[] keys){
for(int delta = keys.length/2; delta>0; delta/=2){
for(int i=delta; i<keys.length; i++){
int temp = keys[i],j;
 for(j=i-delta;j>=0&&temp>keys[j];j-=delta){
keys[j+delta] = keys[j];
}
keys[j+delta] = temp;
}
System.out.print("delta="+delta+" ");
print(keys);
}
}
//输出排序数组
private static void print(int[] keys) {
for(int key : keys){
System.out.print(key+" ");
}
System.out.println();
}

public static void main(String[] args) {
int[] keys = {38, 55, 65, 97, 27, 76, 27, 13, 19};
//测试升序排序
ShellSort.shellSortAsc(keys);
int[] keys2 = {38, 55, 65, 97, 27, 76, 27, 13, 19};
//测试降序排序
ShellSort.shellSortDesc(keys2);
}
}

三、形象的小例子

又是体育老师来排队(升序排序)了,但此次队伍稍微长了一点点,总共有9位学生!初始序列为:

A学生138,B学生155,C学生165,D学生197,E学生127,F学生176,G学生127,H学生113,I学生119

老师开始第一趟排序,首先老师要做的事情是分好组,数数总共有9个学生,9/2=4,按数组的序号从0开始,第4个位置的元素就是第五个学生,然后以间距为4作为分组条件:

分组情况为:A、E、I为第一组,B、F为第二组,C、G为第三组,D、H为第四组总共四组

分组好了,老师就第一组开始进行排序了,首先把E学生拉出队伍,(比较规则比前不比后)与A学生进行比较,结果E<A,所以老师把A学生排到E学生的位置,因为这一分组A学生前面再无其他人,所以老师就把E学生排到A学生的位置!此时第一组的队伍顺序是E、A、I,接着老师把I学生拉出队伍,与A学生进行比较,结果I<A,所以老师把A学生排到了I学生位置,接着又把I学生与E学生进行比较,结果I<E,所以老师又把E学生放到原来A学生的位置,由于此分组到E前面就没人了,所以老师就把I学生放到E学生的位置,此时第一组的排序至此结束,最后结果为I、E、A,改变的这三者的排序,他们三者所对应的位置还是没有改变的。还是0,4,8的位置

老师开始第二组排序,首先把F学生拉出队伍,与B学生进行比较,结果F>B,因为F比B大,F后面又没有其他学生了,所以老师把F学生排到原来的位置,并结束了此组的排序,第二组的排序还是B、F

同样的道理进行第三组与第四组的排序,分别得到的结果是

第三组排序:G、C

第四组排序:H、D

老师这时也结束第一趟的排序了,最后的结果为:I学生119B学生155G学生127H学生113E学生127F学生176、C学生165D学生197、A学生138、此趟排序后分组的排序都趋于升序状态了

老师进行第二趟排序,首先还是要分组,此次分组间距是由上一趟的间距/2来决定的,所以是4/2=2,所以间距为2,从第三个同学即G学生开始排序,分组情况为:

第一组:I学生、G学生、E学生、C学生、A学生

第二组:B学生、H学生、F学生、D学生

老师从第一组开始排序,首先将G学生拉出队伍,与I学生进行比较,结果G>I,将G排到原来的位置!接着拉出E学生,与G学生进行比较,结果E=G,因为排序规则是仅当G>E才会将G学生排到E学生的位置,所以老师依然会将E学生排到原来的位置。然后拉出C学生,与E学生进行比较,结果C>E,将C排到原来的位置。将A学生拉出队伍,与C学生进行比较,结果A<C,老师就将C学生排到A学生的位置,再让A学生与E学生进行比较,结果A>E,老师就将A学生排到原来C学生的位置,结束 第一组的排序,此次排序结果为:I、G、E、A、C

老师开始的第二组的排序,首先将H学生拉出队伍,与B学生进行比较,结果H<B,将B排到H的位置,并把H排到B的位置,此时第二组的排序情况为:H、B、F、D。再将F学生拉出队伍,与B学生进行比较,结果F>B,将F学生排到原来的位置,此时排序顺序不变。将D学生拉出队伍,与F学生进行比较,结果D>F,将D学生排到原来的位置,此时第二组的排序仍不变H、B、F、D

第二趟排序的最终结果为I学生119、H学生113G学生127、B学生155E学生127、F学生176、A学生138、D学生197、C学生165、

老师进行第三趟排序,间距为2/2=1,即最后一趟排序了,从第二个学生(H学生)开始排序

分组情况为:

第一组:I学生119、H学生113、G学生127、B学生155、E学生127、F学生176、A学生138、D学生197、C学生165、

老师开始从第一组也是唯一一组进行排序,

将H学生拉出队伍,与I学生进行比较,结果H>I,把H学生排到原来的位置。

将G学生拉出队伍,与H学生进行比较,结果G>H,把G学生排到原来的位置。

将B学生拉出队伍,与G学生进行比较,结果B>G,把B学生排到原来的位置。

将E学生拉出队伍,与B学生进行比较,结果E<B,把B学生排到E学生的位置,再把E与G进行比较,结果E=G,所以把放到B学生原来的位置上,此时顺序有所变动为:I学生119、H学生113、G学生127、E学生127、B学生155、F学生176、A学生138、D学生197、C学生165、

将F学生拉出队伍,与B学生进行比较,结果F>B,把F学生排到原来的位置

同样的道理进行最后的三位学生的排序

得到最后的排序的结果为:I学生119、H学生113、G学生127、E学生127、A学生138、B学生155、C学生165、F学生176、D学生197、

四、希尔排序算法的时间复杂度

希尔排序算法的时间复杂度分析比较复杂,实际所需的时间取决于具体的增量序列。

五、希尔排序算法的空间复杂度

希尔排序算法中的temp占用一个存储单元,空间复杂度为O(1)

六、稳定性

在希尔排序算法中,会错过关键字相等的比较,比如上面的例子G学生127、E学生127、但是G学生在第一趟排序过程中,直接与C学生进行比较跳过了与E学生的比较,导致关键字相等的元素在最后的结果发生的顺序的改变,所以希尔算法是不稳定的。

七、小结

本博文从希尔插入排序算法分析,升序和降序代码实现,老师排队的例子讲演,时间复杂度,空间复杂度以及稳定性,介绍了希尔排序的方方面面。

如果有疑问或者对该博文有何看法或建议或有问题的,欢迎评论,恳请指正!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值