一、简介

所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。我们在编程过程中会经常接触到排序,比如游戏中的排行榜等。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

C++标准库中各种排序归纳相关推荐

  1. iOS标准库中常用数据结构和算法之二叉排序树

    上一篇:iOS标准库中常用数据结构和算法之排序 ?二叉排序树 功能:二叉排序树的标准实现是一颗平衡二叉树.二叉排序树主要用来解决高效插入和高效检索以及进行排序的问题.系统分别提供了二叉排序树节点的查找 ...

  2. c语言的erase函数,C++ STL标准库中sort,erase,remove_if函数的使用

    本篇介绍C++ STL中常用的几个函数 1.std::sort 1.1.sort函数包含在头文件为#include的c++标准库中,调用标准库里的排序方法可以实现对数据的排序. 1.2.sort函数的 ...

  3. log包在Golang语言的标准库中是怎么使用的?

    Golang 语言的标准库中提供了一个简单的 log 日志包,它不仅提供了很多函数,还定义了一个包含很多方法的类型 Logger.但是它也有缺点,比如不支持区分日志级别,不支持日志文件切割等. 01. ...

  4. iOS标准库中常用数据结构和算法之内存池

    上一篇:iOS标准库中常用数据结构和算法之位串 ⛲️内存池 内存池提供了内存的复用和持久的存储功能.设想一个场景,当你分配了一块大内存并且填写了内容,但是你又不是经常去访问这块内存.这样的内存利用率将 ...

  5. C++标准库中的随机数生成

    C++标准库中的随机数生成 一.伪随机与真随机 数字计算机的结果可以说是固定的.必然的.都是根据现有数据的状态得出接下来的状态.除非硬件损坏,计算机不会产生真正的随机和无法预料的事.在生活中随手抛一个 ...

  6. Git 源码禁止使用 C 标准库中容易被错用的函数

    Git 项目的源码禁止开发者使用 C 标准库中的某些函数,原因是这些函数太容易被误用,就算使用得当也很容易出问题.因此 Git 的源码增加了一个 banned.h 的头函数,一旦你使用了这些被禁用的函 ...

  7. c/c++标准库中的文件操作总结

    1 stdio.h是c标准库中的标准输入输出库 2 在c++中调用的方法 直接调用即可,但是最好在函数名前面加上::,以示区分类的内部函数和c标准库函数. 3 c标准输入输出库的使用 3.1 核心结构 ...

  8. php spl函数,PHP SPL标准库中的常用函数介绍

    这篇文章主要介绍了PHP SPL标准库中的常用函数介绍,本文着重讲解了spl_autoload_extensions().spl_autoload_register().spl_autoload()三 ...

  9. 细数python标准库中低调的模块

    有没有遇到过这种情况,在网络上搜索如何使用Python进行某种操作,最终找到一个第三方库,直到后来发现标准库中包含的模块或多或少都可以满足你的需求.这种情况并不罕见, 整理了一些python标准库中鲜 ...

最新文章

  1. 只需2小时,成本不到7块,你我皆可制作的3D机器人
  2. 云计算学习(4-1)虚拟化技术
  3. Zabbix邮件报警配置
  4. 洛谷 - P4015 运输问题(费用流)
  5. Ubuntu apt-get 更新/查看软件
  6. localhost 已拒绝连接_MySQL连接错误:Access denied for #x27;root#x27;@#x27;localhost#x27;
  7. 【Qt教程】2.2 - Qt5 布局管理器(水平、垂直、栅格布局)、弹簧、设计一个登陆界面
  8. Circular microphone array 1
  9. sony手机刷linux,索尼Z3 Z3C 5.0系统刷recovery教程_Sony Z3第三方recovery
  10. http keepalive原理
  11. TCN机器之心的转载,后面需要实现
  12. 9款常用的数据可视化工具推荐
  13. 【论文翻译】Semantic Relation Reasoning for Shot-Stable Few-Shot Object Detection
  14. radio男女选择取值
  15. Mac JER10.7.3安装
  16. 港科报道 | 香港科技大学(广州)专题新闻发布会成功举办
  17. HDLbits Exams/2013 q2bfsm verilog fpga
  18. 解决bilibili 酷狗等uwp应用登录异常
  19. 至强服务器哪个系列好,至强cpu那么好,为什么日常装机的时候一般都选酷睿系列的呢?...
  20. 2011.11.17,Google已经正式推出Google音乐服务(Google Music)

热门文章

  1. UBUNTU adb连接android设备
  2. Android studio安装与调试
  3. Apache的prefork模式和worker模式
  4. 把Doc文档转换成HTML等其它格式
  5. 设计模式之解释器模式(Interpreter)摘录
  6. OpenCV下车牌定位算法实现代码
  7. php 1到9加,php通过排列组合实现1到9数字相加都等于20的方法
  8. 行上下移动_这有一台你迟早要用到的“移动空调”
  9. 山东大学计算机学院预推免,山东大学计算机科学与技术学院(专业学位)计算机技术保研...
  10. Java学习总结:19