算法实现之希尔排序(C++)

希尔排序原理:希尔排序之前的排序算法时间复杂度都是O(n*n),希尔排序算法是突破这个时间复杂度限制的算法之一。

插入排序:由于插入排序所执行的交换操作涉及近邻元素,使得元素每次只能移动一位,所以插入排序的效率较低。比如当关键字最小的元素刚好在数组的尾端,就需要N步将该元素放到数组最前端。而当整个记录本身是基本有序是,只需插入排序的效率是非常高的。

改进方法:让每次交换操作不要涉及近邻元素,通过非相邻的元素进行交换来提高执行效率,这就是希尔排序对插入排序的扩展。

希尔排序的算法思想:将文件重新排列,使文件具有这样的性质,每第h个元素(从任何地方开始)产生一个排好序的文件。这样的文件称为h-排序文件。即h-排序的文件是h个独立的已排好序的文件,相互交叉在一起。将无序数组分割为若干个子序列,子序列不是逐段分割的,而是相隔特定增量的子序列,对各个子序列进行插入排序;然后再选择更小的增量,再将数组分割为多个子序列进行排序;直到最后选择再来增量为1,使用直接插入排序,使最终数组成为有序。

增量的选择:在每趟排序过程都有一个增量,增量要满足关系:d[1]>d[2]>...>d[t] = 1;增量序列选取不同,时间复杂度也会有变化。增量的选择决定着算法的执行效率。

算法实现:首选增量为n/2,每次增量为原来的1/2,直到增量为1。
代码:

外循环控制步长,内循环进行插入排序。首先选择步长

/*步长选取为n/2*/
 void
shellsort(int v[],int n)
{
 int gap, i, j, temp;
 for(gap = n/2; gap > 0; gap /= 2)
   for(i = gap; i < n; i++)
     for(j = i - gap; j >= 0 && v[j] > v[j+gap]; j -= gap)
  {
   temp = v[j];
   v[j] = v[j+gap];
   v[j+gap] = temp;
  }
} 
/*======================================================================================*/
/*程序源代码:*/
void shell_sort(int v[], int len)
{
 int j,i,key,m;
    int gap=0;
    if( len <= 0 || v == NULL )
        return;
    while( gap <= len )
    {
        gap = gap*3+1;
    }
 for(; gap > 0; gap /= 3)
 {
  cout << "gap = " << gap << endl;
  for(j = gap; j < len; j++)
  {
   cout << "j = " << j << endl;
   key = v[j];
   for(i = j-gap; i >= 0; i -= gap)
   {
    cout << "Hello" << endl << endl;
    cout << "i = " << i <<endl;
    if(key > v[i])
     break;
    else
    {
     v[i+gap] = v[i];
     v[i] = key;
    }
    for(m = 0; m < MAXNUM; m++)
    {
     cout << v[m] << '\t' ;
    }
    cout << endl;
    cout << "World" << endl << endl;
   }
  }
  for(m = 0; m < MAXNUM; m++)
  {
   cout << v[m] << '\t' ;
  }
  cout << endl;
 }
}
/*============================================================================================*/

排序过程:
The input number is:
41 67 34 0 69 24 78 58 62 64
gap = 13
41 67 34 0 69 24 78 58 62 64
gap = 4
j = 4
Hello
i = 0
j = 5
Hello
i = 1
41 24 34 0 69 67 78 58 62 64
World
j = 6
Hello
i = 2
j = 7
Hello
i = 3
j = 8
Hello
i = 4
41 24 34 0 62 67 78 58 69 64
World
Hello
i = 0
j = 9
Hello
i = 5
41 24 34 0 62 64 78 58 69 67
World
Hello
i = 1
41 24 34 0 62 64 78 58 69 67
gap = 1
j = 1
Hello
i = 0
24 41 34 0 62 64 78 58 69 67
World
j = 2
Hello
i = 1
24 34 41 0 62 64 78 58 69 67
World
Hello
i = 0
j = 3
Hello
i = 2
24 34 0 41 62 64 78 58 69 67
World
Hello
i = 1
24 0 34 41 62 64 78 58 69 67
World
Hello
i = 0
0 24 34 41 62 64 78 58 69 67
World
j = 4
Hello
i = 3
j = 5
Hello
i = 4
j = 6
Hello
i = 5
j = 7
Hello
i = 6
0 24 34 41 62 64 58 78 69 67
World
Hello
i = 5
0 24 34 41 62 58 64 78 69 67
World
Hello
i = 4
0 24 34 41 58 62 64 78 69 67
World
Hello
i = 3
j = 8
Hello
i = 7
0 24 34 41 58 62 64 69 78 67
World
Hello
i = 6
j = 9
Hello
i = 8
0 24 34 41 58 62 64 69 67 78
World
Hello
i = 7
0 24 34 41 58 62 64 67 69 78
World
Hello
i = 6
0 24 34 41 58 62 64 67 69 78
0 24 34 41 58 62 64 67 69 78
The duration time is: 0.094000 seconds
/*==================================================================================================*/
/*将序列分为gap组,对每一组分别进行插入排序*/
程序源代码:
/*======================================================================================================*/
/*每次将文件分为gap组,对每一组分别进行直接插入排序*/
void shell_sort(int v[], int len)
{
 int j,i,r,key,m;
    int gap=0;
     if( len <= 0 || v == NULL )
        return;
    while( gap <= len )
    {
        gap = gap*3+1;
    }
 for(; gap > 0; gap /= 3)
 {
  if(gap > len)
   continue;
  cout << "gap = " << gap << endl;
  for(j = 0; j < gap; j++) //分为gap组,每组分别进行直接插入排序
  {
   cout << "Hello" << endl;
 /*直接插入排序*/
   for(i = j+gap; i < len; i += gap)
   {
   
    key = v[i];
    r = i-gap;
    for(; r >= j; r = r-gap)
    {
     if(key > v[r])
      break;
     else
     {
      cout << "r - gap = " << r - gap << endl;
      v[r+gap] = v[r];//v[r] = v[r-gap];v[r-gap] = key;导致数组访问出错:出现访问v[-1],v[-3]等;
      v[r] = key;
     }
    }
   }
  }
  for(m = 0; m < MAXNUM; m++)
  {
   cout << v[m] << '\t' ;
  }
  cout << endl;
 }
}
/*======================================================================================================*/

/*==================================================================================================*/
算法分析
平均时间复杂度:
 步长选定,已知的最好步长序列由Marcin Ciura设计(1,4,10,23,57,132,301,701,1750,…) 这项研究也表明“比较在希尔排序中是最主要的操作,而不是交换。”用这样步长序列的希尔排序比插入排序和堆排序都要快,甚至在小数组中比快速排序还快,但 是在涉及大量数据时希尔排序还是比快速排序慢。
与增量序列的长度选择有关,某些序列可以为O(n^1.3);
空间复杂度:O(1)
稳定性:不稳定。由于记录是跳跃式的移动,希尔排序并不是一 种稳定的排序算法。






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值