主要讲述插入排序与希尔排序的主要思想以及具体实现。
插入排序
主要思想
直 接 插 入 排 序 是 一 种 简 单 的 插 入 排 序 法 , 其 基 本 思 想 是:
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为 止,得到一个新的有序序列。
实际中我们玩扑克牌时,就用了插入排序的思想
当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移。
如图:


算法实现
//插入排序
void InsertSort(int* a, int n)
{
for (int i = 1; i < n; i++)
{
int end = i - 1;
int temp = a[i];
while (end >= 0)
{
if (a[end] > temp)
{
a[end + 1] = a[end];
end--;
}
else
break;
}
a[end + 1] = temp;
}
}
end记录下标 i-1 ,temp记录要插入的数,当a[end]>temp时,将a[end]的数向后移动一位,同时下标end向前移动一位,更新a[end]。直到找到temp的位置或end越界,停下将temp放到a[end+1](end我们已经进行 -- ,空出来的位置应是end+1)的位置上去。如此反复的一个一个插入就变得有序。
直接插入排序的特性总结:
- 元素集合越接近有序,直接插入排序算法的时间效率越高
- 时间复杂度:O(N^2)
- 空间复杂度:O(1),它是一种稳定的排序算法
- 稳定性:稳定
希尔排序
基本思想
希尔排序是在插入排序的基础上进行的优化,我们想插入排序每次都是一个一个的排,可不可以依次跳跃式的排序?
希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成多个距离为整数的组,所有距离为整数的记录分在同一组内,并对每一组内的记录进行排序。然后,缩小整数距离,重复上述分组和排序的工 作。当到达整数距离=1时,所有记录在统一组内排好序。
如图:

每一次都跳跃式的排序,这样可以将有些数更快速的排到应该在的位置。最后,当gap=1时,这个数组就已经接近有序了,再次进行排序就会方便很多(因为有的数就不需要挪动)。我们将gap>1时的排序叫做预排序,gap=1时就是插入排序了。
希尔排序的特性总结:
- 希尔排序是对直接插入排序的优化。
- 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
- 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的 希尔排序的时间复杂度都不固定:
算法实现
//希尔排序
void ShellSort(int* a, int n)
{
//预排序
int gap = n;
while (gap > 1)
{
gap = gap / 3 + 1;//gap的取法并不固定,这里+1是为了保证最后一次gap=1.
for (int i = 0; i < n - gap; i++)
{
int end = i;
int temp = a[i + gap];
while (end >= 0)
{
if (a[end] > temp)
{
a[end + gap] = a[end];
end -= gap;
}
else
break;
}
a[end + gap] = temp;
}
}
}
文章详细介绍了插入排序和希尔排序两种算法的主要思想及其实现过程。插入排序是一种简单的排序方法,通过逐个插入元素并比较来构建有序序列,适合接近有序的数组。希尔排序则是插入排序的优化版本,通过间隔插入来预排序,提高效率。希尔排序的时间复杂度因间隔序列的不同而难以精确计算。
1495





