C++ Set/Multiset 常见用法全解(代码版)

set的特性是所有元素会根据元素的键值自动被排序。set不允许有两个元素有相同的键值。

set由红黑树作为底层结构。


set代码实例:

class struc{
public:
    struc(int a, int b): x(a), y(b){}
    int x;
    int y;
};

bool operator<(const struc& a, const struc& b)
{
    return a.y < b.y;
}

void set_test()     //不允许相同键值的存在
{
    //创建
    set<struc> st;
    
    //插入
    for (int i = 9; i >= 0; i--)
        st.insert(struc(i, i * 5));
    
    st.insert(struc(10, 40));   //添加失败,因为set有struc.y = 40的struc结构,是struc(8, 40)。主要是看比较函数中比较的是struc中的哪个值。
    st.insert(struc(9, 43));    //添加成功,因为set没有struc.y = 43的struc结构
    
    //查看
    for (auto it : st)
        cout<<it.x<<"-"<<it.y<<" ";                      //0-0 1-5 2-10 3-15 4-20 5-25 6-30 7-35 8-40 9-43 9-45
    cout<<endl;
    
    for (auto it = st.rbegin(); it != st.rend(); it++)   //9-45 9-43 8-40 7-35 6-30 5-25 4-20 3-15 2-10 1-5 0-0
        cout<<(*it).x<<"-"<<(*it).y<<" ";
    cout<<endl;
    
    //删除
    st.erase(st.begin());           //st.erase(st.begin() + 3)直接加3这种是不合法的
    st.erase(struc(2, 15));         //这句话会删除struct(3,15)。因为key值是y = 15。不管x是多少。
    
    for (auto it = st.begin(); it != st.end(); it++)    //1-5 2-10 4-20 5-25 6-30 7-35 8-40 9-43 9-45
        cout<<(*it).x<<"-"<<(*it).y<<" ";
    cout<<endl;
    
    //其他
    cout<<st.upper_bound(struc(3,5))->x<<endl;  //4  非递减序列中 大于 struc(3,5)的 第一个 迭代器。比大小依据的是operator<()中所比较的那个结构中的值
    cout<<st.lower_bound(struc(3,5))->x<<endl;  //15 非递减序列中 大于等于 struc(3,5)的 第一个 迭代器。比大小依据的是operator<()中所比较的那个结构中的值
    
    cout<<st.count(struc(9,40))<<endl;          //返回某个值元素的个数。
            //如果是自定义结构,比如struc(9,40)。如果比大小依据的是operator<()中所比较的那个结构中的值(struc.y),那就返回set中struc.y=40的个数。
            //在set中最多一个,因为struc.y = 40重复的struc结构是添加不进set的。
    
    auto it = st.find(struc(-1, 35));           //和上面一样,只会找y = 35的那一项。
    cout<<it->x<<" "<<it->y<<endl;              //7 35
    
    auto ret = st.equal_range(struc(-1, 40));   //返回集合中与给定值相等的上下限的两个迭代器 [)。找的是key值,这里面是y的升序。
    cout<<ret.first->y<<" "<<ret.second->y<<endl;
    
    st.empty();
    st.size();
    st.clear();
}


set另外两种自定义比较函数

    (1)元素不是结构体:

        例:

        //自定义比较函数myComp,重载()操作符

struct myComp

{

    bool operator()(const your_type &a, const your_type &b)

    {

        return a.data > b.data;

    }

}

set<int, myComp>s;


    (2)如果元素是结构体,可以直接将比较函数写在结构体内。

        例:

struct Info

{

    string name;

    float score;

    //重载“<”操作符,自定义排序规则

    bool operator < (const Info &a) const

    {

        //score从大到小排列

        return a.score < score;

    }

};

set<Info> s;



multiset代码实例:

class stru{
public:
    stru(int a, int b): x(a), y(b){}
    int x;
    int y;
};

bool operator<(const stru& a, const stru& b)    //比较的是x的值
{
    return a.x < b.x;
}

