【C++STL】快速排序算法(sort)的原理与使用

一、sort算法原理

std::sort 是 C++ 标准库中提供的排序算法,它使用的是一种经典的排序算法——快速排序(Quicksort)或者是其变种。

快速排序是一种基于比较的排序算法,通过不断地选择一个基准值(pivot),将待排序序列分割为两个子序列,其中一个子序列的所有元素小于等于基准值,另一个子序列的所有元素大于基准值。然后递归地对两个子序列进行排序,最终得到有序序列。

std::sort 在实现快速排序时,通常会结合其他优化技巧,如插入排序或堆排序,以提高算法的性能和效率。

快速排序的基本步骤:

  1. 选择一个基准值(pivot)。可以选择序列的第一个元素、最后一个元素、中间元素或者随机选择一个元素作为基准值。
  2. 将序列分割为两个子序列,使得一个子序列的所有元素小于等于基准值,另一个子序列的所有元素大于基准值。
  3. 递归地对两个子序列进行排序,即对小于等于基准值的子序列和大于基准值的子序列进行排序。
  4. 合并两个排序好的子序列,得到最终的有序序列。

快速排序是一种原地排序算法,它的平均时间复杂度为 O(nlogn),其中 n 是待排序序列的大小。在最坏情况下,快速排序的时间复杂度为 O(n^2),但通过合理选择基准值可以减少最坏情况的发生概率。

std::sort 的实现会考虑到不同情况下的性能和效率,并且在不同的编译器和库实现中可能有所不同。它通常会根据序列的大小、数据类型以及其他因素来选择合适的排序算法,以获得更好的性能。对于小型序列,std::sort 可能会使用插入排序或者其他简单的排序算法,而对于大型序列,它通常会采用快速排序或者其变种。此外,std::sort 还可以接受自定义的比较函数谓词,以满足不同的排序需求。

二、sort算法使用

功能: 对容器内元素进行排列(默认升序排列)

  • sort()属于质变算法
函数原型:sort(iterator beg, iterator end, pred)解释
参数1iterator beg开始迭代器
参数2iterator end结束迭代器
参数3pred谓词

详细信息:

当调用 std::sort 进行排序时,它采用的是一种分治策略的快速排序算法,这意味着它将待排序的元素分割成较小的子集,然后对这些子集进行排序并逐步合并,最终得到完全排序的结果。

  • 排序范围:std::sort 排序的是一个范围,由两个迭代器 firstlast 指定,表示排序的起始位置和结束位置。排序将应用于 [first, last) 区间内的元素。
  • 排序准则: 默认情况下,std::sort 使用 < 运算符进行比较来确定元素的顺序。如果要按照其他准则进行排序,可以提供自定义的比较函数或函数对象作为可选的第三个参数。这个比较函数或函数对象应接受两个参数,并返回一个布尔值,指示第一个参数是否在排序中应排在第二个参数之前。
  • 时间复杂度:std::sort 使用快速排序算法,其平均时间复杂度为 O(n log n),其中 n 是要排序的元素的数量。在最坏情况下,快速排序的时间复杂度为 O(n^2),但这种情况很少发生。
  • 容器要求:std::sort 可以用于标准容器(如 std::vectorstd::dequestd::list 等)以及普通的数组。排序会就地进行,即直接修改容器中的元素顺序,而不会创建新的容器。
  • 可自定义类型:std::sort 不仅可以对基本类型(如整数、浮点数)进行排序,还可以对自定义类型进行排序,只要自定义类型支持比较操作符 < 或提供自定义的比较函数。
  • 迭代器失效:std::sort 不会使迭代器失效,这意味着在排序后仍然可以使用原始容器的迭代器。
  • 稳定性:std::sort 不保证排序的稳定性,即相等元素的顺序可能在排序后发生改变。如果需要保持相等元素的顺序不变,可以使用 std::stable_sort 算法。

示例1: 默认情况下为升序排列

