冒泡排序、插入排序、选择排序、归并排序、快速排序算法(C++实现)

文章目录

  • 一、冒泡排序
    • 上浮法冒泡排序(从小到大排序)
    • 下浮法冒泡排序(从大到小排序)
  • 二、选择排序
  • 三、插入排序
  • 四、归并排序
  • 五、快速排序
  • 参考

一、冒泡排序

冒泡排序应该算是最经典最简单的排序算法,我一开始学习排序算法就是从冒泡排序开始入门的。
冒泡排序算法的基本思路:(循环遍历,相邻元素比较

  1. 冒泡排序通过多轮遍历数组,每一轮比较相邻的元素,如果相邻元素的顺序不符合要求(升序或降序),则交换它们的位置。
  2. 每一轮重复以上的比较操作,就会将当前未排序的最大(升序)或者最小(降序)元素排序到数组的末尾位置。
  3. 重复以上步骤,直到一轮遍历中没有发生任何交换,表示数组已经排序完成。
  4. 循环遍历的次数最多n-1次,最少为1次。
    时间复杂度:最好为O(n) 最差为O(n^2)
    空间复杂度:O(1)

上浮法冒泡排序(从小到大排序)

#include <iostream>
#include <vector>using namespace std;void bubbleSortUp(vector<int> &nums)
{for (int i = 0; i < nums.size() - 1; i++){bool isSwap = false;for (int j = 0; j < nums.size() - i - 1; j++){if (nums[j] > nums[j + 1]){swap(nums[j], nums[j + 1]);isSwap = true;}}if (isSwap == false){cout << "排序已完成" << endl;break;}}
}int main(int argc, char const *argv[])
{vector<int> nums = {5, 6, 675, 4, 43, 63, 1, 2, 3, 8, 5, 6, 675, 4, 43, 63, 1, 2, 3};bubbleSortUp(nums);for (auto num : nums){cout << num << " ";}cout << endl;return 0;
}

下浮法冒泡排序(从大到小排序)

如果会了上浮法冒泡排序,那下浮法的就很简单,只需要将上浮法中的if (nums[j] > nums[j + 1])改成if (nums[j] < nums[j + 1])即可。
时间复杂度:最好为O(n) 最差为O(n^2)
空间复杂度:O(1)

#include <iostream>
#include <vector>using namespace std;void bubbleSortUp(vector<int> &nums)
{for (int i = 0; i < nums.size() - 1; i++){bool isSwap = false;for (int j = 0; j < nums.size() - i - 1; j++){// 下浮法只需要修改这里即可if (nums[j] < nums[j + 1]){swap(nums[j], nums[j + 1]);isSwap = true;}}if (isSwap == false){cout << "排序已完成" << endl;break;}}
}int main(int argc, char const *argv[])
{vector<int> nums = {5, 6, 675, 4, 43, 63, 1, 2, 3, 8, 5, 6, 675, 4, 43, 63, 1, 2, 3};bubbleSortUp(nums);for (auto num : nums){cout << num << " ";}cout << endl;return 0;
}

二、选择排序

选择排序算法的基本思路:(循环遍历,找到最小元素并交换位置

  1. 遍历整个列表的n个元素,找到最小的元素,与第一个元素交换位置。
  2. 遍历列表剩余的n-1个元素,找到最小的元素,与第二个元素交换位置。
  3. 以此类推,重复以上步骤,直到需要遍历的列表元素个数小于等于1,则表示排序完成。
    时间复杂度:O(n^2)
    空间复杂度:O(1)
#include <iostream>
#include <vector>using namespace std;void selectSort(vector<int> &nums)
{for (int i = 0; i < nums.size() - 1; i++){int minIndex = i;for (int j = i + 1; j < nums.size(); j++){if (nums[j] < nums[minIndex]){minIndex = j;}}swap(nums[i], nums[minIndex]);}
}int main(int argc, char const *argv[])
{vector<int> nums = {-1, -181, 0, 0, 5, 6, 675, 4, 43, 63, 1, 2, 3, 8, 5, 6, 675, 4, 43, 63, 1, 2, 3, -999};selectSort(nums);for (auto num : nums){cout << num << " ";}cout << endl;return 0;
}

三、插入排序

插入排序算法的基本思路:(逐个取出元素,与前面有序部分依次比较并插入正确位置

  1. 从第二个元素开始,将这个元素作为待插入元素与前面有序的元素进行比较;
  2. 如果待插入的元素比前面有序的元素小,则将有序的元素往后移动,相当于腾出空间;
  3. 继续比较和移动,直到找到合适的位置(大于等于前一个数且小于等于后一个数),将待插入的元素放入该位置;
  4. 重复上述步骤,直到整个数组有序。
    时间复杂度:正序时最好为O(n) 逆序时最差为O(n^2)
    空间复杂度:O(1)
#include <iostream>
#include <vector>using namespace std;void insertSort(vector<int> &nums)
{for (int i = 1; i < nums.size(); i++){int j = i - 1;int temp = nums[i];while (j >= 0 && nums[j] > temp){nums[j + 1] = nums[j];j--;}nums[j + 1] = temp;}
}int main(int argc, char const *argv[])
{vector<int> nums = {-43, 3, 4, 124, 2345, 456, 5, 6, 7, 6, 5, 0, 12, 33, 3, 22, 2, 77, 2, 34, 55, 5, 56, 1, 100, 88, 21, 99};insertSort(nums);for (auto num : nums){cout << num << " ";}cout << endl;return 0;
}

一开始在写插入排序时,我用到了另一种方法:这种方法虽然也能实现排序,但是这种方法似乎不太符合插入排序的基本思路,而且用到了swap,在一定程度上会增加时间复杂度。

void insertSort(vector<int> &nums) 
{ for (int i = 1; i < nums.size(); i++) { for (int j = i; j > 0; j--) { if (nums[j] < nums[j - 1]) { swap(nums[j], nums[j - 1]); } } } 
}

四、归并排序

归并排序有两种实现方法,一种是递归,一种是迭代。
归并排序的基本思路:(分治算法

  1. 分解,将待排序的数组从中间分成两半,分别递归地对这两半进行排序,不断分解,直到数组的长度为 1,此时每个子数组都被视为有序。
  2. 合并,将子数组两两合并,合并的过程中排序,按大小顺序将元素从两个子数组中取出,形成一个新的有序数组。
    归并排序算法的特点:
  3. 是稳定排序算法
  4. 速度仅次于快速排序
  5. 一般用于对总体无序,但是各子项相对有序的数列。
    时间复杂度:O(nlogn)
    空间复杂度:O(n)
#include <iostream>
#include <vector>
using namespace std;/*** 归并函数(二路合并)* start:第一段的首元素索引* mid:第二段的首元素索引* end:第二段的末尾元素索引*/
void merge(vector<int> &nums, const int start, const int mid, const int end)
{vector<int> merArray;int p1 = start;int p2 = mid;while (p1 < mid && p2 <= end){if (nums[p1] <= nums[p2]){merArray.push_back(nums[p1++]);}else{merArray.push_back(nums[p2++]);}}// 将剩余的元素加入到merArraywhile (p1 < mid){merArray.push_back(nums[p1++]);}while (p2 <= end){merArray.push_back(nums[p2++]);}int pos = start;for (auto it : merArray){nums[pos++] = it;}
}/*** 用迭代的方法实现归并排序* 时间复杂度:O(nlogn)* 空间复杂度:O(n),因为排序过程中多次拆分的子数组需要放在内存*/
void mergeSortIteration(vector<int> &nums)
{for (int i = 0; i < nums.size(); i++){int start = 0;int len = 1 << i;if (len > nums.size())break;while (start < nums.size()){// 注意区分这里的mid和传入merge函数的mid+1// mid是第一段的末尾元素,mid+1是第二段的首元素int mid = start + len - 1;if (mid >= nums.size())break;int end = min(start + 2 * len - 1, (int)nums.size() - 1);merge(nums, start, mid + 1, end);start += len * 2;}}
}/*** 用递归的方法实现归并排序* 时间复杂度:O(nlogn)* 空间复杂度:O(n),因为排序过程中多次拆分的子数组需要放在内存* 传参都是统一传递有效索引*/
void mergeSortRecursion(vector<int> &nums, int start, int end)
{if (start < end){int mid = (start + end) / 2;mergeSortRecursion(nums, start, mid);mergeSortRecursion(nums, mid + 1, end);merge(nums, start, mid + 1, end);}
}int main(int argc, char const *argv[])
{vector<int> nums = {-43, -22, 8, 44, 11, 223, 4, 0, 1, 2, 2, 3, 3, 33, 3};mergeSortIteration(nums); // 迭代法// mergeSortRecursion(nums, 0, nums.size() - 1); // 递归法for (int num : nums){cout << num << " ";}cout << endl;return 0;
}

五、快速排序

快速排序采用的也是分治的策略,它是一种基于二叉树结构的交换排序算法。快速排序是一种不稳定的排序方法,但是他的效率非常高。
快速排序算法的基本思路:

  1. 先从数列中取出一个数作为基准数,然后将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边;
  2. 对左右区间重复步骤一的操作,直到各区间只有一个数。
    时间复杂度:最差为O(n^2),平均为O(NlogN)
    空间复杂度:受递归深度影响,最好为O(logn),最差为O(n)
#include <iostream>
#include <vector>using namespace std;/*** 快速排序算法(左右指针法/hoare法)* 时间复杂度:最差为O(n^2),平均为O(NlogN)* 空间复杂度:受递归深度影响,最好为O(logn),最差为O(n)*/
void quickSort(vector<int> &nums, int begin, int end)
{if (begin >= end)return;// 保存左右节点int left = begin;int right = end;// 选取第begin节点为keyint key = begin;while (begin < end){// 右边选小,遇到大于nums[key]的数就跳过while (begin < end && nums[end] >= nums[key]){end--;}// 左边选大,遇到小于nums[key]的数就跳过while (begin < end && nums[begin] <= nums[key]){begin++;}swap(nums[begin], nums[end]);}// 交换相遇点的值和nums[key]值swap(nums[key], nums[begin]);key = begin;// 递归quickSort(nums, left, key - 1);quickSort(nums, key + 1, right);
}int main(int argc, char const *argv[])
{vector<int> nums = {-43, -22, 8, 44, 11, 223, 4, 0, 1, 2, 2, 3, 3, 33, 3};quickSort(nums, 0, nums.size() - 1);for (auto num : nums){cout << num << " ";}cout << endl;return 0;
}

参考

  1. C++实现排序算法_c++从小到大排序-CSDN博客
  2. 常见的几种排序算法(c++)_c++排序算法-CSDN博客
  3. 六大排序算法:插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用于图像识别的判别图正则化技术

本文所涉及所有资源均在 传知代码平台 可获取。 目录 论文概述 图正则化技术及其优点 算法流程 在标准BLS中嵌入判别图正则化的方法 模型整体架构 代码复现 图拉普拉斯矩阵的构建——generateLmatrix.py文件 复现模型整体架构——bls2deep_graph.py文件 顶层文件——GBLS.py文件…

Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND

Case1 : 表没有主键 show create table xxx desc table Case2 : 表是MEMORY表 show create table xxx desc table https://dev.mysql.com/doc/mysql-replication-excerpt/5.7/en/replication-features-memory.html

KDTS 实现MySQL至KingbaseES迁移实践

此文章以linux环境实践&#xff0c;KingbaseES一下使用KES代替。 KDTS KDTS工具安装KES时会一起安装&#xff0c;一般存在目录为&#xff1a;ClientTools目录下guitools文件夹中 启动 进入KDTS-WEB下bin目录&#xff0c;执行sh文件 cd /opt/Kingbase/ES/V8/ClientTools/guit…

70.【C语言】动态内存管理(重点)(3)

本文为数据结构打下基础 备注:数据结构需要掌握指针,结构体和动态内存管理 承接69.【C语言】动态内存管理(重点)(2)文章 目录 4.calloc函数 cplusplus网的翻译 提炼要点 使用 5.recalloc函数 使用说明 作用 调整内存空间的几种情况 1.原有空间之后有足够大的空间 …

自动猫砂盆是养猫新型智商税吗?测评2024年热门款智能猫砂盆分享

铲屎官们只要一察觉到猫主子拉屎&#xff0c;就要马上去铲掉&#xff0c;这不仅是为了猫砂盆中其他干净的猫砂&#xff0c;更是为了防止猫屎残留发臭&#xff0c;特别是便便这种东西&#xff0c;一旦放久了就很招虫子&#xff0c;家里出现这些虫子又要大扫除消杀&#xff0c;特…

使用Python接口自动化测试post请求和get请求,获取请求返回值

引言 我们在做python接口自动化测试时&#xff0c;接口的请求方法有get,post等&#xff1b;get和post请求传参&#xff0c;和获取接口响应数据的方法&#xff1b; 请求接口为Post时&#xff0c;传参方法 我们在使用python中requests库做接口测试时&#xff0c;在做post接口测试…

论文精读:基于概率教师学习的跨域自适应目标检测(ICML2022)

原文标题&#xff1a;Learning Domain Adaptive Object Detection with Probabilistic Teacher 中文标题&#xff1a;基于概率教师学习的域自适应目标检测 代码地址&#xff1a; GitHub - hikvision-research/ProbabilisticTeacher: An official implementation of ICML 2022 p…

计算机网络——ftp

在网络通信中&#xff0c;控制连接和数据连接是两种不同类型的连接&#xff0c;它们各自具有特定的功能和用途。 一、控制连接 定义与功能&#xff1a; 控制连接主要用于在通信双方之间传输控制信息&#xff0c;以建立、维护和终止数据连接。它负责协调和管理数据传输的过程&am…

图像数据增强库综述:10个强大图像增强工具对比与分析

在深度学习和计算机视觉领域&#xff0c;数据增强已成为提高模型性能和泛化能力的关键技术。本文旨在全面介绍当前广泛使用的图像数据增强库&#xff0c;分析其特点和适用场景&#xff0c;以辅助研究人员和开发者选择最适合其需求的工具。 数据增强的重要性 数据增强在深度学习…

架构设计笔记-7-系统架构设计基础知识

目录 知识要点 单选 案例分析 1.质量属性 / 管道过滤器 / 数据仓库风格 2.面向对象风格 / 控制环路风格 3.软件架构风格 / 架构风格选择 4.体系结构方案对比 5.面向对象风格 / 基于规则风格 6.解释器风格 / 管道过滤器风格 7.面向对象风格 / 解释器风格 8.软件架构复…

直击工博会 | 万物集与四大供应商强强联手,开启战略合作新纪元!

9月24日&#xff0c;第24届中国国际工业博览会在国家会展中心&#xff08;上海&#xff09;开幕。本届工博会设置数控机床与金属加工展、工业自动化展、节能与工业配套展、新一代信息技术与应用展等9大专业主题展&#xff0c;吸引28个国家和地区2600家企业参展。万物集作为参展…

Canal 扩展篇(阿里开源用于数据同步备份,监控表和表字段(日志))

1.Canal介绍 Canal把自己伪装成从数据库&#xff0c;获取mysql主数据库的日志&#xff08;binlog&#xff09;信息&#xff0c;所以要想使用canal就得先开启数据库日志 https://github.com/alibaba/canal Canal 主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量…

影刀RPA在智能客服上的运用

随着人工智能技术的不断发展&#xff0c;智能客服系统逐渐成为企业提升服务效率和质量的重要工具。影刀RPA&#xff08;Robotic Process Automation&#xff0c;机器人流程自动化&#xff09;作为一种模拟人类用户行为的技术&#xff0c;通过自动化执行重复性高、规则明确的任务…

1. Oracle 安装报错——环境变量过长

文章目录 1. 报错详细信息2. 解决方案2.1 方案一&#xff1a;修改配置文件cvu_prereq.xml2.2 方案二&#xff1a;修改环境变量配置 1. 报错详细信息 安装 Oracle 过程中&#xff0c;在执行 “先决条件检查” 时报错&#xff1a; 报错内容&#xff1a; This test checks wheth…

163页PPT罗兰贝格品牌战略升级:华为案例启示与电器集团转型之路

罗兰贝格作为一家全球顶级的战略管理咨询公司&#xff0c;其品牌战略升级理念在多个行业中得到了广泛应用。以下将以华为案例为启示&#xff0c;探讨电器集团的转型之路&#xff0c;并融入罗兰贝格品牌战略升级的思想。 一、华为案例的启示 华为与罗兰贝格联合撰写的《数据存…

MySQL【知识改变命运】03

表的基本操作 1&#xff1a;查看所有表2&#xff1a;创建表3&#xff1a;查看表结构4&#xff1a;修改表5&#xff1a; 删除表 前言&#xff1a;我们先了解一个知识&#xff1a; MySQL安装后会有MySQL服务——管理多个库——每个库管理多个表——每个表管理多行数据——数据行由…

鲁班到家上门安装维修系统源码开发之结构功能解析

随着物联网和智能家居的普及&#xff0c;消费者对便捷、高效的生活方式需求日益增加。鲁班到家作为一款专注于家居安装维修服务的平台&#xff0c;凭借其多渠道预约、智能派单、在线支付与费用明细透明等优势&#xff0c;在市场上赢得了广泛认可。本文将详细解析鲁班到家上门安…

【Unity踩坑】UWP项目安装包认证失败

问题&#xff1a;在Unity导出的VS项目&#xff0c;打包生成appx后&#xff0c;进行应用认证时失败。提示部分API不支持。 API __C_specific_handler in kernel32.dll is not supported for this application type. UnityPlayer.dll calls this API.API DXGIGetDebugInterface1 …

操作系统 | 学习笔记 | 王道 | 4.3 文件系统

4.3 文件系统 4.3.1 文件系统结构 文件系统(File system)提供高效和便捷的磁盘访问&#xff0c;以便允许存储、定位、提取数据。 用一个例子来辅助记忆文件系统的层次结构&#xff1a; 假设某用户请求删除文件"D:/工作目录/学生信息.xIsx"的最后100条记录。 用户需…

MongoDB集群模式详解及应用实战

目录 本节课内容&#xff1a; 集群搭建 1.创建3个目录&#xff1a; 2.编辑配置文件 ​编辑 3.启动&#xff1a; 4.看看&#xff1a; 5.另外&#xff0c;两个如上1&#xff0c;2&#xff0c;3步骤操作 &#xff0c;但是日志目录&#xff0c;端口什么的需要改一下即可。 …