Let’s Make C++ Great Again——multiset与unordered_set

2023-10-27

multiset

multiset 是 C++ STL 中的关联式容器之一,它提供了一种将元素按照一定的排序方式进行存储的方法,允许重复的元素存在。multiset 内部实现使用红黑树数据结构,因此查找和插入元素的时间复杂度都是对数级别。

以下是 multiset 的基本用法:

头文件

要使用 multiset,首先需要包含头文件 :

#include <set>

定义和插入元素

定义 multiset 很简单,可以使用以下语法:

multiset<value_type> my_set;

其中,value_type 是元素的类型。例如,定义一个存储整数的 multiset:

multiset<int> my_set;

可以使用 insert() 函数向 multiset 中插入元素:

my_set.insert(3);
my_set.insert(2);
my_set.insert(4);
my_set.insert(3);

访问元素

multiset 不支持使用下标运算符访问元素。可以使用 find() 函数查找指定元素,如果存在,则返回指向该元素的迭代器;如果不存在,则返回 end() 迭代器:

auto it = my_set.find(3);
if (it != my_set.end()) {
    int n = *it;
}

也可以使用 count() 函数查找指定元素的数量:

int n = my_set.count(3);

遍历元素

可以使用 for 循环遍历 multiset 中的元素:

for (const auto& x : my_set) {
    cout << x << endl;
}

删除元素

可以使用 erase() 函数删除指定元素,用法和 map 相同:

my_set.erase(3);

auto it = my_set.find(3);
if (it != my_set.end()) {
    my_set.erase(it);
}

以上是 multiset 的基本用法,还有一些其他的函数和用法可以根据实际需要选择使用。

注意,由于 multiset 允许重复的元素存在,因此在遍历和删除元素时需要特别注意。遍历时可能会出现重复元素,删除时只能删除指定元素,不能删除所有相同的元素。

以下是一些常用的函数和用法:

size()

可以使用 size() 函数获取 multiset 中元素的数量:

int n = my_set.size();

empty()

可以使用 empty() 函数判断 multiset 是否为空:

if (my_set.empty()) {
    cout << "multiset is empty" << endl;
}

自定义排序方式

默认情况下,multiset 按照元素的大小进行排序,如果需要自定义排序方式,可以定义一个 struct 类型,并重载小于运算符 <:

struct MyCompare {
    bool operator()(const MyType& lhs, const MyType& rhs) const {
        // 自定义排序方式的实现
    }
};

multiset<MyType, MyCompare> my_set;

其中,MyType 是元素的类型,MyCompare 是自定义排序方式的类型。

删除所有相同的元素

如果需要删除 multiset 中所有相同的元素,可以使用 equal_range() 函数获取指定元素的范围,然后使用 erase() 函数删除该范围内的所有元素:

auto range = my_set.equal_range(3);
my_set.erase(range.first, range.second);

其中,range 是一个 pair 类型,包含指向范围起始位置的迭代器 first 和指向范围终止位置的迭代器 second。

以上是 multiset 的一些常用函数和用法,可以根据实际需要选择使用。

multiset和set有什么区别?

multiset 和 set 都是 C++ STL 中的关联式容器,它们的主要区别在于元素的唯一性和重复性。

元素唯一性

set 中的元素是唯一的,不能重复。当尝试插入一个已经存在于 set 中的元素时,插入操作会被忽略。

multiset 中的元素可以重复。插入操作总是成功,不会因为元素已经存在而被忽略。

插入和删除

由于 set 中的元素是唯一的,插入和删除操作的时间复杂度都是对数级别。对于 multiset,由于元素可以重复,插入和删除操作的时间复杂度也都是对数级别。

查找

由于 set 和 multiset 内部实现都使用红黑树数据结构,查找操作的时间复杂度都是对数级别。

综上所述,如果需要存储唯一元素,应该使用 set;如果需要存储可重复元素,应该使用 multiset。另外需要注意的是,由于 multiset 允许重复元素存在,因此在遍历和删除元素时需要特别注意。

unordered_set

unordered_set 是 C++ STL 中的关联式容器之一,它提供了一种将元素按照哈希值进行存储的方法,不允许重复的元素存在。unordered_set 内部实现使用哈希表数据结构,因此插入、查找和删除元素的时间复杂度都是常数级别。

