C++之set/multiset容器

简介: C++之set/multiset容器

一、概念

set/multiset:所有元素都会在插入时自动排序,自定义数据类型构造时,需要指定排序规则。

二、构造与赋值

 //遍历输出
void printSet(const set<int> &s) {
    for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}
 
//set容器构造和赋值
void test01() {
    set<int> s1;
 
    //插入数据 只有insert方式
    s1.insert(10);
    s1.insert(30);
    s1.insert(50);
    s1.insert(30);
    s1.insert(40);
    s1.insert(20);
    // set容器特点,所有元素插入时候自动排序,不允许插入重复数据
    printSet(s1);
    // 拷贝构造
    set<int> s2(s1);
    printSet(s2);
    // 赋值
    set<int> s3;
    s3 = s2;
    printSet(s3);
}
 

三、大小与交换

//set的大小与交换
void test02() {
    set<int> s1;
    set<int> s2;
    s1.insert(1);
    s1.insert(2);
    s1.insert(3);
    s2.insert(100);
    s2.insert(200);
    s2.insert(300);
    cout << "s1大小:" << s1.size() << endl;
    cout << "s1是否为空:" << s1.empty() << endl;
    cout << "交换前:" << endl;
    printSet(s1);
    printSet(s2);
    s1.swap(s2);
    cout << "交换后:" << endl;
    printSet(s1);
    printSet(s2);
}

四、插入与删除

//set的插入和删除
void test03() {
    set<int> s1;
    s1.insert(10);
    s1.insert(30);
    s1.insert(50);
    s1.insert(30);
    s1.insert(40);
    s1.insert(20);
    // 遍历
    printSet(s1);
    // 删除
    s1.erase(s1.begin());
    printSet(s1);
    // 删除一个值
    s1.erase(30);
    printSet(s1);
    // 删除一个区间
    s1.erase(s1.begin(), s1.end());
    // 清空
    s1.clear();
    printSet(s1);
}

五、查找与统计

//set查找和统计
void test04() {
    set<int> s1;
    s1.insert(10);
    s1.insert(30);
    s1.insert(50);
    s1.insert(30);
    s1.insert(40);
    s1.insert(20);
    printSet(s1);
    set<int>::iterator it = s1.find(10);
    if (it != s1.end()) {
        cout << "存在元素" << *it << endl;
    } else {
        cout << "不存在元素" << endl;
    }
    cout << "统计 20 出现的次数" << s1.count(20) << endl;
    cout << "统计 200 出现的次数" << s1.count(200) << endl;
}


六、set与multiset区别

set不可以插入重复数据,而multiset可以;

set插入数据的同时会返回插入结果,表示插入是否成功;

multiset不会检测数据,因此可以插入重复数据;

//set和multiset区别
void test05() {
    set<int> s1;
    //接收set插入返回的数据
    pair<set<int>::iterator, bool> ret = s1.insert(10);
    if (ret.second) {
        cout << "第一次插入成功" << endl;
    } else {
        cout << "第一次插入失败" << endl;
    }
    pair<set<int>::iterator, bool> ret2 = s1.insert(10);
    if (ret2.second) {
        cout << "第二次插入成功" << endl;
    } else {
        cout << "第二次插入失败" << endl;
    }
 
    multiset<int> mus1;
    //接收set插入返回的数据
    mus1.insert(10);
    mus1.insert(10);
    mus1.insert(10);
    cout << mus1.size() << endl;
}

七、pair对组创建

//pair对组创建 成对出现的数据,利用对组可以返回两个数据
void test06() {
    pair<string, int> p("tom", 20);
    cout << p.first << " " << p.second << endl;
 
    pair<string, int> p2 = make_pair("jerry", 10);
    cout << p2.first << " " << p2.second << endl;
 
}

八、set容器排序

1、内置数据

//内置数据,修改排序规则
class MyCompare {
public:
    // 仿函数,重载()
    bool operator()(int v1, int v2) const {
        return v1 > v2;
    }
};
 
void test07() {
    set<int> s1;
    s1.insert(1);
    s1.insert(2);
    s1.insert(3);
    s1.insert(4);
    s1.insert(5);
    printSet(s1);
 
    // 自定义排序规则
    set<int, MyCompare> s2;
    s2.insert(1);
    s2.insert(2);
    s2.insert(3);
    s2.insert(4);
    s2.insert(5);
    for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
 
 
}

2、自定义数据

//自定义类型数据,指定排序规则
class Person {
public:
    Person(string name, int age) {
        this->m_Name = name;
        this->m_Age = age;
    }
 
    string m_Name;
    int m_Age;
};
 
class MyCompareT {
public:
    // 仿函数,重载()
    bool operator()(const Person &v1, const Person &v2) const {
        return v1.m_Age < v2.m_Age;
    }
};
 
