数据结构|排序算法(二)插入排序 希尔排序 冒泡排序

news2025/4/12 15:08:46

一、插入排序

1.算法思想

插入排序(Insertion Sort)是一种简单的排序算法,其基本思想是:将待排序的元素插入到已经有序的序列中,从而逐步构建有序序列。

具体过程如下:

  1. 把待排序的数组分为已排序和未排序两部分。初始时,已排序部分只有第一个元素,即数组的第一个元素被认为是已经有序的
  2. 从第二个元素开始,也就是未排序部分的第一个元素,将其与已排序部分的元素从后往前依次比较(因为从后往前越来越有序,则越快)
  3. 如果当前元素(未排序部分的元素)小于已排序部分的某个元素,就将该元素往后移动一位,为当前元素腾出位置
  4. 重复步骤 3,直到找到一个已排序元素小于或等于当前元素,或者已经比较到了已排序部分的第一个元素。
  5. 将当前元素插入到合适的位置,这样就将一个未排序元素插入到了已排序序列中,使得已排序序列的长度增加 1。
  6. 对未排序部分的下一个元素重复步骤 2 到 5,直到所有元素都被插入到已排序序列中,此时整个数组就完成了排序。

插入排序就像人们平时整理扑克牌一样,每次从手中的未整理牌中拿起一张,然后将其插入到已整理好的牌中的合适位置。

2.代码实现

//插入排序
void InsertSort(int* arr, int len)
{
	int tmp,i,j;
	for (i = 1; i < len; i++)//i是当前要处理的数字的下标
	{
		tmp = arr[i];//取出当前要插入的元素
		//遍历已排序的部分
		for (j = i - 1; j >= 0; j--)//从i的前一个开始找位置,从后往前找,找比当前数字小的,同时移动数据
		{
			if (arr[j] > tmp)
			{
				arr[j + 1] = arr[j];//将比tmp大的元素后移
			}
			else
			{
				//arr[j + 1] = tmp;
				break;
			}
		}
		arr[j + 1] = tmp;//将tmp插入正确位置,放到比tmp小的元素的后面
	}
}

3.复杂度分析 

该算法在最好情况下(数组已经有序)时间复杂度为O(n),越有序越快,完全有序为O(n);在最坏情况下(数组逆序)时间复杂度为O(n2),空间复杂度为O(1),是一种稳定的排序算法。

所以在一组数据基本有序的情况下,用直接插入排序。

二、希尔排序

1.算法思想

希尔排序(Shell Sort)是插入排序的一种改进版本,也称为缩小增量排序。

希尔排序的基本思想是将原始数据分成若干个子序列,每个子序列的元素间隔较大,然后对每个子序列进行插入排序。随着排序的进行,逐渐减小子序列的元素间隔,直到间隔为 1,此时整个序列基本有序,再进行一次普通的插入排序即可完成排序

注意:分组时采用间隔式的排序!

希尔排序采用间隔式排序主要有以下原因:
加快元素移动速度:希尔排序将原始数据分成多个子序列,每个子序列的元素间隔较大。这样在排序过程中,元素可以以较大的步长移动,能更快地将元素移动到其最终位置附近。例如,对于一个很大的数组,如果直接进行插入排序,每个元素可能需要移动很多次才能到达最终位置。但希尔排序通过大间隔分组,让元素先进行 “远距离” 的移动,初步将数据大致排序,减少了后续插入排序时元素的移动次数。
改善最坏时间复杂度:传统的插入排序在最坏情况下(如数组完全逆序)时间复杂度为O(n2)
希尔排序通过间隔式排序,使数组在初始阶段就接近有序状态,当间隔逐渐减小时,数组已经基本有序,此时再进行插入排序,就可以避免最坏情况的发生,其平均时间复杂度介于O(n)
到O(n2)之间,通常能达到O(n1.3)左右,性能相比直接插入排序有显著提升。
利用局部有序性:在间隔式排序过程中,每个子序列内部进行排序,使得子序列逐渐变得有序。随着间隔逐渐缩小,子序列的长度逐渐增加,而之前已经排好序的子序列能为后续更大规模的排序提供一定的有序基础,充分利用了数据的局部有序性,提高排序效率。

