zoukankan      html  css  js  c++  java
  • C++中 set(集合容器)的用法

    set集合容器:

      实现了红黑树(Red-Black Tree)的平衡二叉检索树的数据结构,在插入元素时,

    它会自动调整二叉树的排列,把该元素放到适当的位置,以确保每个子树根节点的键值大于左子树所有节点的键值,

    而小于右子树所有节点的键值;另外,还得确保根节点的左子树的高度与有字数的高度相等,

    这样,二叉树的高度最小,从而检索速度最快。要注意的是,它不会重复插入相同键值的元素,而采取忽略处理。

      平衡二叉检索树的检索使用中序遍历算法,检索效率高于vector、deque、和list的容器。

    另外,采用中序遍历算法可将键值由小到大遍历出来,所以,可以理解为平衡二叉检索树在插入元素时,

    就会自动将元素按键值从小到大的顺序排列。

         构造set集合的主要目的是为了快速检索,使用set前,需要在程序头文件中包含声明“#include<set>”。

     

    c++ stl集合(Set):

      是一种包含已排序对象的关联容器。set/multiset会根据待定的排序准则,

      自动将元素排序。两者不同在于前者不允许元素重复,而后者允许。

      1) 不能直接改变元素值,因为那样会打乱原本正确的顺序,要改变元素值必须先删除旧元素,则插入新元素

      2) 不提供直接存取元素的任何操作函数,只能通过迭代器进行间接存取,而且从迭代器角度来看,元素值是常数

      3) 元素比较动作只能用于型别相同的容器(即元素和排序准则必须相同)

    set的各成员函数列表如下:

    begin()--返回指向第一个元素的迭代器

     clear()--清除所有元素

     count()--返回某个值元素的个数

     empty()--如果集合为空,返回true

     end()--返回指向最后一个元素的迭代器

     equal_range()--返回集合中与给定值相等的上下限的两个迭代器

     erase()--删除集合中的元素

     find()--返回一个指向被查找到元素的迭代器

     get_allocator()--返回集合的分配器

     insert()--在集合中插入元素

     lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器

     key_comp()--返回一个用于元素间值比较的函数

     max_size()--返回集合能容纳的元素的最大限值

     rbegin()--返回指向集合中最后一个元素的反向迭代器

     rend()--返回指向集合中第一个元素的反向迭代器

     size()--集合中元素的数目

     swap()--交换两个集合变量

     upper_bound()--返回大于某个值元素的迭代器

     value_comp()--返回一个用于比较元素间的值的函数

    1.创建set集合对象

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

    1 #include<iostream>  
    2 #include<set>  
    3 using namespace std;  
    4 int main()  
    5 {  
    6     set<int> s;  
    7     return 0;  
    8 } 

    2.元素的插入与中序遍历

            采用inset()方法把元素插入到集合中,插入规则在默认的比较规则下,

    是按元素值从小到大插入,如果自己指定了比较规则函数,则按自定义比较规则函数插入。

    使用前向迭代器对集合中序遍历,结果正好是元素排序后的结果。

     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()两个方法,它们分别给出了反向遍历的开始位置和结束位置。

     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.元素的删除

            与插入元素的处理一样,集合具有高效的删除处理功能,并自动重新调整内部的红黑树的平衡。

        删除的对象可以是某个迭代器位置上的元素、等于某键值的元素、一个区间上的元素和清空集合。

     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()。

     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 */  

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

     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
    ");  
    13         else  
    14             printf("exist
    ");  
    15     }  
    16     return 0;  
    17 }  

    6.自定义比较函数

             使用insert将元素插入到集合中去的时候,集合会根据设定的比较函数奖该元素放到该放的节点上去。

    在定义集合的时候,如果没有指定比较函数,那么采用默认的比较函数,即按键值从小到大的顺序插入元素。

    但在很多情况下,需要自己编写比较函数。

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

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

     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)如果元素是结构体,那么可以直接把比较函数写在结构体内。

     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 */  

     

  • 相关阅读:
    Linxu 挂载光盘和硬盘
    Linux firewall
    指纹获取 Fingerprint2
    Vue 封装的组件生命周期钩子
    vue富文本编辑,编辑自动预览,单个图片上传不能预览的问题解决:
    vue 集成百度富文本编辑器
    axios 的二次封装
    element 列表中已选的标记
    element 表单的input循环生成,并可单个input失去焦点单个验证并保存; (多个表单实例)
    axios 二进制流导出
  • 原文地址:https://www.cnblogs.com/yoke/p/6867302.html
Copyright © 2011-2022 走看看