• STL之set容器和multiset容器


    摘要:本文主要介绍了set容器和multiset容器的相关内容。

     1、基本概念

      set容器 multiset容器
    概念

    所有元素都会根据元素的键值自动被排序,

    元素即是键值又是实值,不允许两个元素

    有相同的键值,元素值不可以被改变

    multiset特性及用法和set完全相同,

    唯一的差别在于它允许键值重复

    实现

    set和multiset的底层实现是红黑树,红黑树为平衡二叉树的一种

    2、二叉树

    2.1 概念

    二叉树就是任何节点最多只允许有两个字节点。分别是左子结点和右子节点。

    2.2 二叉搜索树

    上面我们介绍了二叉搜索树,那么当一个二叉搜索树的左子树和右子树不平衡的时候,那么搜索依据上图表示,搜索9所花费的时间要比搜索17所花费的时间要多,由于我们的输入或者经过我们插入或者删除操作,二叉树失去平衡,造成搜索效率降低。

    所以我们有了一个平衡二叉树的概念,所谓的平衡不是指的完全平衡。

    RB-tree(红黑树)为二叉树的一种。

    3、常用API

      set multiset
      API 意义 API 意义
    构造函数  set<T> st  set默认构造函数  mulitset<T> mst  multiset默认构造函数
    set(const set &st) 拷贝构造函数         
    赋值操作  set& operator=(const set &st)  重载等号操作符
    swap(st) 交换两个集合容器
    大小操作  size()  返回容器中元素的数目
    empty() 判断容器是否为空
    插入和删除操作  insert(elem)
     在容器中插入元素
    clear() 清除所有元素
    erase(pos) 删除pos迭代器所指的元素,返回下一个元素的迭代器
    erase(beg, end) 删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器
    erase(elem) 删除容器中值为elem的元素
    查找操作  find(key)  查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end()
    count(key) 查找键key的元素个数
    lower_bound(keyElem) 返回第一个key>=keyElem元素的迭代器
    upper_bound(keyElem) 返回第一个key>keyElem元素的迭代器
    equal_range(keyElem) 返回容器中keykeyElem相等的上下限的两个迭代器

    4、对组

    对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个公有属性firstsecond访问。

    类模板:template <class T1, class T2> struct pair.创建对组的方式如下:

    第一种方法创建一个对组

    pair<stringint> pair1(string("name"), 20);

    cout << pair1.first << endl; //访问pair第一个值

    cout << pair1.second << endl;//访问pair第二个值

    第二种方法创建一个对组

    pair<stringint> pair2 = make_pair("name", 30);

           cout << pair2.first << endl;

          cout << pair2.second << endl;

    第二种方法pair=赋值

         pair<stringint> pair3 = pair2;

           cout << pair3.first << endl;

          cout << pair3.second << endl;

    5、代码示例

      1 #include<iostream>
      2 #include <set>
      3 #include <string>
      4 
      5 using namespace std;
      6 
      7 void printSet(set<int>&s) {
      8     for (set<int>::iterator it = s.begin(); it != s.end();it++) {
      9         cout << *it << " ";
     10     }
     11     cout << endl;
     12 }
     13 
     14 void test01() {   //定义容器、插入数据、判断是否为空,删除数据
     15     set<int>s;
     16     s.insert(10);   //set容器会自动将添加的数据进行排列,只能用insert
     17     s.insert(8);
     18     s.insert(11);
     19     s.insert(19);
     20     s.insert(2);
     21     printSet(s);
     22 
     23     if (s.empty())    //测试是否为空
     24     {
     25         cout << "容器为空" << endl;
     26     }
     27     else {
     28         cout << "容器不为空,且大小为:" <<s.size()<< endl;
     29     }
     30 
     31     s.erase(s.begin());  //指明删除数据的位置
     32     printSet(s);    
     33     s.erase(11);   //指明具体要删除的数据值
     34     printSet(s);
     35 }
     36 
     37 void test02(){  //进行数据查找
     38     set<int>s;
     39     s.insert(10);
     40     s.insert(8);
     41     s.insert(11);
     42     s.insert(19);
     43     s.insert(2);
     44 
     45     set<int>::iterator pos = s.find(2);  //类函数find返回值是迭代器
     46     if (pos!=s.end()) {
     47         cout << "数据存在,值为:" << *pos << endl;
     48     }
     49     else {
     50         cout << "数据不存在" << endl;
     51     }
     52 
     53     int num = s.count(2);
     54     cout << num << endl;   //输出相应的元素的个数,在set中,只有0和1
     55 
     56     //lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器
     57     set<int>::iterator it = s.lower_bound(10);  
     58     if (it != s.end())
     59     {
     60         cout << "找到了 lower_bound (10)的值为:" << *it << endl;
     61     }
     62     else
     63     {
     64         cout << "未找到" << endl;
     65     }
     66     // upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器
     67     set<int>::iterator it2 = s.upper_bound(10);
     68     if (it2 != s.end())
     69     {
     70         cout << "找到了 upper_bound (10)的值为:" << *it2 << endl;
     71     }
     72     else
     73     {
     74         cout << "未找到" << endl;
     75     }
     76     //equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器
     77     //上下限 就是lower_bound   upper_bound
     78     //注意这里用到了对组
     79     pair<set<int>::iterator, set<int>::iterator>  ret = s.equal_range(10);
     80     if (ret.first != s.end())   //第一个值
     81     {
     82         cout << "找到equal_range中 lower_bound 的值 :" << *(ret.first) << endl;
     83     }
     84     else
     85     {
     86         cout << "未找到" << endl;
     87     }
     88     if (ret.second != s.end())    //第二个值
     89     {
     90         cout << "找到equal_range中 upper_bound 的值 :" << *(ret.second) << endl;
     91     }
     92     else
     93     {
     94         cout << "未找到" << endl;
     95     }
     96 }
     97 
     98 void test03() {   //证明set容器不可以重复插入某一个键值
     99     set<int>s;
    100     pair<set<int>::iterator, bool>ret = s.insert(10); //第二个bool值可以反映是否插入成功
    101     if (ret.second)
    102     {
    103         cout << "插入成功" << endl;
    104     }
    105     else {
    106         cout << "插入失败" << endl;
    107     }
    108     ret = s.insert(10);
    109     if (ret.second)
    110     {
    111         cout << "第二次插入成功" << endl;
    112     }
    113     else
    114     {
    115         cout << "第二次插入失败" << endl;
    116     }
    117     printSet(s);
    118 
    119     //multiset允许插入重复值
    120     multiset<int> mul;
    121     mul.insert(10);
    122     mul.insert(10);
    123 }
    124 
    125 //指定set排序规则 从大到小
    126 //仿函数
    127 class myCompare
    128 {
    129 public:
    130     //重载 ()
    131     bool operator()(int v1, int v2)
    132     {
    133         return v1 > v2;
    134     }
    135 };
    136 //set容器的排序
    137 void test04()
    138 {
    139     set<int, myCompare>s1;
    140 
    141     s1.insert(5);
    142     s1.insert(1);
    143     s1.insert(9);
    144     s1.insert(3);
    145     s1.insert(7);
    146 
    147     //printSet(s1);
    148 
    149     //从大到小排序
    150     //在插入之前就指定排序规则
    151 
    152     for (set<int, myCompare>::iterator it = s1.begin(); it != s1.end(); it++)
    153     {
    154         cout << *it << " ";
    155     }
    156     cout << endl;
    157 }
    158 
    159 //自定义数据类型
    160 class Person
    161 {
    162 public:
    163     Person(string name, int age)
    164     {
    165         this->m_Name = name;
    166         this->m_Age = age;
    167     }
    168 
    169     string m_Name;
    170     int m_Age;
    171 };
    172 
    173 class myComparePerson
    174 {
    175 public:
    176     bool operator()(const Person & p1, const Person & p2)
    177     {
    178         if (p1.m_Age > p2.m_Age) //降序
    179         {
    180             return true;
    181         }
    182         return false;
    183     }
    184 
    185 };
    186 
    187 void test05()
    188 {
    189     set<Person, myComparePerson> s1;
    190 
    191     Person p1("大娃", 100);
    192     Person p2("二娃", 90);
    193     Person p3("六娃", 10);
    194     Person p4("爷爷", 1000);
    195 
    196     s1.insert(p1);
    197     s1.insert(p2);
    198     s1.insert(p3);
    199     s1.insert(p4);
    200 
    201     //插入自定义数据类型,上来就指定好排序规则
    202 
    203     //显示
    204     for (set<Person, myComparePerson>::iterator it = s1.begin(); it != s1.end(); it++)
    205     {
    206         cout << "姓名:" << (*it).m_Name << " 年龄: " << it->m_Age << endl;
    207     }
    208 
    209 }
    210 
    211 int main() {
    212     //test01();
    213     //test02();
    214     //test03();
    215     //test04();
    216     test05();
    217     system("pause");
    218     return 0;
    219 }
  • 相关阅读:
    2015年终总结
    拉格朗日插值编程实现
    dlib库使用
    semi-global matching 算法总结
    为什么有的程序在64位机上跑反而比32位机更慢
    编译并使用带有OpenCL模块的OpenCV for android SDK
    Android OpenGL ES 离屏渲染(offscreen render)
    Django的安装和项目的启动
    实现单例模式的几种方法
    基本数据结构----队列
  • 原文地址:https://www.cnblogs.com/lzy820260594/p/11391260.html
Copyright © 2020-2023  润新知