【数据结构与算法C++实现】3、排序算法

news2024/11/25 22:53:18

原视频为左程云的B站教学


以下所有的swap()函数,函数定义为

void swap(int& a, int& b)
{
	int t = a;
	a = b;
	b = t;
}
// 也可以用异或,但不能传入同一个变量,可以是不同变量相同值
void swap(int& a, int& b)
{
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
}

1 冒泡排序 O ( N 2 ) O(N^2) O(N2)(与数据状况无关)

最基础、最简单的排序,没啥好说的
请添加图片描述

#incldue <vector>
void bubbleSort(std::vector<int>& arr) 
{
    for (int i = 0; i < arr.size() - 1; i++) {
        for (int j = 0; j < arr.size() - 1 - i; j++) {
            if (arr[j] > arr[j+1]) {        // 相邻元素两两对比
				swap(arr[j], arr[j+1]);
            }
        }
    }
}

2 选择排序 O ( N 2 ) O(N^2) O(N2)(与数据状况无关)

基本思想是每次从待排序的元素中选择最小(或最大)的元素,放到已排序序列的末尾。选择排序的主要步骤如下:

  • 1.遍历待排序序列,设定当前位置为最小值的位置。
  • 2.从当前位置开始,依次比较当前元素与后面的元素,找到最小的元素,记录其位置。
  • 3.将最小元素与当前位置的元素进行交换。
  • 4.重复步骤2和步骤3,直到遍历完整个序列。
    请添加图片描述
#include<vector>
void selectionSort(std::vector<int>& arr)
{
	int len = arr.size();
	if (arr.empty() || len < 2) return;

	for (int i = 0; i < len -1; i++){ // len -1 位置不用再循环了,因为最后剩一个必然是最值
		int minIndex = i;		// 在i ~ len-1 上寻找最小值的下标
		for (int j = i; j < len - 1; j++){
			minIndex = arr[j] < arr[minIndex] ? j : minIndex;
		}
		swap(arr[minIndex], arr[i]);
	}
}

3 插入排序 O ( N 2 ) O(N^2) O(N2)(与数据状况相关)

原理类似于对扑克牌手牌进行排序的过程。将未排序的元素逐个插入到已排序部分的合适位置。

逻辑顺序为先做到0~0有序, 然后0~1有序, 0~2 … 0~n-1有序

算法流程为:

  • 1.从第一个元素开始,该元素可以认为已经被排序。
  • 2.从未排序部分取第一个值,插入到已排序部分的适当位置。这个位置的选取方式为:把当前未排序值与左邻值对比,如果更小则交换位置。直到遇到边界或不比左邻值小则结束。(内循环:找适当位置插入)
  • 3.重复步骤2,直到所有元素都被插入到已排序序列中。(外循环:遍历每个未排序的数)

这个不像冒泡排序和选择排序是固定操作(数据状况无关)。插入排序中,如果给的就是有序的,那就外层循环每次比一下就完成了所以会是O(N), 但我们说时间复杂度都是 worst case 所以还是 O ( N 2 ) O(N^2) O(N2)

请添加图片描述

#include <vector>
void insertionSort(std::vector<int>& arr)
{
	int len = arr.size();
	if (arr.empty() || len < 2) return;
	// 0~0已经有序了
	for (int i = 1; i < len; i++){ 	// 0~i做到有序
		// 把当前值(j+1)对比左邻值(j),比他小则交换,不满足循环条件则说明找到合适位置了
		for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--){ 
			swap(arr[j+1], arr[j]);
		}
	}
}

在内层循环中,我们将当前元素 arr[j + 1] 与其左邻元素 arr[j] 进行比较,更小则换位,直到找到合适的插入位置。
循环结束(找到合适的位置)条件为:达到左边界 or 当前值比左邻值大

继续往下看建议先掌握 二分查找

4 归并排序( O ( N l o g N ) O(NlogN) O(NlogN))(数据状况无关)

它的核心思想是将待排序的序列不断划分成更小的子序列,直到每个子序列只有一个元素,然后再将这些子序列两两合并,直到最终整个序列有序。

下面是归并排序的一般步骤:

  • 分割:将待排序的序列从中间位置分割成两个子序列,不断递归地将每个子序列继续分割,直到每个子序列只剩下一个元素。
  • 合并:将两个有序的子序列合并成一个有序序列。从两个子序列的第一个元素开始比较,将较小的元素放入临时数组中,并将对应子序列的索引向后移动一位,直到其中一个子序列的元素全部放入临时数组中。然后将另一个子序列的剩余元素直接放入临时数组中。
  • 重复合并:重复进行合并操作,直到所有子序列都合并为一个有序序列。

