【十六】排序算法(二)--希尔排序算法

1、希尔排序

希尔排序算法示意图

算法步骤:
通俗的说法:
1. 将一个长度为len的待排序列,依照某个间距gap,分割成len/gap份;
2. 对这每个子序列进行插入排序;
3. 完成后,将gap减小,再执行上述过程;
4. 直到gap为1时,排序完成!

算法实现:

/*
  用于交换两个元素的值
*/
void swap(int *array, int i, int j)
{
  int temp = array[i];
  array[i] = array[j];
  array[j] = temp;
}
/*
  希尔排序算法
    通俗的说法:
    将一个长度为len的待排序列,依照某个间距gap,分割成len/gap份,对这每个子序列进行插入排序;
    完成后,将gap减小,再执行上述过程;
    直到gap为1时,排序完成!
*/
void ShellSort(int *array, int len)
{
  int i = 0, j = 0;
  int gap = len;
  int k = 0;
  int z = 0;

#ifdef _STATISTICS_
//添加宏定义:_STATISTICS_,可统计三个循环的执行次数
  int jsum = 0;
  int isum = 0;
  int zsum = 0;
#endif

  do
  {
    gap = gap / 3 +1;
    for(z = 0; z < (len / gap) + 1; z++)
    {
      for(i = z + gap; i < len; i+=gap)
      {
        k = i;
        for(j = i-gap; j>=0; j-=gap)
        {
          if(array[k] < array[j])
          {
            swap(array,j,k);
            k = j;
          }
#ifdef _STATISTICS_
          jsum++;
#endif
        }
#ifdef _STATISTICS_
        isum++;
#endif
      }
#ifdef _STATISTICS_
      zsum++;
#endif
    }
  }while(gap > 1);

#ifdef _STATISTICS_
  printf("jsum=%d\tisum=%d\tzsum=%d\t\n",jsum,isum,zsum);
#endif
}

使用上述的实现方法,在排列一个7元素序列时,每个循环的执行次数如下:
这里写图片描述

可见时间复杂度很高,内层循环居然执行了112次!!

2、已有算法的改进

/*
  希尔排序算法
    对上述ShellSort实现的改进:
      按照上面的描述来说,假如一个待排序列被分割成了3个子序列,那么理应循环3次,分别对
      这3个子序列进行插入排序,然后再使gap减小,再进行下一次分割和排序,但是这样写,上方
      的三个函数的执行次数会很多,算法的时间复杂度很高!
    改进:
      因为希尔排序算法,当gap为1时,实际上就是一个插入排序算法,也就是说,无论如何,一旦
      gap为1,序列就能被排好,所以再待排序列被分割成几个子序列后,我们可以只做第一个子序
      列的插入排序工作,这样能很好的减少算法的时间复杂度,也就少了一层循环!
*/
void Shell_Sort(int *array, int len)
{
  int i = 0, j = 0;
  int gap = len;
  int k = 0;

#ifdef _STATISTICS_
//添加宏定义:_STATISTICS_,可统计三个循环的执行次数
  int jsum = 0;
  int isum = 0;
  int zsum = 0;
#endif

  do
  {
    gap = gap / 3 +1;
    for(i = gap; i < len; i+=gap)
    {
      k = i;
      for(j = i-gap; j>=0; j-=gap)
      {
        if(array[k] < array[j])
        {
          swap(array,j,k);
          k = j;
        }
#ifdef _STATISTICS_
        jsum++;
#endif
      }
#ifdef _STATISTICS_
      isum++;
#endif
    }
#ifdef _STATISTICS_
    zsum++;
#endif
  }while(gap > 1);

#ifdef _STATISTICS_
  printf("jsum=%d\tisum=%d\tzsum=%d\t\n",jsum,isum,zsum);
#endif
}

实际测试:

这里写图片描述

可见时间复杂度减小了很多,内层循环由112次减少到了30次!!

3、完整源码下载

文件名:shellSort-1.0.tar.gz
链接: http://pan.baidu.com/s/1dDjfTRz 密码: 9z2c

编译步骤:

0.1 解压缩:tar -zxvf shellSort-1.0.tar.gz
0.2 编译:gcc -std=c99 -Wall -g shellSort.c -o shellSort
0.3 运行:./shellSort

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值