希尔排序核心思想就是:1 间隔式分组;2 利用直接插入排序使组内有序:越有序越快;3 再缩小分组再排序,直到缩为1组。

2.代码实现

//希尔排序
//一趟希尔排序 gap为组数(间隔)
static void Shell(int* arr, int len, int gap)
{
	int tmp, i, j;
	for (i = gap; i < len; i++)//i是当前要处理的数字的下标
	{
		tmp = arr[i];//取出当前要插入的元素
		//遍历已排序的部分
		for (j = i - gap; j >= 0; j-=gap)//从i的前一个开始找位置,从后往前找,找比当前数字小的,同时移动数据
		{
			if (arr[j] > tmp)
			{
				arr[j + gap] = arr[j];//将比tmp大的元素后移gap
			}
			else
			{
				break;
			}
		}
		arr[j + gap] = tmp;//将tmp插入正确位置
	}
}
void ShellSort(int* arr, int len)
{
	int drr[] = { 5,3,1 };//分组数,最后一个组数一定为1
	for (int i = 0; i < sizeof(drr) / sizeof(drr[0]); i++)//循环控制分组的次数,此处分3次(5,3,1)
	{
		Shell(arr, len, drr[i]);//一趟希尔排序
	}
}

3.复杂度分析

希尔排序不稳定。

时间复杂度:希尔排序的时间复杂度与增量序列的选择有关。在最坏情况下,希尔排序的时间复杂度为O(n2)。在最好情况下,希尔排序的时间复杂度为O(nlogn)。
空间复杂度:希尔排序是一种原地排序算法,只需要常数级别的额外空间,因此空间复杂度为
O(1)。
稳定性:希尔排序是不稳定的排序算法。在排序过程中,相同元素的相对位置可能会发生改变。
希尔排序通过将原始数据分成多个子序列,每个子序列的元素间隔较大,使得元素可以更快地移动到其最终位置,从而提高了排序效率。它在处理大规模数据时表现较好,是一种常用的排序算法。

三、冒泡排序

1.算法思想

基本思想是:相邻两两比较,大的往后排
比较与交换:从数组的第一个元素开始,依次比较相邻的两个元素,如果前一个元素大于后一个元素,就将它们交换位置。这样,每一次比较和交换都会将当前未排序部分的最大元素 “浮” 到最后面。
多次遍历:对数组进行多次遍历,每一次遍历都会将未排序部分的最大元素放到合适的位置上,直到整个数组都被排序。

2.代码实现

