直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。
举一个生活中的例子:我们玩的扑克牌游戏,我们整理牌的时候采用的就是一个插入排序。
当插入第 i(i >= 1) 个元素时,前面的 arr[0],arr[1],…,arr[ i - 1 ]已经排好序,此时用arr[ i ]的排序码与 arr[ i - 1],arr[ i - 2 ],…的排序码顺序进行比较,找到插入位置即将 arr[ i ]插入,原来位置上的元素顺序后移。

void InsertSort(int* arr, int n)
{
for (int i = 0; i < n - 1; i++)
{
int end = i;
int tmp = arr[end + 1];
while (end > 0)
{
if (arr[end] > tmp)
{
arr[end + 1] = arr[end];
end--;
}
else
{
break;
}
}
arr[end + 1] = tmp;
}
}直接插入排序的特性总结
注意:当给定的数组接近有序时我们的时间复杂度会接近于O(N)但是不会真正达到
希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数(通常是gap = n / 3 + 1),把待排序文件所有记录分成各组,所有的距离相等的记录分在同一组内,并对每一组内的记录进行排序,然后gap = gap / 3 + 1得到下一个整数,再将数组分成各组,进行插入排序,当gap = 1时,就相当于直接插入排序。
它是在直接插入排序算法的基础上进行改进而来的,综合来说它的效率肯定是要高于直接插入排序算法的。

void ShellSort(int* arr, int n)
{
int gap = n;
while (gap > 1)
{
//推荐写法:除3
gap = gap / 3 + 1;
for (int i = 0; i < n - gap; i++)
{
int end = i;
int tmp = arr[end + gap];
while (end >= 0)
{
if (arr[end] > tmp)
{
arr[end + gap] = arr[end];
end = end - gap;
}
else
{
break;
}
}
arr[end + gap] = tmp;
}
}
}希尔排序的特性总结
希尔排序的时间复杂度估算:
外层循环:外层循环的时间复杂度可以直接给出为:O(log2 n) 或者 O(log3 n),即O(log n)
内层循环:



希尔排序时间复杂度不好计算,因为 gap 的取值很多,导致很难去计算,因此很多书中给出的希尔排序的时间复杂度都不固定。《数据结构(C语言版)》--- 严蔚敏书中给出的时间复杂度为:
