详解八大排序(一)------(插入排序,选择排序,冒泡排序,希尔排序)

news2024/11/25 8:13:11

文章目录

  • 前言
  • 1.插入排序(InsertSort)
    • 1.1 核心思路
    • 1.2 实现代码
  • 2.选择排序(SelectSort)
    • 2.1 核心思路
    • 2.2 实现代码
  • 3.冒泡排序(BubbleSort)
    • 3.1 核心思路
    • 3.2 实现代码
  • 4.希尔排序(ShellSort)
    • 4.1 核心思路
    • 4.2 实现代码

前言

在日常生活中,我们常常要将各种各样的数据进行排序,例如我要将班上的学生按照数学成绩从大到小的排序,像这种一般情况,编译器自带的sort函数就能满足我们的要求。但是,假如我要将班上姓刘的学生按照数学成绩从大到小的排序呢?

这种时候,编译器自带的sort函数无法满足需求,我们就需要自己定义一个排序函数。 下面我就要介绍目前的八大排序的原理,代码,以及时间,空间复杂度。

1.插入排序(InsertSort)

1.1 核心思路

直接插入排序的核心思路是先分组,再比较。

数组

例如上面的数组,有六个数。那么我们就可以先把[3,6]分成一组进行比较,得到[3,6]数组。 再把[3,6,7]分成一组进行比较,得到[3,6,7]数组。再把[3,6,7,1]分成一组,得到[1,3,6, 7]数组。 以此类推,得到[1,2,3,4,6,7]数组。

1.2 实现代码

// 插入排序
//插入排序的核心思路就是把i个数分成一组,让第i个数与第i+1个数进行比较
//把较大的数放在后面
void InsertSort(int* arr, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;//把i个数分成一组
		int tmp = arr[end + 1];//记录最后一个数

		while (end >= 0){
		//把i + 2个数分成一组,当 end >= 0 时
		//说明这一组的数没有全部比较,循环比较大小
			if (arr[end] > tmp){//位于end的数大于最后一个数
				arr[end + 1] = arr[end];//把位于end的数赋值给end + 1的位置
				end--;//end--,比较下一个数
			}
			else {
				break;
			}
		}
		arr[end + 1] = tmp;//退出while循环有两种情况
		//1.end减少到-1,说明这一组的数均大于最后一个数
		//这样end+1 == 0,把最后一个数赋值给0的位置
		//2.break提前跳出循环,说明此时end的数小于最后一个数
		//那么把最后一个数放在end + 1的位置
	}
}

2.选择排序(SelectSort)

2.1 核心思路

选择排序的核心思路是先找到当前数组中的最大和最小数,再放到相应的位置。

在这里插入图片描述

例如上面的数组,选择排序中我们会定义好第一个位置(0)和最后一个位置(size - 1),再从数组中找到最小(1)和最大数(7),再把1和7放到相应的位置上。 再定义好第二个位置(1)和倒数第二个位置(size - 2),再从数组中找到第二小(2)和 第二大的数(6),再把2和6放到相应的位置上。 以此类推,直到所有的数排序完。

2.2 实现代码

// 选择排序
void SelectSort(int* arr, int n)
{
	int begin = 0;
	int end = n - 1;
	//定义最小数据和最大数据的位置
	while (begin < end)//当begin小于end时,说明数组中的数据没有比较完,循环比较
	{
		int mini = begin, maxi = begin;//先定义一个最小数和最大数
		for (int i = begin + 1; i <= end; i++)//找大找小,从第二个数开始比较
		{
			if (arr[i] > arr[maxi])
			//当前数组轮到的数大于当前的最大数,那么这个数就是新的最大数
			{
				maxi = i;
			}
			if (arr[i] < arr[mini])
			//当前数组轮到的数小于当前的最小数,那么这个数就是新的最小数
			{
				mini = i;
			}
		}

		if (maxi == begin)//防止数组中全是相同的数,导致maxi没有改变
		{
			maxi = mini;
		}
		Swap(&arr[mini], &arr[begin]);//让最小的数与第一个数进行交换
		Swap(&arr[maxi], &arr[end]);//让最大的数与第二个数进行交换
		++begin;//已经找到最小的数,需要找第二小的数,所以begin++
		--end;//已经找到最大的数,需要找第二大的数,所以end--
	}
}

