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

news2024/11/26 5:40:38

在这里插入图片描述

文章目录

  • 前言
  • 一、排序
    • 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--;
	}
}

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

总结

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

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

在这里插入图片描述

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

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

相关文章

C++网络编程之多播

概述 在移动互联网时代&#xff0c;随着多媒体应用的日益普及&#xff0c;如何高效地将数据传输给多个接收者成为了网络通信领域的一个重要课题。多播&#xff08;英文为Multicast&#xff09;作为一种高效的网络通信方式&#xff0c;可以将数据同时发送到多个接收者&#xff0…

AWS的流日志

文章目录 一、aws如何观察vpc的日志&#xff1f;二、aws观测其vpc的入口日志三、 具体配置3.1、配置你的存储神器 S33.2、建立子网的流日志 一、aws如何观察vpc的日志&#xff1f; 排查问题的时候除了去抓包看具体的端口信息的时候&#xff0c;还可以根据其所在的vpc的子网信息…

C++ —— 以真我之名 如飞花般绚丽 - 智能指针

目录 1. RAII和智能指针的设计思路 2. C标准库智能指针的使用 2.1 auto_ptr 2.2 unique_ptr 2.3 简单模拟实现auto_ptr和unique_ptr的核心功能 2.4 shared_ptr 2.4.1 make_shared 2.5 weak_ptr 2.6 shared_ptr的缺陷&#xff1a;循环引用问题 3. shared_ptr 和 unique_…

DAMODEL丹摩|《ChatGLM-6B 在丹摩智算平台的部署与使用指南》

目录 一、引言 二、ChatGLM-6B 模型简介 ChatGLM-6B 的特点 三、DAMODEL 平台部署 ChatGLM-6B 1. 实例创建 2. 模型准备 3. 模型启动 四、通过 Web API 实现本地使用 1. 启动服务 2. 开放端口 3. 使用 PostMan 测试功能 4. 本地代码使用功能 五、总结 一、引言 Ch…

【AI大模型】LLM的检索增强--SELF-RAG

本篇博客参考论文&#xff1a; 《SELF-RAG: LEARNING TO RETRIEVE, GENERATE, AND CRITIQUE THROUGH SELF-REFLECTION》 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;大型语言模型&#xff08;LLMs&#xff09;已成为处理复杂语言任务的强大工具。然而&#xf…

Linux—进程概念学习-03

目录 Linux—进程学习—31.进程优先级1.1Linux中的进程优先级1.2修改进程优先级—top 2.进程的其他概念3.进程切换4.环境变量4.0环境变量的理解4.1环境变量的基本概念4.2添加环境变量—export4.3Linux中环境变量的由来4.4常见环境变量4.5和环境变量相关的命令4.6通过系统调用获…

C# 读取多条数据记录导出到 Word标签模板之图片输出改造

目录 应用需求 设计 范例运行环境 配置Office DCOM 实现代码 组件库引入 ​核心代码 调用示例 小结 应用需求 在我的文章《C# 读取多条数据记录导出到 Word 标签模板》里&#xff0c;讲述读取多条数据记录结合 WORD 标签模板输出文件的功能&#xff0c;原有输出图片的…

Android 性能优化:内存优化(理论篇)

内存作为App程序运行最重要的资源之一&#xff0c;需要运行过程中做到合理的资源分配与回收&#xff0c;不合理的内存占用轻则使得用户应用程序运行卡顿、ANR、黑屏&#xff0c;重则导致用户应用程序发生 OOM&#xff08;out of memory&#xff09;崩溃。喜马直播随着近些年的业…

【AI技术赋能有限元分析应用实践】pycharm终端与界面设置导入Abaqus2024自带python开发环境

目录 一、具体说明1. **如何在 Windows 环境中执行 Abaqus Python 脚本**2. **如何在 PyCharm 中配置并激活 Abaqus Python 环境**3. **创建 Windows 批处理脚本自动执行 Abaqus Python 脚本**总结二、方法1:通过下面输出获取安装路径导入pycharm方法2:终端脚本执行批处理脚本…

