shell排序在不相邻的元素之间比较和交换。利用了插入排序的最佳时间代价特性,它试图将待排序序列变成基本有序的,然后再用插入排序来完成排序工作。
在执行每一次循环时,Shell排序把序列分为互不相连的子序列,并使各个子序列中的元素在整个数组中的间距相同,每个子序列用插入排序进行排序。
1.举例说明希尔排序法过程
以一个整数序列为例来说明{12,45,90,1,34,87,-3,822,23,-222,32},该组序列包含N=11个数。不少已有的说明中通常举例10个数,这里说明一下,排序算法与序列元素个数无关!
首先声明一个参数:增量gap。gap初始值设置为N/2。缩小方式一般为gap=gap/2.
第一步,gap=N/2=5,每间隔5个元素取一个数,组成一组,一共得到5组:
对每组使用插入排序算法,得到每组的有序数列:
至此,数列已变为:
第二步,缩小gap,gap=gap/2=2,每间隔2取一个数,组成一组,共两组:
同理,分别使用插入排序法,得到每组的有序数列:
至此,数列已变为:
第三步,进一步缩小gap,gap=gap/2=1,此时只有一组,直接使用插入排序法,玩完成排序,图略。
2.shell排序C++代码实现
步进方式我这里用的是:gap=gap/3
#include<iostream>
using namespace std;
const int INCRGAP = 3;
void shellSort(int a[],int len)
{
int insertNum = 0;
unsigned gap = len/INCRGAP + 1; // 步长初始化,注意如果当len<INCRGAP时,gap为0,所以为了保证进入循环,gap至少为1!!!
while(gap) // while gap>=1
{
for (unsigned i = gap; i < len; ++i) // 分组,在每个子序列中进行插入排序
{
insertNum = a[i];//将当前的元素值先存起来方便后面插入
unsigned j = i;
while (j >= gap && insertNum < a[j-gap])//寻找插入位置
{
a[j] = a[j - gap];
j -= gap;
}
a[j] = insertNum;
}
gap = gap/INCRGAP;
}
}
int main()
{
int array[11] = {2, 1, 4, 3, 11, 6, 5, 7, 8, 10, 15};
shellSort(array, 11);
for(auto it: array)
{
cout<<it<<endl;
}
return 0;
}
注意:
如果步进方式为gap=gap/2的话不用考虑下面这个问题:
那么gap初始化的时候就不用+1了,代码如下:
#include<iostream>
using namespace std;
const int INCRGAP = 2;
void shellSort(int a[],int len)
{
int insertNum = 0;
unsigned gap = len/INCRGAP; // 步长初始化
while(gap) // while gap>=1
{
for (unsigned i = gap; i < len; ++i) // 分组,在每个子序列中进行插入排序
{
insertNum = a[i];//将当前的元素值先存起来方便后面插入
unsigned j = i;
while (j >= gap && insertNum < a[j-gap])//寻找插入位置
{
a[j] = a[j - gap];
j -= gap;
}
a[j] = insertNum;
}
gap = gap/INCRGAP;
}
}
int main()
{
int array[11] = {2, 1, 4, 3, 11, 6, 5, 7, 8, 10, 15};
shellSort(array, 11);
for(auto it: array)
{
cout<<it<<endl;
}
return 0;
}