set的使用

set和map底层都是由红黑树实现的,每个元素都是红黑树的一个个节点;只不过map是key-value模型,每个节点是key—>value(映射)关系;而set是key模型,每个元素只有一个键值(key),同时也是实值(value),同时也不允许有相同的键值,默认按照升序排列,所以set的用法和map差不多。

set的定义:

set<K> s1;
set<K> s2(s1);
int a[] = {1,2,3,4};
set<int> s(a,a+4);
set<int> s3(s.begin(),s.end());

set的常用接口:

1.insert();

与map相似;常用的插入方法:

pair <iterator,bool> insert(const value_type& val);

参数:就是我们要插入的数;
返回值:返回一个pair,pair的第一个元素first是迭代器,第二个元素second是bool值,插入成功,first是指向该元素位置的迭代器,second的值为true;插入失败,说明该元素在set中已经存在,first是该元素位置的迭代器,second的值为false。
例如:

    set<int> s;
    pair<set<int>::iterator, bool> p;
    s.insert(1);
    s.insert(2);
    s.insert(3);
    s.insert(4);

    p = s.insert(1);
    if (p.second == false)
        cout << *(p.first) << "已经存在!" << endl;

这里写图片描述
也可以在指定位置插入:

iterator insert(iterator position,const value_tytpe& val);

这里写图片描述
与map一样,我们虽然在第一个位置插入8,但是set会自动排序,默认升序。
此时我们应该想到一点,map和set如果频繁的进行插入和删除操作,效率为什么就相对低了;他们的底层是红黑树,每一次的插入和删除都破坏了树的结构欧,为了依然维持结构的有序,都会调整树的结构,所以会影响效率。

2.其他常用的接口与map的用法一样:

就不一个个阐述了,实现一个例子:

int main()
{

    set<int> s;
    pair<set<int>::iterator, bool> p;
    s.insert(1);
    s.insert(2);
    s.insert(3);
    s.insert(4);
    s.insert(5);
    s.insert(6);
    //count
    int ret = 0;
    ret = s.count(1);
    if (ret == 1)
        cout << "1,该值存在!" << endl;
    ret = s.count(100);
    if (ret == 0)
        cout << "100,该值不存在" << endl;
    //find
    set<int>::iterator it;
    it = s.find(2);
    if (it != s.end())
        cout << *it << " 存在" << endl;
    it = s.find(100);
    if (it == s.end())
        cout << "find(100),该值不存在!" << endl;
    //erase
    ret = s.erase(1);
    if (ret == 1)
        cout << "删除 1 成功!" << endl;
    it = s.erase(s.find(4));
    cout << "删除 4 成功,此时迭代器指向下一个元素:"<<*it <<" 的位置!"<< endl;
    //size
    cout << "s现在还有:" << s.size() << " 个元素" << endl;
    //遍历
    it = s.begin();
    while (it != s.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
    //clear和empty
    s.clear();
    if (s.empty())
        cout << "clear(),s已经为空!" << endl;
    system("pause");
    return 0;
}

运行结果:
这里写图片描述

关于set的几个问题:

(1)为何map和set的插入删除效率比用其他序列容器高?

因为对于关联式容器来说,不需要做内存的拷贝和移动,map和set的元素都是以节点的方式来储存,结构和链表相似,所以插入和删除的时候只要改变指针的指向就可以了。

(2)为何每次insert之后,以前保存的iterator不会失效?

这是关于迭代器失效的问题;和vector一样,我们的每次插入和删除都有可能导致指针失效,所以我们在插入的时候,迭代器都指向当前插入的元素的位置,当删除一个元素后,此时该元素的内存已经不再或者被别人使用;所以我们就是迭代器就指向删除元素的下一个元素的位置。我们每次都不会使用过期的itreator。

猜你喜欢

转载自blog.csdn.net/prefect_boy/article/details/80343533