C++,STL里的sort类全部函数简介

刷题的时候经常会遇到不同的问题,有时做一些复杂的问题的时候涉及的方面很多,排序,查找,排重等等,如果每个问题都要自己写,不但浪费时间而且还影响效率。这时我们自然而然就会想到stl模板库里一些标准函数,而且这些函数全都是同等情况下算法最优的函数,所以完全不用担心时间和空间复杂度。

这里首先介绍一下sort的所有类函数:

sort类的函数有好几类:

函数名功能描述
sort对给定区间所有元素进行排序(快排)
stable_sort对给定区间所有元素进行稳定排序
partial_sort对给定区间所有元素部分排序(堆排)
partial_sort_copy对给定区间复制并排序
nth_element找出给定区间的某个位置对应的元素
is_sorted判断一个区间是否已经排好序
partition使得符合某个条件的元素放在前面
stable_partition相对稳定的使得符合某个条件的元素放在前面

函数符号的重载:

一般sort会默认为升序排列,所以如果你也是要sort从小到大那就不用重载了(不需重载就是两个参数,重载就是三个),一般需要重载的情况就是大于,或者一些容器或者结构体之类的,下面给一个sort内置的排序方式:

名称功能描述
equal_to相等
not_equal_to不相等
less小于
greater大于
less_equal小于等于
greater_equal大于等于
例如你要按降序排列只要sort(begin(), end(), greater<int> ())即可,但是有些时候你要排序一些诡异的结构体,例如:

struct student{ string name;int score;};你要排序成绩。那比较的函数就要自己写了:

bool lessthan(student &a, student &b){ return a.score < b.score;};这样再调sort(begin(),end(), lessthan);就可以了

或者你干脆直接在结构体或类里重载“<”符号:

bool operator < (const student &m)const {
                return score < m.score;
        }
这样你也同样可以直接调sort(begin(), end(), less<student>())。当然了方法跟上面那个不同,这个是调用内置的那个less了,不过你得同样告诉sort到底要怎么排序。(感觉后者更专业,毕竟是在对象的包里实现的)



常用的函数介绍:

首先说说最常用的sort和stable_sort,稳定排序在同样情况下是要比sort时间复杂,因为它实现了一个同数顺序不变的功能,简单来说要排序一个坐标(1,2)(2,3)(2,1)(1,4)(3,3)这样五个坐标排序(sort函数只帮你排第一个数,如果你要实现其他功能,下面会详细介绍),如果用sort,它只帮你排完x坐标,其它就不管了。但是如果用stable_sort,他就会帮你把相同x的相对位置保持,也就说,拍完之后(2,3)(2,1)的这个顺序是不会变的


还有另外一个比较常用的是partial_sort(),局部排序,例如我只需要知道最前面的五个就只用局部排序,大多数情况下局部排序都要比sort更优。例如,我只想知道成绩最低的三个人,partial_sort(begin(), begin()+3, end())这样就可以把最低的3个人拍出来,而且还是前三个。


然后就是我们最常见的面试题,从乱序元素中找出第k大的元素(最好的答案是用快排思想,分治递归ab堆来找k与n-k大的数,这里不详细说),但是我要介绍更好的方法,直接调用这个函数,nth_element()指定元素排序。人家这个肯定比你效率高,毕竟是stl库的,而且还会分类讨论来处理问题。

现在讲讲怎么用,加入你要找全班倒数第4位的同学,那就直接nth_element(begin(),begin() + 3, end()),这里注意一下,之前的end()其实都是最后一位的后一位,因为排序都是【)前开后闭的,所以上面的局部排序才是+3,而这里begin() + 3不是排序,而是找,所以直接直指目标,0,1,2,3刚好第四位,然后mark[3]就是倒数第4位的同学了。


分类型的有partition和稳定分类stable_partition(快排思想),举例,要把同学分成60分及格和不及格的两类,这样就可以用到partition了,partition(begin(),end(), bind2nd(less<int>(), 60))。这样就可以把成绩分成及格与不及格的两类了,其中不及格排前面。写到这里相信又会有疑问,这个bind2nd又是什么东西。

下面简单讲一讲bind1st与bind2nd的两个配接器,听起来很高达上,其实也很简单,这两个配接器都是在《functional》里定义的,一般你来一个<algorithm>就全都有了。好,入正题,先说说为什么要配接器,因为你要实现的是分类操作,也就是把你容器里的数跟60作比较,但是less函数的定义是容器里的数跟自己比较,所以这就需要再一次重载了,而这一次重载需要把less函数里小于号“《”的左边或者右边定死为60,而另一边则是容器里的数。所以我们就用配接器来把less定死,其中1st是定左边,2nd是定右边也就是score “< 60”这样子。


sort()可以适用的容器:

sort可以sort()vector,string,deque,但是不能sort树状结构的set, multiset, map, multimap。

总的来说是适用于随机型迭代器,只要自己定义的容器也支持随机型迭代器就没问题了。

而对于list,list是自带一个list::sort的,区别就是这是基于指针来排序的,也就是说排完序之后迭代器还会留在排完序的地方。(而vector等会失效)


选择合适的排序函数:

效率由高到低: partition > stable_partition > nth_element > partial_sort > sort > stable_sort

如果全排:sort, stable_sort

只要前n个:partial_sort

找第k大的数:nth_element

分成两个堆:partition,stable_partition


这里只是粗劣讲讲如何使用,下一章讲详细分析sort的源代码与实现方式



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值