【C语言】排序算法——希尔排序以及插入排序 ——详解!!!

【C语言】排序算法——希尔排序以及插入排序 ——详解!!!

【C语言】排序算法——希尔排序以及插入排序详解

前言

在学习循环的时候,我们学习到了冒泡排序这个算法
那么,除了冒泡排序,还有什么排序算法呢?
今天给大家带来的是插入排序以及希尔排序

一 、插入排序

1. 视频演示

首先给大家看一段视频,让大家先看看插入排序是怎么运行的

插入排序演示

2. 算法思想

我们可以从视频里看见,插入排序就像是我们打扑克牌一样,一张一张插入到了有序队列
每次都有一个数据 x(标红的)要跟前面的数据一一比大小
若 x 比前一个数据小,则 x 就再向前比较
若 x 比前一个数据大,则 x 就插入到这个数据的后面

3. 实现思路

由视频可知,数据 x(标红的)前面的序列都是有序的,故每一次只需要将 x 插入其中即可
  • 第一步
我们给定下标范围【0,end】区间是有序的,tmp为要插入的数据的值,故tmp为下标为end + 1所对应的值
  • 第二步
将下标为end所对应的值与tmp比较
tmp比前一个数据小,则tmp就再向前一个数比较
tmp比前一个数据大,则tmp就插入到这个数据的后面
  • 第三步
循环遍历整个数组,直到数组全部插入进去

4. 代码演示

// 插入排序voidInsertSort(int* a,int n){for(int i =0; i < n -1; i++){int end = i;int tmp = a[end +1];while(end >=0){if(tmp < a[end]){ a[end +1]= a[end]; end--;}else{break;}} a[end +1]= tmp;}}

二 、希尔排序

1. 视频演示

首先给大家看一段视频,让大家先看看希尔排序是怎么运行的

希尔排序视频演示

2. 算法思想

当你看完视频,你也许就会发现希尔排序和插入排序很相似
只不过,希尔排序相当于间隔插入排序 n 次
而每一次都越来越接近有序数组,直到最后一次排成有序

3. 实现思路

那该怎么实现呢?

(1)分组

  • 第一步:分组
由视频可知,每次排序并不是一个一个排,而是每间隔几个数据成一组来排序
一组一组排,这组排完就到下一组,直到全部排完
这里先假设分成3组数据进行排序,也就是每隔2个数据成一组

如图:

在这里插入图片描述

(2)预排序

  • 第二步:预排序
分成了几组后,每一组就开始插入排序,称为预排序
插入排序前面讲了,就不赘述了

代码演示:
( gap 就是被分成了几组)

int gap = n;while(gap >1){ gap =3;for(int i =0; i < n - gap; i++){int end = i;int tmp = a[end + gap];while(end >=0){if(tmp < a[end]){ a[end + gap]= a[end]; end -= gap;}else{break;}} a[end + gap]= tmp;}}
预排序是干什么呢?
预排序的主要功能就是让一个数组接近有序,为了给后面的插入排序节省大量的时间

(3)最终排序

  • 第三步:最终排序
现在,在排序完三组数据后,我们的数组已经很接近有序
所以现在只需要用插入排序排最后一次收尾就行了

这里就不进行代码演示了,就是一个普通的插入排序

(4)gap的取值

  • 第四步:gap的取值
、前面我们的代码中 gap 的取值定为了 3,但是这不可能对于每个数组都适应
那么该如何给 gap 来取值呢?
根据科学的实验,发现当gapn / 3时,排序最快
所以,在排序的过程中,gap 的值是不断发生变化的
、到这里,可能已经有人发现了,刚刚写的预排序和前面写的插入排序几乎一摸一样
只是将 1 变成了 gap
>其实,当gap1时,就是普通的插入排序

那么我们能不能设计一个循环,既能在排序的过程中满足gap的动态变化,又能使gap的最后一次取值为 1 呢?

所以我们可以有一些改进,在函数外面再套一层循环:
int gap = n;
while (gap > 1)
{
gap = gap / 3 + 1;
…………
…………//这里省去代码
}

这样,gap能够很好的动态变化,且最后一次循环的gap值为1,恰好能完成一次普通的插入排序

4. 代码演示

代码演示:

// 希尔排序voidShellSort(int* a,int n){int gap = n;while(gap >1){ gap = gap /3+1;for(int i =0; i < n - gap; i++){int end = i;int tmp = a[end + gap];while(end >=0){if(tmp < a[end]){ a[end + gap]= a[end]; end -= gap;}else{break;}} a[end + gap]= tmp;}}}

