(1) 直接插入排序
直接插入排序是一种简单粗暴的排序算法,即每一步都把一个待排数据按其大小插入到一个已排好序的序列当中, 直到整个序列都排为有序为止。
例如:要以升序排下面这个序列:
直接插入排序算法的的最好情况就是当序列已经有序的时候,这时候只需要进行n-1次比较就行,也不用进行任何的数据移动,这时的时间复杂度是O(N);但最坏的情况下是逆序的时候,此时所有数据都要移动,时间复杂度为O(N^2)非常的低效。因此,插入排序是不适合于数据量特别大的序列排序的。
下面我在再讲另一种排序算法:
(2)希尔排序
希尔排序也是一种插入排序,是直接插入排序算法的优化。采用了分治的思想将一整个序列分成几个组,再对每个组进行排序,尽可能的让较大的数据往序列的的后边移,让较小的数据往序列的前边移。
这里用一个变量gap来记录一个两个分组之间的距离,也可以叫做增量,希尔排序就是通过缩小这个增量进行排序来提高效率的,这一步也叫做预排序:
假如还是对上面提到的数组序列进行排序,则排序结果如下:
这里最重要的就是确定gap的值啦!在我的代码中gap=gap/3+1(gap初始为数组元素个数),因此,第一趟排序中,gap=4;第二趟排序中gap=2;最后一趟排序中gap=3,相当于直接插入排序,但此时整个数组基本接近有序,所以直接插入排序效率还是挺高的。
希尔排序算法就是通过预排序避免了直接插入排序算法中效率较低的情况,再进行直接插入排序,达到了一定的优化效果。
下面给出我自己实现这两种排序算法的代码:
void InsertSort(int *arr,size_t size)
{
for (int index = 1; index < size; index++)
{
int tmp = arr[index];
int pos = index - 1;
while (pos >= 0 && tmp < arr[pos])
{
arr[pos+1] = arr[pos];
pos--;
}
arr[pos + 1] = tmp;
}
}
void ShellSort(int *arr,size_t size)
{
size_t gap = size ;
while (gap > 1)
{
gap = gap / 3 + 1;//分组
for (int index = gap; index < size; index++)
{
int tmp = arr[index];
int pos = index - gap;
while (pos >= 0 && tmp < arr[pos])
{
arr[pos + gap] = arr[pos];
pos -= gap;
}
arr[pos + gap] = tmp;
}
}
}