C++:有序关联容器set

什么是有序关联容器

(1)顺序容器,容器中的元素是按它们在容器中的位置来顺序保存和访问的(可以理解是数组)
(2)顺序容器有array、vector、deque、list、forward_list、string等
(3)关联容器中的元素是按关键字来保存和访问的,关联的意思就是关键字(key)与存储值(value)的关联
(4)主要的关联容器类型是map和set
(5)关联容器支持高效的关键字查找和访问
(6)有序关联容器:容器内元素按顺序排列,一般用树(譬如红黑树)来实现
(7)无序关联容器:容器内元素无顺序排列,一般用哈希表来实现,本质上是一种映射

set的基本使用

(1)set的基本理解:就是一个用来装Key类型对象的筐子,数学上叫集合
(2)set的构造函数
(3)插入数据可以用insert,插入时内部自动排序,元素是唯一的
(4)查询set中元素个数用:empty、size,max_size是理论上的最大元素数
(5)清除全部元素用clear
(6)针对清除某个Key用erase,若erase的元素不存在则不报错

set的三种遍历方法

(1)使用ranged for

#include <iostream>  
#include <set>  
  
int main() {  
    std::set<int> mySet = {1, 2, 3, 4, 5};  
  
    for (int elem : mySet) {  
        std::cout << elem << " ";  
    }  
    std::cout << std::endl;  
  
    return 0;  
}

(2)使用迭代器写for循环


```c
#include <iostream>  
#include <set>  
  
int main() {  
    std::set<int> mySet = {1, 2, 3, 4, 5};  
  
    // 使用范围for循环遍历  
    for (int elem : mySet) {  
        std::cout << elem << " ";  
    }  
    std::cout << std::endl;  
  
    return 0;  
}
(3)使用std::for_each

```c
#include <iostream>  
#include <set>  
#include <algorithm>  
  
void printElement(int elem) {  
    std::cout << elem << " ";  
}  
  
int main() {  
    std::set<int> mySet = {1, 2, 3, 4, 5};  
  
    // 使用std::for_each遍历  
    std::for_each(mySet.begin(), mySet.end(), printElement);  
    std::cout << std::endl;  
  
    return 0;  
}

谓词可以是函数对象、函数、lambda表达式

set的原地构造

(1)set插入新元素一共有3个方法:insert、emplace、emplace_hint
(2)一般来说,emplace比insert效率更高,参考:http://c.biancheng.net/view/6834.html

在这里插入图片描述

移动构造

移动构造函数
(1)移动构造函数特征:传参是一个右值引用的对象(对比copy构造函数)
(2)右值引用的特征就是&&,
(3)右值引用对应移动语义,对应移动构造函数;而左值引用对应复制语义,对应复制构造函数
(4)移动语义就是直接把右值的临时对象给左值,而不是复制右值给左值重新构造一份
(5)移动构造函数可以避免不必要的深拷贝,这在很多时候可以提升效率
(6)此处案例,如果不提供移动构造函数,则会退而匹配调用拷贝构造函数,但不影响insert和emplace的对比

在这里插入图片描述

extract

std::set 引入了 extract 方法,该方法允许从 std::set 中移除一个元素,并返回一个包含该元素的 std::optional<std::set::node_type>。这个node_type 是一个指向 std::set 内部节点的指针,允许你以非破坏性的方式处理这个元素(例如,检查其内容或重新插入到另一个容器中)。如果容器为空或找不到元素,extract 将返回一个空的 std::optional。

#include <set>  
#include <optional>  
#include <iostream>  
  
int main() {  
    std::set<int> s = {1, 2, 3, 4, 5};  
  
    auto extracted = s.extract(3);  
    if (extracted) {  
        std::cout << "Extracted: " << extracted->value() << std::endl;  
  
        // 可以选择性地重新插入到另一个集合  
        // std::set<int> s2;  
        // s2.insert(std::move(extracted.value()));  
        // extracted = std::nullopt; // 必须显式重置extracted,因为node的所有权已转移  
    }  
  
    // s现在不再包含3  
    for (int x : s) {  
        std::cout << x << ' ';  
    }  
    std::cout << std::endl;  
  
    return 0;  
}
#include <iostream>  
#include <set>  
  
int main() {  
    // 创建一个空的set  
    std::set<int> mySet;  
  
    // 插入元素  
    mySet.insert(10);  
    mySet.insert(5);  
    mySet.insert(15);  
    mySet.insert(20);  
  
    // 遍历set(注意:set会自动排序)  
    std::cout << "遍历set(已排序):" << std::endl;  
    for (int elem : mySet) {  
        std::cout << elem << " ";  
    }  
    std::cout << std::endl;  
  
    // 查找元素  
    auto it = mySet.find(15);  
    if (it != mySet.end()) {  
        std::cout << "找到元素:" << *it << std::endl;  
    } else {  
        std::cout << "未找到元素" << std::endl;  
    }  
  
    // 删除元素  
    size_t num_erased = mySet.erase(10);  
    if (num_erased) {  
        std::cout << "删除元素10成功" << std::endl;  
    }  
  
    // 再次遍历set以查看删除效果  
    std::cout << "删除元素后再次遍历set:" << std::endl;  
    for (int elem : mySet) {  
        std::cout << elem << " ";  
    }  
    std::cout << std::endl;  
  
    // 获取set的大小  
    std::cout << "set的大小为:" << mySet.size() << std::endl;  
  
    // 清空set  
    mySet.clear();  
  
    // 检查set是否为空  
    if (mySet.empty()) {  
        std::cout << "set已清空" << std::endl;  
    }  
  
    return 0;  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

li星野

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值