STL list 排序

转载自:http://apps.hi.baidu.com/share/detail/30068696

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
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 <iostream>
#include <list>
#include <string.h>
#include <algorithm>
#include <vector>

using namespace std;

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

namespace std
{
    struct greater<char*> : binary_function<char*, char*, bool> 
    {
    bool operator()(const char*& _X, const char*& _Y) const
        {return (strcmp(_X,_Y) == -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;
    l.sort(greater<char*>()) ;
    copy( l.begin() , l.end() , oit) ;cout<<endl;
    return 0 ;
}


posted on 2012-04-20 23:49  yang3wei  阅读(506)  评论(0编辑  收藏  举报