【C++】STL标准容器之关联容器_什么是标准关联容器-程序员宅基地

技术标签: 【学习笔记】C++  c++  STL  map  

一、标准容器

3、关联容器

主要分为两类:

  • set:集合,存的是关键字key
  • map:映射表存的是 [key,value]键值对

常用增删查方法:

  • 增加:insert(val);

  • 遍历:iterator自己搜索或调用find成员方法,

    unordered_set<int>::iterator it = set1.find(15); cout << *it;

  • 删除:erase(key) erase(it)

3.1、无序关联容器 => 链式哈希表

无序关联容器底层是链式哈希表,里边元素是无序的,增删查O(1)

无序关联容器在有序关联容器前面加了个unordered_,这些容器操作都是一模一样的,无非就是底层数据结构不同,90%的情况都是在使用无序关联容器,因为大部分应用场景只在乎增删查的时间复杂度要快,如果对元素的顺序有要求则只能选择基于红黑树的有序关联容器

四种无序关联容器

  • unordered_set 单重集合:不允许key重复
  • unordered_multiset 多重集合:允许key重复
  • unordered_map 单重映射表
  • unordered_multimap 多重映射表

头文件

//无序关联容器头文件
#include <unordered_set>  //unordered_set  unordered_multiset
#include <unordered_map>  //unordered_map  unordered_multimap 
using namespace std;

unordered_set代码示例

int main()
{
    
    unordered_set<int> set1;  //不会存储key值重复的元素
    for(int i = 0; i < 50; ++i)
    {
    
        set1.insert(rand() % 20 + 1);//不像vector/deque/list的insert(it, val) 
    }
    
    cout<<set1.size()<<endl;  //返回容器元素个数
    cout<<set1.count(15)<<endl;  //返回key为15的元素的个数,单重集合,key唯一,输出0或1
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kIyqd83E-1650361455054)(img/C++%EF%BC%9ASTL%E3%80%81%E5%AE%B9%E5%99%A8.img/image-20210224135805672.png)]
存了50个元素却只有18个元素,说明添加的时候有很多是重复的,单重集合是不存储重复的key的

unordered_map代码示例

/*
map中存的是[key,value]键值对
struct
{
	first;    //key,struct默认访问权限公有
	seconde;  //value
};
*/
int main()
{
    
	unordered_map<int, string> map1;
    
    //增加
	map1.insert(make_pair(1000, "张三"));  //将键值对打包成pair对象插入到map表中
    map1.insert({
    1010, "李四"});
    map1.insert({
    1020, "王五"});
    
    //范文
    cout<<map1.size()<<endl;
    cout<<map1[1000]<<endl;  
    cout<<map1[1010]<<endl;  
    map1[2000] = "wang";  //就相当于 map1.insert({2000,"wang"});
    cout<<map1[2000]<<endl;
    
    //查询
    auto it1 = map1.find(1000);  //find返回的是打包的pair对象
    if(it1 != map1.end())
    {
    
        cout<<"key: "<<it1->first<<endl;
        cout<<"value: "<<it1->second<<endl;
    }
    
    //删除
    map1.erase(1020);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7TZa6mVu-1650361455056)(img/C++%EF%BC%9ASTL%E3%80%81%E5%AE%B9%E5%99%A8.img/image-20210224144825736.png)]
应用场景

  • 处理海量数据查重时候经常用到哈希表
//海量数据查重
#include <iostream>
#include <unordered_map>
using namespace std;

int main()
{
    
	const int ARR_LEN = 1000;
	int arr[ARR_LEN] = {
     0 };
	for (int i = 0; i < ARR_LEN; ++i)
	{
    
		arr[i] = rand() % 200 + 1;
	}

	//上面的1000个整数中,统计那些数字重复了,并且统计数字重复的次数
	unordered_map<int, int> map1;  //<数字,次数>
	for (int k : arr)
	{
    
        /*
		auto it = map1.find(k);
		if (it == map1.end())  //该数字还没存入map表
		{
			map1.insert({ k, 1 });
		}
		else  //之前出现过
		{
			it->second++;
		}*/
        map1[k]++;  //k不存在,[]副作用插入一个新的[k,0],++到[k,1]
	}

    //打印方式1:
	for (const pair<int, int> &p : map1)  //foreach遍历必须用常引用,只是读操作
	{
    
		if (p.second > 1)
		{
    
			cout << "key: " << p.first << "重复次数:" << p.second << endl;
		}
	}
    
    //打印方式2:
    auto it = map1.begin();
    for(; it != map1.end(); ++it)
    {
    
        if(it->second > 1)
        {
    
            cout << "key: " << it->first << "重复次数:" << it->second << endl;
        }
    }
}
  • 海量数据去重用单重set
//海量数据去重
//海量数据查重
#include <iostream>
#include <unordered_set>
using namespace std;

