插入排序:

每一步将一个待排序的元素,按其排序码的大小,插入到前面已经排好序的一组元素的合适位置上去,直到元素全部插完位置。

一、直接插入排序

 基本思想:当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移。


插入排序--直接插入与希尔排序_i++

代码如下:

void InsertSort(int *array, size_t size)
{
for (size_t i = 1; i < size; i++)
{
int key = array[i];
int end = i - 1;

//找插入的位置
while (key < array[end] && end >= 0)
{
array[end + 1] = array[end];
end--;
}
//插入元素
array[end + 1] = key;
}
}

第二种方法:

void InsertSort_OP(int *array, size_t size)
{
for (size_t i = 1; i < size; i++)
{
//在已序序列中查找待插入元素的位置
int left = 0;
int right = i - 1;
int mid = 0;
int key = array[i];
while (left <= right)
{
mid = left + ((right - left) >> 1);
if (key < array[mid])
right = mid - 1;
else
left = mid + 1;
}

//搬移元素
int end = i - 1;
while (end >= left)
{
array[end + 1] = array[end];
end--;
}

//插入元素
array[left] = key;
}
}

时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:稳定
使用场景:数据量少  接近有序

二、希尔排序,又叫做缩小增量排序,可以看做是直接插入的改进版本。

直接插入适合数字基数小,当数字的基数很大时,而且都接近无序,如果用插入算法一个个比较后再插入,十分耗费时间。

我们可以用希尔排序,一个大的无序数组,分成若干个小序列,再进行插入排序这样就会很快。

eg:


插入排序--直接插入与希尔排序_i++_02


插入排序--直接插入与希尔排序_使用场景_03

代码如下:

void ShellSort(int *array, size_t size)
{
int gap = 3;
//int gap=size;
while (gap/*gap>1*/)
{
//gap=gap/3+1;
for (size_t i = gap; i < size; i++)
{
int key = array[i];
int end = i - gap;

//找当前元素插入的位置
while (end >= 0 && key < array[end])
{
array[end + gap] = array[end];
end -= gap;
}
//插入元素
array[end + gap] = key;
}
gap--;
}
}

gap取值有以下几种取法:  素数            除2                     gap/3+1


时间复杂度:O(N^1.25~1.6N^1.25)


空间复杂度:O(1)


稳定性:不稳定


使用场景:数据量大