STL-set

本文详细介绍C++ STL中set容器的基本用法、构造方法、常用成员函数及自定义比较函数等内容,帮助读者掌握set容器的高效使用技巧。

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

原文链接:点击打开链接


set集合容器:

调用头文件:

#include<set>

using namespace std;

详细用法(部分):

set<int> t      ------      定义一个int类型的容器,注意set里的每个元素只会出现1次

t.insert(k)      ------      插入元素k,多次插入同一个元素后面无效

t.count(k)      ------      判断元素k是否在容器内

t.erase(k)  ------      删除元素k,若不存在则删除无效

t,clear()      ------      清空容器

t.size()      ------      返回容器现有元素个数

t.empty()      ------      判断容器是否为空


想遍历set里的元素或进行进一步修改,必须定义对应迭代器,以下三种定义方法(迭代器类似于指针)

set<int>::iterator it      ------      定义正向迭代器

set<int>::reverse_iterator rit;      ------      定义反向迭代器

auto it = t.begin();      ------      因为t.begin()返回正向迭代器,所以it自动被定义为正向迭代器,可适应其他所有操作

以下需要迭代器的操作:

t.begin()      ------      返回set中第一个元素,类型为正向迭代器

t.rbegin()      ------      返回set中最后一个元素,类型为反向迭代器

t.end()      ------返回set中最后一个元素,类型为正向迭代器

t.rend()      ------      返回set中第一个元素,类型为反向迭代器


t.find(k)      ------      寻找k,若找到返回对应的迭代器,否则返回end();

t,insert(a, b)      ------      插入指针[a, b)之间的元素,已有元素不会再次插入

t.erase(it)      ------      删除迭代器it对应的元素

t.erase(l, r)      ------      删除迭代器[l, r)之间的元素

lower_bound(k)      ------      返回第一个大于等于k的元素的迭代器

upper_bound(k)      ------      对于set这种元素唯一的容器,该操作与lower_bound(k)相同,只有一种情况不同,就是

容器中若含有元素k,该操作会返回k下一个元素的迭代器

#include<stdio.h>  
#include<set>  
using namespace std;  
set<int> t;  
int main(void)  
{  
    t.insert(5);  
    t.insert(3);  
    t.insert(8);  
    t.insert(9);  
    t.insert(12);  
    printf("the size is %d\n", t.size());  
    printf("%d %d\n", t.count(5), t.count(-1));     //运行结果:1 0  
  
    set<int>::iterator it;  
    for(it=t.begin();it!=t.end();it++)      //运行结果:3 5 8 9 12  
        printf("%d ", *it);  
    printf("\n");  
  
    set<int>::reverse_iterator rit;  
    for(rit=t.rbegin();rit!=t.rend();rit++)     //运行结果:12 9 8 5 3  
        printf("%d ", *rit);  
    printf("\n");  
  
    auto a = t.begin();  
    auto b = t.begin();  
    b++;  
    t.erase(a,b);  
    for(it=t.begin();it!=t.end();it++)      //运行结果:5 8 9 12  
        printf("%d ", *it);  
    printf("\n");  
  
    a = t.lower_bound(6);  
    b = t.upper_bound(8);  
    printf("%d %d\n", *a, *b);      //运行结果:8 9  
    return 0;  
}


1.创建set集合对象

           创建set对象时,需要指定元素的类型,这一点和其他容器一样。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<iostream>  
  2. #include<set>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     set<int> s;  
  7.     return 0;  
  8. }  
2.元素的插入与中序遍历

        采用inset()方法把元素插入到集合中,插入规则在默认的比较规则下,是按元素值从小到大插入,如果自己指定了比较规则函数,则按自定义比较规则函数插入。使用前向迭代器对集合中序遍历,结果正好是元素排序后的结果。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<iostream>  
  2. #include<set>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     set<int> s;  
  7.     s.insert(5); //第一次插入5,可以插入  
  8.     s.insert(1);  
  9.     s.insert(6);  
  10.     s.insert(3);  
  11.     s.insert(5); //第二次插入5,重复元素,不会插入  
  12.     set<int>::iterator it; //定义前向迭代器  
  13.     //中序遍历集合中的所有元素  
  14.     for(it = s.begin(); it != s.end(); it++)  
  15.     {  
  16.         cout << *it << " ";  
  17.     }  
  18.     cout << endl;  
  19.     return 0;  
  20. }  
  21. //运行结果:1 3 5 6  