int main()
{
    
	const int ARR_LEN = 1000;
	int arr[ARR_LEN] = {
     0 };
	for (int i = 0; i < ARR_LEN; ++i)
	{
    
		arr[i] = rand() % 200 + 1;
	}

	//上面的1000个整数中,把数字进行去重,打印出只出现一次的数字
	unordered_set<int> uset;
	for (int v : arr)
	{
    
		uset.insert(v);
	}

	for (int v : uset)
	{
    
		cout << v << " ";
	}
	cout << endl;
}

3.2、有序关联容器 => 红黑树

有序关联容器底层是红黑树,元素是经过排序的,增删查O(log2n) 2是底数(树的层数,树的高度)

有序关联容器的操作与无序关联容器一模一样

用迭代器去遍历有序集合容器时,其实就是对底层红黑树中序遍历的结果

四种有序关联容器

  • set 单重集合
  • multiset 多重集合
  • map 单重映射表
  • multimap 多重映射表

头文件

//有序关联容器头文件
#include <set>  //set  multiset
#include <map>  //map  multimap
using namespace std;

有序set示例

int main()
{
    
	set<int> set1;  //有序单重集合
	for (int i = 0; i < 20; ++i)
	{
    
		set1.insert(rand() % 20 + 1);
	}
	
	for (int v : set1)
	{
    
		cout << v << " ";
	}
	cout << endl;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9F26HNUZ-1650361455057)(img/C++%EF%BC%9ASTL%E3%80%81%E5%AE%B9%E5%99%A8.img/image-20210224162928121.png)]
向有序容器中添加自定义类型时注意:要提供默认的<运算符的重载函数

class Student
{
    
public:
	Student(int id, string name) :_id(id), _name(name) {
    }
	bool operator<(const Student &stu) const //提供默认的<运算符的重载函数
	{
    
		return _id < stu._id;
	}
private:
	int _id;
	string _name;
	friend ostream& operator<<(ostream &out, const Student & stu);
};

ostream& operator<<(ostream &out, const Student & stu)
{
    
	cout << "id: " << stu._id << " name: " << stu._name << endl;
	return out;
}

int main()
{
    
	set<Student> set1;
	set1.insert(Student(1020, "wang"));
	set1.insert(Student(1010, "yang"));
	set1.insert(Student(1030, "zhang"));

	for (auto it = set1.begin(); it != set1.end(); ++it)
	{
    
		cout << *it << endl;
	}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2LGawi3e-1650361455057)(img/C++%EF%BC%9ASTL%E3%80%81%E5%AE%B9%E5%99%A8.img/image-20210224164444989.png)]
有序map示例

map表中要求value有默认的构造函数,因为[]去引用元素如果不存在会构造一个对象,因此要有默认构造函数

class Student
{
    
public:
	Student(int id=0, string name="") :_id(id), _name(name) {
    }  //构造函数要有默认值
private:
	int _id;
	string _name;
	friend ostream& operator<<(ostream &out, const Student & stu);
};

ostream& operator<<(ostream &out, const Student & stu)
{
    
	cout << "id: " << stu._id << " name: " << stu._name << endl;
	return out;
}

int main()
{
    
	map<int, Student> stuMap;
	stuMap.insert({
     3, Student(1030, "wang") });
	stuMap.insert({
     1, Student(1010, "yang") });
	stuMap.insert({
     2, Student(1020, "zhang") });

	cout << stuMap[4] << endl;

	//打印方式1:
	for (auto it : stuMap)  //stuMap中元素是什么类型,it就是什么类型
	{
    
		cout <<"key: "<<it.first<<"  value: "<< it.second << endl;
	}

	cout << "-------------------------------------------------------------" << endl;

	//打印方式2:
	auto it = stuMap.begin();
	for (; it != stuMap.end(); it++)
	{
    
		cout <<"key: "<<it->first<<"  value: "<< it->second << endl;
	}
	
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DSTcbriX-1650361455058)(img/C++%EF%BC%9ASTL%E3%80%81%E5%AE%B9%E5%99%A8.img/image-20210224171328200.png)]

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lsz20000813/article/details/124279607

智能推荐

CVE-2012-2122 Mysql身份认证漏洞及利用-程序员宅基地

文章浏览阅读3.9k次。目录漏洞描述影响版本漏洞环境搭建漏洞分析漏洞检测msf漏洞利用漏洞加固建议参考链接漏洞描述  当连接MariaDB/MySQL时,输入的密码会与期望的正确密码比较,由于不正确的处理,会导致即便是memcmp()返回一个非零值,也会使MySQL认为两个密码是相同的。 也就是说只要知道用户名,不断尝试就能够直接登入SQL数据库。按照公告说法大约256次就能够蒙对一次。影响版本MariaDB versions from 5.1.62, 5.2.12, 5.3.6, 5.5.23 are not._cve-2012-2122

临界Hashgard创始人许超逸接受光明网专访:DeFi时代到来-程序员宅基地

文章浏览阅读610次。随着互联网、人工智能、大数据特别是区块链技术的发展,金融行业在不知不觉中,进入到一个新阶段。从科大讯飞到中兴华为,从程序员转型投资人,成功投资多个项目。临界Hashgard创始人许超逸,正在经历着金融行业的高速发展与变化。“原有的参与群体、参与方式都会出现很大的变化,第一个特点就是开放。”在许超逸看来,作为金融行业的供给方、需求方、中介方参与到其中,比原来以中心化监管为核心的金融行业要开放很多。..._许超逸

