set/multiset容器

1、set/multiset容器简介

set/multiset容器_第1张图片
但是 set 容器只有键值,在插入数据的时候会自动根据 键值 进行排序,所以不允许有相同的键值存在,也不能修改 set 容器元素值,会破坏 set 的数据结构。set 容器的迭代器是只读迭代器
set/multiset容器_第2张图片

2、set容器 API 操作

set/multiset容器_第3张图片
set/multiset容器_第4张图片

3、set 容器的使用

set容器中只能使用 insert 一个一个插入数据

void printSetInt(set<int> &s)
{
    set<int>::iterator it;
    for(it=s.begin(); it!=s.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
}

void printSetInt(set<int,MyCompare> &s)
{
    set<int,MyCompare>::iterator it;
    for(it=s.begin(); it!=s.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
}


void test01()
{
    set<int,MyCompare> s1;           //使用仿函数更改排序规则  
    s1.insert(30);                   //set容器只能使用 insert 一个一个插入数据,,因为要根据插入的数据进行排序,也没有 n个元素的拷贝构造,因为set中要求键值是不能重复的 
    s1.insert(10);
    s1.insert(20);
    s1.insert(20);
    s1.insert(40);
    printSetInt(s1);
}

set/multiset容器_第5张图片

4、更改 set 容器的排序规则(定义 set 容器时修改)

在这里插入图片描述
但是 set 函数的排序规则默认是按照从小到大,所以使用仿函数更改排序规则从 大到小

#include 
#include
using namespace std;
//仿函数实质上是一个类,使用仿函数更改排序规则
class MyCompare
{
public:
    bool operator()(int v1, int v2)
    {
        return v1>v2;
    }
};
void printSetInt(set<int> &s)
{
    set<int>::iterator it;
    for(it=s.begin(); it!=s.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
}

void printSetInt(set<int,MyCompare> &s)
{
    set<int,MyCompare>::iterator it;
    for(it=s.begin(); it!=s.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
}


void test01()
{
    set<int,MyCompare> s1;           //使用仿函数更改排序规则  
    s1.insert(30);                   //set容器只能使用 insert 一个一个插入数据,,因为要根据插入的数据进行排序,也没有 n个元素的拷贝构造,因为set中要求键值是不能重复的 
    s1.insert(10);
    s1.insert(20);
    s1.insert(20);
    s1.insert(40);
    printSetInt(s1);
}

set/multiset容器_第6张图片

5、如果 set 容器存放的是自定义类型,则需要更改排序规则

#include 
#include
using namespace std;


class Person
{
    friend class MyComparePerson;   //访问私有属性的仿函数作为该类的友元 
    friend ostream& operator<<(ostream &out, Person ob);   //类外函数访问私有属性作为该类的友元 
private:
    int num;
    string name;
    float score;
public:
    Person(){}
    Person(int num,string name, float score)
    {
        this->num = num;
        this->name = name;
        this->score = score;
    }
};

//cout<<(*it);    重载 cout<<(*it);    中的输出运算符 
ostream& operator<<(ostream &out, Person ob)
{
    out<<ob.num<<" "<<ob.name<<" "<<ob.score<<endl;
    return out;
}

class MyComparePerson      //仿函数更改排序规则 
{
public:
    bool operator()(Person ob1, Person ob2)    //仿函数更改排序规则 
    {
        return ob1.num < ob2.num;
    }
};
void printSetInt(set<Person,MyComparePerson>  &s)
{
    set<Person,MyComparePerson> ::iterator it;
    for(it=s.begin(); it!=s.end();it++)
    {
        cout<<(*it);                        //cout的是每一个对象,所以可以为 (*it).num<<(*it).name<<(*it).score,并且要将 void printSetInt(set  &s)设置为友元函数,但是这个涉及到函数关系,也不好设置,所以可以使用上面的重载输出运算符 
    }                                       //所以可以使用上面的重载输出运算符 
    cout<<endl;              
}
void test02()
{
    set<Person,MyComparePerson>  s1;
    s1.insert(Person(100,"lucy", 88.8f));
    s1.insert(Person(104,"bob", 99.8f));
    s1.insert(Person(103,"tom", 77.8f));
    s1.insert(Person(101,"德玛", 66.8f));
    s1.insert(Person(105,"寒冰", 55.8f));
    printSetInt(s1);
}
int main(int argc, char *argv[])
{
    test02();
    return 0;
}

set/multiset容器_第7张图片
对于cout的是每一个 person对象,所以可以为 (*it).num<<(*it).name<<(*it).score,并且要将 void printSetInt(set &s)设置为友元函数,但是这个涉及到函数的位置关系,也不好设置,所以最简单的是使用上面的重载输出运算符,将ostream& operator<<(ostream &out, Person ob)设置 person 类的 友元函数

6、set的find 和 count 函数

find 从前往后查找 键值,直到 容器末尾
count(key);//查找键key的元素个数 set容器的结果只能是0或1,因为键值是不可重复的

void test03()
{
    set<int> s1;
    s1.insert(10);
    s1.insert(30);
    s1.insert(50);
    s1.insert(70);
    s1.insert(90);
    printSetInt(s1);

    set<int>::const_iterator ret;    // find的返回值是一个迭代器,所以要申明这个容器的迭代器 
    ret = s1.find(50);
    if(ret != s1.end())
    {
        cout<<"找到的结果:"<<*ret<<endl;
    }

    //count(key);//查找键key的元素个数  set容器的结果只能是0或1
    cout<<s1.count(50)<<endl;
}

int main(int argc, char *argv[])
{
    test02();
    return 0;
}

set/multiset容器_第8张图片

7、set 的lower_bound、upper_bound、equal_range函数

equal_range函数可以同时 返回两个迭代器,兼具 lower_bound、upper_bound的功能
equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器
返回值类型为pair 对组
在这里插入图片描述

#include 
#include
using namespace std;


void test04()
{
    set<int> s1;
    s1.insert(10);
    s1.insert(30);
    s1.insert(50);
    s1.insert(70);
    s1.insert(90);
    printSetInt(s1);

    set<int>::const_iterator ret;
    //lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。(下限)
    ret = s1.lower_bound(50);
    if(ret !=s1.end())
    {
        cout<<"下限为:"<<*ret<<endl;
    }
    //upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器(上限)
    ret = s1.upper_bound(50);
    if(ret !=s1.end())
    {
        cout<<"上限为:"<<*ret<<endl;
    }
    //equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器
    //返回值类型为pair 对组
    pair< set<int>::const_iterator, set<int>::const_iterator> p;
    p = s1.equal_range(50);
    if(p.first  != s1.end())    //左值
    {
        cout<<"下限为:"<<*(p.first)<<endl;
    }
    if(p.second != s1.end())    //右值
    {
        cout<<"上限为:"<<*(p.second)<<endl;
    }
}

int main(int argc, char *argv[])
{
    test04();
    return 0;
}

set/multiset容器_第9张图片

7、注意事项

set和multiset 的头文件都是 set
set的键值是不可重复的,multiset 的键值是可重复的
其他都是一样的

你可能感兴趣的:(c++,STL,c++)