【C++学习笔记】:set容器

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 在STL中,set是一种按照特定顺序存储唯一元素的容器容器。可以实现存储数据、检索数据等功能。

1、写在前面

大家好,今天文章的内容是:

  • Set容器

2、内容


2.1、介绍

在STL中,set是一种按照特定顺序存储唯一元素的容器容器。可以实现存储数据、检索数据等功能。

注意事项:

  • 不能直接修改set中的元素值,正确的做法是删除旧值,再插入更新后的值。
  • set中的数据元素具有唯一性,各个元素的值必须不同。
  • set中的元素被用作数据自动排序所依据的键值。也就是说,使用set容器存储的各个键值对,键key和值value是相等的。此时,根据key排序也就等同于根据value排序

2.2、set类

(1) 语法

set类的语法如下:

template <class T,
    class Traits = less<T>,
    class Allocator = allocator<T>>
class set

(2) 参数

Key

Key 指的是在set中存储的元素的数据类型

Traits

Traits 是一种提供函数对象的类型,该函数对象将两个元素值作为排序键进行比较,用于指定set中的排序规则;

备注:

  • Traits 属于可选参数
  • 默认值为less <T>,即升序。
  • 也可以设置为greater<T>,即降序。

Allocator

Allocator 是一种用于表示分配器对象的类型。

备注:

  • Allocator 是可选参数
  • 默认值为allocator<T>
  • 该分配器对象封装了set中的内存分配等信息;

2.3、创建set容器

(1) 导入头文件

因为set容器以类模板set<T>的形式定义在<set>头文件中,并位于std命名空间中。

所以我们在使用set容器之前需要导入以下代码:

#include <set>
using namespace std;

在导入头文件后,就可以使用set容器了。


(2) 举例一

创建一个int类型的set空容器s1,注意,这里是使用了默认的less<int>排序规则

代码:

#include <iostream>
#include <set>
using namespace std;

int main() {
    // 创建set 
    set <int> s1;
    // 此时插入三个元素 
    s1.insert(11);
    s1.insert(22);
    s1.insert(33);
    // 输出s1
    cout << "s1: ";
    for(int i : s1) {
        cout << i << " ";
    } 
    cout << '\n';
    return 0; 
}

运行结果:

s1: 11 22 33

(3) 举例二

创建set容器并用已有的容器进行初始化。

代码:

#include <iostream>
#include <set>
using namespace std;

int main() {
    // 创建set 
    set <int> s1;
    // 此时插入三个元素 
    s1.insert(11);
    s1.insert(22);
    s1.insert(33);
    // 复制 s1 
    set<int> s2(s1);
    // 插入新元素
    s2.insert(44); 
    // 输出s2
    cout << "s2: ";
    for(int i : s2) {
        cout << i << " ";
    } 
    cout << '\n';
    return 0; 
}

运行结果:

s2: 11 22 33 44

(4) 举例三

创建容器并用原有的容器的指定区间 $[first, last)$ 内的元素进行初始化。

注意:区间是左闭右开的。

代码:

#include <iostream>
#include <set>
using namespace std;

int main() {
    // 创建set 
    set <int> s1;
    // 此时插入四个元素 
    s1.insert(11);
    s1.insert(22);
    s1.insert(33);
    s1.insert(44);
    // 创建两个迭代器对象 first 和 last
    set <int>::const_iterator first, last;
    // first 指向容器第一个元素 
    first = s1.begin();
    // last 最后指向了容器的第三个元素 
    last = s1.begin();
    last++;
    last++; 
    // 创建set容器 s3 并使用 s1 指定区间 [first,last)上的元素进行初始化 
    set <int> s3(first, last);
    // 输出s3
    cout << "s3: ";
    for(int i : s3) {
        cout << i << " ";
    } 
    cout << '\n';
    return 0; 
}

运行结果:

s3: 11 22

(5) 举例四

在创建newSet容器并利用数组arr的指定区间中的元素来初始化容器。

代码:

#include <iostream>
#include <set>
using namespace std;

int main() {
    // 先创建一个数组
    int arr[]= {11,22,33,44,55};
    // 创建set容器并用数组中的指定区间进行初始化
    set<int> s4(arr, arr+3);
    // 输出s4
    cout << "s4: ";
    for(int i : s4) {
        cout << i << " ";
    } 
    cout << '\n';
    return 0; 
}

运行结果:

s4: 11 22 33

(6) 举例五

代码:

#include <iostream>
#include <set>
using namespace std;

struct classcomp {
  bool operator() (const int& lhs, const int& rhs) const {
    return lhs > rhs;
  }
};

