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

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

  • 前言
  • [一 、插入排序](#一 、插入排序)
    • [1. 视频演示](#1. 视频演示)
    • [2. 算法思想](#2. 算法思想)
    • [3. 实现思路](#3. 实现思路)
    • [4. 代码演示](#4. 代码演示)
  • [二 、希尔排序](#二 、希尔排序)
  • 结语

前言

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

一 、插入排序

1. 视频演示

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

插入排序演示

2. 算法思想

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

3. 实现思路

由视频可知,数据 x(标红的)前面的序列都是有序的,故每一次只需要将 x 插入其中即可

  • 第一步

我们给定下标范围【0,end】区间是有序的,tmp为要插入的数据的值,故tmp为下标为end + 1所对应的值

  • 第二步

将下标为end所对应的值与tmp比较
tmp比前一个数据小,则tmp就再向前一个数比较
tmp比前一个数据大,则tmp就插入到这个数据的后面

  • 第三步

循环遍历整个数组,直到数组全部插入进去

4. 代码演示

c 复制代码
// 插入排序
void InsertSort(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 就是被分成了几组)

c 复制代码
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. 代码演示

代码演示:

c 复制代码
// 希尔排序
void ShellSort(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)

相关推荐
CoderCodingNo2 小时前
【GESP】C++五级真题(前缀和思想考点) luogu-P10719 [GESP202406 五级] 黑白格
开发语言·c++·算法
小毅&Nora2 小时前
【后端】【C++】协程深度解析:从内部机制到实用场景
c++·协程
苦 涩2 小时前
考研408笔记之计算机组成原理(五)——中央处理器
笔记·计算机组成原理·考研408
C雨后彩虹2 小时前
ConcurrentHashMap 扩容机制:高并发下的安全扩容实现
java·数据结构·哈希算法·集合·hashmap
Trouvaille ~2 小时前
【C++篇】让错误被温柔对待(上):异常基础与核心机制
运维·开发语言·c++·后端·异常·基础入门·优雅编程
Chip Design2 小时前
量子–经典混合计算生态:量子启发式、量子模拟、经典算法
算法·量子计算
BB学长2 小时前
Icepak|01功能介绍
算法·数学建模·能源·微信公众平台
QT 小鲜肉2 小时前
【Linux命令大全】001.文件管理之mlabel命令(实操篇)
linux·运维·服务器·前端·笔记
Cathy Bryant2 小时前
傅里叶变换(二):旋转楼梯
笔记·算法·数学建模·信息与通信·傅里叶分析