希尔排序又称为缩小增量排序,是分组增量排序,记录按下标的一定增量分组,对每组使用直接插入排序算法排序。
- 特点:
1.不稳定;
2.时间复杂度最坏情况是O(n^2);
3.插入排序的一种
- 希尔排序的步骤:
1.设置增量的值,分组;
2.在分组的数据中进行直接插入排序;
3.循环前两步,直到增量为1
**********************************************************************
举一个n=10数:【2,6,9,0,4,7,11,21,19,5】
第一步:gap=10/2=5
进行分组之后就成为[2,7][6,11][9,21][0,19,][4,5]排序之后成为:[2,6],[0,9],[4,7],[11,21],[5,19];
第二步:gap=5/2=2
对于[2,0,4,11,5][6,9,7,21,19]组内进行插入排序后的序列是[0,2,4,5,11][6,7,9,19,21];
第三步:gap=2/2=1
对于[0,2,4,5,11,6,7,9,19,21]进行插入排序,因为前面的五个已经排序成功,后面的五个也已经排序成功,只需要从11开始进行插入排序,如果一旦发现11比后面的值小,即刻进行停止排序,6如果比前面的值大,那么即刻停止排序。
***************************************************************
生成代码如下:
/// <summary>
/// 希尔算法-2016-9-5 22:10:17-常银玲
/// 缩小增量排序
/// </summary>
public static int[] Shellsort(int[] arr ,int n){
int i,j,gap;
for(gap=n/2;gap>0;gap/=2) { //步长
for (i = 0; i < gap; i++)
{
//组内进行直接插入排序
for (j = i + gap; j < n; j += gap)
if (arr[j] < arr[j - gap])
{
int min = arr[j];
int k = j - gap;
while (k >= 0 && arr[k] > min)
{
arr[k + gap] = arr[k];
k -= gap;
}
arr[k + gap] = min;
}
}
}
return arr;
}
代码优化部分-减少循环体:
/// <summary>
/// 希尔排序优化版-常银玲 -2016-9-7 18:37:04
/// </summary>
/// <param name="arr">数组</param>
/// <param name="n">数组的个数</param>
/// <returns></returns>
public static int[] SheelSort(int[] arr, int n) {
int i,garp;
for ( garp = n/2; garp >0 ; garp/=2)
{
//组内进行希尔排序,从后面开始进行比较
for ( i = garp; i < n; i++)
{
if (arr[i]<arr[i-garp])
{
int temp = arr[i];
int k = i - garp;
while (k>=0&&arr[k]>temp)
{
arr[k + garp] = arr[k];
k -= garp;
}
arr[k + garp] = temp;
}
}
}
return arr;
}
【总结】
希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些!