【算法-排序之四】希尔排序

本文详细介绍了希尔排序算法的设计原理与实现过程。希尔排序采用分治法思想,通过不断减少子序列数量来逐步逼近最终的完全排序状态。文章还提供了具体的代码示例,并分析了该算法的时间与空间复杂度。

算法-排序之希尔排序


     希尔 排序得名于其设计者设计者希尔(Donald Shell),设计体现了计算机领域的“分治法”思想。在众多排序算法中,目前而言,希尔排序是唯一能在效率上与快速排序(【算法-排序之二】快速排序一较高低的算法,目前只有这两种排序算法的时间复杂度突破O(n2)。值得一提的是,希尔排序与快速排序都基于“分治法”,从这里或许可以解释这两种排序算法在效率上的得天独厚。
           1. 希尔排序ShellSort()
           核心:先将序列分成较多个子序列分别进行排序,再分成较少个子序列分别进行排序,直到最后为一个序列排序。
           形象的说比如先分成  8  个子序分别排序,再 4  个子序,再 2 个子序,最后 1 个(1个也就是全部序列啦)。
           希尔排序的实现方法:
           1.1如何划分子序列:希尔排序采用每隔固定距离选取一个数的方法划分子序。其中间隔距离称为增量。如图:
           
             通过图示,增量的概念很容易理解吧,增量就是隔多少距离的数都为同一个子序。通过这种方法,如果增量选择为N,那么可以分为N个子序,想想是不是这样哦。每次子序都排好后,增量减半,增量减少意味着子序数减少,直到增量为1,便是全部的数序了,希尔排序完成。
             1.2子序内部怎么排序
             讲述1的过程中,说道划分子序后对子序分别排序,那么采取什么排序方法?希尔排序的子序排序方法为插入排序【算法-排序之三】插入排序)。
             算法实现:
    
              希尔排序的代码并不复杂,通过增量是否为1控制整个排序的结束。在增量为为d时,遍历此时的d个子序,从k=0到k=d-1。随后对每个子序进行插入排序操作。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
            
void ShellSort ( int Array [], int n ){
int d = n / 2 ; //设置起始增量
while ( d >= 1 )
{ //增量为1时排序结束
for ( int k = 0 ; k < d ; k ++ )
{ //遍历所有的子序
for ( int i = k + d ; i < n ; i += d )
{ //对每个子序进行插入排序
int temp = Array [ i ]; //插入排序算法参见链接
int j = i - d ;
while ( j >= k && Array [ j ] > temp )
{
Array [ j + d ] = Array [ j ];
j = j - d ;
}
Array [ j + d ] = temp ;
}
}
d = d / 2 ; //缩小增量
}
}
 来自CODE的代码片
ShellSort.c
                  2.算法复杂度
          希尔排序的算法复杂度分析可类比快速排序(【算法-排序之二】快速排序)复杂度分析,一般认为希尔排序时间复杂度为:O(nlogn)。
           3.空间复杂度:
           希尔排序的空间复杂度显然为O(1),仅仅需要一个交换变量。相比快速排序递归调用产生的巨大栈消耗,希尔排序O(1)的空间消耗显得十分让人惊喜。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值