C++标准库中各种排序归纳
一、简介
所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。我们在编程过程中会经常接触到排序,比如游戏中的排行榜等。C++标准库中提供了各种不同的排序算法,这篇博客将逐一介绍。还有在什么场景下,具体该使用哪一个排序算法效率更高。
二、算法
1. sort
原型:
template<typename iterator>
void sort(iterator begin, iterator end)template <typename iterator, typename compare>
void sort(iterator begin, inerator end, compare comp)
事例:
下面是2个参数版本的全排序函数sort的使用事例
#include <iostream>
#include <vector>
#include <iterator> //各种迭代器
#include <algorithm> //各种算法using namespace std;int randint()
{static int sr = time(NULL);srand(++sr);return rand() % 100;
}int main()
{vector<int> vecInt;generate_n(back_inserter(vecInt), 5, randint); //生成5个随机数放入vecInt中sort(vecInt.begin(), vecInt.end());copy(vecInt.begin(), vecInt.end(), ostream_iterator<int>(cout, "\n")); //输出return 0;
}
#程序执行结果 [root@oracle ~]# ./a.out 23 24 88 90 99
这个事例介绍3个参数版本的全排序函数sort,将学生按照分数进行递增、递减排序,下面的事例代码都是基于这个学生分数来写的。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator> //ostream_iterator
#include <functional> //not2using namespace std;struct student
{string name; //名字unsigned int score; //分数student(const string &n, unsigned int s) :name(n),score(s){} friend ostream & operator<<(ostream &os, const student &rhs){ return os << rhs.score << " : " << rhs.name << endl;}
};//按学生的分数进行排序
struct comp : public binary_function<student, student, bool>
{bool operator()(const student &lhs, const student &rhs) const{return lhs.score < rhs.score;}
};int main()
{student stu[] = { student("aa", 100),student("bb", 95),student("cc", 50),student("dd", 40),student("ee", 52),student("ff", 60),student("gg", 86),student("hh", 60),student("ii", 83),student("jj", 91),}; vector<student> stuArray(stu, stu + sizeof(stu) / sizeof(student));sort(stuArray.begin(), stuArray.end(), comp()); //递增排序copy(stuArray.begin(), stuArray.end(), ostream_iterator<student>(cout, ""));cout << "=======" << endl;sort(stuArray.begin(), stuArray.end(), not2(comp())); //递减排序copy(stuArray.begin(), stuArray.end(), ostream_iterator<student>(cout, ""));return 0;
}
#程序执行结果 [root@oracle ~]# ./a.out 40 : dd 50 : cc 52 : ee 60 : ff 60 : hh 83 : ii 86 : gg 91 : jj 95 : bb 100 : aa ======= 100 : aa 95 : bb 91 : jj 86 : gg 83 : ii 60 : hh 60 : ff 52 : ee 50 : cc 40 : dd
2. stable_sort
原型:
template<typename iterator>
void sort(iterator begin, iterator end)template <typename iterator, typename compare>
void sort(iterator begin, inerator end, compare comp)
sort和stable_sort都是全排序函数,但是sort是非稳定排序算法,而stable_sort是稳定排序算法。在稳定排序算法中,如果区间中的两个元素有等价的值,那么在排序之后,它们的相对位置不会发生变化。比如学生A和学生B都是60分,并且学生A在学生B的前面,那么在递增排序后学生A还会在学生B的前面。而非稳定的排序并不保证这一点。
3. partition
原型:
template<typename iterator, typename predicate>
iterator partition(iterator begin, iterator end, predicate pred)
功能:
对[begin,end]区间内满足pred判定条件的所有元素移到前部,然后返回一个迭代器,指向第一个不满足条件元素。
事例:
现在有一个需求,就是从所有学生中筛选中分数大于60分的人。这个时候全排序就不是那么好使了,当然你可以进行递增全排序后,然后找到60的元素所在的位置,输出它之后的元素,这是个很笨的方法。如果换个需求筛选出分数为偶数的人呢,全排序就没辙了,这时候就用到partition了。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator> //ostream_iterator
#include <functional> //not2using namespace std;struct student
{string name;unsigned int score;student(const string &n, unsigned int s) :name(n),score(s){} friend ostream & operator<<(ostream &os, const student &rhs){ return os << rhs.score << " : " << rhs.name << endl;}
};struct comp : public unary_function<student, bool>
{bool operator()(const student &stu) const{return stu.score > 60;}
};int main()
{student stu[] = {student("aa", 100),student("bb", 95),student("cc", 50),student("dd", 40),student("ee", 52),student("ff", 60),student("gg", 86),student("hh", 60),student("ii", 83),student("jj", 91),};vector<student> stuArray(stu, stu + sizeof(stu) / sizeof(student));vector<student>::iterator it = partition(stuArray.begin(), stuArray.end(), comp());copy(stuArray.begin(), it, ostream_iterator<student>(cout, "")); //输出分数大于60分的人cout << "=======" << endl;copy(it, stuArray.end(), ostream_iterator<student>(cout, "")); //输出分数小于等于60分的人return 0;
}
#程序执行结果 [root@oracle ~]# ./a.out 100 : aa 95 : bb 91 : jj 83 : ii 86 : gg ======= 60 : ff 52 : ee 60 : hh 40 : dd 50 : cc
4. stable_partition
原型:
template<typename iterator, typename predicate>
iterator stable_partition(iterator begin, iterator end, predicate pred)
从名字可以看出来,它是partition的稳定排序版本。
5. nth_element
原型:
template<typename iterator>
void nth_element(iterator begin, iterator nth, iterator end)template<typename iterator, typename compare>
void nth_element(iterator begin, iterator nth, iterator end, compare comp)
功能:
迭代器nth用来指向一个全排序的情况下第n个元素的位置,然后根据这个值将[begin, end]区间内的元素分割成2部分,一部分都在元素n的全面,一部分在元素n的后面,但它并不关心分割后元素的排序情况。
事例:
nth_element的功能和partition有点类似,但又不完全相同。partition可以筛选出所有分数大于60分的人,现在需求变成需要筛选出分数最高的前5个人,这时就轮到nth_element出场了。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator> //ostream_iterator
#include <functional> //not2using namespace std;struct student
{string name;unsigned int score;student(const string &n, unsigned int s) :name(n),score(s){} friend ostream & operator<<(ostream &os, const student &rhs){ return os << rhs.score << " : " << rhs.name << endl;}
};struct comp : public binary_function<student, student, bool>
{bool operator()(const student &lhs, const student &rhs) const{return lhs.score > rhs.score;}
};int main()
{student stu[] = {student("aa", 100),student("bb", 95),student("cc", 50),student("dd", 40),student("ee", 52),student("ff", 60),student("gg", 86),student("hh", 60),student("ii", 83),student("jj", 91),};vector<student> stuArray(stu, stu + sizeof(stu) / sizeof(student));nth_element(stuArray.begin(), stuArray.begin() + 5, stuArray.end(), comp());copy(stuArray.begin(), stuArray.begin() + 5, ostream_iterator<student>(cout, ""));return 0;
}
[root@oracle ~]# ./a.out 100 : aa 95 : bb 91 : jj 83 : ii 86 : gg
6. partial_sort
原型:
template<typename iterator>
void partial_sort(iterator begin, iterator middle, iterator end)template<typename iterator, typename compare>
void partial_sort(iterator begin, iterator middle, iterator end, compare comp)
事例:
partial_sort和nth_element的用法和功能基本相同。不同的是nth_element并不关心符合条件的元素具体的排序位置,只是把他们移到了容器的前面(上面的事例输出也很容易看出来)。而partial_sort则关心具体位置,将nth_element事例中的nth_element函数替换成partial_sort后,输出就变了。
#程序执行结果 [root@oracle ~]# ./a.out 100 : aa 95 : bb 91 : jj 86 : gg 83 : ii
三、总结
1. sort、stable_sort、partial_sort和nth_element算法都要求随机访问迭代器,所以这些算法只能被用于vector、string、deque和数组。
2. 如果需要对vector、string、deque或者数组中的元素执行一次完全排序,那么可以使用sort或者stable_sort。
3. 如果有一个vector、string、deque或者数组,并且只需要对等价性最前面的n个元素进行排序,那么可以使用partial_sort。
4. 如果有一个vector、string、deque或者数组,并且需要找到第n个位置的元素,或者,需要找到等价性最前面的n个元素但又不必对这n个元素进行排序,那么nth_element正是你所需要的函数。
5. 如果需要将一个标准序列容器中的元素按照是否满足某个特定的条件区分开来,那么,partition和stable_partition可能比较合适。
6. 如果你的数据在一个list中,那么你仍可以直接调用partition和stable_partition算法;可以用list::sort来代替sort和stable_sort算法。但是,如果你需要获得partial_sort或者nth_element算法的效果,那么只能通过一些间接的途径来完成。比如可以将list中的元素复制到一个提供随机访问迭代器的容器中,然后对该容器执行相应的你所期望的排序。
四、性能
总的来说,算法所做的工作越多,它需要的时间也越多。稳定排序算法要比忽略稳定性的算法更耗时。可以依照算法的时间、空间效率对算法进行排序(消耗资源最少的算法排在前面):
1. partition
2. stable_partition
3. nth_element
4. partial_sort
5. sort
6. stable_sort
转载于:https://blog.51cto.com/svenman/1851716
相关文章:
【数据结构】最小生成树 Prim算法 Kruskal算法
最小生成树应用场景: 假设以下场景,有一块木板,板上钉上一些钉子,这些钉子可以由一些细绳连接起来。假设每个钉子可以通过一根或者多根细绳连接起来,那么一定存在这样得情况,即用最少的细绳把所有的钉子连…

