插入排序--直接插入与希尔排序
原创
©著作权归作者所有:来自51CTO博客作者honeyR的原创作品,请联系作者获取转载授权,否则将追究法律责任
插入排序:
每一步将一个待排序的元素,按其排序码的大小,插入到前面已经排好序的一组元素的合适位置上去,直到元素全部插完位置。
一、直接插入排序
基本思想:当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[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:
代码如下:
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)
稳定性:不稳定
使用场景:数据量大