#include <iostream>
#include <algorithm> //必须包含该头文件
#include <vector>
using namespace std;//函数对象(仿函数)
class print
{
public:void operator()(int value){cout << value << " ";}
};void test01()
{vector<int> vec = {6, 9, 3, 4, 2, 7, 1, 5, 8};//排序前cout << "排序前:";for_each(vec.begin(), vec.end(), print());cout << endl;//排序后-升序cout << "排序后:";sort(vec.begin(), vec.end());   //默认升序for_each(vec.begin(), vec.end(), print());cout << endl;
}int main()
{test01();system("pause");return 0;
}
//result
排序前:6 9 3 4 2 7 1 5 8
排序后:1 2 3 4 5 6 7 8 9

示例2: 使用谓词std::greater<>

  • greater<> 是一个模板类,它是一个二元谓词(binary predicate),用于比较两个值的大小关系。
#include <iostream>
#include <algorithm> //必须包含该头文件
#include <vector>
using namespace std;//函数对象(仿函数)
class print
{
public:void operator()(int value){cout << value << " ";}
};void test01()
{vector<int> vec = {6, 9, 3, 4, 2, 7, 1, 5, 8};//排序前cout << "排序前:";for_each(vec.begin(), vec.end(), print());cout << endl;//排序后-降序-添加谓词greatercout << "排序后:";sort(vec.begin(), vec.end(), greater<int>());for_each(vec.begin(), vec.end(), print());cout << endl;
}int main()
{test01();system("pause");return 0;
}
//result
排序前:6 9 3 4 2 7 1 5 8
排序后:9 8 7 6 5 4 3 2 1

示例3: 自定义类型排序

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;class goods
{
public:goods(string name, int price){m_name = name;m_price = price;}public:string m_name;int m_price;
};// 自定义排序-根据商品价格升序
struct arrange
{bool operator()(const goods& value1, const goods& value2){return value1.m_price < value2.m_price;}
};class print
{
public:void operator()(const goods& value){cout << "名称:" << value.m_name  << "\t价格:" << value.m_price << endl;}
};void test01()
{goods goods1("可乐", 3);goods goods2("红牛", 5);goods goods3("脉动", 4);goods goods4("外星人", 6);goods goods5("雪碧", 3);goods goods6("哇哈哈", 2);vector<goods> vec;vec.push_back(goods1);vec.push_back(goods2);vec.push_back(goods3);vec.push_back(goods4);vec.push_back(goods5);vec.push_back(goods6);// 排序前cout << "排序前:" << endl;for_each(vec.begin(), vec.end(), print());cout << endl;// 排序后-升序-添加谓词arrangecout << "排序后:" << endl;sort(vec.begin(), vec.end(), arrange());for_each(vec.begin(), vec.end(), print());cout << endl;
}int main()
{test01();system("pause");return 0;
}
//result
排序前:
名称:可乐      价格:3
名称:红牛      价格:5
名称:脉动      价格:4
名称:外星人    价格:6
名称:雪碧      价格:3
名称:哇哈哈    价格:2排序后:
名称:哇哈哈    价格:2
名称:可乐      价格:3
名称:雪碧      价格:3
名称:脉动      价格:4
名称:红牛      价格:5
名称:外星人    价格:6

总结:std::sort 是一个高效、通用且灵活的排序算法。它在大多数情况下都能提供良好的性能,并且可以应用于不同类型的容器和自定义类型。然而,对于一些特殊需求,例如需要稳定排序或对大型容器进行排序,可能需要选择其他排序算法或使用自定义的排序实现。


如果这篇文章对你有所帮助,渴望获得你的一个点赞!

在这里插入图片描述

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

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

相关文章

超声波手持气象站的工作原理

TH-CSQ5A超声波手持气象站是一种利用超声波技术进行气象要素测量的便携式设备。它集成了多种气象传感器&#xff0c;包括温度传感器、湿度传感器、风速传感器、风向传感器等&#xff0c;能够同时测量和记录多个气象参数。 超声波手持气象站的工作原理基于超声波的传播特性。它…

