数据结构——排序算法第一幕(插入排序:直接插入排序、希尔排序 选择排序:直接选择排序,堆排序)超详细!!!!

在这里插入图片描述

文章目录

  • 前言
  • 一、排序
    • 1.1 概念
    • 1.2 常见的排序算法
  • 二、插入排序
    • 2.1 直接插入排序
    • 2.2 希尔排序
      • 希尔排序的时间复杂度
  • 三、选择排序
    • 3.1 直接选择排序
    • 3.2 堆排序
  • 总结

前言

时间很快,转眼间已经到数据结构的排序算法部分啦
今天我们来学习排序算法当中的 插入排序选择排序
准备好上车了,fellow me

一、排序

1.1 概念

所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

1.2 常见的排序算法

在这里插入图片描述

今天我们要学习的就是插入排序和选择排序

二、插入排序

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

在这里插入图片描述
实际中我们玩扑克牌时,就用了插入排序的思想

2.1 直接插入排序

当插入第i(i>=1) 个元素时,前面的array[0],array[1],…,array[i-1] 已经排好序,此时用 array[i] 的排序码与array[i-1],array[i-2],… 的排序码顺序进行比较,找到插入位置即将array[i] 插入,原来位置上的元素顺序后移
就像打扑克时,抓到一张新的牌,就一一与前面的牌进行比较,找到适合的位置插入。

实现起来还是相对比较简单的

void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)   //  一个一个插入    
	{
		int end = i;          // end 为以及排好序列的最后一个元素   
		int tmp = a[end + 1];    //  tmp  表示新插入进来的元素   
		while (end >= 0)    //   现在让新插入的元素  与前面的元素一一比较  
		{
			if (a[end] > tmp)   //  如果tmp比当前的元素小  就把当前的元素往后移动
			{
				a[end + 1] = a[end];
				end--;   //   end--  一个一个往前比较   
			}
			else  //  如果tmp比当前元素大  那就已经找到合适位置  
				break;   
		}
		a[end + 1] = tmp;  //  元素往后移动了一位 前面肯定是有空位的  把tmp插入就好啦  
	}    //  这里  end是最近比较过的元素  tmp大于end位置    end+1是空缺的   所以插入到 end+1的 位置    
}

结合着打扑克牌的插入的情景就很好理解了

直接插入排序的特性总结
1.== 元素集合越接近有序,直接插入排序算法的时间效率越高==
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1)

但 O(N^ 2) 终究还是 O(N^2) 太慢啦 下面我来优化优化 直接插入排序的进阶版本

2.2 希尔排序

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数(通常是gap = n/3+1),把待排序文件所有记录分成各组,所有的距离相等的记录分在同一组内,并对每一组内的记录进行排序然后gap=gap/3+1得到下一个整数,再将数组分成各组,进行插入排序,当gap=1时,就相当于直接插入排序。
它是在直接插入排序算法的基础上进行改进而来的,综合来说它的效率肯定是要高于直接插入排序算法的。

有图才能有真相
在这里插入图片描述
一组一组来使用直接插入,组的间隙慢慢变小,最后一层就是直接插入排序,这种方式相比于直接插入排序
外层的 ++循环变成了,gap的递减,从O(N)到 O(logN)
代码优化起来也很简单,在原来的基础上改动一点就好啦

void ShellSort(int* a, int n)
{
	int gap = n;   //  引入gap
	while (gap > 1)   // 外层循环   
	{
		gap = gap / 3 + 1;
		for (int i = 0; i < n - gap; i++)   //  这里直接i截止到n-gap  防止取tmp的时候数组越界
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > tmp)
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
					break;
			}
			a[end + gap] = tmp;   //  这些操作还是 直接插入排序的代码 直接插入排序就是gap==1的情况  
		}
	}
}

可能会有人疑问 虽然外层循环优化了,循环内部的代码和直接插入一样的呀
我来仔细讲解

希尔排序的时间复杂度

希尔排序的时间复杂度估算:
外层循环:
外层循环的时间复杂度可以直接给出为: O(log2(n)) O(log3(n)) 即O(log n)
内层循环:

在这里插入图片描述
在这里插入图片描述
可以画出曲线图:
在这里插入图片描述

因此,希尔排序在最初和最后的排序的次数都为n,即前一阶段排序次数是逐渐上升的状态,当到达某一顶点时,排序次数逐渐下降至n,而该顶点的计算暂时无法给出具体的计算过程

在这里插入图片描述

所以希尔排序的时间复杂度为 :O(nlog n) ~ O(n^2) 最好的情况为O(n ^1.3) 最坏的情况为O(n ^2)

