博客主页:【夜泉_ly】
本文专栏:【算法】
欢迎点赞👍收藏⭐关注❤️
文章目录
💡插入排序
插入排序可以分为直接插入排序和希尔排序。
1. ➡️ 直接插入排序
🖼️示意图
插入排序 − 示意图 插入排序 -示意图 插入排序−示意图
📖简介
直接插入排序常用于处理数据量较小的情况,其思想和打牌类似,都是将新元素插入到有序数组。
时间复杂度为 O ( N 2 ) O(N^2) O(N2) 。如果数据量过大,直接插入排序会因频繁的挪动数据降低效率。
💡实现思路
- 定义一个指针
end
,初始为0
,表示已排序数组的结束位置。 - 取牌,用一个临时变量
tmp
存储end + 1
处的值,表示待插入的值。 - 挪牌,将已排序的数组中小于
tmp
的向后挪动一个位置。(这里end + 1
的值已被保存,可以直接覆盖)- 定义
cur
指向end
。 - 如果
cur
处的值大于tmp
,将该值向后挪动一位,然后cur--
。 - 结束条件为
cur <= -1
或者cur
处的值小于等于tmp
。
- 定义
- 插入,将
tmp
插入cur + 1
处,然后end++
。 - 结束条件为
end >= size - 1
,即所有元素都已排序。
💻代码实现
cpp
void InsertSort(int* arr, int size)
{
for (int end = 0; end != size - 1; end++)
{
int tmp = arr[end + 1];
int cur = end;
while (cur > -1 && arr[cur] > tmp)
{
arr[cur + 1] = arr[cur];
cur--;
}
arr[cur + 1] = tmp;
}
}
📝具体示例
待排序数组:
首先,定义一个指针 end
,指向 0
处,表示已排序手牌:
取牌,用一个临时变量 tmp
存储 end + 1
处的值,表示待插入的手牌:
挪牌:(当cur == -1
,停止挪牌)
插入:(将tmp
插入cur + 1
处)
第二轮取牌加挪牌:(当cur
处的值小于 tmp
,也停止挪牌)
插入:
之后,重复上述过程即可。
2. ⬆️ 希尔排序
🖼️示意图
希尔排序 − 示意图 希尔排序 -示意图 希尔排序−示意图
📖简介
希尔排序是插入排序的升级版,本质是通过分组进行插入排序,可以将较大的数据尽快的挪到数组后面,从而减少挪动数据的次数,提高了效率。
时间复杂度大约为 O(N ^ 1.3),具体时间复杂度会随分组的标准而变。
💡实现思路
- 定义
gap
,初始值为size/3 + 1
,间隔为gap
的数被分到一组。 - 对每组进行插入排序
- 定义一个指针
end
,初始为0
,表示已排序数组的结束位置。 - 取牌,用一个临时变量
tmp
存储end + gap
处的值,表示待插入的值。 - 挪牌,将已排序的数组中小于
tmp
的向后挪动一个位置。(这里end + gap
的值已被保存,可以直接覆盖)- 定义
cur
指向end
。 - 如果
cur
处的值大于tmp
,将该值向后挪动一位,然后cur -= gap
。 - 结束条件为
cur <= -1
或者cur
处的值小于等于tmp
。
- 定义
- 插入,将
tmp
插入cur + gap
处,然后end++
。 - 结束条件为
end >= size - gap
,即所有元素都已排序。
- 定义一个指针
gap = gap/3 + 1
gap == 1
为最后一次排序,此时变为直接插入排序。(经过了预处理,此时的直接插入排序效率大大提高)
💻代码实现
cpp
void ShellSort(int* arr, int size)
{
int gap = size;
while (gap != 1)
{
gap = gap / 3 + 1;
int end = 0;
while (end < size - gap)
{
int tmp = arr[end + gap];
int cur = end;
while (cur > -1 && arr[cur] > tmp)
{
arr[cur + gap] = arr[cur];
cur -= gap;
}
arr[cur + gap] = tmp;
end++;
}
}
}
希望本篇文章对你有所帮助!并激发你进一步探索编程的兴趣!
本人仅是个C语言初学者,如果你有任何疑问或建议,欢迎随时留言讨论!让我们一起学习,共同进步!