C++STL set介绍与使用方法

set(集合)

set容器用来存储唯一元素,并且这些元素按照一定的规则排序。在一个集合里面,每个元素同时也是自身的关键字,与map相比,set的key与value是同一个值,所以每个元素必须是唯一的。同时,一旦某个元素插入到容器内,则不能修改其中任何元素,类比map,在map中也不能修改key。但set容器可以插入与删除。

set作为关联容器,与map一样,其内部数据结构为红黑树。


关于set与map这里提几个问题
  • 为何map和set的插入与删除效率比用其它容器要高
  • 为何每次insert之后,以前保存的iterator不会失效
  • 当数据元素增多时候(10000到20000),map和set的插入和搜索速度变化如何

    1. 对于第一个问题,只要清楚关联容器内部数据结构便知道为何,对于关联容器,容器内部所有元素都以结点的方式来存储,结点结构和链表差不多。红黑树也是树形结构,因此在插入、删除时都只是添加或删除结点,而其它序列容器在插入或者删除时均需要内存拷贝、移动内存内数据。
    2. 第二个问题,同样是理解内部数据结构,对于树形结构,iterator相当于指向结点的指针,插入结点后,之前的iterator仍然指向原来的结点。
    3. 仍然还是依据内部数据结构,红黑树的查找过程类似于二分查找,查找过程的时间复杂度是$O(logN)$,也就是说10000个结点,查找最多比较14次,数据增加一倍,比较次数只是多一次,相比序列容器的顺序查找,效率高了很多。
构造函数
std::set<int> first;    // empty set of ints

int myints[]= {10,20,30,40,50};
std::set<int> second (myints,myints+5);  // range

std::set<int> third (second);        // a copy of second

std::set<int> fourth (second.begin(), second.end());  // iterator ctor.
迭代器
  • 与其他容器一样,可以使用迭代器

set<int> first = {1, 2, 3, 4};
set<int>::iterator it;

for (it = first.begin(); it != first.end(); it++)
{
    cout << *it << endl;
}
容器容量

set<int> first = {1, 2, 3, 4};

cout << first.size() << endl;
cout << first.empty() << endl;

容器修改
//插入
//插入函数的返回值是一个pair,pair里面第一个值为迭代器,第二个值为是否插入成功,如果插入的值已经在关键字中,则插入失败。
std::set<int> myset;
std::set<int>::iterator it;
std::pair<std::set<int>::iterator,bool> ret;

// set some initial values:
for (int i=1; i<=5; ++i) myset.insert(i*10);    // set: 10 20 30 40 50

ret = myset.insert(20);

if (ret.second == false)
{
    it = ret.first;
}

myset.insert(it, 25);

int myints[]= {5,10,15}; 
myset.insert(myints, myints+3);

//前面知道,关联容器内部数据结构为红黑树,树形结构在插入时,需要找到正确的插入位置,因此上面这种先查找,查找失败,但迭代器指向了比较近的结点位置,因此再次插入时,则需要查找的次数就会比较少。如果不提供插入迭代器,则会从树根开始查找,时间效率较低。


//删除
int n = first.erase(20);   //返回被删除元素个数,set里面只会是1或者0

first.swap(myset);    //两个set互换
first.clear();    //集合清空

it = first.find(20);   //查找,返回迭代器,未查找到则返回first.end()

first.count(20);  //类似于find,如果查找到则返回1,未查找到返回0

后记

set可以看成是key/value相同的map,在实际使用中,能够set的地方都可以用map进行替换,关联式容器每次插入元素都会自动排序,因此要获取元素只能通过关键字,而不能通过绝对的索引(如序列式容器vector,list,string等)。而且一旦元素插入后,只要没有删除操作,元素位置不会改变,因此即便是插入元素,之前的iterator仍然可以使用。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值