3.元素的方向遍历

        使用反向迭代器reverse_iterator可以反向遍历集合,输出的结果正好是集合元素的反向排序结果。它需要用到rbegin()和rend()两个方法,它们分别给出了反向遍历的开始位置和结束位置。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<iostream>  
  2. #include<set>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     set<int> s;  
  7.     s.insert(5); //第一次插入5,可以插入  
  8.     s.insert(1);  
  9.     s.insert(6);  
  10.     s.insert(3);  
  11.     s.insert(5); //第二次插入5,重复元素,不会插入  
  12.     set<int>::reverse_iterator rit; //定义反向迭代器  
  13.     //反向遍历集合中的所有元素  
  14.     for(rit = s.rbegin(); rit != s.rend(); rit++)  
  15.     {  
  16.         cout << *rit << " ";  
  17.     }  
  18.     cout << endl;  
  19.     return 0;  
  20. }  
  21. //运行结果:6 5 3 1  
4.元素的删除

        与插入元素的处理一样,集合具有高效的删除处理功能,并自动重新调整内部的红黑树的平衡。删除的对象可以是某个迭代器位置上的元素、等于某键值的元素、一个区间上的元素和清空集合。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<iostream>  
  2. #include<set>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     set<int> s;  
  7.     s.insert(5); //第一次插入5,可以插入  
  8.     s.insert(1);  
  9.     s.insert(6);  
  10.     s.insert(3);  
  11.     s.insert(5); //第二次插入5,重复元素,不会插入  
  12.     s.erase(6); //删除键值为6的元素  
  13.     set<int>::reverse_iterator rit; //定义反向迭代器  
  14.     //反向遍历集合中的所有元素  
  15.     for(rit = s.rbegin(); rit != s.rend(); rit++)  
  16.     {  
  17.         cout << *rit << " ";  
  18.     }  
  19.     cout << endl;   
  20.     set<int>::iterator it;  
  21.   
  22.     it = s.begin();  
  23.     for(int i = 0; i < 2; i++)  
  24.         it = s.erase(it);   
  25.     for(it = s.begin(); it != s.end(); it++)  
  26.         cout << *it << " ";  
  27.     cout << endl;  
  28.   
  29.     s.clear();  
  30.     cout << s.size() << endl;  
  31.   
  32.     return 0;  
  33. }  
  34. /* 
  35. 运行结果: 
  36. 5 3 1 
  37. 5 
  38. 0     
  39. */  
5.元素的检索

          使用find()方法对集合进行检索,如果找到查找的的键值,则返回该键值的迭代器位置;否则,返回集合最后一个元素后面的一个位置,即end()。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<iostream>  
  2. #include<set>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     set<int> s;  
  7.     s.insert(5); //第一次插入5,可以插入  
  8.     s.insert(1);  
  9.     s.insert(6);  
  10.     s.insert(3);  
  11.     s.insert(5); //第二次插入5,重复元素,不会插入  
  12.     set<int>::iterator it;  
  13.     it = s.find(6); //查找键值为6的元素  
  14.     if(it != s.end())  
  15.         cout << *it << endl;  
  16.     else  
  17.         cout << "not find it" << endl;  
  18.     it = s.find(20);  
  19.     if(it != s.end())  
  20.         cout << *it << endl;  
  21.     else  
  22.         cout << "not find it" << endl;  
  23.     return 0;  
  24. }  
  25. /* 
  26. 运行结果: 
  27. 6 
  28. not find it    
  29. */  

下面这种方法也能判断一个数是否在集合中:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <cstdio>  
  2. #include <set>  
  3. using namespace std;  
  4. int main() {  
  5.     set <int> s;  
  6.     int a;  
  7.     for(int i = 0; i < 10; i++)  
  8.         s.insert(i);  
  9.     for(int i = 0; i < 5; i++) {  
  10.         scanf("%d", &a);  
  11.         if(!s.count(a)) //不存在  
  12.             printf("does not exist\n");  
  13.         else  
  14.             printf("exist\n");  
  15.     }  
  16.     return 0;  
  17. }  

