一、直接插入排序算法
1、直接插入排序算法(Straight Insertion Sort)的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数加一的有序表;它属于一种插入排序的方法。
2、实现如下代码所示:
#include <stdio.h>
// 定义待排序记录类型
typedef int RecordType;
/**
* 将待排序记录数组的下标i和下标j的两个记录进行交换
*/
void Swap(RecordType *rs, int i, int j)
{
RecordType tmp = *(rs + i);
*(rs + i) = *(rs + j);
*(rs + j) = tmp;
}
/**
* 打印待排序记录数组
*/
void PrintRs(RecordType rs[])
{
int i, count = rs[0];
for (i = 1; i <= count; i++)
{
printf("%d ", rs[i]);
}
printf("\n");
}
/**
* 对记录列表进行直接插入排序
*/
void StraightInsertionSort(RecordType *rs)
{
int i, j, count = rs[0];
for (i = 2; i <= count; i++)
{
if (*(rs + i) < *(rs + i - 1))
{
*rs = *(rs + i); // 用下标0的位置来保存当前记录
for (j = i - 1; *(rs + j) > *rs; j--) // 当j=1时,其实就指向了当前记录,是不可能大于自己的,所以这里的条件是不需要加上j >= 1判断的
{
*(rs + j + 1) = *(rs + j);
}
*(rs + j + 1) = *rs;
}
}
*rs = count; // 恢复下标0的元素为待排序记录个数
}
int main()
{
RecordType rs[] = {5, 1, 5, 3, 2, 4};
printf("排序前记录列表排序为:\t\t");
PrintRs(rs);
StraightInsertionSort(rs);
printf("从小到大排序后,记录列表排序为:");
PrintRs(rs);
return 0;
}
3、时间复杂度
从空间复杂度角度看,它只需要一个记录的辅助空间(下标0的位置)。从时间复杂度角度看,最好的情况是要排序的记录列表本身就是有序的,那么只需要n - 1次比较而已,没有移动,时间复杂度为O(n);最坏情况是待排序列表是倒序排列的,此时需要比较2+3+...+n=(n+2)(n-1)/2次,而记录的移动次数是达到最大值3+4+...+(n+1)=(n+4)(n-1)/2次。所以如果排序记录是随机的,根据概率相同的原则,平均比较和移动次数均约为(n^2)/4次,所以直接插入排序算法的时间复杂度为O(n^2)。同样是O(n^2)的时间复杂度,直接插入排序算法比冒泡算法和简单选择排序算法的性能稍好一些。
参考书籍:《大话数据结构》