.net内存回收与Dispose﹐Close﹐Finalize方法
.net内存回收与Dispose﹐Close﹐Finalize方法 一. net的对象使用一般分为三种情况﹕ 1.创建对象2.使用对象3.释放对象 二.创建对象1.创建对象实际分为两个步骤﹕变量类型宣告和初始化对象 2.变量类型宣告(declare),如﹕ FileStream fs这行代码会在当前的变量作用域空间(栈或堆)…
SLAM学习--------相机位姿表示-李群李代数
slam 求解相机的位姿求解核心思想:将有约束的李群问题转换成无约束的李代数问题,然后使用高斯牛顿算法或者LM(列文伯格-马夸尔特法)求解。 人们找了很多以相机位姿为变量的误差函数,比如光度误差,重投影误差,3D几何误…
【ACM】杭电OJ 2063
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid2063 借鉴:http://blog.sina.com.cn/s/blog_ac5ed4f30101ewjk.html 二分图(二部图):图论中的一种特殊模型。设G(V,E)是一个无向图,如果顶点V可以分割…

AngularJs表单自动验证
angular-auto-validate 地址:https://github.com/jonsamwell/angular-auto-validate 引用: <script src"/Assets/JS/AngularJS/angular-auto-validate/dist/jcs-auto-validate.js" charset"utf-8"></script> 依赖&#…
AlwaysVisibleControlExtender
今天早上学习了AlwaysVisibleControlExtender控件,感觉还是不错。下午就写点东西,总结一下使用方法。 简单使用示例(显示当前时间) 1)在VS下,新建一个ASP.NET AJAX-Enabled Web Project项目,命名为AlwaysVisibleC…
Depth graph
深度相机 定义:可以直接获取场景中物体距离摄像头物理距离的相机。在计算机视觉系统中,三维场景信息为图像分割、目标检测、物体跟踪等各类计算机视觉应用提供了更多的可能性,而深度图像(Depth map)作为一种普遍的三维…

