zoukankan      html  css  js  c++  java
  • STL关联式容器之set和multiset

    一,set和multiset的基础知识

    1.set和multiset的基础

    • set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按照一定的顺序排列,元素插入过程是按照排序规则插入的。所以不能指定插入元素的位置。
    • set的底层数据结构是红黑二叉树,红黑树属于平衡二叉树。在插入操作和删除操作比vector快。
    • set不可以直接存取元素,即不能使用像序列式容器中(vector,deque)那样随机存取。
    • multiset和set的区别在于set支持元素唯一,而multiset允许插入多个重复的元素。
    • 不可以直接修改set和multiset容器中的元素值,因为该类容器是自动排序的,如果想要修改某个元素的值,需要先删除该元素,然后再重新插入新的元素。
    • 要使用set或者multiset要引入的头文件是# include<set>。

    2.函数对象的基础知识

      set集合默认是从小到大的顺序排序的,如果我们存储的是学生类,想要自定义排序,那么STL提供了函数对象这个概念,所谓的函数对象就是重载了结构体的()操作符。然后返回结果是bool类型。

    二,set和multiset的代码示例

    1.set和multiset的基本比较

    # include<iostream>
    # include<set>
    # include<string>
    
    using namespace std;
    
    int main01()
    {
        // 定义set集合
        set<string> s1;
        // 定义multiset集合
        multiset<string> s2;
        
        // 往set集合中插入元素,其返回结果是一个pair,包含插入进去后的迭代器以及是否插入成功的标志
        pair<set<string>::iterator, bool> p1 =  s1.insert("Hello");
        cout << *p1.first << "," << p1.second << endl;
        // 我们发现往set集合中插入相同的元素会插入不成功
        pair<set<string>::iterator, bool> p2 = s1.insert("Hello");
        cout << *p2.first << "," << p2.second << endl;
        // 遍历
        for (string tmp : s1)
        {
            cout << tmp << endl;
        }
        // 我们往multiset集合中插入元素
        s2.insert("Hello");
        s2.insert("Hello");
        for (string tmp : s2)
        {
            cout << tmp << endl;
        }
    
        return 0;
    }

    2.set集合的遍历

    # include<iostream>
    # include<string>
    # include<set>
    using namespace std;
    
    int main02()
    {
        // 定义集合
        set<string> s;
        // 插入集合
        s.insert("Hello");
        s.insert("world");
        s.insert("C++");
        // 增强for遍历
        for (string tmp : s)
        {
            cout << tmp << " ";
        }
        cout << endl;
        // 迭代器正向遍历
        for (set<string>::iterator it = s.begin(); it != s.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
        // 迭代器逆向遍历
        for (set<string>::reverse_iterator it = s.rbegin(); it != s.rend(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    
        return 0;
    }

    3.set集合的删除

    # include<iostream>
    # include<set>
    # include<string>
    
    using namespace std;
    
    int main03()
    {
        // 创建集合
        set<string> s;
        // 插入元素
        s.insert("Hello");
        s.insert("World");
        s.insert("Unreal");
        s.insert("C++");
        // 删除元素World
        for (set<string>::iterator it = s.begin(); it != s.end();)
        {
            if (*it == "World")
            {
                it = s.erase(it);
            }
            else {
                it++;
            }
        }
        // 输出集合的长度
        int size1 = s.size();
        cout << "size1 = " << size1 << endl;
        // 遍历元素删除
        set<string>::iterator it = s.begin();
        while (!s.empty())
        {
            cout << *it << endl;
            it = s.erase(it);
        }
        // 输出集合的长度
        int size2 = s.size();
        cout << "size = " << size2 << endl;
    
        return 0;
    }

    4.set常用的函数

    # include<iostream>
    # include<set>
    # include<string>
    
    using namespace std;
    
    int main04()
    {
        // set集合默认是从小到大排序的
        set<int> s;
        // 插入元素
        s.insert(3);
        s.insert(2);
        s.insert(0);
        s.insert(1);
        // 遍历元素
        for (int tmp : s)
        {
            cout << tmp << " ";
        }
        cout << endl;
        // 统计元素出现的次数
        int cs = s.count(0);
        cout << "cs = " << cs << endl;
        // 查找元素为2的迭代器
        set<int>::iterator it = s.find(2);
        cout << *it << endl;
    
        return 0;
    }

    5.自定义函数对象实现对学生类的排序

    # include<iostream>
    # include<string>
    # include<set>
    using namespace std;
    /*
        定义学生类,按照其年龄进行排序
    */
    class Student
    {
    public:
        string name;
        int age;
    public:
        Student(string name, int age)
        {
            this->name = name;
            this->age = age;
        }
    };
    /* 
        定义函数对象:所谓的函数对象,就是重载了()操作符的结构体
    */
    struct StudentFunctor
    {
        bool operator()(const Student& stu1,const Student& stu2)
        {
            // 如果是>则是从大到小排序,如果是<则是从小到大排序
            return stu1.age > stu2.age;
        }
    };
    
    
    int main()
    {
        // 定义学生集合
        set<Student,StudentFunctor> s;
        // 插入学生
        s.insert(Student("张飞",34));
        s.insert(Student("关羽", 45));
        s.insert(Student("赵云", 30));
        s.insert(Student("马超", 21));
        // 打印学生
        for (Student stu : s)
        {
            cout << stu.name << " = " << stu.age << endl;
        }
    
        return 0;
    }
  • 相关阅读:
    python 中: lambda
    python 学习 argparse
    深度学习 ——style reconstruction
    简单linux命令1
    intptr_t 指针
    MySQL数据库基本命令-1
    交换机和路由器的区别
    UML图的使用
    操作系统总结链接
    操作系统总结
  • 原文地址:https://www.cnblogs.com/metalsteel/p/6306863.html
Copyright © 2011-2022 走看看