set存储自定义类
1) 二叉树类型的容器的sort和find都会调用operator < 。
2)线性类型容器sort会调用operator <;线性容器使用std::find会调用operator ==。
需要非常注意重载<运算符,分类讨论要周全。不然重则会导致dump机问题,轻则会导致排序不对。
对于< 号的重载要满足严格弱序的要求。
严格弱排序——strict weak ordering
严格是说在判断的时候会用"<",而不是"<=",弱排序是因为,一旦"<"成立便认为存在"<"关系,返回ture,而忽略了"="关系和">"区别,把它们归结为false。
满足严格弱序的3个条件:
1.两个关键字不能同时严格弱序于对方。
2.如果a严格弱序于b,且b严格弱序于c,则a必须严格弱序于c。
3.如果存在两个关键字,任何一个都不严格弱序于另一个,则这两个关键字是相等的。
/* * setSelfDe.cpp * * Created on: 2021年6月11日 * Author: */ #include <iostream> #include <set> using namespace std; class Bar { public: int m_i; Bar(int x):m_i(x){} friend bool operator <(const Bar& lhs, const Bar& rhs) { return lhs.m_i < rhs.m_i; } private: }; int main() { set<Bar> sbr; Bar b(3); Bar b1(3); Bar b2(4); sbr.insert(b); sbr.insert(b1); sbr.insert(b2); set<Bar>::iterator iter = sbr.find(b); if(iter != sbr.end()) { cout << iter->m_i << endl; } else { cout << "not found" << endl; } set<Bar>::iterator iter1 = sbr.find(b1); if(iter1 != sbr.end()) { cout << iter1->m_i << endl; } else { cout << "not found" << endl; } cout << "sbr size:" << sbr.size() << endl; return 0; }
STL::set自定义排序
简介作用:set一般插入元素时,默认使用关键字类型的<运算符比较两个关键字,因此一般都是升序排列。
如果你是自定义的数据结构,结构中没有<运算符,则无法进行比较。因此就有了set自定义排序(如果不自
定义排序,无法编译生成),如下介绍三种方法:
// 1.重载<:在自定义的数据结构中重载<即可, #include<iostream> #include<string> using namespace std; #include<set> struct Person { string name; int age; Person(string _name, int _age) : name(_name), age(_age){} bool operator <(const Person &rhs) const { if (name != rhs.name) return name < rhs.name; else return age < rhs.age; } friend ostream &operator<<(ostream &os, const Person &per){ //声明为友元,重载输出运算符 os << per.name << " " << per.age << std::endl; return os; } }; int main(){ set<Person> personSet; personSet.insert(Person("za", 2)); personSet.insert(Person("zb", 5)); personSet.insert(Person("za", 3)); personSet.insert(Person("zb", 4)); for (auto it = personSet.begin(); it != personSet.end(); it++){ cout << *it; } return 0; } //输出结果为(za,2) (za,3) (zb,4) (zb,5) // 2.重载() #include<iostream> #include<string> using namespace std; #include<set> struct Person { string name; int age; Person(string _name, int _age) : name(_name), age(_age){} friend ostream &operator<<(ostream &os, const Person &per){ //声明为友元 os << per.name << " " << per.age << std::endl; return os; } }; typedef struct{ bool operator ()(const Person lhs, const Person rhs){ if (lhs.name != rhs.name) return lhs.name < rhs.name; return lhs.age < rhs.age; } }Compare; int main(){ set<Person,Compare> personSet; personSet.insert(Person("za", 2)); personSet.insert(Person("zb", 5)); personSet.insert(Person("za", 3)); personSet.insert(Person("zb", 4)); for (auto it = personSet.begin(); it != personSet.end(); it++){ cout << *it; } return 0; } // C++ primer(第五版 #include<iostream> #include<string> using namespace std; #include<set> struct Person { string name; int age; Person(string _name, int _age) : name(_name), age(_age){} friend ostream &operator<<(ostream &os, const Person &per){ //声明为友元 os << per.name << " " << per.age << std::endl; return os; } }; bool cmp(const Person lhs, const Person rhs){ if (lhs.name != rhs.name) return lhs.name < rhs.name; return lhs.age < rhs.age; } int main(){ set<Person,decltype(cmp)*> personSet(cmp); personSet.insert(Person("za", 2)); personSet.insert(Person("zb", 5)); personSet.insert(Person("za", 3)); personSet.insert(Person("zb", 4)); personSet.emplace("az", 23); for (auto it = personSet.begin(); it != personSet.end(); it++){ cout << *it; } return 0; }
decltype关键字:
decltype来指出自定义操作的类型。当使用decltype 来获得一个函数指针类型时,
必须加上一个* 来指出我们要使用一个给定函数类型的指针。用cmp 来初始化personSet
对象,这表示当我们向personSet中插入元素时,通过调用cmp来为这些元素排序。可以使
用cmp代替&cmp作为构造函数的参数,因为当我们使用一个函数的名字时,在需要的情况下
会自动转化为一个指针,使用&cmp 效果也是一样的。