multiset用法总结

2023-10-30

       c++语言中,multiset是<set>库中一个非常有用的类型,它可以看成一个序列,插入一个数,删除一个数都能够在O(logn)的时间内完成,而且他能时刻保证序列中的数是有序的,而且序列中可以存在重复的数

简单应用:

通过一个程序来看如何使用multiset:

#include <string>
#include <iostream>
#include <set>
using namespace std;
void main(){
    intx;
    scanf("%ld",&x);
    multiset<int>h;          //建立一个multiset类型,变量名是h,h序列里面存的是int类型,初始h为空
    while(x!=0){
        h.insert(x);         //将x插入h中
        scanf("%ld",&x);
    }    
    while(!h.empty()){       // 序列非空 h.empty()==true时 表示h已经空了
        __typeof(h.begin()) c=h.begin();
                             //c指向h序列中第一个元素的地址,第一个元素是最小的元素
        printf("%ld ",*c);   //将地址c存的数据输出
        h.erase(c);          //从h序列中将c指向的元素删除
    }
}

对于输入数据:32 61 12 2 12 0,该程序的输出是:2 12 12 32 61。  

放入自定义类型的数据:

不只是int类型,multiset还可以存储其他的类型诸如 string类型,结构(struct或class)类型。而我们一般在编程当中遇到的问题经常用到自定义的类型,即struct或class。例如下面的例子:

struct rec{
    int x,y;
};
multiset<rec>h;

不过以上的代码是没有任何用处的,因为multiset并不知道如何去比较一个自定义的类型。怎么办呢?我们可以定义multiset里面rec类型变量之间的小于关系的含义(这里以x为第一关键字为例),具体过程如下:

定义一个比较类cmp,cmp内部的operator函数的作用是比较rec类型a和b的大小(以x为第一关键字,y为第二关键字):

struct cmp{
    bool operator()(const rec&a,const rec&b){
        return a.x<b.x||a.x==b.x&&a.y<b.y;
    }
};

 然后将语句"multiset<rec>h ;”改成"multiset<rec,cmp>h;"这样以后,我们就告诉了序列h如何去比较里面的元素(重载运算符)

此时rec以及multiset的定义部分完整代码可参考如下:

struct rec{
    int x,y;
};
struct cmp{
    bool operator()(const rec&a,const rec&b){
        return a.x<b.x||a.x==b.x&&a.y<b.y;
    }
};
multiset<rec,cmp>h;

通过以上代码,能够建立一个集合h使得该集合能够存储和排序自定义类型

常用函数总结:

构造、拷贝、析构

操作

效果

set c

产生一个空的set/multiset,不含任何元素

set c(op)

以op为排序准则,产生一个空的set/multiset

set c1(c2)

产生某个set/multiset的副本,所有元素都被拷贝

set c(beg,end)

以区间[beg,end)内的所有元素产生一个set/multiset

set c(beg,end, op)

以op为排序准则,区间[beg,end)内的元素产生一个set/multiset

c.~set()

销毁所有元素,释放内存

set<Elem>

产生一个set,以(operator <)为排序准则

set<Elem,0p>

产生一个set,以op为排序准则

非变动性操作

操作

效果

c.size()

返回当前的元素数量

c.empty ()

判断大小是否为零,等同于0 == size(),效率更高

c.max_size()

返回能容纳的元素最大数量

c1 == c2

判断c1是否等于c2

c1 != c2

判断c1是否不等于c2(等同于!(c1==c2))

c1 < c2

判断c1是否小于c2

c1 > c2

判断c1是否大于c2

c1 <= c2

判断c1是否小于等于c2(等同于!(c2<c1))

c1 >= c2

判断c1是否大于等于c2 (等同于!(c1<c2))

特殊的搜寻函数

  sets和multisets在元素快速搜寻方面做了优化设计,提供了特殊的搜寻函数,所以应优先使用这些搜寻函数,可获得对数复杂度,而非STL的线性复杂度。比如在1000个元素搜寻,对数复杂度平均十次,而线性复杂度平均需要500次。

操作

效果

count (elem)

返回元素值为elem的个数

find(elem)

返回元素值为elem的第一个元素,如果没有返回end()

lower _bound(elem)

返回元素值为elem的第一个可安插位置,也就是元素值 >= elem的第一个元素位置

upper _bound (elem)

返回元素值为elem的最后一个可安插位置,也就是元素值 > elem 的第一个元素位置

equal_range (elem)

返回elem可安插的第一个位置和最后一个位置,也就是元素值==elem的区间

赋值

操作

效果

c1 = c2

将c2的元素全部给c1

c1.swap(c2)

将c1和c2 的元素互换

swap(c1,c2)

同上,全局函数

迭代器相关函数

  sets和multisets的迭代器是双向迭代器,对迭代器操作而言,所有的元素都被视为常数,可以确保你不会人为改变元素值,从而打乱既定顺序,所以无法调用变动性算法,如remove()。

操作

效果

c.begin()

返回一个随机存取迭代器,指向第一个元素

c.end()

返回一个随机存取迭代器,指向最后一个元素的下一个位置

c.rbegin()

返回一个逆向迭代器,指向逆向迭代的第一个元素

c.rend()

返回一个逆向迭代器,指向逆向迭代的最后一个元素的下一个位置

安插和删除元素

  必须保证参数有效,迭代器必须指向有效位置,序列起点不能位于终点之后,不能从空容器删除元素。

操作

效果

c.insert(elem)

插入一个elem副本,返回新元素位置,无论插入成功与否。

c.insert(pos, elem)

安插一个elem元素副本,返回新元素位置,pos为收索起点,提升插入速度。

c.insert(beg,end)

将区间[beg,end)所有的元素安插到c,无返回值。