以下是 unordered_set 的基本用法:

头文件

要使用 unordered_set,首先需要包含头文件 <unordered_set>:

#include <unordered_set>

定义和插入元素

定义 unordered_set 很简单,可以使用以下语法:

unordered_set<value_type> my_set;

其中,value_type 是元素的类型。例如,定义一个存储字符串的 unordered_set:

unordered_set<string> my_set;

可以使用 insert() 函数向 unordered_set 中插入元素:

my_set.insert("apple");
my_set.insert("banana");
my_set.insert("pear");

访问元素

unordered_set 不支持使用下标运算符访问元素。可以使用 find() 函数查找指定元素,如果存在,则返回指向该元素的迭代器;如果不存在,则返回 end() 迭代器:

auto it = my_set.find("apple");
if (it != my_set.end()) {
    string s = *it;
}

也可以使用 count() 函数查找指定元素的数量:

int n = my_set.count("apple");

遍历元素

可以使用 for 循环遍历 unordered_set 中的元素:

for (const auto& x : my_set) {
    cout << x << endl;
}

删除元素

可以使用 erase() 函数删除指定元素,用法和 set 相同:

my_set.erase("apple");

auto it = my_set.find("apple");
if (it != my_set.end()) {
    my_set.erase(it);
}

以上是 unordered_set 的基本用法,还有一些其他的函数和用法可以根据实际需要选择使用。

需要注意的是,由于 unordered_set 不允许重复的元素存在,因此在插入元素时,如果元素已经存在,则插入操作会被忽略。在使用 unordered_set 存储自定义类型时,需要自定义哈希函数和相等比较函数,以便 unordered_set 正确地进行哈希和比较操作。

以下是一些常用的函数和用法:

size()

可以使用 size() 函数获取 unordered_set 中元素的数量:

int n = my_set.size();

empty()

可以使用 empty() 函数判断 unordered_set 是否为空:

if (my_set.empty()) {
    cout << "unordered_set is empty" << endl;
}

自定义哈希函数和相等比较函数

由于 unordered_set 使用哈希表数据结构,因此在使用自定义类型时,需要自定义哈希函数和相等比较函数,以便 unordered_set 正确地进行哈希和比较操作。以下是一个示例:

struct MyType {
    int x;
    string y;

    bool operator==(const MyType& other) const {
        return x == other.x && y == other.y;
    }
};

struct MyHash {
    size_t operator()(const MyType& obj) const {
        return hash<int>()(obj.x) ^ hash<string>()(obj.y);
    }
};

unordered_set<MyType, MyHash> my_set;

其中,MyType 是自定义类型,MyHash 是自定义哈希函数类型,重载了括号运算符 (),实现了哈希函数的功能。MyType 类型还需要重载相等比较运算符 ==,以便 unordered_set 可以正确地进行相等比较。

删除所有相同的元素

如果需要删除 unordered_set 中所有相同的元素,可以使用 equal_range() 函数获取指定元素的范围,然后使用 erase() 函数删除该范围内的所有元素:

auto range = my_set.equal_range("apple");
my_set.erase(range.first, range.second);

其中,range 是一个 pair 类型,包含指向范围起始位置的迭代器 first 和指向范围终止位置的迭代器 second。

以上是 unordered_set 的一些常用函数和用法,可以根据实际需要选择使用。

unordered_set和set有什么区别?

unordered_set 和 set 都是 C++ STL 中的关联式容器,它们的主要区别在于元素的存储方式和时间复杂度。

元素存储方式

set 中的元素是按照红黑树的顺序进行存储的,因此遍历 set 时可以按照元素的大小顺序进行遍历,但是插入、删除和查找操作的时间复杂度都是对数级别。

unordered_set 中的元素是按照哈希表的顺序进行存储的,因此遍历 unordered_set 时无法按照元素的大小顺序进行遍历,但是插入、删除和查找操作的时间复杂度都是常数级别。

时间复杂度

由于 set 中的元素是按照红黑树的顺序进行存储的,因此插入、删除和查找操作的时间复杂度都是对数级别。而且由于红黑树是一种自平衡二叉搜索树,因此插入、删除和查找操作的时间复杂度可以保证为 O(log n)。

unordered_set 中的元素是按照哈希表的顺序进行存储的,因此插入、删除和查找操作的时间复杂度都是常数级别,平均情况下的时间复杂度为 O(1)。但是最坏情况下的时间复杂度为 O(n),即当哈希表的冲突比较严重时,插入、删除和查找操作的时间复杂度会退化为线性级别。

其他区别

由于 set 中的元素是按照红黑树的顺序进行存储的,因此 set 支持按照元素的大小顺序进行遍历,而且元素之间的顺序可以通过自定义比较函数进行控制。

unordered_set 中的元素是按照哈希表的顺序进行存储的,因此无法按照元素的大小顺序进行遍历,而且元素之间的顺序是不确定的。

总的来说,如果需要按照元素的大小顺序进行遍历,或者需要控制元素之间的顺序,可以使用 set。如果需要快速进行插入、删除和查找操作,并且不需要按照元素的大小顺序进行遍历,可以使用 unordered_set。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Let’s Make C++ Great Again——multiset与unordered_set 的相关文章

  • c和java语言中的换行符

    现在行分隔符取决于系统 但在 C 程序中我使用 n 作为行分隔符 无论我在 Windows 还是 Linux 中运行它都可以正常工作 为什么 在java中 我们必须使用 n 因为它与系统相关 那么为什么我们在c中使用 n 作为新行 而不管我
  • VB.NET 相当于 C# 属性简写吗?

    是否有与 C 等效的 VB NET public string FirstName get set 我知道你能做到 Public Property name As String Get Return name ToString End Ge
  • std::cout 和 std::wcout 有什么区别?

    在c 中 有什么区别std cout and std wcout 它们都控制流缓冲区的输出或将内容打印到控制台 或者它们只是相似吗 它们作用于不同的字符类型 std cout uses char作为字符类型 std wcout uses w
  • 使用Physics.Raycast 和Physics2D.Raycast 检测对象上的点击

    我的场景中有一个空的游戏对象 带有 2D 组件盒碰撞器 我将脚本附加到该游戏对象 void OnMouseDown Debug Log clic 但是当我点击我的游戏对象时 没有任何效果 你有什么想法 如何检测我的盒子碰撞器上的点击 使用光
  • 启动时出现 OData v4 错误:找不到段“Whatever”的资源

    我正在构建新的 v4 服务 一切进展顺利 直到我为新模型 实体添加了新控制器 并在启动站点进行测试运行时收到此错误 控制器似乎编码正确 就像其他控制器一样 控制器 CustomersOData 中的操作 GetFeed 上的路径模板 Cus
  • 在新的浏览器进程中打开 URL

    我需要在新的浏览器进程中打开 URL 当浏览器进程退出时我需要收到通知 我当前使用的代码如下 Process browser new Process browser EnableRaisingEvents true browser Star
  • 使用 C 语言使用 strftime() 获取缩写时区

    我看过this https stackoverflow com questions 34408909 how to get abbreviated timezone and this https stackoverflow com ques
  • 无法在 Windows 运行时组件库的 UserControl 中创建依赖项属性

    我想在用户控件内创建数据可绑定属性 这个用户控件包含一个 Windows 运行时组件 项目 我使用下面的代码来创建属性 public MyItem CurrentItem get return MyItem GetValue Current
  • 获取 WPF 控件的所有附加事件处理程序

    我正在开发一个应用程序 在其中动态分配按钮的事件 现在的问题是 我希望获取按钮单击事件的所有事件 因为我希望删除以前的处理程序 我尝试将事件处理程序设置为 null 如下所示 Button Click null 但是我收到了一个无法分配 n
  • 关于在 Windows 上使用 WiFi Direct Api?

    我目前正在开发一个应用程序 我需要在其中创建链接 阅读 无线网络连接 在桌面应用程序 在 Windows 10 上 和平板电脑 Android 但无关紧要 之间 工作流程 按钮 gt 如果需要提升权限 gt 创建类似托管网络的 WiFi 网
  • 使用 JNI 从 Java 代码中检索 String 值的内存泄漏

    我使用 GetStringUTFChars 从使用 JNI 的 java 代码中检索字符串的值 并使用 ReleaseStringUTFChars 释放该字符串 当代码在 JRE 1 4 上运行时 不会出现内存泄漏 但如果相同的代码在 JR
  • 未经许可更改内存值

    我有一个二维数组 当我第一次打印数组的数据时 日期打印正确 但其他时候 array last i 的数据从 i 0 到 last 1 显然是一个逻辑错误 但我不明白原因 因为我复制并粘贴了 for 语句 那么 C 更改数据吗 I use g
  • 如何使用 watin 中的 FileUploadDialogHandler 访问文件上传对话框

    我正在使用 IE8 和 watin 并尝试通过我的网页测试上传文件 我不能简单地使用 set 方法设置上传文件 例如 ie FileUpload Find ById someId Set C Desktop image jpg 因为上传文本
  • 如何在 Blackberry Cascades 中显示具有特定号码的电话板

    我正在使用带有 C QT 和 QML 的 Blackberry Cascades 10 Beta 3 SDK 以及 Blackberry 10 Dev Alpha Simulator 和 QNX Momentics IDE 并且我正在尝试实
  • std::async 与重载函数

    可能的重复 std bind 重载解析 https stackoverflow com questions 4159487 stdbind overload resolution 考虑以下 C 示例 class A public int f
  • 如何对 Web Api 操作进行后调用?

    我创建了一个 Web API 操作 如下所示 HttpPost public void Load string siteName string providerName UserDetails userDetails implementat
  • gcc 的配置选项如何确定默认枚举大小(短或非短)?

    我尝试了一些 gcc 编译器来查看默认枚举大小是否很短 至少一个字节 强制使用 fshort enums 或无短 至少 4 个字节 强制使用 fno short enums user host echo Static assert 4 si
  • C++ 密码屏蔽

    我正在编写一个代码来接收密码输入 下面是我的代码 程序运行良好 但问题是除了数字和字母字符之外的其他键也被读取 例如删除 插入等 我知道如何避免它吗 特q string pw char c while c 13 Loop until Ent
  • memset 未填充数组

    u32 iterations 5 u32 ecx u32 malloc sizeof u32 iterations memset ecx 0xBAADF00D sizeof u32 iterations printf 8X n ecx 0
  • 如何正确使用 std::condition_variable?

    我很困惑conditions variables以及如何 安全 使用它们 在我的应用程序中 我有一个创建 gui 线程的类 但是当 gui 是由 gui 线程构造时 主线程需要等待 情况与下面的函数相同 主线程创建互斥体 锁和conditi

