容器set和map的使用

本文详细介绍了C++标准库中的关联式容器set和map。set不允许重复元素且自动排序,而map由键值对组成,同样自动排序且不允许重复键值。文章讲解了set和map的迭代器使用、插入、删除、查找、修改等功能,强调了map中可以通过[]操作符访问和修改实值但不能修改键值。此外,还提供了利用map统计数组中元素出现次数的三种方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

set和map都是关联式容器
先介绍两个值:
键值:key 实值:value

set特性:所有的元素都会根据元素的键值(key)自动的被排序。对于set元素来说键值就是实值,实值就是键值,set不允许两个元素有相同的键值(我们不能通过set的迭代器去修改set的元素,原因后面会解释)

map特性:所有的元素都会根据元素的键值(key)自动的被排序,map的所有元素都是pair,同时拥有实值(value)和键值(key),pair的第一个元素被视为键值,第二个元素被视为实值,map不允许两个元素拥有相同键值。(可以通过map的迭代器修改实值,不能修改键值)。

实际上pair的结构体为:

template<class K,class V>
struct pair
{
    k first;
    v second;
}

set

我们先来看一下set的成员函数:
的

    int a[5] = { 0, 1, 2, 4, 3 };
    set<int> set1();//建立一个空set
    set<int> set2(a, a + 5);//指定范围的set
    set<int> set3(set2);//拷贝构造函数
    set<int> set4(set2.begin(),set2.end());//使用了迭代器来构造set4
    set<int> set5 = set3;//赋值运算符重载

迭代器:
set的迭代器(左闭右开)
这里begin是指向首元素,end指向的是最后一个元素的下一个位置
rbegin和rend是倒过来的。即,rbegin是最后一个元素,rend是首元素的上一个位置
cbegin和cend是const迭代器
crbegin和crend返回的是倒过来的const迭代器。
广泛大概
这里使用begin和end来举例子

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

遍历刚才s2,输出结果
佛挡杀佛

但是复苏的

插入insert

    s2.insert(7);
    s2.insert(6);
    s2.insert(8);

输出结果:
单发

删除erase
三屌
删除

1,删除一个值
第三方

2,删除一个位置
的

3,删除一个区间

饿的

三者区别:
值:找到了删,找不到了就不删直接返回
位置:先找到这个是否存在,若存在则删除,不存在了程序会崩溃
删除一个区间(左闭右开):问题:若找不到其中一边的会报错,

查找find
我们将find函数加入到遍历中应用
fsd

我们看了查找和删除,那么我们可以替换元素吗?
find一个值,去修改这个值,出来的结果会是错误的,只改变了值,而不满足二叉搜索树的性质了,
在C++11中会报错,解决这个问题,返回值应该为const&

交换swap
我们把s1和s2进行交换
第三方

清空clear

clear就是将set中所有元素都删除。
三屌

容量

佛挡杀佛
空empty

他经常被作为循环条件或者防御式编程使用

while(!s2.empty())//循环条件
assert(!s2.empty())//防御式编程

大小size和max_size
fd

count
具有特定值的计数元素
搜索容器中的元素等效于val,并返回匹配的数量。

由于集合容器中的所有元素都是唯一的,函数只能返回1(如果找到了元素)或零(否则)。

如果容器的比较对象返回了条件反射(即,不管元素作为参数传递的顺序),那么一个集合的两个元素被认为是等价的。

dsf

map

成员函数
撒旦

map<char, int> m1;//创建一个空map
    m1['a'] = 1;//添加
    m1['b'] = 2;
    m1['c'] = 3;
    m1['d'] = 4;

    map<char, int> m2(m1);//拷贝构造
    map<char, int> m3 = m2;//赋值运算符重载
    map<char, int> m4(m1.begin(), m1.end());//初始化为一段区间

但是

在map中下图的用法与set相同,就不在说了
发

这个是set中没有的,由于map有键值有实值所以他可以用[]来访问实值
第三方

范德萨

查找find:

map<char, int>::iterator it = m1.find('c');

删除erase
1,删除一个位置:
查找到,然后删除
这里写图片描述

2,删除一个值:
这里写图片描述

3,删除一段区间
大幅度

插入

的

修改map中实值:
释放时

注意键值不能修改

关于输出

cout<<*dIt<<endl;//会报错
//解引用不能返回2个值,只能返回一个值
//解决
cout<<(*dIt).first()<<(*dIt).second()<endl;
cout<<dIt->first<<dIt->second()<<endl;

map中的operator[]
hjk
我们可以看到它的返回值是带引用的
这说明它不止可以访问,还可以修改
若给的key不存在,那么就会添加
大是大非

我们可以看到,我们先创建了一个空的map,我们去访问一个不存在的key时,就会创建这个,我们试图访问m1[‘d’],并且把他修改为5
然后遍历一遍,我们可以看到修改成功了。

我们还可以用map来统计数组中每个元素出现的次数

    //方法一:
    map<string, int> countMap;
    string strs[] = { "red", "blue", "white", "red" };
    for (size_t i = 0; i < sizeof(strs) / sizeof(strs[0]); ++i)
    {
        map<string, int>::iterator ret = countMap.find(strs[i]);
        if (ret != countMap.end())
        {
            ret->second++;
        }
        else
        {
            //countMap.insert(pair<string, int>(strs[i], 1));
            countMap.insert(make_pair(strs[i], 1));
        }
    }

第一种方法:我们用了insert,我们先找到一个key接着遍历所有的如果在再次出现了让它的second++,如果没有出现就插入。这个方法的缺点就是时间复杂度高,每查找一个就要遍历整个数组

    //方法二:
    map<string, int> countMap;
    string strs[] = { "red", "blue", "white", "red" };
    for (size_t i = 0; i < sizeof(strs) / sizeof(strs[0]); ++i)
    {
        pair<map<string, int>::iterator, bool> ret = countMap.insert(make_pair(strs[i], 1));
        {
            if (ret.second == false)
            {
                ret.first->second++;
            }

        }
    }

方法二我们可以定义一个pair类型的变量ret,这个变量包含了map类型,和bool类型,我们每次插入一个他都为true,如果插入失败(之前出现过了就会插入失败),那么我们就ret.first->second++
我们举例ret中的结构是这样的
vh

//方法三:
    map<string, int> countMap;
    string strs[] = { "red", "blue", "white", "red" };
    for (size_t i = 0; i < sizeof(strs) / sizeof(strs[0]); ++i)
    {
    countMap[strs[i]]++;
    }

方法三充分的用了operator[]的性质,实现相对简单

三种的运行出现的结果都是一样的
我们用调试窗口看一下
的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值