天天看点

STL list 排序

1.algorithm 里的sort()只接收RandomAccessIterator

用于像vector,dequeue的排序

2.像set,map,这种关联式容器,本身就由RBTree维护了有序,只要遍历一遍就行了。

3.而list比较特殊一点,由于只有BidirectionalIterator。而又不本身有序。

所以该容器自带了一个用来排序的函数。

list.sort()          //默认排序,如果是指针则按地址大小排序

list.sort(greater<int>())     //升序 比较符号为 >

list.sort(less<int>())          //降序 比较符号为 <

//其他如 >= <= 为greater_equal, less_equal...

list.sort()里面也可以是自定义函数:

#include <iostream>

#include <list>

#include <string.h>

#include <iterator>

using namespace std;

char *ss[] = { "bb" , "aa" , "cc" , "ee" , "dd" } ;

bool mycmp( char *&s1 , char *&s2)

{

    return strcmp(s1 , s2) == -1 ;

}

int main()

    list<char*> l(ss , ss + sizeof(ss) / sizeof(char*)) ;

    ostream_iterator<char*> oit(cout , " ") ;              //构造输出迭代器 

    copy( l.begin() , l.end() , oit) ;cout<<endl;           //输出原序列 

    l.sort() ;                        //默认的排序,其实是按指针大小排序 

    copy( l.begin() , l.end() , oit) ;cout<<endl;         //输出1 

    l.sort(mycmp);             //传入函数指针的排序 

    copy( l.begin() , l.end() , oit) ;cout<<endl;          //输出2 

    system("pause");

    return 0 ;

输出:

bb aa cc ee dd

aa bb cc dd ee

可见不带参数的是按指针从小到大排序的。

而这段在VC6里就会报错,即使把mycmp加上ptr_fun的修饰也不行。

主要是list的sort参数实在太奇怪了。

STL里面有很多函数提供两个版本,其中一个以默认方式进行比较,

另一个版本可以允许传入一个functor,以该functor进行比较。

而这个list.sort直接限定死了传进去的是greater<T>

比如,我们直接设计一个functor

struct c{

    operator()(char *&s1 , char *&s2){

        return strcmp(s1,s2) == -1 ;

    }

};

后面调用:l.sort(c());

编译器会给出下面的信息:

cannot convert parameter 1 from 'struct c' to 'struct std::greater<char *>'

        No constructor could take the source type, or constructor overload resolution was ambiguous

其实就是类型不匹配。。。-_-编译器只认greater这个functor。

就是这里纠结了很久。。后来终于不小心搞定了,用特化!!

像下面这样:(代码直接从泛化的greater复制过来,做相应修改就可以了)

    struct greater<char*> : binary_function<char*, char*, bool> {

    bool operator()(const char*& _X, const char*& _Y) const

        {return (strcmp(_X,_Y) == -1); }

    };

在DEV里面,全特化要求加入 template<>开头,VC里面可以不加。

那么后面直接这样调用就可以了:l.sort(greater<char*>()) ;

这时编译器选择的就不是前面泛化的greater了,就是我们量身定做的char* 的greater。

且慢,在VC6里面还要报错。

error C2934: 'greater<char *>' : template-class-id redefined as a nested 'struct' of '<Unknown>'

原来是namespace的问题。因为greater是定义在std里面的。

下面这份代码和前面的差不多。在VC6下运行正常:

相信通过前面的解释能够很容易明白。

#include <algorithm>

#include <vector>

namespace std

    struct greater<char*> : binary_function<char*, char*, bool> 

    {

    ostream_iterator<char*> oit(cout , " ") ;

    copy( l.begin() , l.end() , oit) ;cout<<endl;

    l.sort() ;

    l.sort(greater<char*>()) ;

上一篇: Java List 排序
下一篇: List sort 排序