插入排序就到这里啦


三、选择排序

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

3.1 直接选择排序

  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)
{
	int begin = 0, end = n - 1;   
	while (begin < end)
	{
		int mini = begin, maxi = begin;
		for (int i = begin; i < end; i++)   //  每一躺找出最大和最小值  
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}
			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}
		if (maxi == begin)   //  注意有最大值在当前区域的第一个位置  如果先把最小的换过去,最大的位置就变了
		{
			maxi = mini;   //   所以这里要处理一下  
		}
		swap(a[mini], a[begin]);
		swap(a[maxi], a[end]);   //  把最小换到前面,把最大换到后面
		begin++;   //  数组需要遍历的元素减少两个  每次都排一个当前区域的最大值和最小值
		end--;
	}
}

直接选择排序的特性总结:

  1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
  2. 时间复杂度:O(N^2) 注定是上不了台面
  3. 空间复杂度: O(1)

3.2 堆排序

博客链接:堆排序

堆排序在之前的二叉树第一幕已经讲过啦
这里就不多赘述了,主要是深刻理解向下调整算法和向上调整算法
实现一下代码吧

void AdjustDown(int* a, int parent, int n)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child] > a[child + 1])
		{
			child++;
		}
		if (a[child] < a[parent])
		{
			swap(a[child], a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}
void HeapSort(int *a, int n)
{
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, i, n);
	}
	int end = n - 1;
	while (end > 0)
	{
		swap(a[0], a[end]);
		AdjustDown(a, 0, end);
		end--;
	}
}

堆排序就到这里啦,以上代码供复习使用,详情去 ----博客链接:堆排序

总结

今天就学习了插入排序和选择排序,总体来说就是希尔排序有一些难处理堆排序在前面的博客已经讲过啦
其他的都挺简单的,平常也很容易想到
下一篇,小编可是要放大招了嗷,听说快速排序用起来可是非常爽的,不要走开,小编持续更新中~~~

欲望以提升热忱,毅力以磨平高山。又是充实的一天

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第32周:猴痘病识别(Tensorflow实战第四周)

目录 前言 一、前期工作 1.1 设置GPU 1.2 导入数据 1.3 查看数据 二、数据预处理 2.1 加载数据 2.2 可视化数据 2.3 再次检查数据 2.4 配置数据集 2.4.1 基本概念介绍 2.4.2.代码完成 三、构建CNN网络 四、编译 五、训练模型 六、模型评估 6.1 Loss和Accuracy…

【创建型设计模式】工厂模式

【创建型设计模式】工厂模式 创建型设计模式第二期&#xff01;本期介绍简单工厂模式和工厂方法模式。 简单工厂模式 简单工厂模式&#xff08;又叫作静态工厂方法模式&#xff09;&#xff0c;其属于创建型设计模式&#xff0c;简单工厂模式不属于设计模式中的 23 种经典模…

【Linux】安装cuda

一、安装nvidia驱动 # 添加nvidia驱动ppa库 sudo add-apt-repository ppa:graphics-drivers/ppa sudo apt update# 查找推荐版本 sudo ubuntu-drivers devices# 安装推荐版本 sudo apt install nvidia-driver-560# 检验nvidia驱动是否安装 nvidia-smi 二、安装cudatoolkit&…

上天入地 灵途科技光电技术赋能空间感知

近来&#xff0c;人工智能技术频频亮相各大马拉松赛事&#xff0c;成为引人注目的科技亮点。 11月3日&#xff0c;杭州马拉松首次启用了机器狗作为配速员&#xff0c;以稳定的节奏为选手提供科学的跑步节奏。 11月11日&#xff0c;亦庄半程马拉松的终点处&#xff0c;人形机器…

Java三大特性:封装、继承、多态【详解】

封装 定义 隐藏对象的属性和实现细节&#xff0c;仅对外公开接口&#xff0c;控制在程序中属性的读取和修改的访问级别便是封装。 在开发中造一个类就是封装&#xff0c;有时也会说封装一个类。封装可以隐藏一些细节或者包含数据不能被随意修改。 比如这是一个敏感的数据&a…

40分钟学 Go 语言高并发:【实战】并发安全的配置管理器(功能扩展)

【实战】并发安全的配置管理器&#xff08;功能扩展&#xff09; 一、扩展思考 分布式配置中心 实现配置的集中管理支持多节点配置同步实现配置的版本一致性 配置加密 敏感配置的加密存储配置的安全传输访问权限控制 配置格式支持 支持YAML、TOML等多种格式配置格式自动…

