zoukankan      html  css  js  c++  java
  • STL容器的排序

    STL容器的排序,支持随机访问的容器vector,deque,string没有sort成员,可调用std::sort排序;list排序调用自带的list::sort。

    下面是std::sort函数,有两个版本:

    [cpp] view plain copy
     
    1. template <class RandomAccessIterator>  
    2. void sort ( RandomAccessIterator first, RandomAccessIterator last );  
    3.   
    4. template <class RandomAccessIterator, class Compare>  
    5. void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp );  

    sort函数有以下特征:
    1. 要求输入一个范围[first, last)
    2. 随机迭代器,能用此算法的容器是支持随机访问的容器:vector, deque, string。
    3.第一个版本使用operator<进行比较,默认升序排序,第二个版本使用comp做比较.

    关于参数comp,comp带两个同类型的参数,如果第一个参数排在第二个参数前面,返回true,否则返回false
    它可以是函数指针,也可以是函数对象。函数指针好理解,何谓函数对象?
    函数对象(Function Object),是重载了operator()函数的类(或结构体)实例化出来的对象,使用起来像函数,又叫仿函数。

    STL本身提供了几个比较函数,下面这些都是仿函数:
    less(小于)
    greater(大于)
    equal_to(等于)
    not_equal_to(不相等)
    less_equal(小于等于)
    greater_equal(大于等于)

    当容器元素为内建类型时可以使用,注意使用的格式,要加模版参数(由于是模板类)和后面的(),如下:

    [cpp] view plain copy
     
    1. sort(vec.begin(), vec.end(), less<int>());  

    对于复合类型,实现排序方式有3种方法:
    1) 重载operator<操作符
    2) 写全局的比较函数
    3) 写仿函数,重载operator()形式为:bool operator()(const 类名& 参数){…}

    下面看看这3种方法的实现:

    [cpp] view plain copy
     
    1. // 排序元素,比较的对象  
    2. struct Person  
    3. {  
    4.   Person(int id, const string& name, int age): id_(id), name_(name), age_(age)  
    5.   {}  
    6.     
    7.   int id_;  
    8.   string name_;  
    9.   int age_;  
    10. };  
    [cpp] view plain copy
     
    1. // 方式1:重载operator<用于排序时的比较(写在函数体内)  
    2. bool operator< (const Person& rt)  
    3. {  
    4.   return this->id_ < rt.id_;  
    5. }  
    6.   
    7. // 排序函数写法,默认调用operator<  
    8. sort(members.begin(), members.end());  
    [cpp] view plain copy
     
    1. // 方式2:写比较函数  
    2. bool CompAge(const Person& pl, const Person& pr)  
    3. {  
    4.   return pl.age_ < pr.age_;  
    5. }  
    6.   
    7. // 排序时传入比较函数指针  
    8. sort(members.begin(), members.end(), CompAge);  
    [cpp] view plain copy
     
    1. // 方式3:仿函数  
    2. struct CompName  
    3. {  
    4.   bool operator()(const Person& pl, const Person& pr)  
    5.   {  
    6.     return pl.name_ < pr.name_;  
    7.   }  
    8. };  
    9.   
    10. // 排序时传入函数对象  
    11. sort(members.begin(), members.end(), CompName());  

    用函数对象代替函数指针的优点:
    1. 函数对象可以存储中间结果在数据成员中,而函数想要存中间结果须要设全局变量或静态变量,这个是我们不想要的。
    2. 在函数对象中编译器可以实现内联调用,从而提升性能。

    下面看一个函数对象的扩展应用

    [cpp] view plain copy
     
    1. // 利用函数对象实现升降排序  
    2. struct CompNameEx{  
    3.   CompNameEx(bool asce) : asce_(asce)  
    4.   {}  
    5.   bool operator()(const Person& pl, const Person& pr)  
    6.   {  
    7.     return asce_ ? pl.name_ < pr.name_ : pr.name_ < pl.name_;<span style="white-space:pre">   </span>// 《Eff STL》条款21: 永远让比较函数对相等的值返回false  
    8.   }  
    9. private:  
    10.   bool asce_;  
    11. };  
    12. // 使用仿函数排序(升降序)  
    13. sort(members.begin(), members.end(), CompNameEx(false));  
     

    注意:如果是指针的容器,比较函数的参数也应是指针。

  • 相关阅读:
    android的布局管理器
    android控件---自定义带文本的ImageButton
    新建android项目src和layout文件夹中没有内容的问题
    android控件---spinner
    maven+springMVC+mybatis+junit详细搭建过程 ***
    JUnit4的使用
    Jenkins集成Docker镜像实现自动发布
    Docker部署tomcat及应用
    Docker的离线安装
    Java中的static关键字解析
  • 原文地址:https://www.cnblogs.com/xzh1993/p/5868946.html
Copyright © 2011-2022 走看看