始终都是 O(nlogn) 的时间复杂度,与数据无关。虽然相对前面的冒泡、选择、插入排序更快,但是需要额外的内存空间。

下图对于这个过程的描述是非常准确的,请添加图片描述

// 第二阶段:merge阶段时,L~M 和 M~R 之间的数必然有序
void merge(std::vector<int>& arr, int L, int M, int R)
{
	std::vector help(R - L + 1);
	int i = 0;
	int p1 = L;
	int p2 = M + 1;
	while (p1 <= M && p2 <= R){ //类似链表合并,把两个子数组中的元素从小到大放到help数组
		help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
	}
	while (p1 <= M){ // 如果左边部分还有剩的,全部加到help中
		help[i++] = arr[p1++];
	}
	while (p2 <= R){ // 同理如果右边还有剩的
		help[i++] = arr[p2++];
	}

	// 结束,把临时数组的内容覆盖到原数组中
	for (i = 0; i < R - L + 1; i++){
		arr[L + i] = help[i]; // 注意arr从L位置开始写入的
	}
}

// 务必先看这个函数 这算是第一阶段拆分
void mergeSort(std::vector<int>& arr, int L, int R)
{
	if (L == R) return;	// 拆分完毕,不能再拆了
	
	int mid = L + ((R - L) >> 1);
	mergeSort(arr, L, mid);
	mergeSort(arr, mid+1, R);
	merge(arr, L, mid, R); // 执行到这一步的条件是 L == mid 且 mid+1 == R
}

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

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

相关文章

极智开发 | 让wsl2读取宿主机usb设备

欢迎关注我的公众号 [极智视界]&#xff0c;获取我的更多经验分享 大家好&#xff0c;我是极智视界&#xff0c;本文介绍一下 让wsl2读取宿主机usb设备的方法。 邀您加入我的知识星球「极智视界」&#xff0c;星球内有超多好玩的项目实战源码下载&#xff0c;链接&#xff1a;…

高效处理消息:使用Spring Boot实现消息重试机制

当涉及到消息发送和接收的可靠性&#xff0c;Spring Boot提供了一些机制来确保消息的可靠传递。其中包括消息确认机制和重试机制。下面是一个示例代码&#xff0c;演示如何在Spring Boot中实现可靠的消息发送和接收。 首先&#xff0c;我们需要配置RabbitMQ的连接信息和相关属性…

58 KVM工具使用指南-应用 LibcarePlus 热补丁

文章目录 58 KVM工具使用指南-应用 LibcarePlus 热补丁58.1 前期准备58.2 加载热补丁58.3 查询补丁58.4 卸载热补丁 58 KVM工具使用指南-应用 LibcarePlus 热补丁 本节以原文件 foo.c 和补丁文件 bar.c 为例&#xff0c;介绍 LibcarePlus 热补丁的应用指导。 58.1 前期准备 …

小小面试题之赛马问题

各家大厂面试时都喜欢出一些逻辑题&#xff0c;简单的考验一下应试者的逻辑思维能力。 题目是&#xff1a;现在有64匹赛马和8条赛道&#xff0c;最少需要多少轮比赛才能选出最快的4匹马。 依据现实情况来说&#xff0c;这个问题很好回答。需要经过小组赛&#xff0c;16强赛&am…

王道操作系统学习笔记(2)——进程管理

前言 本文介绍了操作系统中的进程管理&#xff0c;文章中的内容来自B站王道考研操作系统课程&#xff0c;想要完整学习的可以到B站官方看完整版。 二&#xff1a;进程管理 2.1.1&#xff1a;进程的概念、组成、特征 程序&#xff1a;是静态的&#xff0c;就是存放在磁盘里的…

【好书精读】网络是怎样连接的 —— UDP 协议的收发操作

&#xff08; 该图由我使用 AI 绘制 &#xff09; 目录 不需要重发的数据用 UDP 发送更高效 控制用的短数据 音频和视频数据 不需要重发的数据用 UDP 发送更高效 DNS 服务器查询 IP 地址的时候我们用的是 UDP 协议 简单的说就是&#xff0c;TCP之所以复杂&#xff0c;是…

3-css高级特效-1

01-平面转换 简介 作用&#xff1a;为元素添加动态效果&#xff0c;一般与过渡配合使用 概念&#xff1a;改变盒子在平面内的形态&#xff08;位移、旋转、缩放、倾斜&#xff09; 平面转换也叫 2D 转换&#xff0c;属性是 transform 平移 transform: translate(X轴移动距…

Jetpack Compose 入门难点解疑

作者&#xff1a;晴天小庭 近些年声明式布局开发方式逐渐从网页端延展到了手机端&#xff0c;说到底还是声明式太香了&#xff0c;其代码更加清晰、简洁&#xff0c;并且更接近于自然语言的表达方式。这使得代码易于理解和维护&#xff0c;降低了开发人员的心智负担。 谷歌和苹…