//冒泡排序
void Bubble(int* arr, int len)
{
	int tmp;
	for (int i = 0; i < len-1; i++)//len个数字需要len-1趟,最后一个数字默认有序
	{
		tmp = arr[i];
		for (int j = 0; j +1< len-i; j++)//注意越界问题;len-i提高效率
		{
			if (arr[j] > arr[j + 1])
			{
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

3.复杂度分析

时间复杂度O(n2);空间复杂度O(1);稳定

以上是排序算法第二部分关于插入排序、希尔排序以及冒泡排序的知识,如果有帮助可以点赞收藏一下,会持续更新输出有用的内容,感兴趣可以关注我!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2331140.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

案例-流量统计

1.建一个data目录&#xff0c;在data下建log.txt文件 输入手机号码 上行流量 下行流量 2.在com.example.flow下建四个Java类3.flowBean flowMapper flowReducer flowDriver

Codeforces Round 1011 (Div. 2)

Dashboard - Codeforces Round 1011 (Div. 2) - Codeforces Problem - B - Codeforces 题目大意&#xff1a; 给你一个数组&#xff0c;你可以用一段子序列中没有出现的最小非负整数,替换数组中的组序列&#xff0c;经过若干操作&#xff0c;让数组变为长度为1&#xff0c;值…

时序数据异常检测-综述

更新中 异常检测基本概念 广义的Out-of-Distribution(广义的OOD)来描述异常检测的相关问题。OOD包括五个相关的子领域,分别为Anomaly Detection(AD)、Novelty Detection(ND)、Open Set Recogntion(OSR)、Out-of-Distribution(OOD)和Outlier Detection(OD)。这5个…

多类型医疗自助终端智能化升级路径(代码版.下)

医疗人机交互层技术实施方案 一、多模态交互体系 1. 医疗语音识别引擎 # 基于Wav2Vec2的医疗ASR系统 from transformers import Wav2Vec2Processor, Wav2Vec2ForCTC import torchaudioclass MedicalASR:def __init__(self):self.processor = Wav2Vec2Processor.from_pretrai…

蓝桥杯专项复习——双指针

目录 双指针算法&#xff1a;双指针算法-CSDN博客 最长连续不重复子序列 P8783 [蓝桥杯 2022 省 B] 统计子矩阵 双指针优化思路&#xff1a;当存在重复枚举时&#xff0c;可以考虑是否能使用双指针进行优化 双指针算法&#xff1a;双指针算法-CSDN博客 最长连续不重复子序列…

BetaFlight参数配置解读

BetaFlight参数配置解读 &#x1f4cc;相关篇《Betaflight固件编译和烧录说明》&#x1f955;各型号已编译好的配置文件资源&#xff08;.config&#xff09;&#xff1a;https://github.com/betaflight/unified-targets/tree/master/configs/default&#x1f33f;各型号配置头…

Java 容器源码分析

一、哈希表 1、引入 hash 表 在无序数组中按照内容查找&#xff0c;效率底下&#xff0c;时间复杂度是 O(n) 在有序数组中按照内容查找&#xff0c;可以使用折半查找&#xff0c;时间复杂度 O&#xff08;log2n&#xff09; 哈希表可以不进行比较&#xff0c;通过计算得到地…

【Java中级】11章、枚举 - java引用数据类型,枚举介绍、快速入门,了解枚举类的基本使用方式【1】

文章内容&#xff1a; 自定义实现枚举enum关键字实现枚举 ❤️内容涉及枚举的定义&#xff0c;快速入门&#xff0c;注意事项和小题巩固知识点 &#x1f308; 跟着B站一位老师学习的内部类内容&#xff0c;现写这篇文章为学习内部类的小伙伴提供思路支持&#xff0c;希望可以一…

Jmeter 插件【性能测试监控搭建】

1. 安装Plugins Manager 1.1 下载路径&#xff1a; Install :: JMeter-Plugins.org 1.2 放在lib/ext目录下 1.3 重启Jmeter&#xff0c;会在菜单-选项下多一个 Plugins Manager菜单&#xff0c;打开即可对插件进行安装、升级。 2. 客户端(Jmeter端) 2.1 安装plugins manager…

【ES系列】Elasticsearch从入门到精通保姆级教程 | 启篇

🔥 本系列将带你从零开始学习Elasticsearch,通过保姆级教程,手把手教你掌握这个强大的搜索与分析引擎。无论你是完全的新手,还是想系统学习ES的开发者,这个系列都能满足你的需求。 📚博主匠心之作,强推专栏: JAVA集合专栏 【夜话集】JVM知识专栏数据库sql理论与实战【…

Unity中Spine骨骼动画完全指南:从API详解到避坑实战

Unity中Spine骨骼动画完全指南:从API详解到避坑实战 一、为什么要选择Spine? Spine作为专业的2D骨骼动画工具,相比传统帧动画可节省90%资源量。在Unity中的典型应用场景包括: 角色换装系统(通过插槽替换部件)复杂连招系统(动画混合与过渡)动态表情系统(面部骨骼控制)…

C++Cherno 学习笔记day17 [66]-[70] 类型双关、联合体、虚析构函数、类型转换、条件与操作断点

b站Cherno的课[66]-[70] 一、C的类型双关二、C的union&#xff08;联合体、共用体&#xff09;三、C的虚析构函数四、C的类型转换五、条件与操作断点——VisualStudio小技巧 一、C的类型双关 作用&#xff1a;在C中绕过类型系统 C是强类型语言 有一个类型系统&#xff0c;不…

wordpress 利用 All-in-One WP Migration全站转移

导出导入站点 在插件中查询 All-in-One WP Migration备份并导出全站数据 导入 注意事项&#xff1a; 1.导入部分限制50MB 宝塔解决方案&#xff0c;其他类似&#xff0c;修改php.ini配置文件即可 2. 全站转移需要修改域名 3. 大文件版本&#xff0c;大于1G的可以参考我的…

【工具使用】在OpenBMC中使用GDB工具来定位coredump原因

在OpenBMC调试中&#xff0c;有时会产生coredump却不知道从哪里入手分析&#xff0c;GDB工具就可以提供帮助。 1 编译带GDB工具的镜像 OpenBMC镜像中默认没有加入GDB工具&#xff0c;因此首先需要编译一个带GDB工具的OpenBMC镜像用于调试。在recipes-phosphor/packagegroups/…

Linux系统(Ubuntu和树莓派)的远程操作练习

文章目录 一、实验一&#xff08;一&#xff09;实验准备&#xff08;二&#xff09;Ubuntu 下的远程操作&#xff08;三&#xff09;树莓派下的远程操作&#xff08;四&#xff09;思考 二、实验二1.talk程序2. C 编写 Linux 进程间通信&#xff08;IPC&#xff09;聊天程序 一…

高效创建工作流,可实现类似unreal engine的蓝图效果,内部使用多线程高效执行节点函数

文章目录 前言&#xff08;Introduction&#xff09;开发环境搭建&#xff08;Development environment setup&#xff09;运行&#xff08;Run test&#xff09;开发者&#xff08;Developer&#xff09;编译&#xff08;Compile&#xff09;报错 前言&#xff08;Introductio…

Design Compiler:语法检查工具dcprocheck

相关阅读 Design Compilerhttps://blog.csdn.net/weixin_45791458/category_12738116.html?spm1001.2014.3001.5482 dcprocheck是一个在Design Compiler存在于安装目录下的程序&#xff08;其实它是一个指向snps_shell的符号链接&#xff0c;但snps_shell可以根据启动命令名判…

aws(学习笔记第三十八课) codepipeline-build-deploy-github-manual

文章目录 aws(学习笔记第三十八课) codepipeline-build-deploy-github-manual学习内容&#xff1a;1. 整体架构1.1 代码链接1.2 全体处理架构 2. 代码分析2.1 创建ImageRepo&#xff0c;并设定给FargateTaskDef2.2 创建CodeBuild project2.3 对CodeBuild project赋予权限&#…

深度学习|注意力机制

一、注意力提示 随意&#xff1a;跟随主观意识&#xff0c;也就是指有意识。 注意力机制&#xff1a;考虑“随意线索”&#xff0c;有一个注意力池化层&#xff0c;将会最终选择考虑到“随意线索”的那个值 二、注意力汇聚 这一部分也就是讲第一大点中“注意力汇聚”那个池化…

京东店铺托管7*16小时全时护航

内容概要 京东店铺托管服务的*716小时全时护航模式&#xff0c;相当于给商家配了个全年无休的"运营管家"。专业团队每天从早7点到晚11点实时盯着运营数据和商品排名&#xff0c;连半夜流量波动都能通过智能系统秒级预警。这种全天候服务可不是单纯拼人力——系统自动…