C++中的map和set

1、set集合

1.1、介绍

set称为集合,是一个内部自动有序且不含重复元素的容器。他只有key值,不是键值对类型的。底层实现是依靠红黑树实现。插入和删除元素时间复杂度为O(logN)。set最重要的作用就是自动去重和按照升序排序。set中的元素唯一,如果需要处理不唯一的情况,需要使用multiset。unordered_set可以用来处理只去重但不排序的要求,速度比set要快许多。可以对比map。

1.2、定义

#include 
set<类型>s;//类型可以是:int double,char,结构体,set,vector等等。set(集合)的特点就是可以忽略set中元素类型的影响,可以理解为纯粹的容器。
sets[100];//set数组,s[0]-s[99]的每一个元素都是一个set容器。

int arry[] = {1,2,3,4,5};
sets1(arry,arry+sizeof(arry) / sizeof(arry));//使用arry数组初始化s1。

1.3、set容器元素的访问

set容器的访问只能通过迭代器。

set<类型>::iterator it;//这样就得到了set的迭代器it,可以通过*it来访问set的元素。

vector和string之外的STL容器都不支持*(it+i)的访问方式,因此访问set内的元素只能按如下方式。

sets;
/*省略set赋值的部分*/
set::iterator it;
it=s.begin();
while(it!=s.end())
{
    cout<<*it++<<' ';
}
//或者
for(auto &e : s)
{
    cout<< e <<' ' ;
}

1.4、set的一些函数

插入元素:insert函数。

sets;
s.insert(1);//插入元素1。

查询元素:find函数。返回值是元素的迭代器。

set::iterator it=s.find(1);//查找值为1的元素,返回的是1这个元素的迭代器。
printf("%d",*it);

删除元素:erase函数。erase函数有多种用法。

用法1:结合find,删除单个元素。
set::iterator it=s.find(1);
s.erase(it);//it为元素值为1的迭代器。
用法2:
s.erase(1);//直接删除值为1的元素。
用法3:删除一个区间的元素。
s.erase(first,last);//删除[first,last)内的所有元素其中first为其实元素的迭代器,last为删除区间的末尾迭代器的下一个。

其他函数:

//逆向打印s1的元素的值。(即从大到小打印)
for (auto it=s1.rbegin(); it!=s1.rend();++it)
    {
        cout << *it << ' ';
    }
//计算值为2的元素出现了几次。
cout << s1.count(2) << endl;

2、set的补充—unordered_set和multiset

2.1、unordered_set

unordered_set和set基本相同,也是不允许有重复元素。底层实现是哈希表存储结构。只是set内的元素是有序的,set自动排序。unordered_set是无序的,按插入元素先后顺序排列。且unordered_set没有rbegin和rend函数。(由于unordered_set比较简单,这里不对此做过多介绍。)

#include 
unordered_sets1;
2.2、multiset

multiset是库中一个非常有用的类型。他可以时刻保证序列中的元素是有序的,且允许序列中存在重复的元素。底层实现和set相同,都是红黑树。插入和删除元素都能在O(logN)时间内完成。

#include //头文件
multisetm;
    m.insert(2);m.insert(1); m.insert(3); m.insert(2);
    for (auto &e : m)
    {
        cout << e << " ";
    }
    cout << endl;
输出结果:1 2 2 3

multiset和set用法一样,也可以放入自定义的类型。只不过,放入自定义的类型需要说明一下如何比较类型的大小。比如:

struct rec
    {
        int x, y;
    };
    struct cmp 
    {
        bool operator()(const rec&a, const rec&b)
        {
            //x为第一关键字,y为第二关键字进行比较。
            return a.x < b.x || a.x == b.x && a.y < b.y;
        }
    };
    multisetm;//m的每一个元素都是rec这个结构体,如何比较m元素之间的大小关系呢,通过cmp来比较。

multiset的函数和set相同,此处不做说明,如需要可自行查找。

3、map

map是由一对键值对组成(key----value),map是有序的,里面的元素排序是根据key的大小按升序排列,底层实现和set一样都是红黑树。如果是自定义类型无法比较时,需要用户自己显式传递比较规则。头文件:#include

unordered_map是无序的哈希表。STL容器中所有的无序容器底层实现都是采用哈希表的存储结构。更准确的说是用“链地址法”解决哈希冲突。头文件:#include

4、map和set的区别

Map和Set的区别

map和set都是C++的关联容器,其底层实现都是红黑树(RB-Tree) 。于map和

set所开放的各种操作接口,RB-ree 也都提供了,所以几乎所有的map和set的操作

行为,都只是转调RB-tree的操作行为。

map和set区别在于:

● map中的元素是key-value (关键字-值)对:关键字起到索引的作用,值则表示与

索引相关联的数据; Set与之相对就是关键字的简单集合, set中每个元索只包含一

个关键字。

● set的迭代器是const的,不允许修改元素的值; map允许修改value,但不允许修改

key。其原因是因为map和set是根据关键字排序来保证其有序性的,如果允许修改

key的话,那么首先需要删除该键,然后调节平衡,再插入修改后的键值,调节平

衡,如此-来,严重破坏了map和set的结构,导致iterator失效, 不知道应该指向

改变前的位置,还是指向改变后的位置。所以STL中将set的迭代器设置成const,

不允许修改迭代器的值;而map的迭代器则不允许修改key值,允许修改value值。

● map支持下标操作,set不支持下标操作。map可以用key做下标,map的下标运算

符[ ]将关键码作为下标去执行查找,如果关键码不存在,则插入一个具有该关键码

和mapped_ _type类型默认值的元素至map中,因此下标运算符[ ]在map应用中需要

慎用,const_ map不能用,只希望确定某一个关键值是否存 在而不希望插入元素时

也不应该使用,mapped_ type类型没有默认值也不应该使用。如果find能解决需

要,尽可能用find。

你可能感兴趣的:(STL容器,c++,算法,数据结构)