c.erase(elem)

删除与elem相等的所有元素,返回被移除的元素个数。

c.erase(pos)

移除迭代器pos所指位置元素,无返回值。

c.erase(beg,end)

移除区间[beg,end)所有元素,无返回值。

c.clear()

移除所有元素,将容器清空

 

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

multiset用法总结 的相关文章

随机推荐

  • android studio更改代码字体,Android Studio怎么改变代码字体大小?

    Android Studio怎么改变代码字体大小 以后Android再也不用寄人篱下了 有了自己的编程工具 可是字体的大小 看着很不舒服 如何调节字体的大小呢 1 打开AndroidStudio工具 点击 设置 按钮 如图 2 左侧导航栏
  • 计算机网络——五层与七层模型

    前言 在网络上有非常都关于计算机网络的知识 常常感觉看懂了 但没几天就忘得没影了 自己写一篇相关的文章是一个总结和消化的过程 这篇文章大致讲明白了各层通信协议的要点 此文对于了解整个网络通信流程有较大帮助 PS 时间充裕的话 还是建议看书
  • R语言 ggplot2 多箱图 多个箱线图 分组箱线图 多个箱线图

    ggplot2 多箱图 多个箱线图 分组箱线图 使用本地数据 鸢尾花 yu n w i hu 做示例 结果输出如下面的图 data iris 用本地数据 鸢尾花 yu n w i hu 做示例 data lt iris table data
  • 【MAC】 M2 brew安装 docker 运行失败 解决

    MAC 安装 brew install cask docker 之后一直显示docker Cannot connect to the Docker daemon at unix var run docker sock Is the dock
  • 何晖光:“深度学习类脑吗?”--- 基于视觉信息编解码的深度学习类脑机制研究

    点击上方 深度学习大讲堂 可订阅哦
  • Fiddler 抓不到浏览器包的种种原因

    代理未设置成功 fiddler 之所以能抓包 本质上是因为浏览器 App 软件设置了代理为 fiddler 一旦遇到抓不到包的情况 首先应排查浏览器代理是否设置正确 以 Chrome 为例 代理设置为 右上角菜单按钮 gt 设置 gt 高级
  • vue -- router路由跳转错误 , NavigationDuplicated

    const originalPush Router prototype push Router prototype push function push location return originalPush call this loca
  • springboot中使用ApplicationRunner接口

    springboot中使用ApplicationRunner接口 applicationRunner使用 Spring Boot如何解决项目启动时初始化资源 在我们实际工作中 总会遇到这样需求 在项目启动的时候需要做一些初始化的操作 比如初
  • Open3D(C++) 模型滤波——Taubin滤波

    目录 一 概述 1 主要函数 2 算法源码 二 代码实现 三 结果展示 1 原始模型 2 滤波后的模型 一 概述 均值滤波和拉普拉斯滤波都会使三角网格收缩 Taubin滤波器使用两种不同参数的拉普拉斯滤波器来防止网格收缩 这个滤波器的实现接
  • 国内常用免费公共DNS服务(整理)

    国内部分常用免费公共DNS服务整理 2021 09 DNS服务名称 首选 备选 114DNS服务 114 114 114 114 114 114 115 115 阿里DNS服务 223 5 5 5 223 6 6 6 百度DNS服务 180
  • unity 从apk包中提取资源

    unity 从apk包中提取资源 前提 使用本方法来提取资源有个前提就是资源没有被加密 1 打开apk包 首先 将你的apk包重命名为zip或者rar类型的文件 然后进行解压缩 获取下面的文件 各个部分的说明如下表 文件 说明 assets
  • vue2基础增删改查

  • 51单片机定时器扫描按键

    定时器扫描按键 定时器每隔20毫秒扫描一次按键 问题 在之前写的按键检测函数中 要在按键按下后用Delay函数进行软件消抖 还要用while P3 1 0 来判断是否松手 如果长期不松手 则CPU会 卡在该死循环里 不能执行其他代码 造成某
  • 享受技术带来的快乐

    http blog csdn net jdsjlzx article details 45815531
  • 细数以太坊生态的另类项目:通向Web3.0的桥梁

    DeFi之外 以太坊生态还有许多另类生态项目值得关注 作者 谷昱 近段时间 以BSC Solana与Fontom等为代表的公链对以太坊发起了激烈挑战 特别是在应用生态方面 正在在借贷 交易 聚合器等赛道全方位复制以太坊生态 通过IDO 空投
  • 如何用matlab代码表白——matlab画爱心和玫瑰、I LOVE YOU

    写在前面 本篇博客主要是利用matlab2016a绘制一些玫瑰花或表白语句 通过绘制掌握matlab画图的一些常规操作 话不多说 直接上代码及注释 1 爱心 2 玫瑰 3 I LOVE YOU 4 参考文献与链接 1 爱心 clear cl
  • Ubuntu+Matlab 在终端输入matlab实现打开matlab

    1 找到安装的Matlab路径 usr local MATLAB R2017a bin matlab 2 打开命令行 输入 sudo ln s usr local MATLAB R2017a bin matlab usr local bin
  • DH参数介绍

    机械手末端到基坐标系的变换关系 通常 每一个变换需要 个独立参数来描述坐标系 相对坐标系 的关系 个用来描述位置另外 个用来描述方向 在 年 Jacques Denavit 和 Richard Hartenberg 提出了一种系统化的方法来
  • BUILDROOT配置QT5和TSLIB

    在buildroot下面 打开配置界面 make menuconfig 选择target packages项 默认的模拟配置并不支持勾选QT选项 修改Toolchain后 终于可以用QT的选项了 找到QT5 勾选 进入QT5选项 勾选gui
  • multiset用法总结

    c 语言中 multiset是