【ChatGPT大模型开发调用】如何获得 OpenAl API Key?

如何获取 OpenAI API Key 获取 OpenAI API Key 主要有以下三种途径&#xff1a; OpenAI 官方平台 (推荐): 开发者用户可以直接在 OpenAI 官方网站 (platform.openai.com) 注册并申请 API Key。 通常&#xff0c;您可以在账户设置或开发者平台的相关页面找到申请入口。 Azure…

苹果系统中利用活动监视器来终止进程

前言 苹果系统使用的时候总是感觉不太顺手。特别是转圈的彩虹球出现的时候&#xff0c;就非常令人恼火。如何找到一个像Windows那样任务管理器来终止掉进程呢&#xff1f; 解决办法 Commandspace 弹出搜索框吗&#xff0c;如下图&#xff1a; 输入“活动”进行搜索&#xff…

实战项目负载均衡式在线 OJ

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;能自己实现负载均衡式在线 OJ。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xff1…

python Flask指定IP和端口

from flask import Flask, request import uuidimport json import osapp Flask(__name__)app.route(/) def hello_world():return Hello, World!if __name__ __main__:app.run(host0.0.0.0, port5000)

burp suite-1

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…

【Spring boot】微服务项目的搭建整合swagger的fastdfs和demo的编写

文章目录 1. 微服务项目搭建2. 整合 Swagger 信息3. 部署 fastdfsFastDFS安装环境安装开始图片测试FastDFS和nginx整合在Storage上安装nginxnginx安装不成功排查:4. springboot 整合 fastdfs 的demodemo编写1. 微服务项目搭建 版本总结: spring boot: 2.6.13springfox-boot…

【区块链】深入理解椭圆曲线密码学(ECC)

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 深入理解椭圆曲线密码学(ECC)1. 概述2. 椭圆曲线的数学基础2.1 基本定义2.2 有限…

【Qt流式布局改造支持任意位置插入和删除】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、源代码二、删除代码三、扩展总结 前言 最近在做一个需求需要流式布局&#xff0c;虽然官方example里有一个流式布局范例&#xff0c;但是不能满足我的需求…

JQuery -- 第九课

文章目录 前言一、JQuery是什么&#xff1f;二、JQuery的使用步骤1.引入2.书写位置3. 表示方法 三、JQuery选择器1.层级选择器2. 筛选选择器3. 排他思想4. 精品展示 四、jQuery样式操作1. 修改样式2.类操作1. 添加2. 移除3. 切换 五、jQuery动画1. 显示和隐藏2. 滑动1. slide2.…

Python 版本的 2024详细代码

2048游戏的Python实现 概述&#xff1a; 2048是一款流行的单人益智游戏&#xff0c;玩家通过滑动数字瓷砖来合并相同的数字&#xff0c;目标是合成2048这个数字。本文将介绍如何使用Python和Pygame库实现2048游戏的基本功能&#xff0c;包括游戏逻辑、界面绘制和用户交互。 主…

在Elasticsearch中,是怎么根据一个词找到对应的倒排索引的?

大家好&#xff0c;我是锋哥。今天分享关于【在Elasticsearch中&#xff0c;是怎么根据一个词找到对应的倒排索引的&#xff1f;】面试题。希望对大家有帮助&#xff1b; 在Elasticsearch中&#xff0c;是怎么根据一个词找到对应的倒排索引的&#xff1f; 在 Elasticsearch 中…

C# 数据结构之【图】C#图

1. 图的概念 图是一种重要的数据结构&#xff0c;用于表示节点&#xff08;顶点&#xff09;之间的关系。图由一组顶点和连接这些顶点的边组成。图可以是有向的&#xff08;边有方向&#xff09;或无向的&#xff08;边没有方向&#xff09;&#xff0c;可以是加权的&#xff…

Mac 系统上控制台常用性能查看命令

一、top命令显示 在macOS的控制台中&#xff0c;top命令提供了系统当前运行的进程的详细信息以及整体系统资源的利用情况。下面是对输出中各个字段的解释&#xff1a; Processes: 483 total: 系统上总共有483个进程。 2 running: 当前有2个进程正在运行。 481 sleeping: 当前有…

Docker--通过Docker容器创建一个Web服务器

Web服务器 Web服务器&#xff0c;一般指网站服务器&#xff0c;是驻留于因特网上某种类型计算机的程序。 Web服务器可以向浏览器等Web客户端提供文档&#xff0c;也可以放置网站文件以供全世界浏览&#xff0c;或放置数据文件以供全世界下载。 Web服务器的主要功能是提供网上…