# 插入排序
# 算法思想
每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。
// 举例
int arr[] = { 3, 1, 5, 7, 2, 4, 9, 6 };
// 第一轮替换
int arr[] = { 1, 3, 5, 7, 2, 4, 9, 6 };
// 第二轮替换
int arr[] = { 1, 2, 3, 5, 7, 4, 9, 6 };
// 第三轮替换
int arr[] = { 1, 2, 3, 4, 5, 7, 9, 6 };
// 第四轮替换
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 9 };
// 代码实现
void insertSort(int *arr, int length) {
int i, j, temp;
// 从第二个元素开始,因为第一个元素默认是有序的
for (i = 1; i < length; ++i) {
// 如果当前元素比前一个元素小,那么就需要将当前元素插入到前面的有序序列中
if (arr[i] < arr[i - 1]) {
// 保存当前元素
temp = arr[i];
// 从当前元素的前一个元素开始,依次和当前元素比较,如果比当前元素大,那么就将该元素后移一位
for (j = i - 1; j >= 0 && arr[j] > temp; --j) {
//这里将大于temp的数都后移一位
arr[j + 1] = arr[j];
}
// 将当前元素插入到合适的位置
arr[j + 1] = temp;
}
}
}
//第二种实现方式 (这种方式比较好理解)
void insertSort(int *arr, int length) {
int i, j, temp;
// 从第二个元素开始,因为第一个元素默认是有序的
for (i = 1; i < length; ++i) {
// 如果当前元素比前一个元素小,那么就需要将当前元素插入到前面的有序序列中
if (arr[i] < arr[i - 1]) {
// 保存当前元素
temp = arr[i];
// 从当前元素的前一个元素开始,依次和当前元素比较,如果比当前元素大,那么就将该元素后移一位
for (j = i - 1; j >= 0; --j) {
if (arr[j] > temp) {
arr[j + 1] = arr[j];
} else {
break;
}
}
// 将当前元素插入到合适的位置
arr[j + 1] = temp;
}
}
}
// 第三种实现方式 (带哨兵) 这种就是把下表为0的元素当做哨兵,这样就不用每次都判断j>=0了 个人认为没啥必要
void insertSort(int *arr, int length) {
int i, j;
// 从第二个元素开始,因为第一个元素默认是有序的
for (i = 2; i < length; ++i) {
// 如果当前元素比前一个元素小,那么就需要将当前元素插入到前面的有序序列中
if (arr[i] < arr[i - 1]) {
// 将当前元素插入到合适的位置
arr[0] = arr[i];
// 从当前元素的前一个元素开始,依次和当前元素比较,如果比当前元素大,那么就将该元素后移一位
for (j = i - 1; arr[j] > arr[0]; --j) {
arr[j + 1] = arr[j];
}
// 将当前元素插入到合适的位置
arr[j + 1] = arr[0];
}
}
}
# 算法分析
# 时间复杂度
最好情况:O(n)
- 一般就是有序的 是不需要移动的 也是常数级别的
最坏情况:O(n^2)
- 一般就是逆序的,每一项都需要移动
平均情况:O(n^2)
# 空间复杂度
O(1)
# 稳定性
稳定
# 折半插入排序
也叫二分插入排序,是对直接插入排序算法的一种改进,由于排序过程中,前面的元素总是已经排好序的,所以可以使用折半查找的方式来减少比较次数,提高效率。
- 只能用于顺序存储结构,不适用于链式存储结构。顺序查找支持下表随时访问
- 个人认为 时间复杂度还是O(n^2) 就是少了一些比较次数
// 代码实现
void binaryInsertSort(int *arr, int length) {
int i, j, temp, low, high, mid;
// 从第二个元素开始,因为第一个元素默认是有序的
for (i = 1; i < length; ++i) {
// 如果当前元素比前一个元素小,那么就需要将当前元素插入到前面的有序序列中
if (arr[i] < arr[i - 1]) {
// 保存当前元素
temp = arr[i];
// 从当前元素的前一个元素开始,依次和当前元素比较,如果比当前元素大,那么就将该元素后移一位
low = 0;
high = i - 1;
while (low <= high) {
mid = (low + high) / 2;
if (arr[mid] > temp) {
high = mid - 1;
} else {
low = mid + 1;
}
}
// 将当前元素插入到合适的位置
for (j = i - 1; j >= high + 1; --j) {
arr[j + 1] = arr[j];
}
arr[high + 1] = temp;
}
}
}