int main () {
    // 创建set,并使用自定义的排序规则 
    set<int, classcomp> s5;
    // 此时插入三个元素 
    s5.insert(11);
    s5.insert(22);
    s5.insert(33);
    // 输出s5
    cout << "s5: ";
    for(int i : s5) {
        cout << i << " ";
    } 
    cout << '\n';
    return 0;
}

运行结果:

s5: 33 22 11

2.4、成员函数

set的成员函数有很多,这里记录几个常用的。


begin

begin()函数用于返回一个迭代器,指向set中的第一个元素的位置。

备注:

如果使用begin()函数后将返回值赋给了iterator,则可以修改set中的数据元素。但是,如果将begin()函数的返回值赋给const_iterator,则不能修改set中的数据元素。

举个例子:

#include <iostream>
#include <set>
using namespace std;

int main() {
    // 创建一个空的set容器 
    set<int> s1;
    // 插入三个元素 
    s1.insert(100);
    s1.insert(200);
    s1.insert(300);
    // begin()函数返回指向第一个元素的迭代器 
    set<int>::iterator s1_iter = s1.begin();
    // 输出
    cout << "set容器中的第一个数据元素为:" << *s1_iter << endl;
    return 0;
}

运行结果:

set容器中的第一个数据元素为:100

end

end()函数用于返回一个迭代器,指向set中最后一个元素的后一个位置。(注意,不是指向末尾元素)

备注:

  • 如果set是一个空容器,则此时set::end() == set::begin()
  • 使用end()函数,可以判断迭代器是否超过了set的末尾。

erase

erase()函数用于移除指定元素、移除指定位置的元素以及移除指定范围内的元素。

语法如下:

// 移除指定元素
size_type erase(const key_type& key);
// 移除指定位置的元素
iterator erase(const_iterator where);
// 移除指定范围内的元素
iterator erase(const_iterator first, const_iterator last);

举个例子:

#include <iostream>
#include <set>
using namespace std;

void printMySet(const set<int, greater<int>>& s) {
    cout << "[ ";
    for (const auto& iter : s) {
        cout << iter << " ";
    }
    cout<< "]" << endl;
}

int main() {
    // 创建一个容器,并使用降序规则
    set<int, greater<int>> s1;
    // 插入五个元素
    s1.insert(111);
    s1.insert(222);
    s1.insert(333);
    s1.insert(444);
    s1.insert(555);
    cout << "删除前set中的元素为:";
    printMySet(s1);
    s1.erase(333);
    cout << "删除后set中的元素为:";
    printMySet(s1);
    return 0;
}

运行结果:

删除前set中的元素为:[ 555 444 333 222 111 ]
删除后set中的元素为:[ 555 444 222 111 ]

find

find()函数用于从set容器中查找与指定键等效的数据元素,并返回一个迭代器指向其位置。

语法如下:

iterator find(const Key& key);
const_iterator find(const Key& key) const;

举个例子:

#include <iostream>
#include <set>
using namespace std;

void printMySet(const set<int>& s) {
    cout << "set容器中的元素为:[ ";
    for (const auto& iter : s) {
        cout << iter << " ";
    }
    cout<< "]" << endl;
}

void findVal(const set<int>& s, int value) {
    cout << "查找中..." << endl; 
    auto result = s.find(value);
    if(result == s.end()) {
        cout << "找不到指定元素 => (" << value << ")" << endl; 
    }else {
        cout << "已找到指定元素 => (" << value<< ")"<< endl; 
    }
}

int main() {
    // 创建一个空容器 
    set<int> s;
    // 插入五个元素 
    s.insert(111);
    s.insert(222);
    s.insert(333);
    s.insert(444);
    s.insert(555);
    // 打印容器信息 
    printMySet(s);
    // 查找元素 
    findVal(s, 666);
    findVal(s, 333);
    return 0; 
}

运行结果:

set容器中的元素为:[ 111 222 333 444 555 ]
查找中...
找不到指定元素 => (666)
查找中...
已找到指定元素 => (333)

insert

insert()函数可用于插入单个元素、若干个元素以及插入数组中的元素等。

举个例子:

#include<iostream>
#include<set>
#include<vector> 
using namespace std;

void printMySet(const set<int>& s) {
    cout << " 容器中的元素为:[ ";
    for (const auto& iter : s) {
        cout << iter << " ";
    }
    cout<< "]" << endl;
}

int main() {
    // 创建 s1
    set<int> s1;
    // 插入五个元素 (容器中的元素会自动按照一定的顺序排列)
    s1.insert({22, 55, 33, 11, 44});
    // 打印容器信息
    cout << "s1";
    printMySet(s1);
    
    // ==============================
    
    // 创建 s2
    set<int> s2;
    // 创建一个vector数组 
    vector<int> v;
    v.push_back(48);
    v.push_back(64);
    v.push_back(15);
    v.push_back(37);
    v.push_back(88);
    // 插入数组 
    s2.insert(v.begin(), v.end());
    // 打印容器信息
    cout << "s2";
    printMySet(s2);
    
    return 0; 
}