void multiset_test()
{
    //创建
    multiset<stru> st;
    
    //插入
    for (int i = 9; i >= 0; i--)
        st.insert(stru(i, i * 5));
    
    st.insert(stru(10, 40));   //添加成功,因为multiset可以有重复的值,也就是说有x = 10的stru也可以。
    st.insert(stru(9, 43));    //添加成功
    
    //查看
    for (auto it : st)
        cout<<it.x<<"-"<<it.y<<" ";                      //0-0 1-5 2-10 3-15 4-20 5-25 6-30 7-35 8-40 9-45 9-43 10-40
    cout<<endl;
    
    for (auto it = st.rbegin(); it != st.rend(); it++)   //10-40 9-43 9-45 8-40 7-35 6-30 5-25 4-20 3-15 2-10 1-5 0-0
        cout<<(*it).x<<"-"<<(*it).y<<" ";
    cout<<endl;
    
    //删除
    st.erase(st.begin());           //st.erase(st.begin() + 3)直接加3这种是不合法的
    st.erase(stru(2, 15));          //这句话会删除所有struct.x = 2的stru。不管y是多少。
    
    for (auto it = st.begin(); it != st.end(); it++)    //1-5 3-15 4-20 5-25 6-30 7-35 8-40 9-45 9-43 10-40
        cout<<(*it).x<<"-"<<(*it).y<<" ";
    cout<<endl;
    
    //其他
    cout<<st.upper_bound(stru(9,5))->y<<endl;  //10-40  非递减序列中 大于 stru(9,5)的 第一个 迭代器。比大小依据的是operator<()中所比较的那个结构中的值
    cout<<st.lower_bound(stru(9,5))->y<<endl;  //9-45 非递减序列中 大于等于 stru(9,5)的 第一个 迭代器。比大小依据的是operator<()中所比较的那个结构中的值
    
    cout<<st.count(stru(9,40))<<endl;          //2 返回某个值元素的个数。
    //如果是自定义结构,比如stru(9,40)。如果比大小依据的是operator<()中所比较的那个结构中的值(stru.x),那就返回multiset中struc.x = 9的个数。
    
    auto it = st.find(stru(9, 35));           //和上面一样,只会找x = 9的第一项。
    cout<<it->x<<" "<<it->y<<endl;            //9 45
    
    auto ret = st.equal_range(stru(9, 35));   //返回集合中与给定值相等的上下限的两个迭代器 [)。找的是key值,这里面是y的升序。
    cout<<ret.first->y<<" "<<ret.second->y<<endl;  //ret.first是9-45  ret.second是10-40
    
    st.empty();
    st.size();
    st.clear();
}




C++中,`set` 和 `multiset` 都属于关联容器,存储的元素都会根据元素的值自动进行排序。但两者存在以下区别: ### 元素唯一性 - `set` 容器中不允许有重复的元素,当插入重复元素时,插入操作会失败。例如以下代码: ```cpp #include <iostream> #include <set> using namespace std; void test01() { set<int> s; pair<set<int>::iterator, bool> ret = s.insert(10); if (ret.second) { cout << "第一次插入成功" << endl; } else { cout << "第一次插入失败" << endl; } ret = s.insert(10); if (ret.second) { cout << "第二次插入成功" << endl; } else { cout << "第二次插入失败" << endl; } } int main() { test01(); return 0; } ``` 该代码展示了 `set` 插入重复元素时,第二次插入会失败[^1]。 - `multiset` 容器允许有重复的元素,插入重复元素会成功。如下代码: ```cpp #include <iostream> #include <set> using namespace std; void testMultiset() { multiset<int> ms; ms.insert(10); ms.insert(10); ms.insert(10); ms.insert(10); for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++) { cout << *it << " "; } cout << endl; } int main() { testMultiset(); return 0; } ``` 该代码展示了 `multiset` 可以多次插入相同元素,且能正常存储并遍历输出[^1]。 ### 容器大小 由于 `set` 不允许重复元素,而 `multiset` 允许,所以对于包含重复元素的初始化序列,两者的大小可能不同。例如: ```cpp #include <string> #include <iostream> #include <set> #include <vector> using namespace std; int main() { vector<int> ivec; for(int i = 0; i!= 10;++i) { ivec.push_back(i); ivec.push_back(i); } set<int> iset(ivec.begin(),ivec.end()); multiset<int> miset(ivec.begin(),ivec.end()); cout << iset.size() << endl; cout << miset.size() << endl; cout << ivec.size() << endl; return 0; } ``` 此代码中,`iset` 的大小为 10,`miset` 的大小为 20,因为 `iset` 会去重,而 `miset` 保留所有元素[^2]。 ### 插入返回值 - `set` 的 `insert` 方法返回一个 `pair`,其中 `pair` 的 `second` 成员是一个布尔值,表示插入是否成功。 - `multiset` 的 `insert` 方法返回一个迭代器,指向新插入元素的位置,因为 `multiset` 插入总是成功,所以不需要返回布尔值表示插入结果。 ### 查找元素 - 在 `set` 中查找元素,若找到,返回指向该元素的迭代器;若未找到,返回 `end()` 迭代器。 - 在 `multiset` 中查找元素,若找到,返回指向该元素的迭代器;由于可能存在多个相同元素,`multiset` 还提供了 `count` 方法用于统计某个元素的出现次数。 ### 元素删除 - 在 `set` 中删除元素,若元素存在则删除并返回 1,若不存在则返回 0。 - 在 `multiset` 中删除元素,会删除所有与指定值相等的元素,并返回被删除元素的数量。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值