1.前言
和上面的直接插入排序一样,希尔排序也是一种插入的排序,更加准确的来说希尔排序是直接插入排序的一个升级版,是在直接插入排序上进行修改然后效率更高的一种插入排序。
2.原理介绍
在直接插入的排序当中,没一次都是后一个数和前一个数进行比较,满足条件的话就加一,然后再是后一个数与前一个数比较.....直到执行结束后退出。执行的间隔是1,而再希尔排序当中,执行的间隔是大于1的数,本次当中我们设定的间隔是5(这个间隔数定在1到数据的总和之间),如下面的图所示,在下面的10个数当中,由于我们设定的时间间隔是5,所以先是9和2进行比较,然后就是6和7进行比较,3和4进行比较,8和1进行比较,5和5进行比较,然后循环退出。
经过这一轮循环之后,我们将这个间隔变成5的一半2,然后再重复上面的步骤同样循环结束后退出。
最后我们再将间隔2变成它的一半1,最后我们再重复上面的步骤,需要注意的是,当间隔变成1的时候,这时的插入也就变成了直接插入排序的思想了(图形解释省略)
3.代码的展示
3.1数据准备和导入到动态数组当中
#define N 10
struct information
{
int size;
int capacity;
int* head;
};
int TestData[N] = { 9,6,3,8,5,2,7,4,1,5 };
struct information pt;
//初始化数据
InitData(&pt);
//数据进入到数组当中
for (int i = 0; i < N; i++)
{
EnterData(&pt, TestData[i]);
}
在这里主要是创造我们测试时所需要的数据,然后将数组导入到动态数组当中,为后面的排序做准备。
3.2 希尔排序的主体
//shell排序
ShellSort(&pt);
//shell排序
void ShellSort(struct information* ps)
{
int step = N;
while (step > 1)
{
step = step / 2;
for (int i = 0; i < N - step; i++)
{
while (i >= 0)
{
if (ps->head[i] > ps->head[i + step])
{
swap(&ps->head[i], &ps->head[i + step]);
i -= step;
}
else
break;
}
}
}
}
上面的step就是上面原理中所说到的间隔,在这里面我们可以看到这里有三层循环,最外面的一层是设置间隔,对应上面图中的间隔5然后间隔2然后间隔1,然后第二层循环是设置执行的前进步长,对应的是上面图一当中的由9和2交换完成后变成6和7进行交换,然后3和4交换......然后第三层是每一次的间隔之下所进行的步骤,对应上面原理图一中的 9和2进行交换比较的步骤。
3.3排序的结果展示
排序前:9 6 3 8 5 2 7 4 1 5
排序后:1 2 3 4 5 5 6 7 8 9
4.结论
希尔排序主要的思想还是直接插入排序的思想,只是它的这个设置的间隔是一个渐渐变化的过程,而不像直接插入排序那样间隔是一个恒定不变的1,希尔排序也正是利用这个改变使得其排序的效率大大的提高。