Linux下的C++开发系列(四) C++中的排序和踢重(使用stlmap和set)
本文介绍通过stl的map和set来实现的排序和踢重,对于简单的数据类型,比如说int和long等,由于可以直接比较大小,所以可以直接作为map的键和set的值,而对于class类型的数据,则不能直接作为map的键和set的值,需要对小于号的操作符进行重载。stl中的string也是数据class类型的数据,stl本身重载了小于号,这点可以从stl的源码中查看:
// operator < /** * @brief Test if string precedes string. * @param lhs First string. * @param rhs Second string. * @return True if @a lhs precedes @a rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> inline bool operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) { return __lhs.compare(__rhs) < 0; } /** * @brief Test if string precedes C string. * @param lhs String. * @param rhs C string. * @return True if @a lhs precedes @a rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> inline bool operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) { return __lhs.compare(__rhs) < 0; } /** * @brief Test if C string precedes string. * @param lhs C string. * @param rhs String. * @return True if @a lhs precedes @a rhs. False otherwise. */ template<typename _CharT, typename _Traits, typename _Alloc> inline bool operator<(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) { return __rhs.compare(__lhs) > 0; }
compare的方法可以参考http://www.cplusplus.com/reference/string/string/compare/上面的解释
对于自定义类型的class,需要自己重载小于号,下面是一个例子:
#include<iostream> #include<string> #include<map> using namespace std; template<class Key, class Value> inline ostream& operator<<(ostream& str, const map<Key, Value>& data) { str << "{\n\t"; typedef typename map<Key, Value>::const_iterator ConstIterator; for(ConstIterator iter = data.begin(); iter != data.end(); ++iter) { ConstIterator iterTmp = iter; iterTmp++; if(iterTmp == data.end()) { str << *iter << "\n"; } else { str << *iter << "\n\t"; } } return str << "}"; } template<class Key, class Value> inline ostream& operator<<(ostream& str, const pair<Key, Value>& data) { return str << "[key = " << data.first << "," << "value = " << data.second << "]"; } class CTest { public: CTest(){} ~CTest(){} bool operator <(const CTest& cTest) const { #ifdef POS return m_iSize < cTest.get_size(); #endif return m_iSize > cTest.get_size(); } public: inline int get_size() const { return m_iSize; } inline void set_size(const int & iSize) { m_iSize = iSize; } private: int m_iSize; }; inline ostream& operator<<(ostream& str, const CTest& data) { return str << "[size = " << data.get_size() << "]"; } int main(int args,char* argvs[]) { map<string,string> mapStr; mapStr.insert(make_pair("ab","ab")); mapStr.insert(make_pair("1","1")); mapStr.insert(make_pair("2","2")); mapStr.insert(make_pair("abc","abc")); mapStr.insert(make_pair("aba","aba")); map<CTest,string> mapClass; CTest cTest1; CTest cTest2; cTest1.set_size(1); cTest2.set_size(2); mapClass.insert(make_pair(cTest1,"1")); mapClass.insert(make_pair(cTest2,"2")); cout << mapStr << endl; cout << mapClass << endl; }
如果编译命令为:g++ testmap.cpp -DPOS -o testmap -g
此时对于CTest排序使用的从小到大,结果如下:
{ [key = 1,value = 1] [key = 2,value = 2] [key = ab,value = ab] [key = aba,value = aba] [key = abc,value = abc] } { [key = [size = 1],value = 1] [key = [size = 2],value = 2] }
如果编译命令为: g++ testmap.cpp -o testmap -g
此时对于CTest的排序使用的是从达到小,结果如下:
{ [key = 1,value = 1] [key = 2,value = 2] [key = ab,value = ab] [key = aba,value = aba] [key = abc,value = abc] } { [key = [size = 2],value = 2] [key = [size = 1],value = 1] }
下面是一个set的例子:
#include<iostream> #include<string> #include<set> using namespace std; /** * 重载<< 用于输出 */ template<class Data> inline ostream& operator<<(ostream& str, const set<Data>& data) { str << "{\n\t"; typedef typename set<Data>::const_iterator ConstIterator; for(ConstIterator iter = data.begin(); iter != data.end(); ++iter) { ConstIterator iterTmp = iter; iterTmp++; if(iterTmp == data.end()) { str << *iter << "\n"; } else { str << *iter << "\n\t"; } } return str << "}"; } /** * 测试类 */ class CTest { public: CTest(){} ~CTest(){} bool operator <(const CTest& cTest) const { #ifdef POS return m_iSize < cTest.get_size(); #endif return m_iSize > cTest.get_size(); } public: inline int get_size() const { return m_iSize; } inline void set_size(const int & iSize) { m_iSize = iSize; } private: int m_iSize; }; /** * 重载<< 用于输出 */ inline ostream& operator<<(ostream& str, const CTest& data) { return str << "[size = " << data.get_size() << "]"; } int main(int args,char* argvs[]) { set<string> setStr; setStr.insert("ab"); setStr.insert("1"); setStr.insert("2"); setStr.insert("abc"); setStr.insert("aba"); set<CTest> setClass; CTest cTest1; CTest cTest2; cTest1.set_size(1); cTest2.set_size(2); setClass.insert(cTest1); setClass.insert(cTest2); set<int> setInt; setInt.insert(1); setInt.insert(2); setInt.insert(2); cout << setStr << endl; cout << setClass << endl; cout << setInt << endl; }
如果编译命令为g++ testset.cpp -DPOS -o testset -g
输出的结果为:
{ 1 2 ab aba abc } { [size = 1] [size = 2] } { 1 2 }
如果编译命令为g++ testset.cpp -o testset -g
输出的结果为:
{ 1 2 ab aba abc } { [size = 2] [size = 1] } { 1 2 }
由这个例子可以看出,通过重载<的方式,可以直接对class类型的数据进行排序。