使用POI创建Excel无法打开_poi 5.1.0 c-程序员宅基地

文章浏览阅读8.6k次,点赞2次,收藏2次。如果使用的XSSFWorkbook创建的xls,打开的时候会有这样的提示:这样 XSSFWorkbook 和HSSFWorkbook的区别。 使用POI创建一个新的xlsx,提示创建成功,但是打开xlsx文件的时候,会报错打不开 代码如下: HSSF - 提供读写Microsoft Excel XLS格式档案的功能。 X..._poi 5.1.0 c

init.rc_root/init.rc-程序员宅基地

文章浏览阅读509次。在Android中使用启动脚本init.rc,可以在系统的初始化中进行简单的操作。init.rc启动脚本路径:system/core/rootdir/init.rc内容:Commands:命令Actions:动作Triggers:触发条件Services:服务Options:选项Properties:属性Commands是一些基本操作。如:_root/init.rc

An Improved Baseline for Sentence-level Relation Extraction-程序员宅基地

文章浏览阅读612次。论文地址: An Improved Baseline for Sentence-level Relation ExtractionAbstract & Contribution目前的句子级的关系抽取任务效果,还有远远达不到人工的效果。本文反思已有模型并指出两个被忽视的方面:关系实例包含多个方面的实体信息,如实体名字、范围、类型;已有的模型并没有将其作为输入。由于预定义的知识本体还具有一定的限制,所以不可避免地有一些关系并不在知识本体中并被标注为NA类别,但是实际上他们可能有更多样的语义._an improved baseline for sentence-level relation extraction

使用navicat premium远程连接centos7的mysql出现10038错误如何解决_navicate连接虚拟机centos7数据库10038-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏10次。对于使用navicat premium工具链接MySQL的一些写错误发,百度上面有很多都是让你在my.ini/my.cnf/my.cnf.d下面删除IP地址,我找了很久都没有找到出现上述情况1、首先 设置远程访问权限 在mysql语句中执行语句grant all privileges on *.* to 'root'@'%' identified by 'youpassword' wi..._navicate连接虚拟机centos7数据库10038

随便推点

高精地图应用(四)横向定位_std::fabs-程序员宅基地

文章浏览阅读1.5k次。这里的横向定位是基于ICP算法的改进实现的3d-3d的配准方法,步骤:1.将单帧重建车道线的形值点,向高精度地图中的车道线做垂足,考虑到不受高程差异的影响,这里是在平面上完成的。求得的形值点与垂足就组成了一对同名点,我将形值点命名为source,垂足命名为target。会生成很多这样的同名点。2...._std::fabs

POM标签大全-程序员宅基地

文章浏览阅读189次。<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/maven-v4_0_0.xsd"> <!--父项目的坐标。如果项目中没有规定某个元素的值,那么父项目中的对应值即

VsCode开发工具的入门及基本使用_vscode yaml-程序员宅基地

文章浏览阅读6.7k次,点赞8次,收藏61次。VsCode开发工具的入门及基本使用_vscode yaml

dhtmlxSuite宣布新的DHTMLX工具_dhtmlx suite git-程序员宅基地

文章浏览阅读196次。dhtmlxSuite是一个用JavaScript建立的富客户端开发框架。它是一个JavaScript UI库,用于建立一个完整的具有Ajax能力的前台组件。用户可以使用它建立一个企业级的跨浏览器Web应用和移动应用程序,它能提供优秀的性能和更丰富的用户体验。点击下载dhtmlxSuite最新版我们的开发团队将继续扩展开发人员帮助工具的产品组合,这些工具有助于提高开发效率并确保在使用DHTMLX产品时获得更大的便利。这次,我们很高兴地宣布一个新的代码片段工具,该工具作为一种有效且更快的方式来构建组件的交_dhtmlx suite git

阿里中间件——消息中间件Notify和MetaQ简介及对比_notify和metaq的区别-程序员宅基地

文章浏览阅读5.1k次。3.1、NotifyNotify是淘宝自主研发的一套消息服务引擎,是支撑双11最为核心的系统之一,在淘宝和支付宝的核心交易场景中都有大量使用。消息系统的核心作用就是三点:解耦,异步和并行。下面让我以一个实际的例子来说明一下解耦异步和并行分别所代表的具体意义吧:假设我们有这么一个应用场景,为了完成一个用户注册淘宝的操作,可能需要将用户信息写入到用户库中,然后通知给红包中心给用户发新手_notify和metaq的区别

安秉网盾内网终端管理系统配置源代码防泄密实战-程序员宅基地

文章浏览阅读381次,点赞4次,收藏4次。安秉网盾的防泄密方案对普通员工计算机进行透明加密,代码被上传到Git服务器中为密文保存。

推荐文章

热门文章

相关标签