C++ 标准库 sort() / stable_sort() / partial_sort() 对比
C++ STL标准库中提供了多个用于排序的Sort函数,常用的包括有sort() / stable_sort() / partial_sort(),具体的函数用法如下表所示:
| 函数 | 用法 | 
|---|---|
| std::sort(first,last) | 对容器或数组first~last范围内的元素进行排序,默认升序排序 | 
| std::stable_sort(first,last) | 对容器或数组first~last范围内的元素进行排序,保持原有数组相对顺序,默认升序排序 | 
| std::partial_sort(first,middle,last) | 在容器或数组first~last范围内,查找最小(大)middle-first个元素排序,放入first-middle区间,默认升序 | 
1. std::sort(first,last)
std::sort()是STL标准库提供的模板函数,用于对容器或者数组中指定的范围(first~last)元素进行排序,默认的排序方法是以元素的值的大小做升序排序,同时也可以指定其他的排序规则(如std::greater),也可以自定义排序规则。
std::sort()函数底层基于快速排序进行实现,时间复杂度为N * log(N),因此需要容器或者数组注意以下几点:
- 容器的迭代器必须是随机访问迭代器,如std::array、std::vector、std::deque。
 - 如果采用默认的升序排序方法,则元素必须支持operate<运算符。
 - 自定义类对象容器使用std::sort()排序时,因为需要交换位置,所以必须提供拷贝构造函数和赋值运算符。
 - std::sort()无法保证相同元素的原始位置,这里的相同是指进行比较的结果为相等,而对象本身不相同。如果需要保持相对顺序相同,则应该使用std::stable_sort()
 