6.自定义比较函数

         使用insert将元素插入到集合中去的时候,集合会根据设定的比较函数奖该元素放到该放的节点上去。在定义集合的时候,如果没有指定比较函数,那么采用默认的比较函数,即按键值从小到大的顺序插入元素。但在很多情况下,需要自己编写比较函数。

编写比较函数有两种方法。

(1)如果元素不是结构体,那么可以编写比较函数。下面的程序比较规则为按键值从大到小的顺序插入到集合中。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<iostream>  
  2. #include<set>  
  3. using namespace std;  
  4. struct mycomp  
  5. //自定义比较函数,重载“()”操作符  
  6.     bool operator() (const int &a, const int &b)  
  7.     {  
  8.         if(a != b)  
  9.             return a > b;  
  10.         else  
  11.             return a > b;  
  12.     }  
  13. };  
  14. int main()  
  15. {  
  16.     set<int, mycomp> s; //采用比较函数mycomp  
  17.     s.insert(5); //第一次插入5,可以插入  
  18.     s.insert(1);  
  19.     s.insert(6);  
  20.     s.insert(3);  
  21.     s.insert(5); //第二次插入5,重复元素,不会插入  
  22.     set<int,mycomp>::iterator it;  
  23.     for(it = s.begin(); it != s.end(); it++)  
  24.         cout << *it << " ";  
  25.     cout << endl;  
  26.     return 0;  
  27. }  
  28. /* 
  29. 运行结果:6 5 3 1   
  30. */  
(2)如果元素是结构体,那么可以直接把比较函数写在结构体内。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<iostream>  
  2. #include<set>  
  3. #include<string>  
  4. using namespace std;  
  5. struct Info  
  6. {  
  7.     string name;  
  8.     double score;  
  9.     bool operator < (const Info &a) const // 重载“<”操作符,自定义排序规则  
  10.     {  
  11.         //按score由大到小排序。如果要由小到大排序,使用“>”即可。  
  12.         return a.score < score;  
  13.     }  
  14. };  
  15. int main()  
  16. {  
  17.     set<Info> s;  
  18.     Info info;  
  19.   
  20.     //插入三个元素  
  21.     info.name = "Jack";  
  22.     info.score = 80;  
  23.     s.insert(info);  
  24.     info.name = "Tom";  
  25.     info.score = 99;  
  26.     s.insert(info);  
  27.     info.name = "Steaven";  
  28.     info.score = 60;  
  29.     s.insert(info);  
  30.   
  31.     set<Info>::iterator it;  
  32.     for(it = s.begin(); it != s.end(); it++)  
  33.         cout << (*it).name << " : " << (*it).score << endl;   
  34.     return 0;  
  35. }  
  36. /* 
  37. 运行结果: 
  38. Tom : 99 
  39. Jack : 80 
  40. Steaven : 60 
  41. */  

Set常用函数:跟其他容器的函数差不多,好像都通用

c++ stl容器set成员函数:begin()--返回指向第一个元素的迭代器

c++ stl容器set成员函数:clear()--清除所有元素

c++ stl容器set成员函数:count()--返回某个值元素的个数

c++ stl容器set成员函数:empty()--如果集合为空,返回true

c++ stl容器set成员函数:end()--返回指向最后一个元素的迭代器

c++ stl容器set成员函数:equal_range()--返回集合中与给定值相等的上下限的两个迭代器

c++ stl容器set成员函数:erase()--删除集合中的元素

c++ stl容器set成员函数:find()--返回一个指向被查找到元素的迭代器

c++ stl容器set成员函数:get_allocator()--返回集合的分配器

c++ stl容器set成员函数:insert()--在集合中插入元素

c++ stl容器set成员函数:lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器

c++ stl容器set成员函数:key_comp()--返回一个用于元素间值比较的函数

c++ stl容器set成员函数:max_size()--返回集合能容纳的元素的最大限值

c++ stl容器set成员函数:rbegin()--返回指向集合中最后一个元素的反向迭代器

c++ stl容器set成员函数:rend()--返回指向集合中第一个元素的反向迭代器

c++ stl容器set成员函数:size()--集合中元素的数目

c++ stl容器set成员函数:swap()--交换两个集合变量

c++ stl容器set成员函数:upper_bound()--返回大于某个值元素的迭代器

c++ stl容器set成员函数:value_comp()--返回一个用于比较元素间的值的函数

