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 效果也是一样的。

posted @ 2021-06-11 16:53  PKICA  阅读(108)  评论(0编辑  收藏  举报