结语

OK,本期的排序算法详解到这里就结束了

若内容对大家有所帮助,可以收藏慢慢看,感谢大家支持

本文有若有不足之处,希望各位兄弟们能给出宝贵的意见。谢谢大家!!!

新人,本期制作不易希望各位兄弟们能动动小手,三连走一走!!!

支持一下(三连必回QwQ)

Read more

初探算法的魅力——【暴力枚举】

初探算法的魅力——【暴力枚举】

点击下面查看作者专栏🔥🔥C语言专栏🔥🔥🌊🌊编程百度🌊🌊🌠🌠如何获取自己的代码仓库🌠🌠 🌐索引与导读 * 暴力枚举(BF)的概念 * 暴力枚举的算法步骤 * 例题讲解 * 经典案例讲解一:百鸡问题 * 题目解析 * 思路方案 * 经典案例讲解二:盛最多水的容器 * 暴力枚举算法 * 最优解 * 经典案例讲解三:两数之和 * 经典案例讲解四:2025 * 💻 代码实现 * 希望读者多多三连 * 给小编一些动力 * 蟹蟹啦! 暴力枚举(BF)的概念 暴力枚举也称为穷举法,是计算机算法中最基础、最直观,但也是最费劲的一种解题思路 像我们平时没有最优解的算法题,往往都可以通过暴力枚举去算出最终结果 * 核心思想 不靠巧妙的技巧,而是利用计算机强大的计算能力,把所有可能的情况列举出来,一个一个去验证,直到找到正确答案 暴力枚举的算法步骤 * 列举 :确定解空间的范围,列出所有可能的解候选者 * 检验 :对每一个候选者进行判断,看它是否满足题目

By Ne0inhk
哈希表的介绍和使用

哈希表的介绍和使用

一.哈希表的概念   哈希又称散列,本质是通过一种键值对存储的高校组织方式。通过一个哈希函数,将数据的关键字直接映射到存储的数据中,实现快速的定位。   就像在图书馆中可以根据图书的编号来快速查找图书的位置。 二.直接定址法   直接借用关键字作为存储位置的下标, class Solution { public:     int first(string s) {         int count[26] = { 0 };         for (auto e : s) {             count[e - 'a']++;         }         for (size_t i = 0; i < s.size(); i++) {             if (count[s[i] - 'a'

By Ne0inhk
数据结构:手撕堆和哈希表,字符串哈希详解----小白也能懂

数据结构:手撕堆和哈希表,字符串哈希详解----小白也能懂

🎬 博主名称:个人主页 🔥 个人专栏: 《算法通关》,《Java讲解》 ⛺️心简单,世界就简单 序言 其实是想把这篇写到上一篇里面的,但是中途困了,趴桌子上睡着了,真是没招 这篇文章,来手撕 堆和哈希表,这一般面试可能会问到,我们来了解他的思想和思路也是比较舒服的 目录 序言 堆 堆的存储 堆有两个基本操作 1,down( x ) 2 , up( x ) 操作一:插入一个数 操作二:求集合中的最小值 操作三:删除最小值 操作四:删除任意一个元素 操作五:修改任意一个元素 题目模板练习1 题目模板练习二 总结: 哈希表 存储结构:拉链法 存储结构:开放寻址法 处理冲突思路: 查找 删除 总结

By Ne0inhk
极致性能的服务器Redis之Hash类型及相关指令介绍

极致性能的服务器Redis之Hash类型及相关指令介绍

目录 1. Hash介绍 2. hset 3. hget 3. hdel 5. hkeys 6. hvals 编辑 7. hgetall  8. hexists 9. hmget 10. hlen 11. hsetnx 12. hincrby 13. hincrbyfloat 1. Hash介绍 Redis 哈希类型是键值对的集合,字段与值均支持字符串、数字等类型,适合建模用户信息、配置项等对象类数据。其支持单字段 / 多字段的增删改查、字段存在性判断、值自增自减等原子操作,且底层通过压缩列表或哈希表优化存储,空间利用率高、查询效率快,是 Redis 中存储结构化数据的核心类型之一。 在Redis中因为本身就是按照哈希的KV结构来进行存储的,所以当我们想要使用Redis里面的哈希的时候,实际上是哈希的哈希,在后者中,

By Ne0inhk