不同库对std::sort()的实现:libstdc++和libc++.
示例代码:
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
void Print(std::string message,const std::vector<int>& vec)
{
    cout << message << ": ";
    for(const auto c : vec)
	cout << c << " ";
    cout <<endl;
}
int main()
{
    std::vector<int> myVector{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
    // 1. 以默认的排序规则
    std::sort(myVector.begin(),myVector.end());
    Print("Sorted Default", myVector);
    // 2. 以标准库的greater函数进行排序
    std::sort(myVector.begin(),myVector.end(),std::greater<int>());
    Print("Sorted Standard Compare Function",myVector);
    // 3.以自定义的函数定义排序规则
    // lamda 表达式
    auto cmp1 = [](const int a,const int b)
    {
        return a < b;
    };
    std::sort(myVector.begin(),myVector.end(),cmp1);
    Print("Sorted Lamda Function",myVector);
    // 可调用对象
    struct
    {
        bool operator()(const int a,const int b){return a > b;}
    } cmp2;
    std::sort(myVector.begin(),myVector.end(),cmp2);
    Print("Sorted Function Object",myVector);
    return 0;
}
输出结果为:
Sorted Default : 0 1 2 3 4 5 6 7 8 9
Sorted Standard Compare Function : 9 8 7 6 5 4 3 2 1 0
Sorted Lamda Function : 0 1 2 3 4 5 6 7 8 9
Sorted Function Object : 9 8 7 6 5 4 3 2 1 0
2. std::stable_sort(first,last)
使用std::sort()的一个问题是在排序时,无法保证值相等时的元素相对位置保持不变,如果程序中对相对顺序有要求,那么就需要使用std::stable_sort(),这是对std::sort()的一个升级版本,调用的方式和std::sort()相同,但是可以保证排序后的结果能够保持原有的相对顺序。
std::stable_sort()底层是基于归并排序,时间复杂度是N * log(N)^2,如果可以使用额外的内存空间,那么时间复杂度可以降低为N * log(N),std::sort()对容器和数组的要求与std::sort()相同。
不同库对std::stable_sort()的实现:libstdc++和libc++.
3. std::partial_sort(first,middle,last)
上述的std::sort()和std::stable_sort()都是对所选的范围内的所有数据进行排序,但是如果对于一个容器或者数组,我们只需要找到其最小的几个元素,那么采用全局排序的方法效率将会很低,尤其是容器中的元素数量非常大时,将会对性能产生很大的影响。因此,C++标准库提供了std::partial_sort()函数,来应用于这种场景。
std::partial_sort()函数的功能从其名字就可以得到,可以理解为部分排序,即从元素区间范围内取出部分元素进行排序。函数参数列表中first,last表示元素范围,middle用于定义需要进行排序的元素个数,具体的,std::partial_sort()会将范围first-last范围内最小(大)的middle-first个元素移动到first~middle范围,并对这些元素进行升(降)序排序。
std::partial_sort()底层采用堆排序,时间复杂度为N * log(M),其中N为last-first,M为middle-first。由于底层实现的限制,std::partial_sort()对容器的要求与std::sort()和std::stable_sort()相同。
不同库对std::stable_sort()的实现:libstdc++和libc++.
示例代码:
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
void Print(std::string message,const std::vector<int>& vec)
{
    cout << message << ": ";
    for(const auto c : vec)
	cout << c << " ";
    cout <<endl;
}
int main()
{
    std::vector<int> myVector{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
    // 1. 以默认的排序规则
    std::partial_sort(myVector.begin(),myVector.begin() + 4,myVector.end());
    Print("Sorted Default", myVector);
    // 2. 以标准库的greater函数进行排序
    std::partial_sort(myVector.begin(),myVector.end(),std::greater<int>());
    Print("Sorted Standard Compare Function",myVector);
    // 3.以自定义的函数定义排序规则
    // lamda 表达式
    auto cmp1 = [](const int a,const int b)
    {
        return a < b;
    };
    std::sort(myVector.begin(),myVector.end(),cmp1);
    Print("Sorted Lamda Function",myVector);
    return 0;
}
Sorted Default: 0 1 2 3 8 7 6 9 5 4
Sorted Standard Compare Function: 9 8 7 6 5 0 1 2 3 4
Sorted Lamda Function: 0 1 9 8 7 6 5 2 3 4
* C#中的Array.Sort()
笔者在用C++复刻C#代码的时候发现对相同的数组排序的结果有时候会出现不一致,查了C#的官方文档后才发现,C#中Array.Sort()函数是unstable_sort,也就是说其排序是无法保证相对顺序的,而且Array似乎也没有提供Stable_Sort版本的排序函数,因此如果需要保证相对顺序不变,需要手动给原始的数据添加一个index,这样再其他的key判等都相等时可以采用额外的Index来保持相对的原始序。而且有意思的是,Array.Sort()函数具体使用的排序方法是根据数据规模发生改变的
-如果数据量小于等于16个,则采用插入排序
-如果需要排序的数量超过2 * log(N),其中N为输入的排序范围,则采用堆排序
-其余情况均采用快速排序

以上是对常用的标准库排序算法的总结和不同语言的对比,可以根据实际需要和数据量的大小来选择合适的排序算法。
C++ 标准库 sort() / stable_sort() / partial_sort() 对比的更多相关文章
- 【C++】标准库sort函数的自定义排序
		
自定义排序需要单独写一个compare函数 例1 LeetCode 056. Merge Intervals Given a collection of intervals, merge all ov ...
 - C++STL标准库学习笔记(一)sort
		
前言: 近来在学习STL标准库,做一份笔记并整理好,方便自己梳理知识.以后查找,也方便他人学习,两全其美,快哉快哉! 这里我会以中国大学慕课上北京大学郭炜老师的<程序设计与算法(一)C语言程序设 ...
 - STL笔记(6)标准库:标准库中的排序算法
		
STL笔记(6)标准库:标准库中的排序算法 标准库:标准库中的排序算法The Standard Librarian: Sorting in the Standard Library Matthew A ...
 - C++ Pirmer : 第十四章 : 重载运算符与类型转换之函数调用运算符与标准库的定义的函数对象
		
函数调用运算符 struct test { int operator()(int val) const { return (i > 0 ? i : -i); } }; 所谓的函数调用就是一个类重 ...
 - c/c++ 标准库 bind 函数 详解
		
标准库 bind 函数 详解 bind函数:接收一个函数名作为参数,生成一个新的函数. auto newCallable = bind(callbale, arg_list); arg_list中的参 ...
 - [技术] OIer的C++标准库 : STL入门
		
注: 本文主要摘取STL在OI中的常用技巧应用, 所以可能会重点说明容器部分和算法部分, 且不会讨论所有支持的函数/操作并主要讨论 C++11 前支持的特性. 如果需要详细完整的介绍请自行查阅标准文档 ...
 - C++标准库(体系结构与内核分析)(侯捷第一讲)
		
一.C++标准库介绍 C++标准库:C++ Standard Library C++标准库与STL有什么关系: STL:Standard Template Library STL包含6大部件,基本占标 ...
 - Python标准库14 数据库 (sqlite3)
		
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Python自带一个轻量级的关系型数据库SQLite.这一数据库使用SQL语言.S ...
 - 把《c++ primer》读薄(3-2 标准库vector容器+迭代器初探)
		
督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正. 标准库vector类型初探,同一种类型的对象的集合(类似数组),是一个类模版而不是数据类型,学名容器,负责管理 和 存储的元素 ...
 - 【转】C++标准库和标准模板库
		
C++强大的功能来源于其丰富的类库及库函数资源.C++标准库的内容总共在50个标准头文件中定义.在C++开发中,要尽可能地利用标准库完成.这样做的直接好处包括:(1)成本:已经作为标准提供,何苦再花费 ...
 
随机推荐
- base64与中文字符串互转
			
实现代码如下 // 字符串转base64 getEncode64(str){ return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g ...
 - centos7  系统运行中做raid磁盘阵列
			
插入磁盘 lsblk查看磁盘总体情况 对sdb1等需要做的硬盘进行制作 fdisk /dev/sdb 开始 n 创建 p 给资源回车 重选代码 t 确认磁盘阵列代码 fd 保存w 首先安装工具 mda ...
 - 磊磊零基础打卡算法:day19 c++字符串hash
			
5.22 字符串hash: 字符哈希串的意思 其实就是将字符串的前缀转换为数来存值由于每位的权值是不一样的 所以每个前缀值都对应着唯一的一种字符串: 主要用途:字符串/数据的比较,是kmp的一种替代: ...
 - DBCC大全集之(适用版本MS SQLServer 2008 R2)----DBCC SHRINKDATABASE收缩指定数据库中的数据文件和日志文件的大小
			
收缩指定数据库中的数据文件和日志文件的大小. Transact-SQL 语法约定 语法 DBCC SHRINKDATABASE ( database_name | database_id | 0 [ ...
 - python 猜数字
			
方法一 import randomif __name__ == '__main__': yourname = input("你好! 你的名字是什么?\n"); prin ...
 - 4.javaweb-thymeleaf
			
1.知识回顾: 1. post提交方式下的设置编码,防止中文乱码 request.setCharacterEncoding("utf-8"); get提交方式,tomcat8开始, ...
 - 英码科技边缘计算智慧工地解决方案——给工地戴上AI“安全帽”
			
据统计显示,2021年全国共发生房屋市政工程生产安全事故734起,死亡840人:且近3年来,工地事故数量.死亡人数连续攀升.这不仅仅是一个普通的数字,每个数字都代表一个独特.鲜活的生命.为什么每年会发 ...
 - 用猿大师的VLC播放插件在高版本Chrome播放RTSP视频流,并抓图、录像、回放、倍速等
			
因为项目上需要把海康威视摄像头集成到WEB网页中播放,于是开始了对WEB播放摄像头方案的各种折腾. 2015年之前还可以用VLC原生播放器在Chrome.Firefox等浏览器中直接播放,延迟比较低, ...
 - C# 微信开发 微信号接入 (附完整源码)(1)
			
1. 首先配置微信服务器设置 a) 企业号配置信息 (详见:ConfigurationManager类) b) 企业号服务器配置: ConfigurationManager ...
 - 一条随手的Arduino sketch优化 以Examples-02.Digital-Debounce为例
			
1 const int buttonPin = 2; 2 const int ledPin = 13; 3 4 int ledState = HIGH; 5 int buttonState; 6 in ...