arm学习总结

AHB总线连接的都是这些需要高速处理的内存、内核啥的 APB连接的都是些外设 GPIO并不需要高速处理的

【redis 】string类型详解

string类型详解 一、string类型的概念二、string类型的常用指令2.1 SET2.2 GET2.3 MSET2.4 MGET2.5 SETNX2.6 INCR2.7 INCRBY2.8 DECR2.9 DECRBY2.10 INCRBYFLOAT2.11 APPEND2.12 GETRANGE2.13 SETRANGE2.14 STRLEN 三、string类型的命令小结四、string类型的内部编码五、strin…

Mysql案例之COALESCE函数使用详解

hello&#xff0c;大家好&#xff0c;我是灰小猿&#xff01;最近在做一个三表关联查询的场景处理时&#xff0c;遇到了一个比较有用的MySQL函数&#xff0c;在这里记录一下&#xff0c;大概场景如下&#xff1a; 需求场景 场景&#xff1a;有一张object_rel表&#xff0c;表中…

C语言菜鸟入门·关键字·int的用法

目录 1. int关键字 1.1 取值范围 1.2 符号类型 1.3 运算 1.3.1 加法运算() 1.3.2 减法运算(-) 1.3.3 乘法运算(*) 1.3.4 除法运算(/) 1.3.5 取余运算(%) 1.3.6 自增()与自减(--) 1.3.7 位运算 2. 更多关键字 1. int关键字 int 是一个关键字&#xff0…

D74【 python 接口自动化学习】- python 基础之HTTP

day74 http基础定义 学习日期&#xff1a;20241120 学习目标&#xff1a;http定义及实战 -- http基础介绍 学习笔记&#xff1a; HTTP定义 HTTP 是一个协议&#xff08;服务器传输超文本到浏览器的传送协议&#xff09;&#xff0c;是基于 TCP/IP 通信协议来传递数据&…

基于FPGA(现场可编程门阵列)的SD NAND图片显示系统是一个复杂的项目,它涉及硬件设计、FPGA编程、SD卡接口、NAND闪存控制以及图像显示等多个方面

文章目录 0、前言 1、目标 2、图片的预处理 3、SD NAND的预处理 4、FPGA实现 4.1、详细设计 4.2、仿真 4.3、实验结果 前言 在上一篇文章《基于FPGA的SD卡的数据读写实现&#xff08;SD NAND FLASH&#xff09;》中&#xff0c;我们了解到了SD NAND Flash的相关知识&am…

【计算机网络】网段划分

一、为什么有网段划分 IP地址 网络号(目标网络) 主机号(目标主机) 网络号: 保证相互连接的两个网段具有不同的标识 主机号: 同一网段内&#xff0c;主机之间具有相同的网络号&#xff0c;但是必须有不同的主机号 互联网中的每一台主机&#xff0c;都要隶属于某一个子网 -&…

Java-反序列化

序列化与反序列化 简单demo&#xff1a; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable;public class serialize implements Serializable{private…

webkit浏览器内核编译(2024年11月份版本)

webkit浏览器内核编译 本文详细介绍了如何安装和配置Webkit的编译环境和工具的安装&#xff0c;以及在Windows上编译和运行WebKit浏览器引擎的过程&#xff0c;包括安装依赖、设置环境变量、生成解决方案并最终运行附带的MiniBrowser示例。 一、WebKit简介 WebKit 是一个开源的…

论文阅读--Evidence for the utility of quantum computing before fault tolerance

量子计算有望在某些问题上提供比传统计算更快的速度。然而&#xff0c;实现其全部潜力的最大障碍是这些系统固有的噪声。这一挑战被广泛接受的解决方案是实现容错量子电路&#xff0c;而这超出了当前处理器的能力范围。我们在此报告了在嘈杂的127 量子比特处理器上进行的实验&a…

构建高效在线教育:SpringBoot课程管理系统

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理在线课程管理系统的相关信息成为必然。开发…