详细解说 STL 排序(Sort)
来源:互联网 发布:赛鸽软件 编辑:程序博客网 时间:2024/06/05 07:53
- 详细解说 STL 排序(Sort)
- 0 前言: STL,为什么你必须掌握
- 1 STL提供的Sort 算法
- 1.1 所有sort算法介绍
- 1.2 sort 中的比较函数
- 1.3 sort 的稳定性
- 1.4 全排序
- 1.5 局部排序
- 1.6 nth_element 指定元素排序
- 1.7 partition 和stable_partition
- 2 Sort 和容器
- 3 选择合适的排序函数
- 4 小结
- 5 参考文档
0 前言: STL,为什么你必须掌握
对于程序员来说,数据结构是必修的一门课。从查找到排序,从链表到二叉树,几乎所有的算法和原理都需要理解,理解不了也要死记硬背下来。幸运的是这些理论都已经比较成熟,算法也基本固定下来,不需要你再去花费心思去考虑其算法原理,也不用再去验证其准确性。不过,等你开始应用计算机语言来工作的时候,你会发现,面对不同的需求你需要一次又一次去用代码重复实现这些已经成熟的算法,而且会一次又一次陷入一些由于自己疏忽而产生的bug中。这时,你想找一种工具,已经帮你实现这些功能,你想怎么用就怎么用,同时不影响性能。你需要的就是STL, 标准模板库!
西方有句谚语:不要重复发明轮子!
STL几乎封装了所有的数据结构中的算法,从链表到队列,从向量到堆栈,对hash到二叉树,从搜索到排序,从增加到删除......可以说,如果你理解了STL,你会发现你已不用拘泥于算法本身,从而站在巨人的肩膀上去考虑更高级的应用。
排序是最广泛的算法之一,本文详细介绍了STL中不同排序算法的用法和区别。
1 STL提供的Sort 算法
C++之所以得到这么多人的喜欢,是因为它既具有面向对象的概念,又保持了C语言高效的特点。STL 排序算法同样需要保持高效。因此,对于不同的需求,STL提供的不同的函数,不同的函数,实现的算法又不尽相同。
1.1 所有sort算法介绍
所有的sort算法的参数都需要输入一个范围,[begin, end)。这里使用的迭代器(iterator)都需是随机迭代器(RadomAccessIterator), 也就是说可以随机访问的迭代器,如:it+n什么的。(partition 和stable_partition 除外)如果你需要自己定义比较函数,你可以把你定义好的仿函数(functor)作为参数传入。每种算法都支持传入比较函数。以下是所有STL sort算法函数的名字列表:
1.2 sort 中的比较函数
当你需要按照某种特定方式进行排序时,你需要给sort指定比较函数,否则程序会自动提供给你一个比较函数。vector < int > vect;//...sort(vect.begin(), vect.end());//此时相当于调用sort(vect.begin(), vect.end(), less<int>() );
less<int>()greater<int>()当你的容器中元素时一些标准类型(int float char)或者string时,你可以直接使用这些函数模板。但如果你时自己定义的类型或者你需要按照其他方式排序,你可以有两种方法来达到效果:一种是自己写比较函数。另一种是重载类型的<操作赋。
#include <iostream>#include <algorithm>#include <functional>#include <vector>using namespace std;class myclass { public: myclass(int a, int b):first(a), second(b){} int first; int second; bool operator < (const myclass &m)const { return first < m.first; }};bool less_second(const myclass & m1, const myclass & m2) { return m1.second < m2.second;}int main() { vector< myclass > vect; for(int i = 0 ; i < 10 ; i ++){ myclass my(10-i, i*3); vect.push_back(my); } for(int i = 0 ; i < vect.size(); i ++) cout<<"("<<vect[i].first<<","<<vect[i].second<<")/n"; sort(vect.begin(), vect.end()); cout<<"after sorted by first:"<<endl; for(int i = 0 ; i < vect.size(); i ++) cout<<"("<<vect[i].first<<","<<vect[i].second<<")/n"; cout<<"after sorted by second:"<<endl; sort(vect.begin(), vect.end(), less_second); for(int i = 0 ; i < vect.size(); i ++) cout<<"("<<vect[i].first<<","<<vect[i].second<<")/n"; return 0 ;}
(10,0)(9,3)(8,6)(7,9)(6,12)(5,15)(4,18)(3,21)(2,24)(1,27)after sorted by first:(1,27)(2,24)(3,21)(4,18)(5,15)(6,12)(7,9)(8,6)(9,3)(10,0)after sorted by second:(10,0)(9,3)(8,6)(7,9)(6,12)(5,15)(4,18)(3,21)(2,24)(1,27)
1.3 sort 的稳定性
你发现有sort和stable_sort,还有 partition 和stable_partition, 感到奇怪吧。其中的区别是,带有stable的函数可保证相等元素的原本相对次序在排序后保持不变。或许你会问,既然相等,你还管他相对位置呢,也分不清楚谁是谁了?这里需要弄清楚一个问题,这里的相等,是指你提供的函数表示两个元素相等,并不一定是一摸一样的元素。例如,如果你写一个比较函数:
bool less_len(const string &str1, const string &str2){ return str1.length() < str2.length();}
1.4 全排序
全排序即把所给定范围所有的元素按照大小关系顺序排列。用于全排序的函数有
template <class RandomAccessIterator>void sort(RandomAccessIterator first, RandomAccessIterator last);template <class RandomAccessIterator, class StrictWeakOrdering>void sort(RandomAccessIterator first, RandomAccessIterator last,StrictWeakOrdering comp);template <class RandomAccessIterator>void stable_sort(RandomAccessIterator first, RandomAccessIterator last);template <class RandomAccessIterator, class StrictWeakOrdering>void stable_sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering comp);
班上有10个学生,我想知道他们的成绩排名。
#include <iostream>#include <algorithm>#include <functional>#include <vector>#include <string>using namespace std;class student{ public: student(const string &a, int b):name(a), score(b){} string name; int score; bool operator < (const student &m)const { return score< m.score; }};int main() { vector< student> vect; student st1("Tom", 74); vect.push_back(st1); st1.name="Jimy"; st1.score=56; vect.push_back(st1); st1.name="Mary"; st1.score=92; vect.push_back(st1); st1.name="Jessy"; st1.score=85; vect.push_back(st1); st1.name="Jone"; st1.score=56; vect.push_back(st1); st1.name="Bush"; st1.score=52; vect.push_back(st1); st1.name="Winter"; st1.score=77; vect.push_back(st1); st1.name="Andyer"; st1.score=63; vect.push_back(st1); st1.name="Lily"; st1.score=76; vect.push_back(st1); st1.name="Maryia"; st1.score=89; vect.push_back(st1); cout<<"------before sort..."<<endl; for(int i = 0 ; i < vect.size(); i ++) cout<<vect[i].name<<":/t"<<vect[i].score<<endl; stable_sort(vect.begin(), vect.end(),less<student>()); cout <<"-----after sort ...."<<endl; for(int i = 0 ; i < vect.size(); i ++) cout<<vect[i].name<<":/t"<<vect[i].score<<endl; return 0 ;}
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- HTTP/1.1 500 Server Error错误解决方法
- 查询XML内容中节点的几个常用方法
- EVC4升级到VS.NET 2005的转换
- 用VB编写链表
- PHP的编码问题
- 详细解说 STL 排序(Sort)
- 测试
- 一个很好的相册切换效果
- 将 .cs 文件 编译 成 dll
- 关于登录认证过程
- 编写DirectShow Filters—DirectShow and COM
- 如何从Win32环境编写MFC程序?
- 值得大家看清的问题“藏独引起”
- 尽量使用C++风格的类型转换