【ACM】POJ 1852
【问题描述】 一队蚂蚁在一根水平杆上行走,每只蚂蚁固定速度 1cm/s. 当一只蚂蚁走到杆的尽头时,立即从秆上掉落. 当两只蚂蚁相遇时它们会掉头向相反的方向前进. 我们知道每只蚂蚁在杆上的初始位置, 但是, 我们不知道蚂蚁向哪个方向前行. 你的任务是计算…

ZStack--通过Ansible实现全自动化
2019独角兽企业重金招聘Python工程师标准>>> Agent是一种常见的IaaS软件管理设备的方式;例如,ZStack使用Python agents去管理KVM主机。因为海量的设备,安装和升级agents成为巨大的挑战,所以大多数IaaS软件把这个问题留…
SVO 半直接视觉里程计
SVO 从名字来看,是半直接视觉里程计,所谓半直接是指通过对图像中的特征点图像块进行直接匹配来获取相机位姿,而不像直接匹配法那样对整个图像使用直接匹配。整幅图像的直接匹配法常见于RGBD传感器,因为RGBD传感器能获取整幅图像的…

css构造文本
1. 1. 文本缩进text-indent:值;值为数字,最常用的数值单位是px(像素),也可以直接是百分比!text-indent:100px;text-indent:10%;2. 文本对齐text-align:对其方式;可以的值为:left、center、right3. 文本行高…
【数据结构】单链表的逆序输出(两种方法)
第一种方法:转换指针方向 即:将一个已经创建好的单链表进行指针域的改变 今天突然被问到单链表逆序的问题,弄了好久才看出别人的程序有啥问题,就重新写了一遍。 今天才在CSDN客户端上看到美团的面试题是冒泡排序。 一个看似简单…

