数据结构专栏~排序
- (꒪ꇴ꒪(꒪ꇴ꒪ ),我是Scort
- 博客主页:张小姐的猫~江湖背景
- 快上车,握好方向盘跟我有一起打天下嘞!
- 送给你们一句罗翔老师的话:
- 你迷茫的原因,在于读书太少,而想的太多
- 作者水平很有限,如果发现错误,可在评论区指正,感谢
- 欢迎持续关注!
插入排序可以分为:直接插入排序 和 希尔排序
直接插入排序是一种简单的插入排序法,其基本思想是:
逐个插入
到一个已经排好序的有序序列
中,直到所有的记录插入完为止,得到一个新的有序序列 。实际中我们玩扑克牌时,就用了插入排序的思想
tmp
,最后一个元素的下标为end
end
比tmp
大就向后移,若比tmp
小,跳出循环,tmp放到比插入的数小的数的后面先break
,再插入tmp
void InserSort(int* a, int n)
{
//[0,end]有序,把end+1位置的值插入,保持有序
for (int i = 0; i < n - 1; i++)
{
//记录有序序列最后一个元素的下标
int end = i;
//待插入的元素
int tmp = a[end + 1];
//单趟排序
while (end >= 0)
{
//比插入的数大就向后移
if (end > tmp)
{
a[end + 1] = a[end];
--end;
}
//比插入的数小,跳出循环
else
{
break;
}
}
//tmp放到比插入的数小的数的后面
a[end + 1] = tmp;
//代码执行到此位置有两种情况:
//1.待插入元素找到应插入位置(break跳出循环到此)
//2.待插入元素比当前有序序列中的所有元素都小(while循环结束后到此)
}
}
直接插入排序的特性总结:
越接近有序
,直接插入排序算法的时间效率越高
O(N^2)
O(N)
O(1)
,它是一种稳定的排序算法希尔排序法又称缩小增量法。希尔排序法的基本思想是:
emm这里说人话就是:
举个例子
现在我们用希尔排序对该序列进行排序。
上述示例中,前两趟就是希尔排序的预排序,最后一趟就是希尔排序的直接插入排序。
void ShellSort(int* a, int n)
{
for (int j = 0; j < n; j++)
{
//gap > 1时候是预排序
//gap最后一次等于1,是直接插入排序
int gap = n;
while (gap > 1)
{
//每次循环gap都在减少
gap = gap / 3 + 1;//+1保证gap最后 一次为1
}
for (int i = j; 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;
}
}
}
小伙伴可能对上面的多组并排的i
的取值有疑惑,为什么是i < n - gap呢?
n-gap
的时候就停止了,同理其他颜色的组也是不能超过n-gap
,不然就越界
,因为后面已经没有值去比较了
- 希尔排序是对直接插入排序的优化。
- 当
gap > 1
时都是预排序
,目的是让数组更接近于有序。当gap == 1
时,数组已经接近有序
的了,这样就 会很快。这样整体而言,可以达到优化的效果。- 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的 希尔排序的时间复杂度都不固定: