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;
}

 

posted @ 2017-01-19 15:37  MetalSteel  阅读(887)  评论(0编辑  收藏  举报