set 基本概念

set容器特点:

  1. 所有元素在插入时会自动被排序
  2. set属于关联式容器,底层结构通常为 二叉树
  3. set不允许容器中有重复元素

set 构造和赋值

  • set<T> st; // 默认构造函数

  • set(const set &st); // 拷贝构造函数

  • set& operator=(const set &st); // 重载等号操作符

  • 示例

    // set构造和赋值
    /**
     * set<T> st;                       // 默认构造函数
     * set(const set &st);              // 拷贝构造函数
     * set& operator=(const set &st);   // 重载等号操作符
     *
     * set容器特点:
     * 1. 所有元素在插入时会自动被排序
     * 2. set属于关联式容器,底层结构通常为二叉树
     * 3. set不允许容器中有重复元素
     */
    #include <iostream>
    #include <set>
    
    using namespace std;
    
    void print_set(const set<int>& s)
    {
        for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0()
    {
        // 1. 默认构造
        set<int> s1;
    
        // set容器只能通过insert插入元素
        // insert 
        s1.insert(10);
        s1.insert(20);
        s1.insert(30);
        // 插入重复元素,不会插入成功
        s1.insert(30);
        s1.insert(40);
        cout << "s1 = ";
        print_set(s1);
    
        // 2. 拷贝构造
        set<int> s2(s1);
        cout << "s2 = ";
        print_set(s2);
    
        // 3. 赋值
        set<int> s3;
        s3 = s1;
        cout << "s3 = ";
        print_set(s3);
    }
    
    int main()
    {
        test0();
        return 0;
    }
    
    

set 大小和交换

  • size(); // 返回容器中元素的数目

  • empty(); // 判断容器是否为空

  • swap(set); // 交换两个集合容器

  • 示例

    // set大小和交换
    /**
     * size();      // 返回容器中元素的数目
     * empty();     // 判断容器是否为空
     * swap(set);    // 交换两个集合容器
     */
    #include <iostream>
    #include <set>
    
    using namespace std;
    
    void print_set(const set<int>& s)
    {
        for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0()
    {
        set<int> s1;
    
        // 1. empty
        if (s1.empty())
        {
            cout << "s1 is empty" << endl;
        }
        else
        {
            cout << "s1 is not empty" << endl;
        }
        
        // insert
        s1.insert(10);
        s1.insert(20);
        s1.insert(30);
        s1.insert(40);
    
        // 2. size
        cout << "the size of s1 is: " << s1.size() << endl;
        cout << "s1 = ";
        print_set(s1);
    
        // 3. swap
        set<int> s2;
        s2.insert(100);
        s2.insert(200);
        s2.insert(300);
        s2.insert(400);
        cout << "s2 = ";
        print_set(s2);
    
        s1.swap(s2);
        cout << "after swap: " << endl;
        cout << "s1 = ";
        print_set(s1);
        cout << "s2 = ";
        print_set(s2);
    }
    
    int main()
    {
        test0();
        return 0;
    }
    
    

set 插入和删除

  • insert(elem); // 在容器中插入元素

  • erase(pos); // 删除pos迭代器所指的元素,返回下一个元素的迭代器

  • erase(beg, end); // 删除区间[beg, end)的所有元素,返回下一个元素的迭代器

  • erase(elem); // 删除容器中值为elem的元素

  • clear(); // 清除所有元素

  • 示例

    // set插入和删除
    /**
     * insert(elem);       // 在容器中插入元素
     * erase(pos);         // 删除pos迭代器所指的元素,返回下一个元素的迭代器
     * erase(beg, end);    // 删除区间[beg, end)的所有元素,返回下一个元素的迭代器
     * erase(elem);        // 删除容器中值为elem的元素
     * clear();            // 清除所有元素
     */
    #include <iostream>
    #include <set>
    
    using namespace std;
    
    void print_set(const set<int>& s)
    {
        for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0()
    {
        set<int> s1;
        // 1. insert
        s1.insert(10);
        s1.insert(20);
        s1.insert(30);
        s1.insert(40);
        s1.insert(50);
        cout << "s1 = ";
        print_set(s1);
    
        // 2. erase(pos)
        s1.erase(s1.begin());
        cout << "s1 = ";
        print_set(s1);
    
        // 3. erase(beg, end)
        s1.erase(--s1.end(), s1.end());
        cout << "s1 = ";
        print_set(s1);
    
        // 4. erase(elem)
        s1.erase(20);
        cout << "s1 = ";
        print_set(s1);
    
        // 5. clear
        s1.clear();
        cout << "s1 = ";
        print_set(s1);
    }
    
    int main()
    {
        test0();
        return 0;
    }
    
    

set 查找和统计

  • find(key); // 查找key是否存在,若存在返回该键的元素的迭代器,若不存在返回 set.end()

  • count(key); // 统计key的元素个数

  • 对于set容器,count(key)的结果只能是0或1,因为set不允许插入重复元素。

  • 示例

    // set查找和统计
    /**
     * find(key);      // 查找key是否存在,若存在返回该键的元素的迭代器,若不存在返回set.end()
     * count(key);     // 统计key的元素个数
     *
     * 对于set容器,count(key)的结果只能是0或1,因为set不允许插入重复元素。
     */
    #include <iostream>
    #include <set>
    
    using namespace std;
    
    void test0()
    {
        set<int> s1;
        s1.insert(10);
        s1.insert(20);
        s1.insert(30);
        s1.insert(40);
        s1.insert(50);
    
        // 1. find
        set<int>::iterator pos = s1.find(30);
        if (pos != s1.end())
        {
            cout << "find the element: " << *pos << endl;
        }
        else
        {
            cout << "not find the element" << endl;
        }
    
        set<int>::iterator pos2 = s1.find(300);
        if (pos2 != s1.end())
        {
            cout << "find the element: " << *pos2 << endl;
        }
        else
        {
            cout << "not find the element" << endl;
        }
        
    
        // 2. count
        int num = s1.count(30);
        cout << "the number of 30 is: " << num << endl;
    }
    
    int main()
    {
        test0();
        return 0;
    }
    
    

set 和multiset的区别

  • set不允许容器中有重复元素

    • set插入数据的同时会返回插入结果,表示插入是否成功
    • pair<set<T>::iterator, bool> ret = st.insert(elem);
    • pair用于表示一对值,在这里first表示插入的元素的迭代器,second表示插入是否成功
  • multiset允许容器中有重复元素

    • multiset不会检测数据是否重复,因此可以插入重复数据
  • 示例

    // set和multiset的区别
    /**
     * set不允许容器中有重复元素
     * multiset允许容器中有重复元素
     *
     * set插入数据的同时会返回插入结果,表示插入是否成功
     * pair<set<T>::iterator, bool> ret = st.insert(elem);
     * pair用于表示一对值,在这里first表示插入的元素的迭代器,second表示插入是否成功
     *
     * multiset不会检测数据是否重复,因此可以插入重复数据
     * multiset<T> mst;
     * mst.insert(elem);
     */
    #include <iostream>
    #include <set>
    
    using namespace std;
    
    void test0()
    {
        // set
        set<int> s1;
        s1.insert(10);
        s1.insert(20);
        
        pair<set<int>::iterator, bool> ret = s1.insert(20);
        if (ret.second)
        {
            cout << "insert success" << endl;
        }
        else
        {
            cout << "insert failed" << endl;
        }
    
        // print set
        for (set<int>::iterator it = s1.begin(); it != s1.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    
        // multiset
        multiset<int> ms1;
        ms1.insert(10);
        ms1.insert(20);
        ms1.insert(20);
        ms1.insert(20);
        
        // print multiset
        for (multiset<int>::iterator it = ms1.begin(); it != ms1.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    int main()
    {
        test0();
        return 0;
    }
    
    

set 中pair的创建

pair用于存储一对数据,通过first和second来分别访问

  • pair<T1, T2> p(value1, value2); // 方式一:通过构造函数创建pair

  • pair<T1, T2> p = make_pair(value1, value2); // 方式二:通过make_pair创建pair

  • pair.first // 获取第一个元素

  • pair.second // 获取第二个元素

  • 示例

    // pair的创建
    /**
     * pair<T1, T2> p(value1, value2);              // 方式一:通过构造函数创建pair
     * pair<T1, T2> p = make_pair(value1, value2);  // 方式二:通过make_pair创建pair
     * 
     * pair.first   // 获取第一个元素
     * pair.second  // 获取第二个元素
     */
    #include <iostream>
    #include <utility>
    
    using namespace std;
    
    void test0()
    {
        // 1.构造函数创建
        pair<string, int> p1("GG bond", 18);
        cout << "p1.first = " << p1.first << ", p1.second = " << p1.second << endl;
    
        // 2. make_pair创建
        pair<string, int> p2 = make_pair("Xi Yangyang", 88);
        cout << "p2.first = " << p2.first << ", p2.second = " << p2.second << endl;
    }
    
    int main()
    {
        test0();
        return 0;
    }
    
    

set 指定排序规则

  1. 内置类型

    1. 和sort函数一样,set已经包含了对内置类型的比较函数(这里是仿函数),实现升序效果
    2. 可以提供仿函数来实现降序效果
    • 仿函数语法示例

      class my_compare
      {
      public:
          bool operator()(int v1, int v2) const
          {
              return v1 > v2; // 降序
          }
      };
      
      set<int, my_compare> st; // 对内置数据类型指定排序规则
      
    • 示例

      // set指定排序规则 - 内置类型
      /**
       * set<T, Compare> st;     // 创建set容器时指定排序规则
       *
       * 仿函数示例:
       * class my_compare
       * {
       * public:
       *     bool operator()(int v1, int v2) const
       *     {
       *         return v1 > v2; // 降序
       *     }
       * };
       *
       * set<int, my_compare> st; // 对内置数据类型指定排序规则
       */
      #include <iostream>
      #include <set>
      
      using namespace std;
      
      // 仿函数
      class my_compare
      {
      public:
          bool operator()(int v1, int v2) const
          {
              return v1 > v2; // 降序
          }
      };
      
      void print_set(const set<int, my_compare>& s)
      {
          for (set<int, my_compare>::const_iterator it = s.begin(); it != s.end(); it++)
          {
              cout << *it << " ";
          }
          cout << endl;
      }
      
      void test0()
      {
          // 在创建时就要指定排序规则
          set<int, my_compare> s1;
          s1.insert(10);
          s1.insert(20);
          s1.insert(30);
          s1.insert(40);
          s1.insert(50);
          
          cout << "s1 = ";
          print_set(s1);
      }
      
      int main()
      {
          test0();
          return 0;
      }
      
      
  2. 自定义类型

    1. 对于自定义数据类型,set必须指定排序规则才可以插入数据
    2. 如果不提供排序规则,编译器会报错,因为无法比较自定义类型
    • 仿函数语法示例

      class compare_person
      {
      public:
          bool operator()(const person &p1, const person &p2) const
          {
              return p1.m_age > p2.m_age; // 按年龄降序
          }
      };
      
      set<person, compare_person> st; // 对自定义数据类型指定排序规则
      
    • 示例

      // set指定排序规则 - 自定义类型
      /**
       * 对于自定义数据类型,set必须指定排序规则才可以插入数据
       * 如果不提供排序规则,编译器会报错,因为无法比较自定义类型
       *
       * 自定义排序规则示例:
       * class compare_person
       * {
       * public:
       *     bool operator()(const person &p1, const person &p2) const
       *     {
       *         return p1.m_age > p2.m_age; // 按年龄降序
       *     }
       * };
       *
       * set<person, compare_person> st; // 对自定义数据类型指定排序规则
       */
      #include <iostream>
      #include <set>
      
      using namespace std;
      
      // 自定义类型
      class person
      {
      public:
          person(string name, int age) : name_(name), age_(age) {}
      
          string name_;
          int age_;
      };
      
      // 仿函数
      class compare_person
      {
      public:
          bool operator()(const person &p1, const person &p2) const
          {
              return p1.age_ > p2.age_;  // 年龄降序
          }
      };
      
      void test0()
      {
          set<person, compare_person> s1;
          s1.insert(person("GG bond", 12));
          s1.insert(person("Mask",    50));
          s1.insert(person("Lei Jun", 45));
      
          // print
          for (set<person, compare_person>::const_iterator it = s1.begin(); it != s1.end(); it++)
          {
              cout << (*it).name_ << " " << (*it).age_ << endl;
          }
      }
      
      int main()
      {
          test0();
          return 0;
      }
      
      

更多推荐