3.冒泡排序(BubbleSort)

3.1 核心思路

冒泡排序的核心思路是暴力比较,所有的数都比较一遍。

在这里插入图片描述

例如上面的数组,将3与剩下所有的数字比较,3大于1,则把3放在1的位置,1放在3的位置。 所有的数比较完成后就能得到有序的数组。

3.2 实现代码

void BubbleSort(int* arr, int n)
{
	for (int i = 0; i < n; i++)//找好第一个数
	{
		for (int j = i + 1; j < n; j++)//从第二个数开始
		{
			if (arr[i] > arr[j])//所有的数与第一个数进行比较
			{
				Swap(&arr[i], &arr[j]);
				//如果第一个数大于比较的数,则交换这两个数
			}
		}
	}
}

4.希尔排序(ShellSort)

4.1 核心思路

希尔排序的核心思路是将数组分成若干个小组,小组先进行预排序,小组预排序完成后,再将 所有的组合并并且进行排序。

在这里插入图片描述

例如上面的数组,将数组分成三分之一,则得到[3,6][7,1][4,2]三个数组。先对这三个数组进行排序,得到[3,6][1,7][2,4]三个数组。 然后将这三个数组合并成两个数组,得到[3,6,1][7,2,4]两个数组。再对[3,6,1][7,2,4]进行排序。得到[1,3,6][2,4,7]两个数组。 再将这两个数组合并,得到[1,3,6,2,4,7],排序得到[1,2,3,4,6,7]。

4.2 实现代码

// 希尔排序
void ShellSort(int* arr, int n)
{
	int gap = n;

	while (gap > 1)
	{
		gap = gap / 3 + 1;
		//将数组分成三分之一。+ 1 是为了防止gap < 3从而导致gap / 3 == 0
		//同时for循环结束时,再将数组进行细分
		for (int i = 0; i < n - gap; i++)
		//由于数组被分成三分之一个,所以数组的大小也变为三分之一
		{
			int end = i;
			//第一个小组的第一个成员,i++之后就是第二个小组的第一个成员
			int tmp = arr[end + gap];
			//第一个小组的最后一个成员,i++之后就是第二个小组的最后一个成员
			while (end >= 0)
			//
			{
				if (arr[end] > tmp)
				//当第一个小组里的第一个成员大于最后一个成员时
				{
					arr[end + gap] = arr[end];
					//把第一个成员放到最后一个成员的位置
					end -= gap;
					//由于开始比较的是所有组的第一个成员
					//当end > gap时,说明要开始比较组里的第二个成员了
					//第二个成员比较完,再比较第三个成员
				}
				else {
					break;
				}
			}
			arr[end + gap] = tmp;//有两种情况
			//1.end减少到 < 0,说明这一组的数成倒序
			//则需要把组里所有的数比较并交换完之后结束循环
		    //2.break提前跳出循环
		    //说明此时组里所有比end位置大的数均位于end + gap之后
		}
	}
}

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

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

相关文章

02 —— Webpack 修改入口和出口

概念 | webpack 中文文档 | webpack中文文档 | webpack中文网 修改入口 webpack.config.js &#xff08;放在项目根目录下&#xff09; module.exports {//entry设置入口起点的文件路径entry: ./path/to/my/entry/file.js, }; 修改出口 webpack.config.js const path r…

《InsCode AI IDE:编程新时代的引领者》