集合

使用set或multiset之前,必须加入头文件<set>

Set、multiset都是集合类,差别在与set中不允许有重复元素,multiset中允许有重复元素。


sets和multiset内部以平衡二叉树实现



1.   常用函数

1)        构造函数和析构函数

set c:创建空集合,不包含任何元素

set c(op):以op为排序准则,产生一个空的set

set c1(c2):复制c2中的元素到c1中

set c(const value_type *first, const value_type* last):复制[first, last)之间元素构成新集合

set c(const value_type *first, const value_type* last,op):以op为排序准则,复制[first, last)之间元素构成新集合。

c.~set()销毁所有元素,释放内存

multiset mc:创建空集合,不包含任何元素

multiset mc(op):以op为排序准则,产生一个空的set

multiset c1(c2):复制c2中的元素到c1中

multiset c(const value_type *first, const value_type* last):复制[first, last)之间元素构成新集合

multiset c(const value_type *first, const value_type* last,op):以op为排序准则,复制[first, last)之间元素构成新集合。

c.~set()销毁所有元素,释放内存

[cpp]  view plain  copy
  1. // constructing sets  
  2. #include <iostream>  
  3. #include <set>  
  4.   
  5. bool fncomp (int lhs, int rhs) {return lhs<rhs;}  
  6.   
  7. struct classcomp {  
  8.   bool operator() (const int& lhs, const int& rhs) const  
  9.   {return lhs<rhs;}  
  10. };  
  11.   
  12. int main ()  
  13. {  
  14.   std::set<int> first;                           // empty set of ints  
  15.   
  16.   int myints[]= {10,20,30,40,50};  
  17.   std::set<int> second (myints,myints+5);        // range  
  18.   
  19.   std::set<int> third (second);                  // a copy of second  
  20.   
  21.   std::set<int> fourth (second.begin(), second.end());  // iterator ctor.  
  22.   
  23.   std::set<int,classcomp> fifth;                 // class as Compare  
  24.   
  25.   bool(*fn_pt)(int,int) = fncomp;  
  26.   std::set<int,bool(*)(int,int)> sixth (fn_pt);  // function pointer as Compare  
  27.   
  28.   return 0;  
  29. }  


2)        大小、判断空函数

    int size() const:返回容器元素个数
    bool empty() const:判断容器是否为空,若返回true,表明容器已空


3)        增加、删除函数

      pair<iterator,bool> insert( x):插入元素x

    iterator insert(iterator it,x):在迭代器it处插入元素x

    void insert(const value_type *first,const value_type *last):插入[first, last)之间元素

    iterator erase(iterator it):删除迭代器指针it处元素

    iterator erase(iterator first,iterator last):删除[first, last)之间元素

    size_type erase(const Key& key):删除元素值等于key的元素

