活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 一键部署Llama3大模型学习机 0代码一键部署,预装最新主流大模型Llama3与StableDiffusion
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 产品能力
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      DS初阶:八大排序之直接插入排序、希尔排序和选择排序

      首页 知识中心 软件开发 文章详情页

      DS初阶:八大排序之直接插入排序、希尔排序和选择排序

      2025-05-08 09:04:49 阅读次数:1

      array,元素,复杂度,排序,插入排序,有序

      一、排序的概念及运用

      1.1 排序的概念

      排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
      稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列                   r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
      内部排序:数据元素全部放在内存中的排序。
      外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据                      的排序。

      关于这些基础概念我会在后面慢慢介绍! 

      1.2 排序的运用

      DS初阶:八大排序之直接插入排序、希尔排序和选择排序

      我们在淘宝购买商品的时候,可以选择让商品根据销量、信用、价格、综合程度进行排序

      DS初阶:八大排序之直接插入排序、希尔排序和选择排序

       还有高校排名,以及考试的排名,都是通过排序来完成的!!

      排序存在的意义:帮助我们筛选出最优的选择

      1.3 常见的排序算法

      DS初阶:八大排序之直接插入排序、希尔排序和选择排序

      二、直接插入排序

      2.1 思路

      直接插入排序的思想:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。

       这就和我们小时候玩扑克牌摸牌整理的一样,一次与前面的排比较找到合适的位置插入!

      DS初阶:八大排序之直接插入排序、希尔排序和选择排序

      2.2 直接插入排序的实现

              当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移

                 我们先按照上面的思路,先模拟摸一张牌的过程,假设目前手上的牌是2 4 9 然后摸到了1张3,我们设置最后一张牌9的下标位置为end(2),然后让新摸的牌为temp(a[3]),开始慢慢往前比较,发现较大的就交换位置。

          int end=2;
      	int temp=a[3];
      	while (end >= 0)
      	{
      		if (a[end] > temp)//如果前面的数比后面的数大,就前面元素插入到后面的位置
      			{        
                    a[end + 1] = a[end];
                   --end;
                    }
      		else
      			break;
      		
      	}
      	a[end+1] = temp;//不写在循环里面,是避免end减成-1,此时说明新加入的牌是最小的,正好放在一开始的位置
      

       上述过程可以实现插入一张牌,那么整体的实现就在外面加个for循序即可!!

      void InsertSort(int* a, int n)
      {
      	for (int i = 0; i < n - 1; i++)
      	{
      		int end = i;
      		int temp = a[i+1];
      		while (end >= 0)
      		{
      			if (a[end] > temp)//如果前面的数比后面的数大,就前面元素插入到后面的位置
      				a[end + 1] = a[end];
      			else
      				break;
      			--end;
      		}
      		a[end + 1] = temp;//不写在循环里面,是避免end减成-1,此时说明新加入的牌是最小的,正好放在一开始的位置
      	}
      }

      但要注意的是:外面的for循环的判断条件,i < n - 1, 也就是说i最多走到n - 2的位置即倒数第二个元素,原因是:tmp是每次要插入的元素,而tmp = a[end +1]是end的下一个位置,如果让end到最后一个元素的位置即n-1处,那tmp = a[end+1]就会越界!所以i只能到倒数第二个元素的位置!

      2.3 复杂度分析

      时间复杂度:O(N^2)  ---> 单趟是O(N),最坏情况N个元素都要走一次单趟(基本上逆序)

      空间复杂度:O(1)  ---> 额外使用空间的个数是常数个

      当要排序的序列接近有序时性能最好O(N)(接近有序)

      三、希尔排序

      3.1 思路

               希尔排序其实是直接插入排序的一种变形,我们知道对于直接插入排序来说,最坏的情况就是逆序,此时的时间复杂度就是O(N^2),最好的情况是接近有序,此时时间复杂度为O(N),这个时候希尔有了一个想法:有没有一种方法可以让一组无序的数据经过处理后使他接近有序,然后再最后实现一次直接插入排序呢?

            最后希尔发明出来了希尔排序

      3.2 希尔排序的实现

      具体思路:

      1、对无序的数组进行预排序,使其接近有序。

      2、最后再来一次直接插入排序

       这里的预排指的是:间隔gap的元素为一组,总计gap组,我们先假设gap为3,然后我们画个图来理解一下:

      DS初阶:八大排序之直接插入排序、希尔排序和选择排序

       根据我们之前写的直接插入排序算法,我们可以先实现将红色的一组进行排序的算法

      int gap = 3;
      for (int i = 0; i < n - gap; i+=gap)
      {
      	int end = i;
      	int temp = a[i + gap];
      	while (end >= 0)
      	{
      		if (a[end] > temp)//如果前面的数比后面的数大,就前面元素插入到后面的位置
      			a[end + gap] = a[end];
      		else
      			break;
      		end -= gap;
      	}
      	a[end + gap] = temp;
      }

       我们发现,如果我们一开始让i=1,就可以实现蓝色组的排序,让i=2的话,就可以实现绿色组的排序,所以为了让三组都完成排序,我们再外面再嵌套一层循环!

      int gap = 3;
      for (int j = 0; j < gap; j++)
      {
      	for (int i = j; i < n - gap; i += gap)
      	{
      		int end = i;
      		int temp = a[i + gap];
      		while (end >= 0)
      		{
      			if (a[end] > temp)//如果前面的数比后面的数大,就前面元素插入到后面的位置
      				a[end + gap] = a[end];
      			else
      				break;
      			end -= gap;
      		}
      		a[end + gap] = temp;
      	}
      }

      这样我们就实现了三组的预排序了!! 

      但其实上面的代码还可以优化成两层循环!!

      int gap = 3;
      	for (int i = 0; i < n - gap; i ++)
      	{
      		int end = i;
      		int temp = a[i + gap];
      		while (end >= 0)
      		{
      			if (a[end] > temp)//如果前面的数比后面的数大,就前面元素插入到后面的位置
      				a[end + gap] = a[end];
      			else
      				break;
      			end -= gap;
      		}
      		a[end + gap] = temp;
      	}

      刚刚那种写法是一组一组去完成预排,而现在这种写法是实现多组并排,效果是一样的!! 

      这样的预排序有什么意义呢?

      1、 gap越大,大的数可以更快到后面,小的数可以更快到前面,但是越不接近有序

      2、gap越小,大的小的就挪动的越慢,但是也越接近有序

      3、gap==1时,就是直接插入排序(我们可以发现当gap等于1时,这个预排序算法与直接插入排序算法的写法是一样的!!)

      现在来分析gap该取多少合适?

           首先,gap是不能随便取的,因为比如说有100万个数据,gap取3,显然是不合适的,所以我们的gap一定要跟数据个数n建立联系,gap具体取多少是最合适的没有得到很好的证明,所以我们使用Knuth的思路来将我们的希尔排序完善好!!

      DS初阶:八大排序之直接插入排序、希尔排序和选择排序

      void ShellSort(int* a, int n)
      {
      	//gap>1  预排序
      	//gap=1 直接插入排序
      	int gap = n;
      	while (gap > 1)
      	{
      		gap = gap / 3 + 1;//这是为了保证gap最后一定为0
      		for (int i = 0; i < n - gap; i++)
      		{
      			int end = i;
      			int temp = a[i + gap];
      			while (end >= 0)
      			{
      				if (a[end] > temp)//如果前面的数比后面的数大,就前面元素插入到后面的位置
      					a[end + gap] = a[end];
      				else
      					break;
      				end -= gap;
      			}
      			a[end + gap] = temp;
      		}
      	}
      }

      需要注意的是:gap = gap / 3 + 1是为了保证gap最后一定会等于1,也就是一定会在最后进行一次直接插入排序,保证有序,而前面gap>1的过程都是在进行预排序!!

      3.3 复杂度分析

      DS初阶:八大排序之直接插入排序、希尔排序和选择排序因为预排是一个逐渐转好的过程,所以我们还按照最坏情况去考虑是不合理的,因此这边是难以计算的,我们看看书上的讲解

       《数据结构(C语言版)》--- 严蔚敏
      DS初阶:八大排序之直接插入排序、希尔排序和选择排序

      《数据结构-用面相对象方法与C++描述》--- 殷人昆
       DS初阶:八大排序之直接插入排序、希尔排序和选择排序

      因为咋们的gap是按照Knuth提出的方式取值的,而且Knuth进行了大量的试验统计,我们暂时就按o(N^1.25)到o(1.6N^1.25)到来算

      四、选择排序

      4.1 思路

      选择排序的思想:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。

            这个其实也跟摸扑克牌有关,但是这次跟直接插入排序不一样的是,直接插入排序是一次摸一张牌然后插入调整,而选择排序是一次性拿了所有牌,再逐个把小的数往前放!

      4.2 选择排序的实现

      1、在元素集合array[i]--array[n-1]中选择关键码最大(小)的数据元素

      2、若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
      3、在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素

      我们拿到所有的牌后,每次都把最小的牌往前放

      void SelectSort(int* a, int n)
      {
      	for (int begin = 0; begin < n; begin++)
      	{
      		int min = begin;//记录最小元素的下标
      		for (int i = begin+1; i < n; i++)
      		{
      			if (a[min] > a[i])
      				min = i;//记录最小的牌的下标
      		}
      		Swap(&a[begin], &a[min]);
      	}
      }

       但是每次遍历就记一张最小的牌,效率太低下了,所以我们改造一下该算法,使得该算法每遍历一次就记住最小的牌和最大的牌,然后分别放在两边!!

      void SelectSort(int* a, int n)
      {
      	int left = 0; 
      	int right = n - 1;
      	while (left < right)
      	{
      		int min = left;
      		int max = left;
      		for (int i = left+1; i <= right; i++)
      		{
      		
      			if (a[min] > a[i])
      			    min = i;
      		    if (a[max] < a[i])
      				max = i;
      		}
      		//这里要考虑一种情况,就是如果最大的数恰好就在最左端,那么就会导致第二次swap换到后面的就不是最大的数而是最小的数了
      		Swap(&a[min], &a[left]);
      		//如果max和begin重叠,修正一下
      		if (max == left)
      			max = min;
      		Swap(&a[max], &a[right]);
      		left++;
      		right--;
      	}
      }

      易错点1:min和max要从他们后面的第一张牌开始去一张一张比较 

      易错点2:交换的时候,如果最大的元素恰好在最左边,那么就有可能被最小的元素给交换过去了,所以这个时候要注意及时地修正!!

      4.3 复杂度分析

      时间复杂度:O(N^2)

      单趟无论选择一个还是选择两个,都得遍历一遍,复杂度为O(N),整体还得遍历一遍O(N)

      空间复杂度:O(1)

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.csdn.net/weixin_51142926/article/details/136116379,作者:✿༺小陈在拼命༻✿,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:DS初阶:顺序栈的实现

      相关文章

      2025-05-08 09:04:49

      DS初阶:循环队列的实现

      DS初阶:循环队列的实现

      2025-05-08 09:04:49
      rear , 元素 , 循环 , 指针 , 数组 , 返回 , 队列
      2025-05-08 09:04:49

      DS初阶:栈和队列的相互实现

      栈和队列的相互实现是用两个栈去实现队列或者是用两个队列去实现栈

      2025-05-08 09:04:49
      为空 , 代码 , 元素 , 初始化 , 实现 , 获取 , 队列
      2025-05-08 09:04:49

      DS初阶:八大排序之堆排序、冒泡排序、快速排序

      DS初阶:八大排序之堆排序、冒泡排序、快速排序

      2025-05-08 09:04:49
      key , 复杂度 , 快排 , 指针 , 排序 , 递归
      2025-05-08 09:04:25

      DS初阶:时间复杂度和空间复杂度

      算法(Algorithm):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出。简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果。                                                      

      2025-05-08 09:04:25
      CPU , 复杂度 , 数据 , 时间 , 空间 , 算法 , 缓存
      2025-05-08 09:04:25

      DS初阶:顺序栈的实现

      栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

      2025-05-08 09:04:25
      元素 , 出栈 , 括号 , 栈顶 , 顺序
      2025-05-08 09:04:25

      DS初阶:顺序表、链表经典OJ题(2)

      DS初阶:顺序表、链表经典OJ题(2)

      2025-05-08 09:04:25
      复杂度 , 思路 , 指针 , 数组 , 空间 , 结点 , 链表
      2025-05-08 09:04:15

      构造相同颜色的正方形。

      用go语言,给定一个3x3的矩阵,每个格子是'B'或'W'。你需要判断是否可以通过修改最多一个格子的颜色,使得矩阵中存在一个2x2的颜色完全相同的正方形。

      2025-05-08 09:04:15
      复杂度 , 格子 , 正方形
      2025-05-08 09:04:15

      字符串的分数。

      用go语言,给定一个字符串 s,我们可以定义其“分数”为相邻字符的 ASCII 码差值绝对值的总和。请计算并返回字符串 s 的分数。

      2025-05-08 09:04:15
      分数 , 复杂度 , 字符串
      2025-05-08 09:04:15

      直角三角形。

      用go语言,给定一个二维布尔矩阵 grid,要求找出在该矩阵中以数值为 1 的元素构成的集合中,有多少个直角三角形。直角三角形的定义是其中的三个元素分别在同一行、同一列。

      2025-05-08 09:04:15
      元素 , 复杂度 , 矩阵
      2025-05-08 09:04:15

      划分数组得到最小的值之和。

      划分数组得到最小的值之和。用go语言,你有两个数组,nums 和 andValues,它们的长度分别为 n 和 m。定义数组的“值”为其最后一个元素。

      2025-05-08 09:04:15
      lt , nums , 元素 , 数组
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33086

      阅读量

      4927352

      查看更多

      最新文章

      DS初阶:循环队列的实现

      2025-05-08 09:04:49

      DS初阶:栈和队列的相互实现

      2025-05-08 09:04:49

      DS初阶:顺序栈的实现

      2025-05-08 09:04:25

      划分数组得到最小的值之和。

      2025-05-08 09:04:15

      直角三角形。

      2025-05-08 09:04:15

      构造相同颜色的正方形。

      2025-05-08 09:04:15

      查看更多

      热门文章

      python学习(6)——列表元素的添加、删除、修改及排序

      2023-05-22 03:00:29

      C++ 实现排序问题:时间复杂度O(n),空间复杂度O(1)

      2023-03-14 09:17:29

      20.6.5快速排序头文件的使用

      2023-03-20 02:06:43

      Python字典按键/值排序的几种方法

      2023-04-27 06:29:38

      Lc27_移除元素

      2023-04-28 06:45:00

      Lc面试题1710主要元素

      2023-05-19 05:50:39

      查看更多

      热门标签

      java Java python 编程开发 开发语言 代码 算法 线程 html Python 数组 C++ javascript 元素 c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      【c语言实现动态顺序表的内存扩容】

      JavaSE: 七大经典排序算法——冒泡排序

      数据结构之 - 深入了解栈数据结构

      力扣经典 4. 寻找两个正序数组的中位数(多种语言解)

      Java List操作详解及常用方法

      CSS浮动(如果想知道CSS有关浮动的知识点,那么只看这一篇就足够了!)

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 权益商城
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 权益商城
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号