你好,我是史丰源
欢迎你的来访,希望我的博客能给你带来一些帮助。
我的Gitee:代码仓库.☀️
我的联系方式:
QQ:1756786195
邮箱:Marksky126@outlook.com🌐
插入排序
就像它的名字一样,插入进来的元素进行排序。
一、单趟插入排序
我们先思考最简单的情形,原数组有序,然后插入元素进行排序。
如下图,我们要插入的元素为3标记为end+1,标记原数组最后一个元素为end。
然后依次将3与end所标记的元素作比较,将比3大的元素都向后移动,直到遇到比它小的元素,就不再比较,插入这个位置,即比它小元素后的位置。
这样我们的单趟排序就完成了。
二、插入排序(乱序数据)
乱序排序思想:把第一个数(标记为end)看作有序,然后将后面的一个数据(标记为end+1 )作为插入数据,相互比较,如果小则两个数据换位置。然后重复这个过程直到整个数组有序。
如图 我们把9作为有序数据标记为end,1作为插入数据作为 end+1。1<9则end与end+1数据进行交换。然后end依次增加。
代码示例:
void Insertsort(int *a,int n)
{
int i = 0;
int end = n;
int tmp = a[end + 1];
for (i = 0; i < n - 1; i++)
{
while (end>=0)//升序
{
if (tmp < a[end])
{
a[end + 1] = a[end];//要插入的元素向前移动
--end;
}
else
break;
}
a[end+1] = tmp;//替换数据的操作
}
}
插入排序的时间复杂度为O(n^2)
因为最坏的情况是逆序。
希尔排序
希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。”——引用于百度百科。
简单的来讲:希尔排序就是插入排序的简化版,它按照步长将数组元素分为几块,然后进行插入排序。
希尔排序分为两部分:
1.预排序 :让数组元素接近有序(比如要升序排序,让大的数更快到后面,小的数更快到前面)。
2.直接插入排序(将数组元素完全有序排序)。
如图所示,我们步长为3,从第一个元素开始,依次进行插入排序。
void Shellsort(int *a,int n)
{
int i = 0;
int gap = 3;//步长
while (gap > 1)
{
gap = gap / 3 + 1;//让gap最终等于1,至于除于几都要考虑最后gap是否等于1
for (i = 0; i < n - gap; ++i)
{
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + gap] = a[end];//要插入的元素向前移动
end -= gap;
}
else
break;
}
a[end + gap] = tmp;
}
}
}
从两个代码段可以看出,希尔排序与插入排序的异同点就是 插入排序每次向后移动1个元素,而希尔排序每次向后移动步长个元素进行排序,然后将步长减小,从而实现排序。
希尔排序的时间复杂度不好确定,下面我们引用一下资料上的文字:希尔排序的时间复杂度很⼤程度取决于step序列的设计,故此在前⽂中不建议⼤家⾃⾏设计step序列。对于本⽂所给出的step序列,其时间复杂度不超过平⽅阶。就到底什么样的step序列是最优的,⽬前该问题依然⽆解。