【c语言12】字符串函数(strlen,strcmp,strcpy,strcat,strstr,strtok,strerror)

文章目录 一、字符串函数1.1strlen&#xff08;求字符串长度&#xff09;1.2strcmp&#xff08;比较字符串&#xff09;1.3strcpy&#xff08;拷贝字符串&#xff09;1.4strcat&#xff08;追加字符串&#xff09;1.5strstr&#xff08;判断子串&#xff09;1.6sttok&#xff0…

【C/C++】使用类和对象 封装链表

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

SpringMVC全套详解

1、SpringMVC是什么1.1、MVC定义1.2、MVC和 SpringMVC的关系2.创建SpringMVC项目 2.1、SpringMVC 链接2.2、RequestMapping 注解说明2.3 、 GetMapping 和 PostMapping 3、获取参数3.1、传递单个参数3.2、传递多个参数/表单参数传递3.3、传递对象3.4、后端参数重命名(后端参数映…

C语言笔记-1

文章目录 C 基础语法注意 C 其他知识点编译过程编译器数据模型区别32/64位机器中&#xff0c;各数据类型所占位数assert() 断言&#xff08;宏&#xff09;用法总结与注意事项 C 基础语法 注意 if(a表达式) 判断的就是a的值&#xff0c;而不是判断这个赋值操作的成功与否。 查…

老天如果给我一次重来的机会,我还会选测试

在我们选择测试这行前&#xff0c;想象总是美好&#xff0c;然而现实无比扎心。 在办公环境上 想象中&#xff1a;美女&#xff08;帅哥&#xff09;环绕&#xff0c;前卫时尚&#xff0c;拥有独立办公间&#xff0c;没事转转座椅&#xff0c;偶尔来点咖啡和音乐。 现实中&…

【数据结构与算法C++实现】2、二分查找

原视频为左程云的B站教学 1 在有序数组中查找特定元素 基本思想是通过比较中间元素与目标元素的大小关系&#xff0c;将查找范围缩小一半&#xff0c;直到找到目标元素或查找范围为空为止。 时间复杂度O(logN) 因为比如说数组个数为N16, 最差的情况要分 4 次 ( [ 8 ∣ 8 ] →…

变化太快的Roop项目(版本1.0.1)

文章目录 &#xff08;一&#xff09;版本1.0.1的变化&#xff08;1.1&#xff09;项目依赖&#xff08;1.2&#xff09;模型位置&#xff08;1.3&#xff09;命令行&#xff08;1.4&#xff09;界面UI&#xff08;1.5&#xff09;处理与结果 最早的&#x1f517;接触和介绍&am…

带三维重建和还原功能的医学影像管理系统(pacs)源码

一、概述 它集影像存储服务器、影像诊断工作站及RIS报告系统于一体,主要由图像处理模块、影像数据管理模块、RIS报告模块、光盘存档模块、DICOM通讯模块、胶片打印输出等模块组成&#xff0c; 具有完善的影像数据库管理功能&#xff0c;强大的图像后处理功能&#xff08;三维重…

2-css-3

一 选择器 1 结构伪类选择器 作用&#xff1a;根据元素的结构关系查找元素。 选择器说明E:first-child查找第一个E元素E:last-child查找最后一个E元素E:nth-child(N)查找第N个E元素&#xff08;第一个元素N值为1&#xff09; li:first-child {background-color: green; }2 :…

AgilePLM应用周期性崩溃-问题解决

​ 问题现象 每周六2点左右&#xff0c;AgilePLM应用进程都会崩溃&#xff0c;具体表现为登录Agile应用服务器之后&#xff0c;找不到weblogic应用进程&#xff08;ps -ef | grep java&#xff09;。从服务器所有相关日志中没有找到任何可疑的异常日志。 当天Agile应用重启之…

UDS通信服务解析

InputOutputControlByIdentifier (0x2F)----通过ID对输入输出进行控制 2F的03子功能是"暂时接管控制权" ReadDataByIdentifier(0x2A)—通过ID读取数据或特定器件状态 ClearDiagnosticInformation(0x14)—清除故障诊断信息 UDS规定用FF FF FF表示所有种类的DTC Rou…

技术干货 | 开始使用 Redis

Redis 是一个使用 C 语言编写的开源、BSD 许可、高级的键值存储&#xff0c;。它也被称为数据结构服务器&#xff0c;因为键可以包含字符串、哈希、列表、集合和有序集合。本教程将介绍使用 Redis 所需的基本概念。Navicat Premium 和 Navicat for Redis 现已支持 Redis, 如果你…