目录
希尔排序
希尔排序又称“缩小增量排序”。基本思想:先取一个小于n的整数d1作为第一个增量,然后把文件的全部记录分成d1个组。所有距离为d1的倍数的记录放在同个一个组中,现在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组中的分组和排序,直到所取的增量dt=(dt<dt-1<0<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
实质上希尔排序也是直接插入排序一种,只是它是分组插入的,相比直接插入而言,它的效率更高一点,首先它把较大的数据集合分割成若干个小组(逻辑上分组),然后对每一个小组分别进行插入排序,此时,插入排序所作用的数据量比较小(每一个小组),插入的效率比较高。
希尔排序是记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
一、操作方法
操作流程图:
二、排序方法:
一般取d1=n/2,di+1=di/2。如果结果为偶数,则加1,以保证di为奇数。
如上图所示,目前这组数据有10个数,这是将这组数据分组,根据公式d1=n/2,则第一趟排序为10/2=5,将数据分为5组。这5组数据那两个为一组呢?这时就看他们中间的空,因为第一趟排序d=5组,所以以他们中间的空为准,就是说隔五个空格为一组。
这里所要注意的是如果出现除完之后结果为小数的则向下取整。
例如:5/2=2.5,所以这里应该取2。在分组的时候隔两个空为一组。
三、动图演示
由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。
相关博客
https://blog.csdn.net/qq_39207948/article/details/80006224
四、C#实现代码
using System;
namespace ConsoleApplication8
{
//希尔排序类
class ShellSorter
{
public void Sort(int[] list)
{
int _d = list.Length;
int _len = list.Length;
for (_d = _d / 2; _d > 0; )
{
if (_d % 2 == 0) _d++;
//按d分组
for (int i = 0; i < _d; i++)
{
//每组执行直接插入排序算法
for (int j = i + _d; j < _len; j += _d)
{
if (j < _len)
{
if (list[j] < list[j - _d])//后面小于前面
{
int temp = list[j];
int k = 0;
for (k = j - _d; k >= i && temp < list[k]; k -= _d)//比它大的元素后移动
{
list[k + _d] = list[k];
}
list[k + _d] = temp;//插入最后比它小的后面
}
}
}
}
Console.WriteLine("第一次d->" + _d);
for (int i = 0; i < _len; i++)
{
Console.Write(string.Format("{0},", list[i]));
}
Console.WriteLine("");
_d = _d / 2;
}
}
}
五、性能分析:
空间效率:仅仅使用了常数个辅助单元,空间复杂度为o(1)
时间效率:由于其是依赖于增量函数的排序,在某个特定范围内,希尔排序的时间复杂度约为o(n^1.3),最坏情况下时间复杂度为o(n^2)。
稳定性:在划分字表的同时,会造成元素相对位置的变化,因此是不稳定的。
适用性:希尔排序算法仅仅适用于当线性表为顺序存储的情况。