title: 直接插入排序
date: 2020-12-22 16:48:21
tags: 排序算法
categories: 数据结构
平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|
O(n^2) | O(n^2) | O(1) | 稳定 |
讲解版
#include <stdio.h>
int main(void)
{
// 初始化一个数组,0号空间不用,给它赋值成0
int arr[11] = {0, 0, 8, 5, 1, 2, 9, 4, 3, 7, 6};
int arrLen = 10;
// 长度是10, 但是由于0号空间不用,
// 所以在for循环中,判断条件应该是 < arrLen + 1 或 <= arrLen
for (int i = 2; i < arrLen + 1; i++)
{
// 比前面已经排好的序列的最后一个小,就插入排序,
// 如果比前面已经排好的序列的最后一个大,说明这个数直接插最后边就行
// 所以外层循环直接过就可,不用执行 if 中的语句
if (arr[i] < arr[i - 1])
{
// 进入这个if 就说明要开始插入的流程了
// 复制哨兵
arr[0] = arr[i];
// 给新的数腾地方
// 因为刚才比较过 arr[i] 和 arr[i - 1]的大小了,
// 所以在这里直接腾地方就可
arr[i] = arr[i - 1];
// 接着比较前面的,只要比哨兵中的值(哨兵的值即是要插入的新数的值)大
// 就往后走一个,给新数腾地方
// 直到遇见一个 >= 要插入的新数的数,
// 此时循环中断, j 是第一个比新数大的数的下标,
// 由于j之后的数都挪地方了, 而j比新数大,所以不挪地方
// 所以将新数放到 j 指向的位置的下一个就行
int j = i - 2;
for (j = i - 2; arr[j] > arr[0]; j--)
arr[j + 1] = arr[j];
arr[j + 1] = arr[0];
}
}
for (int i = 1; i < arrLen + 1; i++)
printf("%d\n", arr[i]);
return 0;
}
封装版
// 数组封装成数据类型
// 排序封装成函数
#include <stdio.h>
#define MAXSIZE 100
typedef struct
{
int arr[MAXSIZE + 1];
// 数组有效长度不包括0号元素
// 单纯指有效数据的个数
int length;
}Sql;
void insertSort(Sql *sql)
{
for (int i = 2; i <= sql->length; i++)
{
if (sql->arr[i - 1] > sql->arr[i])
{
sql->arr[0] = sql->arr[i];
sql->arr[i] = sql->arr[i - 1];
int j;
for (j = i - 2;sql->arr[j] > sql->arr[0]; j--)
sql->arr[j + 1] = sql->arr[j];
sql->arr[j + 1] = sql->arr[0];
}
}
}
int main(void)
{
Sql sql;
sql.length = 10;
// 初始化一个倒序数组
for (int i = 1; i <= sql.length; i++)
sql.arr[i] = sql.length - i;
// 打印排序前的数组
for (int i = 1; i <= sql.length; i++)
printf("%d ", sql.arr[i]);
printf("\n");
// 调用插入排序函数
insertSort(&sql);
// 打印排序后的数组
for (int i = 1; i <= sql.length; i++)
printf("%d ", sql.arr[i]);
printf("\n");
return 0;
}