随机推荐

  • 智能工厂中,MES管理系统数据采集的方式有哪些

    在工业领域 制造企业的数字化转型正在如火如荼地进行 智能和工业互联网的应用也在加速推进 在这个过程中 工控系统软硬件发挥着关键作用 工控系统涵盖了可编程逻辑控制器 PLC 数据采集与监控系统 SCADA 和分布式控制系统 DCS PLC通常
  • Python 缓存库

    文章目录 缓存库 缓存库的类型 Python中有用的缓存库 Python中的Redis缓存库 Python中的lru cache库 Python中的其他缓存库 总结 缓存是一种可以存储数据以供快速访问的内存类型 它是一个小而快速的内存 用于
  • 图的邻接矩阵

    邻接矩阵 是表示顶点之间相邻关系的矩阵 设G V E 是一个图 其中V v1 v2 vn G的邻接矩阵是一个具有下列性质的n阶方阵 对无向图而言 邻接矩阵一定是对称的 而且主对角线一定为零 在此仅讨论无向简单图 副对角线不一定为0 有向图则
  • Python中enumerate用法详解

    enumerate的意思即为枚举 列举 一句话来说 enumerate的作用就是对可迭代的数据进行标号并将其里面的数据和标号一并打印出来 看一下enumerate的函数 描述 enumerate 函数用于将一个可遍历的数据对象 如列表 元组
  • ElasticSearch Python Client ReadTimeout

    ElasticSearch Python Client ReadTimeout ElasticSearch Python Client API Bulk操作时 当ElasticSearch服务端的性能不足时 Client可能会超时 打印类似
  • 链表—C语言链表中数据域是结构体该如何操作

    链表是数据结构中的首先接触到的 常规的链表数据域为int型 如果链表中数据域是一个结构体该如何操作呢 首先看一个例子 定义一个学生结构体 然后用单向链表保存学生信息 由scanf输入学生信息后形成链表 再打印出所有学生信息 include
  • shell编程之if判断

    目录 一 格式 1 格式1 2 格式2 3 格式3 二 注意 三 例子 1 判断两个数是否相等 2 判断两个数中的最大值 一 格式 1 格式1 if 判断条件 then 判断为true执行的代码 fi 2 格式2 if 判断条件 then
  • Java 的七种垃圾收集器

    了解 Java 中的内存管理 用 C 或 C 这样的编程语言写一个应用时 需要编写代码来销毁内存中不再需要的对象 当应用程序扩展得越来越复杂时 未使用对象被忽略释放的可能性就越大 这会导致内存泄露 最终内存耗尽 在某个时刻将没有更多的内存可
  • Qt串口通信接收数据不完整的解决方法

    在使用串口接收数据时 当数据量大的时候会出现数据接收不完整的情况 因为串口数据获取函数readAll 由readyRead 信号触发 但readyRead 信号在串口读到起始标志时立即发送 并不保证一定是当前所发数据的起始部分 因此串口通信
  • SpringBoot2.x 集成Activiti6.0

    任务要求 集成Activiti6 0 流程引擎开发环境 核心依赖pom文件如下
  • VIM列编辑

    有时候需要多行编辑 例如注释多行代码 或者取消注释 虽然有插件支持 但插件不能插入特殊的字符 此时可以借助vim的列编辑模式 可以允许同时编辑多行 具体的操作如下 在normal模式下按ctrl v进入列编辑模式 通过hjkl选中编辑的区域
  • Numpy数据类型对象(dtype)

    常用方法 记住引入numpy时要是用别名np 则所有的numpy字样都要替换 查询数值类型 gt gt gt type float dtype float64 查询字符代码 gt gt gt dtype f dtype float32 gt
  • 安装博途时一直提示重启电脑,如何操作?

    1 在安装博途时 一直要求重启电脑的提示 如下图所示 2 如果出现上图所以提示 需要进行如下操作 3 在电脑开始菜单里右击 选择运行 点击运行命令 会弹出如下图操作 4 删掉注册表的键值 如下图的位置 5 删掉上图所以键值后 再运行博途安装
  • 电子设计竞赛电源题(2)-检波与采样

    电赛中的电源题说好做也好做 说不好做也不好做 电源是一个危险的东西 硬件和软件稍有不慎可能就会炸板子炸芯片 在19年前的电赛电源题一般都是做开关电源逆变器之类的 但是这类题做的太多了 已经饱和了或者说现在的单纯的电源已经做的效率达到非常之高
  • UGUI中UI朝向某一个物体

    做一个上一剪头朝向下一箭头的效果 代码 Vector3 dir arrows i 1 transform position arrows i transform position dir z 0 dir Normalize arrows i
  • 如何解决技术难点

    1 可以从宏观方面处理 分解为小的demo 大处着眼 小处着手 2 分解为基本的技术 实现 3 切换一个电脑画图理解 画图有助于自己对整个流程分析 代码只是流程的实现 画图理解逻辑 保证自己有清晰的逻辑 清楚的思路和顺序 这点很重要 4 写
  • oracle hint之hint_index_ffs,index_join

    oracle hint index ffs index join index ffs hint 1 对表用快速索引全扫描进行访问 2 经测 仅count可以使用index ffs 而非count聚合函数好像不能使用index ffs SQL
  • 【IDEA】The IDE is running low on memory and this might affect performance. Please consider increasing

    今天在看Java源码 IDEA突然提示这个信息 The IDE is running low on memory and this might affect performance Please consider increasing av
  • Android 移动安全知识技术全解(加固技术、常规漏洞、Android 逆向......),移动安全问题不容忽视

    前言 您的设备是否处于遭受攻击 劫持或损害的风险中 毫无疑问 剑桥大学的研究人员发现 87 的 Android 智能手机有至少一个严重漏洞 Zimperium Labs 在早些时候发现 黑客只需通过一条简单的短信便能对 95 的 Andro
  • Let’s Make C++ Great Again——multiset与unordered_set

    文章目录 multiset 头文件 定义和插入元素 访问元素 遍历元素 删除元素 以下是一些常用的函数和用法 size empty 自定义排序方式 删除所有相同的元素 multiset和set有什么区别 元素唯一性 插入和删除 查找 uno