[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <set>  
  3.   
  4. int main ()  
  5. {  
  6.   std::set<int> myset;  
  7.   std::set<int>::iterator it;  
  8.   std::pair<std::set<int>::iterator,bool> ret;  
  9.   
  10.   // set some initial values:  
  11.   for (int i=1; i<=5; ++i) myset.insert(i*10);    // set: 10 20 30 40 50  
  12.   
  13.   ret = myset.insert(20);               // no new element inserted  
  14.   
  15.   if (ret.second==false) it=ret.first;  // "it" now points to element 20  
  16.   
  17.   myset.insert (it,25);                 // max efficiency inserting  
  18.   myset.insert (it,24);                 // max efficiency inserting  
  19.   myset.insert (it,26);                 // no max efficiency inserting  
  20.   
  21.   int myints[]= {5,10,15};              // 10 already in set, not inserted  
  22.   myset.insert (myints,myints+3);  
  23.   
  24.   std::cout << "myset contains:";  
  25.   for (it=myset.begin(); it!=myset.end(); ++it)  
  26.     std::cout << ' ' << *it;  
  27.   std::cout << '\n';  
  28.   
  29.   return 0;  
  30. }  

[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <set>  
  3.   
  4. int main ()  
  5. {  
  6.   std::set<int> myset;  
  7.   std::set<int>::iterator it;  
  8.   
  9.   // insert some values:  
  10.   for (int i=1; i<10; i++) myset.insert(i*10);  // 10 20 30 40 50 60 70 80 90  
  11.   
  12.   it = myset.begin();  
  13.   ++it;                                         // "it" points now to 20  
  14.   
  15.   myset.erase (it);  
  16.   
  17.   myset.erase (40);  
  18.   
  19.   it = myset.find (60);  
  20.   myset.erase (it, myset.end());  
  21.   
  22.   std::cout << "myset contains:";  
  23.   for (it=myset.begin(); it!=myset.end(); ++it)  
  24.     std::cout << ' ' << *it;  
  25.   std::cout << '\n';  
  26.   
  27.   return 0;  
  28. }  


4)        遍历函数

     iterator begin():返回首元素的迭代器指针

    iterator end():返回尾元素的迭代器指针
    reverse_iterator rbegin():返回尾元素的逆向迭代器指针
    reverse_iterator rend():返回首元素前一个位置的迭代器指针

     

[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <set>  
  3.   
  4. int main ()  
  5. {  
  6.   int myints[] = {75,23,65,42,13};  
  7.   std::set<int> myset (myints,myints+5);  
  8.   
  9.   std::cout << "myset contains:";  
  10.   for (std::set<int>::iterator it=myset.begin(); it!=myset.end(); ++it)  
  11.     std::cout << ' ' << *it;  
  12.   
  13.   std::cout << '\n';  
  14.   
  15.   return 0;  
  16. }  

5)        操作函数

       const_iterator lower_bound(const Key& key):返回容器中大于等于key的迭代器指针

    const_iterator upper_bound(const Key& key):返回容器中大于key的迭代器指针

    int count(const Key& key) const:返回容器中元素等于key的元素的个数
    pair<const_iterator,const_iterator> equal_range(const Key& key) const:返回容器中元素值等于key的迭代指针[first, last)
    const_iterator find(const Key& key) const:查找功能,返回元素值等于key的迭代器指针
    void swap(set& s):交换集合元素
    void swap(multiset& s):交换多集合元素  

[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <set>  
  3.   
  4. int main ()  
  5. {  
  6.   std::set<int> myset;  
  7.   std::set<int>::iterator itlow,itup;  
  8.   
  9.   for (int i=1; i<10; i++) myset.insert(i*10); // 10 20 30 40 50 60 70 80 90  
  10.   
  11.   itlow=myset.lower_bound (30);                //       ^  
  12.   itup=myset.upper_bound (60);                 //                   ^  
  13.   
  14.   myset.erase(itlow,itup);                     // 10 20 70 80 90  
  15.   
  16.   std::cout << "myset contains:";  
  17.   for (std::set<int>::iterator it=myset.begin(); it!=myset.end(); ++it)  
  18.     std::cout << ' ' << *it;  
  19.   std::cout << '\n';  
  20.   
  21.   return 0;  
  22. }  
[cpp]  view plain  copy
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. #include <set>  
  4.   
  5. using namespace std;  
  6.   
  7. int main ()  
  8. {  
  9.     set<int> myset;  
  10.   
  11.     for (int i=1; i<=5; i++) myset.insert(i*10);   // myset: 10 20 30 40 50  
  12.   
  13.     pair<set<int>::const_iterator,set<int>::const_iterator> ret;  
  14.     ret = myset.equal_range(30);  
  15.   
  16.     cout << "the lower bound points to: " << *ret.first << '\n';  
  17.     cout << "the upper bound points to: " << *ret.second << '\n';  
  18.   
  19.     return 0;  
  20. }  

[cpp]  view plain  copy
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. #include <set>  
  4.   
  5. using namespace std;  
  6.   
  7. int main ()  
  8. {  
  9.     int myints[]={12,75,10,32,20,25};  
  10.     set<int> first (myints,myints+3);     // 10,12,75  
  11.     set<int> second (myints+3,myints+6);  // 20,25,32  
  12.   
  13.     first.swap(second);  
  14.   
  15.     cout << "first contains:";  
  16.     for (set<int>::iterator it=first.begin(); it!=first.end(); ++it)  
  17.         cout << ' ' << *it;  
  18.     cout << '\n';  
  19.   
  20.     cout << "second contains:";  
  21.     for (set<int>::iterator it=second.begin(); it!=second.end(); ++it)  
  22.         cout << ' ' << *it;  
  23.     cout << '\n';  
  24.   
  25.     return 0;  
  26. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值