void test08() {
    // 自定义的数据类型,都会指定排序规则
    set<Person, MyCompareT> s1;
    Person p1("刘备", 35);
    Person p2("曹操", 45);
    Person p3("孙权", 40);
    Person p4("赵云", 25);
    Person p5("张飞", 35);
    Person p6("关羽", 35);
    s1.insert(p1);
    s1.insert(p2);
    s1.insert(p3);
    s1.insert(p4);
    s1.insert(p5);
    s1.insert(p6);
    for (set<Person, MyCompareT>::iterator it = s1.begin(); it != s1.end(); it++) {
        cout << "姓名:" << (*it).m_Name << " 年龄:" << (*it).m_Age << endl;
    }
}

九、全部代码

#include <iostream>
#include <set>
#include <string>
 
using namespace std;
 
//遍历输出
void printSet(const set<int> &s) {
    for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}
 
//set容器构造和赋值
void test01() {
    set<int> s1;
 
    //插入数据 只有insert方式
    s1.insert(10);
    s1.insert(30);
    s1.insert(50);
    s1.insert(30);
    s1.insert(40);
    s1.insert(20);
    // set容器特点,所有元素插入时候自动排序,不允许插入重复数据
    printSet(s1);
    // 拷贝构造
    set<int> s2(s1);
    printSet(s2);
    // 赋值
    set<int> s3;
    s3 = s2;
    printSet(s3);
}
 
//set的大小与交换
void test02() {
    set<int> s1;
    set<int> s2;
    s1.insert(1);
    s1.insert(2);
    s1.insert(3);
    s2.insert(100);
    s2.insert(200);
    s2.insert(300);
    cout << "s1大小:" << s1.size() << endl;
    cout << "s1是否为空:" << s1.empty() << endl;
    cout << "交换前:" << endl;
    printSet(s1);
    printSet(s2);
    s1.swap(s2);
    cout << "交换后:" << endl;
    printSet(s1);
    printSet(s2);
}
 
//set的插入和删除
void test03() {
    set<int> s1;
    s1.insert(10);
    s1.insert(30);
    s1.insert(50);
    s1.insert(30);
    s1.insert(40);
    s1.insert(20);
    // 遍历
    printSet(s1);
    // 删除
    s1.erase(s1.begin());
    printSet(s1);
    // 删除一个值
    s1.erase(30);
    printSet(s1);
    // 删除一个区间
    s1.erase(s1.begin(), s1.end());
    // 清空
    s1.clear();
    printSet(s1);
}
 
//set查找和统计
void test04() {
    set<int> s1;
    s1.insert(10);
    s1.insert(30);
    s1.insert(50);
    s1.insert(30);
    s1.insert(40);
    s1.insert(20);
    printSet(s1);
    set<int>::iterator it = s1.find(10);
    if (it != s1.end()) {
        cout << "存在元素" << *it << endl;
    } else {
        cout << "不存在元素" << endl;
    }
    cout << "统计 20 出现的次数" << s1.count(20) << endl;
    cout << "统计 200 出现的次数" << s1.count(200) << endl;
}
 
//set和multiset区别
void test05() {
    set<int> s1;
    //接收set插入返回的数据
    pair<set<int>::iterator, bool> ret = s1.insert(10);
    if (ret.second) {
        cout << "第一次插入成功" << endl;
    } else {
        cout << "第一次插入失败" << endl;
    }
    pair<set<int>::iterator, bool> ret2 = s1.insert(10);
    if (ret2.second) {
        cout << "第二次插入成功" << endl;
    } else {
        cout << "第二次插入失败" << endl;
    }
 
    multiset<int> mus1;
    //接收set插入返回的数据
    mus1.insert(10);
    mus1.insert(10);
    mus1.insert(10);
    cout << mus1.size() << endl;
}
 
//pair对组创建 成对出现的数据,利用对组可以返回两个数据
void test06() {
    pair<string, int> p("tom", 20);
    cout << p.first << " " << p.second << endl;
 
    pair<string, int> p2 = make_pair("jerry", 10);
    cout << p2.first << " " << p2.second << endl;
 
}
 
//内置数据,修改排序规则
class MyCompare {
public:
    // 仿函数,重载()
    bool operator()(int v1, int v2) const {
        return v1 > v2;
    }
};
 
void test07() {
    set<int> s1;
    s1.insert(1);
    s1.insert(2);
    s1.insert(3);
    s1.insert(4);
    s1.insert(5);
    printSet(s1);
 
    // 自定义排序规则
    set<int, MyCompare> s2;
    s2.insert(1);
    s2.insert(2);
    s2.insert(3);
    s2.insert(4);
    s2.insert(5);
    for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
 
 
}
 
