在数据结构中,排序算法是处理数据经常遇到的,而排序又分为内排序和外排序。内排序是指排序期间,数据放在内存进行排序。外排序是指所要处理的数据量太大,不能一次放在内存中,排序过程中需要不断进行内外存之间移动的排序。选择合适的排序可以帮我们减少一些时间或者空间上不可避免的开销。
我们所说的八大排序算法,都是属于内排序。
插入排序常用的有直接插入排序和希尔排序。排序算法的基本思想是:每一步都待排序的对象,按照关键码大小,插入到已经排好序的一组数据中适当位置去,直到所有对象全部插入完成。
1.直接插入排序
基本思想:
1)将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
2)从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
重点:设置一个边界监视,不断缩小边界监视以找到合适位置插入。
时间复杂度:O(N^2)
空间复杂度:O(1)
因为我们在插入时,如果待插入的元素与有序序列中的某个元素相等,就将待插入元素插入到相等元素的后面。所以,直接插入排序是稳定的。
void InsertSort(int a[] ,size_t n)
{
assert(a);
for (size_t i = 0; i < n - 1; i++)
{
int tmp = a[i + 1];
int end = i;
while (end >= 0)
{
if (a[end]>tmp)
{
a[end + 1] = a[end];
end--;
}
else
break;
}
a[end + 1] = tmp;
}
}
2.希尔排序
基本思想:将待排序数组按照步长gap进行分组,然后将每组的元素利用直接插入排序的方法进行排序;每次将gap折半减小,循环上述操作;当gap=1时,利用直接插入,完成排序。
重点:合理选择增量因子gap
时间复杂度:O(N^3/2)
空间复杂度:O(1)
下面就一个例子分布展示:
希尔排序的实时性分析比较难,比较次数与增量因子和移动次数有关,增量因子的取法比较多,但是最后一次增量因子必定为1,并且希尔排序是一个不稳定的排序。
void ShellSort(int a[],size_t n)
{
int gap = n;
while (gap > 1)
{
gap = gap / 2;
for (size_t i = 0; i < n - gap; i++)
{
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (a[end]>tmp)
{
a[end + gap] = a[end];
}
else
break;
end -= gap;
}
a[end + gap] = tmp;
}
}
}