运行结果:

s1 容器中的元素为:[ 11 22 33 44 55 ]
s2 容器中的元素为:[ 15 37 48 64 88 ]

size

size()函数用于返回当前set中的元素个数。

语法如下:

size_type size() const;

举个例子:

#include <set>
#include <iostream>
using namespace std;

void printMySet(const set<int>& s) {
    cout << "容器中的元素为:[ ";
    for (const auto& iter : s) {
        cout << iter << " ";
    }
    cout << "]" << endl;
    cout << "size =  " << s.size() << '\n' <<  endl;
}

int main( ) {
    set<int>s;
    
    s.insert(100);
    printMySet(s);
    
    s.insert(600);
    printMySet(s);
    
    s.insert({400, 500, 300, 200});
    printMySet(s);
    return 0;
}

运行结果:

容器中的元素为:[ 100 ]
size =  1

容器中的元素为:[ 100 600 ]
size =  2

容器中的元素为:[ 100 200 300 400 500 600 ]
size =  6

2.5、小结:

对set容器小结:

  • set容器是一种关联式容器,支持使用键值来高效检索元素值,但需要注意到,set容器的键值就是它的元素值,即set是一种简单的关联式容器。
  • set容器是有序的,其元素在容器中是根据指定的比较函数按键值进行排序的。
  • set容器提供了双向迭代器来访问其元素。
  • set容器中的元素具有唯一性,即每个元素都具有唯一的键。

3、写在最后

好了,今天就先记录到这里,感谢观看。

目录
相关文章
|
1月前
|
存储 C++ 容器
【C++】map、set基本用法
本文介绍了C++ STL中的`map`和`set`两种关联容器。`map`用于存储键值对,每个键唯一;而`set`存储唯一元素,不包含值。两者均基于红黑树实现,支持高效的查找、插入和删除操作。文中详细列举了它们的构造方法、迭代器、容量检查、元素修改等常用接口,并简要对比了`map`与`set`的主要差异。此外,还介绍了允许重复元素的`multiset`和`multimap`。
30 3
【C++】map、set基本用法
|
1月前
|
存储 算法 C++
【C++】unordered_map(set)
C++中的`unordered`容器(如`std::unordered_set`、`std::unordered_map`)基于哈希表实现,提供高效的查找、插入和删除操作。哈希表通过哈希函数将元素映射到特定的“桶”中,每个桶可存储一个或多个元素,以处理哈希冲突。主要组成部分包括哈希表、哈希函数、冲突处理机制、负载因子和再散列,以及迭代器。哈希函数用于计算元素的哈希值,冲突通过开链法解决,负载因子控制哈希表的扩展。迭代器支持遍历容器中的元素。`unordered_map`和`unordered_set`的插入、查找和删除操作在理想情况下时间复杂度为O(1),但在冲突较多时可能退化为O(n)。
22 5
|
1月前
|
存储 C++ 容器
【C++】set模拟实现
C++中的`set`是STL提供的一种关联容器,用于存储唯一元素并自动按特定顺序(默认升序)排序。其内部通过红黑树实现,保证了高效的插入、删除和查找操作,时间复杂度均为O(log n)。`set`支持迭代器遍历,提供了良好的数据访问接口。
35 3
|
1月前
|
存储 设计模式 C++
【C++】优先级队列(容器适配器)
本文介绍了C++ STL中的线性容器及其适配器,包括栈、队列和优先队列的设计与实现。详细解析了`deque`的特点和存储结构,以及如何利用`deque`实现栈、队列和优先队列。通过自定义命名空间和类模板,展示了如何模拟实现这些容器适配器,重点讲解了优先队列的内部机制,如堆的构建与维护方法。
35 0
|
2月前
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
66 2
|
2月前
|
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容器编排
93 3
|
2月前
|
存储 C++ 容器
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器1
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
71 5
|
2月前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
83 2
|
3月前
|
存储 JSON NoSQL
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
这篇文章是关于Redis基本数据结构的学习笔记,包括了String、Hash、Set、List和SortedSet的介绍和常用命令。文章解释了每种数据结构的特点和使用场景,并通过命令示例演示了如何在Redis中操作这些数据结构。此外,还提供了一些练习示例,帮助读者更好地理解和应用这些数据结构。
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
|
2月前
|
设计模式 存储 C++
【C++】C++ STL探索:容器适配器 Stack 与 Queue 的使用及模拟实现(二)
【C++】C++ STL探索:容器适配器 Stack 与 Queue 的使用及模拟实现