//自定义类型数据,指定排序规则
class Person {
public:
    Person(string name, int age) {
        this->m_Name = name;
        this->m_Age = age;
    }
 
    string m_Name;
    int m_Age;
};
 
class MyCompareT {
public:
    // 仿函数,重载()
    bool operator()(const Person &v1, const Person &v2) const {
        return v1.m_Age < v2.m_Age;
    }
};
 
void test08() {
    // 自定义的数据类型,都会指定排序规则
    set<Person, MyCompareT> s1;
    Person p1("刘备", 35);
    Person p2("曹操", 45);
    Person p3("孙权", 40);
    Person p4("赵云", 25);
    Person p5("张飞", 35);
    Person p6("关羽", 35);
    s1.insert(p1);
    s1.insert(p2);
    s1.insert(p3);
    s1.insert(p4);
    s1.insert(p5);
    s1.insert(p6);
    for (set<Person, MyCompareT>::iterator it = s1.begin(); it != s1.end(); it++) {
        cout << "姓名:" << (*it).m_Name << " 年龄:" << (*it).m_Age << endl;
    }
}
 
int main() {
    // test01();
    // test02();
    // test03();
    // test04();
    // test05();
    // test06();
    // test07();
    test08();
    system("pause");
    return 0;
}
 

相关文章
|
6月前
|
编译器 C++ 容器
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
163 2
|
3月前
|
存储 编译器 容器
set、map、multiset、multimap的介绍及使用以及区别,注意事项
set是按照一定次序存储元素的容器,使用set的迭代器遍历set中的元素,可以得到有序序列。set当中存储元素的value都是唯一的,不可以重复,因此可以使用set进行去重。set默认是升序的,但是其内部默认不是按照大于比较,而是按照小于比较。set中的元素不能被修改,因为set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树。
179 0
|
7月前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
6月前
|
存储 算法 C++
【c++丨STL】set/multiset的使用
本文深入解析了STL中的`set`和`multiset`容器,二者均为关联式容器,底层基于红黑树实现。`set`支持唯一性元素存储并自动排序,适用于高效查找场景;`multiset`允许重复元素。两者均具备O(logN)的插入、删除与查找复杂度。文章详细介绍了构造函数、迭代器、容量接口、增删操作(如`insert`、`erase`)、查找统计(如`find`、`count`)及`multiset`特有的区间操作(如`lower_bound`、`upper_bound`、`equal_range`)。最后预告了`map`容器的学习,其作为键值对存储的关联式容器,同样基于红黑树,具有高效操作特性。
239 3
|
10月前
|
存储 C++ 容器
【C++】map、set基本用法
本文介绍了C++ STL中的`map`和`set`两种关联容器。`map`用于存储键值对,每个键唯一;而`set`存储唯一元素,不包含值。两者均基于红黑树实现,支持高效的查找、插入和删除操作。文中详细列举了它们的构造方法、迭代器、容量检查、元素修改等常用接口,并简要对比了`map`与`set`的主要差异。此外,还介绍了允许重复元素的`multiset`和`multimap`。
223 3
【C++】map、set基本用法
|
10月前
|
存储 算法 C++
【C++】unordered_map(set)
C++中的`unordered`容器(如`std::unordered_set`、`std::unordered_map`)基于哈希表实现,提供高效的查找、插入和删除操作。哈希表通过哈希函数将元素映射到特定的“桶”中,每个桶可存储一个或多个元素,以处理哈希冲突。主要组成部分包括哈希表、哈希函数、冲突处理机制、负载因子和再散列,以及迭代器。哈希函数用于计算元素的哈希值,冲突通过开链法解决,负载因子控制哈希表的扩展。迭代器支持遍历容器中的元素。`unordered_map`和`unordered_set`的插入、查找和删除操作在理想情况下时间复杂度为O(1),但在冲突较多时可能退化为O(n)。
168 5
|
10月前
|
存储 C++ 容器
【C++】set模拟实现
C++中的`set`是STL提供的一种关联容器,用于存储唯一元素并自动按特定顺序(默认升序)排序。其内部通过红黑树实现,保证了高效的插入、删除和查找操作,时间复杂度均为O(log n)。`set`支持迭代器遍历,提供了良好的数据访问接口。
143 3
|
10月前
|
存储 设计模式 C++
【C++】优先级队列(容器适配器)
本文介绍了C++ STL中的线性容器及其适配器,包括栈、队列和优先队列的设计与实现。详细解析了`deque`的特点和存储结构,以及如何利用`deque`实现栈、队列和优先队列。通过自定义命名空间和类模板,展示了如何模拟实现这些容器适配器,重点讲解了优先队列的内部机制,如堆的构建与维护方法。
143 0
|
11月前
|
Kubernetes Cloud Native 流计算
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
289 3
|
11月前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
180 2