set容器初探索

一、set容器

1.1 set与multiset区别与联系:

  • set 是一个集合容器,其中包含的元素唯一,集合中的元素按顺序排列。元素插入过程是按规则插入的,所有的元素都会根据元素的键值自动排序不能指定插入位置

  • set与multiset都采用红黑树作为底层容器,set与multiset的底层容器都是自动排序的。红黑树是平衡二叉树,所以插入和删除的操作比vector快。

  • set不可以直接存取元素

  • multiset与set的区别在于,multiset允许存储多个相同的元素

  • 不可以直接修改set或multiset容器中的元素值,因为该类型的容器是自动排序的。如果确实需要修改元素值,必须先删除旧元素,再插入新元素。

1.2 set与multiset的默认构造函数

    set<int> setInt;
    set<float> setFloat;
    set<string> setString;
    multiset<int> multiInt;
    multiset<float> multiFloat;
    multiset<string> multiString;

1.3 set与multiset的插入和删除

set与multiset的插入和删除操作都是使用insert函数,set与multiset的插入和删除的函数原型如下:

    set.insert(const value_type& val);      //插入元素val
    set.insert(iterator pos, const value_type& val);    //在迭代器指向位置插入元素val
    set.erase(elem);        //删除容器中值为elem的元素
    set.erase(pos);         //删除迭代器指向的元素
    set.erase(begin(), end());      //删除区间内的元素

1.3.1 插入

    set<int> s1;
    s1.insert(3);
    s1.insert(7);
    s1.insert(9);
    s1.insert(0);

    set<int>::iterator it = s1.begin();
    for(it = s1.begin(); it != s1.end(); it++)
    {
        cout << *it << endl;
    }
    //输出结果 :0 3 7 9
    //set默认是升序排序的

    set<int>::reverse_iterator it2;

    for(it2 = s1.rbegin(); it2 != s1.rend(); it2++)
    {
        cout << *it2 << endl;
    }

    //输出:9 7 3 0 
    //使用反向迭代器可以倒序排序

1.3.2 删除

使用迭代器删除set容器中的元素:

    //删除set容器中的最小值 5
    it = s.begin();
    s.erase(it);        

    for(it = s.begin(); it != s.end(); it++)
    {
        cout << *it << " " ;
    }
    cout << endl;

    //删除set容器中的最大值 100
    it = s.end();
    it--;
    s.erase(it);

    cout << "it :"<<  *it << endl;
    for(it = s.begin(); it != s.end(); it++)
    {
        cout << *it << " " ;
    }
    cout << endl;

注意1:不能对end进行解引用* 或者是 ++操作

    set<int> s = {5, 9, 37, 100};  // 自动排序为 5,9,37,100

    // 步骤1:it指向end()(最后一个元素的下一个位置)
    it = s.end();    // it → [100的后面]

    // 步骤2:it--,指向最后一个元素
    it--;            // it → 100

    // 步骤3:删除100,erase返回新的end()
    it = s.erase(it); // 删除100后,it → [37的后面](即新的end())

    // 步骤4:危险操作!解引用end()
    cout << *it;     // 错误!it现在是end(),不能取它的值
                    // 有时会崩溃,有时会输出随机数

    // 步骤5:更危险操作!对end()执行++
    it++;            // 错误!标准不允许end()++
                    // 可能:1.崩溃 2.绕回begin() 3.随机值
    cout << *it;     // 完全不可预测的结果

注意2:erase()必须使用正向迭代器,不支持反向迭代器。

    //使用反向迭代器删除set容器中最后一个元素
    set<int>::reverse_iterator rit = s.begin();
    s.erase(rit);
    //erase() 方法不接受 reverse_iterator,必须使用正向迭代器。

3、三原则

1、end()是禁区

2、不能*end(),不能end()++(不能在悬崖边跳舞)

3、删除元素后要更新迭代器:

删除指定的值:

s.erase(5);
for(it = s.begin(); it != s.end(); it++)
{
    cout << *it << " " ;
}
cout << endl;

如果需要删除的元素在set容器中不存在,返回false;如果在返回true。

    cout << s.erase(5) << endl;     //返回0,因为5已经不在set容器中了
    cout << s.erase(9) << endl;   //返回1,因为9在set容器中
it = s.erase(it);   // 必须接收返回值

操作前检查有效性:
if(it != s.end()) { /* 安全操作 */ }

1.4 set与multiset的拷贝构造与赋值

set与multiset的拷贝构造与赋值函数原型如下:

    set(const set& s);        //拷贝构造函数
    set& operator=(const set& s);    //重载等号操作符
    set<int> s2(s1);    //调用拷贝构造函数
    set<int> s3;        //调用默认构造函数

    s3 = s2;   
    set<int>::iterator it3;
    for(it3 = s3.begin(); it3 != s3.end(); it3++)
    {
        cout << *it3 << endl;
    }   

    s3.insert(100);                 //插入元素100
    cout << "s3插入100" << endl;
    s3.swap(s1);                    //交换s1和s3的内容

    //交换后的s1的内容
    cout << "交换后的s1的内容:" << endl;
    for(it = s1.begin(); it != s1.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;

    cout << "交换后的s3的内容:" << endl;
    for(it3 = s3.begin(); it3 != s3.end(); it3++)
    {
        cout << *it3 << " ";
    }
    return 0;

1.5 set与multiset的大小和判空

set.size()        //返回set容器中元素的个数
set.empty()        //判断set容器是否为空,空返回true,非空返回false

1.6 set与multiset的查找

set.find(elem);    //查找elem元素,返回指向elem的迭代器;否则返回set.end()
set.count(elem);   //查找elem元素,返回elem元素的个数。set容器中元素都是唯一的,所以返回值为0或1。如果是multiset容器,则可能大于1
set.lower_bound(elem);    //返回第一个 >= elem元素的迭代器
set.upper_bound(elem);    //返回第一个 > elem元素的迭代器
set.equal_range(elem);    //返回一个pair,pair.first为lower_bound(elem),pair.second为upper_bound(elem)
posted @ 2025-05-23 18:53  baobaobashi  阅读(23)  评论(0)    收藏  举报