全网最详细的Jmeter自动化测试

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、Jmeter的安装与部署 1.1 环境要求 jdk1.8、配置jdk环境变量&#xff08;JAVA_HOME:C:\Progr…

java工程师面试突击中华石杉,开发人员必学

如何高效的学习MyBatis源码呢&#xff1f; 市面上真正适合学习的MyBatis资料太少&#xff0c;有的书或资料虽然讲得比较深入&#xff0c;但是语言晦涩难懂&#xff0c;大多数人看完这些书基本都是从入门到放弃。学透MyBatis源码难道就真的就没有一种适合大多数同学的方法吗&am…

【笔记】深度学习入门:基于Python的理论与实现(六)

深度学习 深度学习是加深了层的深度神经网络 加深网络 本节我们将这些已经学过的技术汇总起来&#xff0c;创建一个深度网络&#xff0c;挑战 MNIST 数据集的手写数字识别 向更深的网络出发 基于33的小型滤波器的卷积层。激活函数是ReLU。全连接层的后面使用Dropout层。基…

4_怎么看原理图之协议类接口之SPI笔记

SPI&#xff08;Serial Peripheral Interface&#xff09;是一种同步串行通信协议&#xff0c;通常用于在芯片之间传输数据。SPI协议使用四根线进行通信&#xff1a;主设备发送数据&#xff08;MOSI&#xff09;&#xff0c;从设备发送数据&#xff08;MISO&#xff09;&#x…

机器学习-强化学习扩充

AI RL DL 基于Action&#xff0c;Enviroment给予Reward enviroment是对手 alpha go is supervised learning reinforcement learning 学两个agent&#xff0c;让两个互相沟通。 使用一些预定义的规则来判断对话的好坏。 更多应用 强化学习的困难就是奖励延迟…

android后端开发书籍,阿里内部核心Android进阶手册

努力的人&#xff0c;应该像好色那样好学 做Android开发的同学&#xff0c;对Gradle肯定不陌生&#xff0c;我们用它配置、构建工程&#xff0c;可能还会开发插件来促进我们的开发&#xff0c;我们必须了解Gradle&#xff0c;而不仅限于只会当配置构建工具&#xff0c;我想学习…

only office-用着确实很省心

小程一言 最近一直在使用各种办公软件进行学习笔记整理&#xff0c;但是在使用过程中&#xff0c;总感觉不是自己想要的一款软件&#xff0c;想要一款真正懂自己的软件&#xff0c;是一个选择的过程。最近在网上闲逛发现一款宝藏软件&#xff0c;好奇心驱使我去进行适用&#…

【MySQL】基本查询(表的增删改查)-- 详解

CRUD&#xff1a;Create&#xff08;创建&#xff09;&#xff0c;Retrieve&#xff08;读取&#xff09;&#xff0c;Update&#xff08;更新&#xff09;&#xff0c;Delete&#xff08;删除&#xff09;。 一、Create insert [into] table_name [(column [, column] ...)] v…

Jenkins与服务器时间不一致

问题复现 今天在Jenkins上设置定时部署项目时&#xff0c;发现Jenkins显示的时间与Linux系统显示的时间不一致&#xff0c;这太难过了&#xff0c;必须保持颗粒度一致。 解决办法 ①查看当前服务器上的时区 因为是CentOS系统&#xff0c;直接通过以下命令即可查看时区&#xf…

Java Stream流指南:优雅处理集合数据

文章目录 一、为什么要使用stream流呢&#xff1f;二、如何获取Stream流&#xff1f;三、Stream流的中间方法四、Stream流的终结方法总结 一、为什么要使用stream流呢&#xff1f; 想必我们在日常编程中&#xff0c;会经常进行数据的处理&#xff0c;我们先来看看没有stram流时…

要在Javascript中实现表格新增行功能,且添加元素,增删操作

起始表格元素&#xff1a; <!-- table>(thead>tr>th*6)(tbody>tr>td*6) --><div class"container"><table id"myTable"><caption><h3>员工信息管理系统</h3></caption><thead><tr>&…