koa+mongoose基础入门
1.mongoose基本使用 1.安装mongodb npm install mongodb 2.引入mongodb数据表,连接mongodb,通过node来对mongodb进行异步的增删改查 const mongodb requrie(mongodb); mongodb.MongoClient.connect("mongodb://localhost/db1", function(err,…

视觉SLAM学习(三)--------SLAM 综述
SLAM概述 参考资料分享来自本人博客:https://blog.csdn.net/Darlingqiang/article/details/78840931 SLAM一般处理流程包括track和map两部分。所谓的track是用来估计相机的位姿,也叫front-end。而map部分(back-end)则是深度的构建,通过前面…
【数据结构】所有顶点对的最短路径 Floyd算法
所有顶点对的最短路径问题是指:对于给定的有向图G(V,E),求任意一对顶点之间的最短路径。 可以求解得到的 的递推公式: #include <stdio.h> #include <stdlib.h> const int FINITY 5000; const int M 20; typedef struct {ch…

backbone学习总结(二)
今天来看下backbone的路由控制的功能。其实个人感觉backbone,模块就那么几个,熟悉它的框架结构,以及组成,就差不多。 废话不多说,我们来看看还剩下的功能。 关于路由和历史管理 通过 Backbone.Router.extend 来创建路由…

人工智能--野人过河
课程简介 人工智能(Artificial Intelligence),英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能的定义可以分为两部分,即“人工”和“智能”。“人工”比较好…

java对cookie的操作
原文:http://www.cnblogs.com/muzongyan/archive/2010/08/30/1812552.html java对cookie的操作比较简单,主要介绍下建立cookie和读取cookie,以及如何设定cookie的生命周期和cookie的路径问题。 建立一个无生命周期的cookie,即随着…

【ACM】POJ 3069
【问题描述】 Saruman the White must lead his army along a straight path from Isengard to Helm’s Deep. To keep track of his forces, Saruman distributes seeing stones, known as palantirs, among the troops. Each palantir has a maximum effective range of R u…

sparkCore源码解析之思维脑图
2019独角兽企业重金招聘Python工程师标准>>> 在学习sparkCore时,有几个模块的概念理解不是很透彻,故对照源码进行学习,并将结果一脑图的形式呈现,方便后续的持续学习。 详细内容见: sparkCore源码解析之blo…

pangilin 安装编译
make pangolin 的时候报错 ootsun:/home/sun/AR/orb/Pangolin-0.5/build# make [ 1%] Building CXX object src/CMakeFiles/pangolin.dir/log/packetstream.cpp.o /home/sun/AR/orb/Pangolin-0.5/src/log/packetstream.cpp: 在函数‘void pangolin::WaitUntilPlaybackTim…

PHP实现求阶乘
function factorial ($x){if ($x > 1) {$s $x * factorial ($x - 1);} else {$s $x;}return $s; }$x 100;echo $x."的阶乘的为".factorial($x);转载于:https://blog.51cto.com/chensenlin/1854679

【ACM】杭电OJ 2064(汉诺塔III)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid2064 思路: 1、将n-1个盘从A移到C f(n-1)次 2、将第n个从A移到B 1次 3、将n-1个盘从C移到A f(n-1)次 4、将第n个从B移到C 1次 5、将n-1个盘从A移到C f(n-1)次 #include<cstdio> #inclu…

文件上传至阿里云
public static String uploadFile2OSS(InputStream instream, String fileName) throws IOException {String imageName null;OSSClient ossClient null;try {ClientConfiguration conf new ClientConfiguration();// 请求超时时间设置conf.setConnectionTimeout(5000);// 请…

ORB-SLAM2安装
安装顺利与否可能会与Ubuntu版本有关。(ubuntu16.04 gcc4.8.5这个很重要偶,本班的直接决定Pangolin能不能安装成功,如果遇到哦问题的朋友可以参考一下链接 http://blog.csdn.net/Darlingqiang/article/details/78928873)亲测可用…
iOS 系统分析(一) 阅读内核准备知识
原文出自【听云技术博客】:http://blog.tingyun.com/web/a... 0x01 iOS体系架构1.1 iOS 系统的整体体系架构 用户体验( The User Experience layer ):SpringBoard 同时支持 Spotlight。 应用软件开发框架(The Application Frameworks layer&a…
【数据结构】拓扑排序
如果一个有向图中没有包含简单的回路,这样的图为有向无环图。 图中的顶点代表事件(活动),图中的有向边说明了事件之间的先后关系。这种用顶点表示活动,用弧表示活动时间的优先关系的有向图称为顶点表示活动的网&#…

Java8自定义条件让集合分组
** 将一个指定类型对象的集合按照自定义的一个操作分组; 每组对应一个List、最终返回结果类型是:List<List<T>> param <T>*/static class GroupToList<T> implements Collector<T, List<List<T>>, List<List<T>&g…
ROS_Kinetic ubuntu 16.04
ROS_Kinetic系列学习(一),在ubuntu 16.04安装ROS Kinetic。 http://wiki.ros.org/kinetic/Installation/Ubuntu 通过网页快速了解Linux(Ubuntu)和ROS机器人操作系统,请参考实验楼在线系统如下: 纯净定制版镜像已经…

android 获取手机GSM/CDMA信号信息,并获得基站信息
本文转自:http://software.intel.com/zh-cn/blogs/2011/12/16/android-gsmcdma/ 在Android中我们常用的轻松获取WIFI信号列表,那如何获取CDMA或者GSM的手机信号呢?系统提供了TelephonyManager类,此类非常丰富,基本你所…