有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——插入排序插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。
希尔排序是一种插入排序算法,它出自D.L.Shell,因此而得名。Shell排序又称作缩小增量排序。
算法分析
代码实现
#include<stdio.h>
#include<stdlib.h>
void print_array(int *array, int length)
{
int index = 0;
printf("array:\n");
for(; index < length; index++){
printf(" %d,", *(array+index));
}
printf("\n\n");
}
void insertSort(int *array, int length)
{
int index_i, index_j, tmp;
for (index_i = 1; index_i < length; index_i++){ // 从第二个元素往后得到哨兵元素
tmp = array[index_i];
for (index_j = index_i - 1; index_j >= 0 ; index_j--){ // 和前面有序的元素进行比较 调整
if (array[index_j] > tmp) array[index_j + 1] = array[index_j];
else break;
}
array[index_j + 1] = tmp;// 找到合适的位置插入
}
}
void shellSort(int *array, int length)
{
int d = 5;
int i , j, tmp;
while(d){ // 判断增量
for ( i = d; i < length; i = i + d){ // 从第一个增量值往后 得到哨兵元素
tmp = array[i];
for (j = i -d ; j >= 0; j = j - d){ // 和前面有序的元素进行调整
if (array[j] > tmp) array[j+d] = array[j];
else break;
}
array[j+d] = tmp;
}
d = d/2; // 缩小增量的值
}
}
int main(void)
{
//int array[] = {12, 1, 32, 201, 9987, 5, 10, 10090, 123, 453};
int array[] = {2, 1, 3, 201, 987, 5, 10, 90, 13, 45};
int length = (sizeof(array)) / (sizeof(array[1]));
print_array(array, length);
insertSort(array, length);
print_array(array, length);
printf("\n\n======================\n\n");
shellSort(array, length);
print_array(array, length);
return 0;
}
运行结果
时间复杂度
插入排序的时间复杂度:
在最好的情况下(元素已经排好顺序):那么只需要循环 n-1 次就可以了,时间复杂度 O(n)
在最差的情况下 (元素是逆序的):要循环调整次数: [ n * (n-1) ] / 2 ,时间复杂度为 O(n ^ 2)
平均时间复杂度为:O(n ^ 2)
shell排序的时间复杂度:
shell排序的时间复杂度是根据选中的 增量d 有关的,所以分析shell排序的时间复杂度是个比较麻烦的事;这里只给出答案,不推算了;
在最优的情况下,时间复杂度为:O(n ^ (1.3) ) (元素已经排序好顺序)
在最差的情况下,时间复杂度为:O(n ^ 2);
空间复杂度
空间复杂度都为:O(1);

本文介绍了插入排序的基本原理,适用于少量数据排序,时间复杂度为O(n^2),是稳定的排序方法。接着讲解了希尔排序,作为插入排序的改进版,其时间复杂度与增量d有关,在最优情况下为O(n^(1.3)),最差情况为O(n^2),空间复杂度均为O(1)。
458





