插入排序常见的两种:直接插入排序和希尔排序
直接插入排序思想 :把一个数x插入到一个有序序列a[0,…,n]中,所得到的序列依然有序
具体插入步骤(以升序为例):从有序序列a[0,…,n]的最后一个位置开始往前找,若a[i]大于x,就让a[i]后移,直到找到第一个小于x的数,将x放在该数的下一个位置。
void InsertSort(int *array, size_t size)
{
assert(array);
int tmp = 0;
for (size_t index = 1; index < size; ++index)
{
tmp = array[index];
int end = index - 1;
while (end>=0 && array[end]>tmp)
{
array[end + 1] = array[end];
--end;
}
array[end + 1] = tmp;
}
}
希尔排序是直接插入排序的一种优化,也叫域排序;顾名思义,思想:将要排序的序列按某一间距值分组,每组进行插入排序,再不断缩小间距,直到间距为一,最后一次就是直接插入排序。
void ShellSort(int *array, size_t size)
{
assert(array);
//设置gap
int gap = size;
while (gap > 1)
{
gap = gap / 3 + 1; //保证最后一次间距为1
for (size_t index = gap; index < size; index += gap)//从gap开始后面的数依次往差距为gap 的区间插
{
int end = index - gap;
int tmp = array[index];
while (end >= 0 && array[end]>tmp)
{
array[end + gap] = array[end];
end -= gap;
}
array[end + gap] = tmp;
}
}
//gap等于1,直接插入排序
for (size_t index = 1; index < size; ++index)
{
int tmp = array[index];
int end = index - gap;
while (end >= 0 && array[end]>tmp)
{
array[end + gap] = array[end];
end -= gap;
}
array[end + gap] = tmp;
}
}
直接插入排序时间复杂度O(n^2),空间复杂度O(1);
**直接插入排序在序列本身接近于有序时最优;
当数多、最小的几个数在最后面时,直接插入排序效率低。**
希尔排序时间复杂度O(n^1.3),空间复杂度O(1)。
希尔排序让最大的数尽快靠后,最小的数尽快靠前,保证了最后一次排序效率更高。