《InsCode AI IDE&#xff1a;编程新时代的引领者》 一、InsCode AI IDE 的诞生与亮相二、独特功能与优势&#xff08;一&#xff09;智能编程体验&#xff08;二&#xff09;多语言支持与功能迭代 三、实际应用与案例&#xff08;一&#xff09;游戏开发案例&#xff08;二&am…

ubuntu 16.04 中 VS2019 跨平台开发环境配置

su 是 “switch user” 的缩写&#xff0c;表示从当前用户切换到另一个用户。 sudo 是 “superuser do” 的缩写&#xff0c;意为“以超级用户身份执行”。 apt 是 “Advanced Package Tool” 的缩写&#xff0c;Ubuntu中用于软件包管理的命令行工具。 1、为 root 用户设置密码…

[Docker#11] 容器编排 | .yml | up | 实验: 部署WordPress

目录 1. 什么是 Docker Compose 生活案例 2. 为什么要使用 Docker Compose Docker Compose 的安装 Docker Compose 的功能 使用步骤 核心功能 Docker Compose 使用场景 Docker Compose 文件&#xff08;docker-compose.yml&#xff09; 模仿示例 文件基本结构及常见…

C++时间复杂度与空间复杂度

一、时间复杂度&#xff08;Time Complexity&#xff09; 1. 概念 时间复杂度是用来衡量算法运行时间随着输入规模增长而增长的量级。它主要关注的是算法执行基本操作的次数与输入规模之间的关系&#xff0c;而非具体的运行时间&#xff08;因为实际运行时间会受硬件、编程语…

【Linux】【Shell】Shell 基础与变量

Shell 基础 Shell 基础查看可用的 Shell判断当前 Shell 类型 变量环境变量查看环境变量临时环境变量永久环境变量PATH 变量 自定义变量特殊赋值(双引号、单引号、反撇号) 预定义变量bashrc Shell 基础 Shell 是一个用 C 语言编写的程序&#xff0c;相当于是一个翻译&#xff0c…

【SpringBoot】26 实体映射工具(MapStruct)

Gitee 仓库 https://gitee.com/Lin_DH/system 介绍 现状 为了让应用程序的代码更易于维护&#xff0c;通常会将项目进行分层。在《阿里巴巴 Java 开发手册》中&#xff0c;推荐分层如下图所示&#xff1a; 每层都有对应的领域模型&#xff0c;即不同类型的 Bean。 DO&…

理解和选择Vue的组件风格:组合式API与选项式API详解

目录 前言1. Vue 的两种组件风格概述1.1 选项式 API&#xff1a;直观且分块清晰1.2 组合式 API&#xff1a;灵活且逻辑集中 2. 深入理解组合式 API 的特点2.1 响应式变量与函数式编程2.2 逻辑组织更清晰2.3 更好的代码复用 3. 应用场景分析&#xff1a;如何选择 API 风格3.1 适…

Windows和mac OS共用VMware虚拟机

在Windows下使用VMware Workstation Pro创建的虚拟机&#xff0c;是以文件夹形式存储在硬盘中的&#xff0c;在mac OS中对应的虚拟机产品是VMware Fusion&#xff0c;那么在Windows下创建的虚拟机怎么在mac OS中使用呢&#xff1f; 在下图中我们可以看到&#xff0c;Windows 1…

【K8S系列】Kubernetes Pod节点ImagePullBackOff 状态及解决方案详解【已解决】

在 Kubernetes 中,当某个 Pod 的容器无法从指定的镜像仓库拉取镜像时,Pod 的状态会变为 ImagePullBackOff。这通常是因为指定的镜像不存在、镜像标签错误、认证失败或网络问题等原因。 以下是关于 ImagePullBackOff 的详细分析及解决方案。 1. ImagePullBackOff 状态分析 1.…

04 —— Webpack打包CSS代码

加载器css-loader &#xff1a;解析css代码 webpack 中文文档 | webpack中文文档 | webpack中文网 加载器style-loader&#xff1a;把解析后的css代码插入到DOM style-loader | webpack 中文文档 | webpack中文文档 | webpack中文网 准备css代码&#xff0c;放到src/login目…

单元测试框架gtest学习(二)—— 认识断言

前言 我们在上一篇文章中&#xff0c;简要介绍了gtest是如何使用的 单元测试框架gtest学习&#xff08;一&#xff09;——初始gtest-CSDN博客 这篇文章我们主要总结gtest中的所有断言相关的宏。首先需要明确的是&#xff0c;gtest是通过各种断言宏进行测试的&#xff0c;而这…

网安瞭望台第2期:零日漏洞密集爆发、2024年常见网络安全漏洞类型及分析

国内外要闻 Ubuntu 服务器 Needrestart 软件包惊现严重安全漏洞 近日&#xff0c;Ubuntu 服务器&#xff08;自 21.04 版本起默认安装&#xff09;的 Needrestart 软件包被曝存在多个可追溯至数十年前的安全漏洞。这些漏洞允许本地攻击者在无需用户交互的情况下获取根…

PDF内容提取,MinerU使用

准备环境 # python 3.10 python3 -m pip install huggingface_hub python3 -m pip install modelscope python3 -m pip install -U magic-pdf[full] --extra-index-url https://wheels.myhloli.com下载需要的模型 import json import osimport requests from huggingface_hub…

【TDOA最小二乘解算】两步最小二乘迭代的TDOA解算方法,适用于二维平面、自适应锚点(附MATLAB代码)

本文所述的MATLAB代码实现了一个基于两步加权最小二乘法的二维目标定位算法&#xff0c;利用多个锚点&#xff08;基站&#xff09;和时间差到达&#xff08;TDOA&#xff09;数据来估计未知目标的位置。 文章目录 运行结果代码代码功能概述代码结构和详细说明初始化部分参数和…

Comfy UI 工作流(三)高清修复 - 低显存放大

前面提到的几种高清修复、高清放大都会占用&#xff0c;较多的现存。 和 Sd Web UI 中的 SD Upscale 放大一样&#xff0c;Comfy UI 中也提供有类似的自定义节点&#xff0c;通过分块的方式进行图片放大&#xff0c;从而减少现、显存的占用&#xff0c;该方式也经常用于 Com…

形态学图像处理(Morphological Image Processing)

形态学图像处理(Morphological Image Processing) 前言 ‍ 本博客为个人总结数字图像处理一课所写&#xff0c;并给出适当的扩展和相应的demo。 写博客跟做 checkpoint​ 很像&#xff0c;毕竟个人还不能达到那种信手拈来的境界&#xff0c;忘了就是从零开始训练&#xff0…

数据库迁移--laravel进阶篇

本地开发中的数据库和线上发布的数据库是不一样的,每进行一个线上版本的更新,很可能也涉及大量数据库的改动,那么这些数据库的改动在laravel中可以使用数据库迁移来处理。 比如我想创建一张flights数据表 执行php artisan make:migration create_flights_table命令就能自动生…

正则表达式完全指南,总结全面通俗易懂

目录 元字符 连接符 限定符 定位符 修饰符&#xff08;标记&#xff09; 运算符优先级 普通字符集及其替换 零宽断言 正向先行断言 负向先行断言 正向后发断言 负向后发断言 捕获组 普通捕获组 命名捕获组 PS:非捕获组 正则表达式在线测试: 正则在线测试工具 …

vulfocus在线靶场:CVE-2018-7600 速通手册

目录 一、启动环境&#xff0c;访问页面&#xff0c;语言选择中文&#xff0c;打开phpmyadmin 二、phpmyadmin中打开小房子 三、选择显示php信息 四、ctrlF&#xff0c;搜索flag&#xff0c;复制粘贴到任务中&#xff0c;通关 一、启动环境&#xff0c;访问页面&#xff0c;…