当前位置: 首页 > news >正文

【C++】map与set

人虽然可以为所欲为,但却不能得偿所愿。 

序列式容器与关联式容器

1. stringvectorstackqueuedeque序列式容器逻辑结构为线性序列,两个位置的储存值之间没有紧密的关联关系

2. 序列式容器保存和访问储存值时,一般依靠储存值在容器中储存的位置

3. map、set系列unordered_map、unordered_set系列关联式容器逻辑结构为非线性结构两个位置的储存值之间存在紧密的关联关系

4. 关联式容器保存和访问储存值时,一般依靠容器中的关键字

set类

set类的介绍 

1. 在使用set类时,必须包含 #include <set> 这一行。

2. set类的底层其实是一个红黑树结构,使用时需要显示实例化

3. 下面是set类的官方文本介绍,里面有详细的用法讲解。

- C++ Reference https://legacy.cplusplus.com/reference/set/

set类对象的常见构造

1. set<int> s1,什么也不需要传入,构造一个空的set类对象

2. set<int> s2(s1.begin(),s1.end()),使用另一个set类对象进行迭代器构造

3. set<int> s3(const set<int>& s2),使用另一个set类对象进行拷贝构造

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

int main()
{
	set<int> s1;
	set<int> s2(s1.begin(), s1.end());
	set<int> s3(const set<int>&s2);
	return 0;
}

set类对象的容量操作  

1. set.size(),返回set类对象有效元素个数

2. set.empty(),检测set类对象有效节点个数是否为空,为空返回true不为空返回flase

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

int main()
{
	set<int> s1;
	s1.insert(1);
	s1.insert(4);
	s1.insert(3);
	s1.insert(2);
	s1.insert(5);
	s1.insert(6);
	cout << s1.size() << endl;
	cout << s1.empty() << endl;
	return 0;
}

set容器的修改操作

1. set.insert(int num)向set类对象中插入整数num如果插入set类对象已有的元素则插入失败

2. set.erase(int num)向set类对象中删除整数num如果删除set类对象没有的元素则删除失败

3. set.erase(iterator pos)向set类对象中删除迭代器为pos的值

4. set.find(int num)检查set类对象中是否存在某个特定的元素num效率为log(N)返回一个迭代器

5. set.count(int num)检查set类对象中是否存在某个特定的元素num返回1或者0

6. set.lower_bound(int num)返回一个迭代器指向set类对象中第一个大于等于num的元素

7. set.upper_bound(int num)返回一个迭代器指向set类对象中第一个大于num的元素

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

int main()
{
	set<int> s1;
	s1.insert(1);
	s1.insert(4);
	s1.insert(3);
	s1.insert(2);
	s1.insert(5);
	s1.insert(6);
	s1.insert(6);//如果插入set对象中已有元素,则插入失败
	for (auto it : s1)
	{
		cout << it << " ";
	}
	cout << endl;
	s1.erase(6);
	s1.erase(7);//如果删除set对象中未有元素,则删除失败
	for (auto it : s1)
	{
		cout << it << " ";
	}
	cout << endl;
	s1.erase(s1.begin());
	for (auto it : s1)
	{
		cout << it << " ";
	}
	cout << endl;
	auto it = s1.find(4);
	cout << *it << endl;
	if (s1.count(3))
	{
		cout << "存在3";
	}
	return 0;
}

set类对象的遍历操作 

1. set类支持迭代器操作迭代器遍历走二叉搜索树的中序遍历因此默认为升序

2. set.begin()set.end()set.begin()获取第一个元素的迭代器,set.end()获取最后一个元素的下一个位置的迭代器。

3. set.rbegin()set.rend()set.rbegin()获取最后一个元素的迭代器,set.rend()获取第一个元素的上一个位置的迭代器。

//insert()
#include <iostream>
#include <set>
using namespace std;

int main()
{
	set<int> s1;
	s1.insert(1);
	s1.insert(4);
	s1.insert(3);
	s1.insert(2);
	s1.insert(5);
	s1.insert(6);
	s1.insert(6);//如果插入set对象中已有元素,则插入失败
	for (auto it : s1)
	{
		cout << it << " ";
	}
	return 0;
}
//1 2 3 4 5 6

multiset类

1. multiset set 的使用 基本类似 ,主要区别点在于 multiset支持值冗余 ,那么 insert find count erase 都围绕着 支持冗余 有所差异。
2. insert 插入 multiset类对象 已有元素时,不会插入失败,而会正常插入。
3.  find 查找 multiset类对象 已有元素时, 若存在多个 则返回第一个元素的迭代器
4.  erase 删除 multiset类对象 已有元素时, 若存在多个 删除全部的该元素
5.  count 查找 multiset类对象 已有元素时, 若存在多个 则会返回该元素的个数
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <set>
using namespace std;

int main()
{
	multiset<int> m1;
	m1.insert(1);
	m1.insert(1);
	m1.insert(2);
	m1.insert(3);
	m1.insert(3);
	m1.insert(4);
	m1.insert(5);
	m1.insert(6);
	m1.insert(2);
	m1.insert(4);
	for (auto e : m1)
	{
		cout << e << " ";
	}
	cout << endl;
	auto it = m1.find(3);
	cout << *it << endl;
	cout << m1.count(1) << endl;
	m1.erase(2);
	for (auto e : m1)
	{
		cout << e << " ";
	}
	cout << endl;
	return 0;
}

map类

map类的介绍 

1. 在使用map类时,必须包含 #include <map> 这一行。

2. map类的底层其实是一个红黑树结构,使用时需要显示实例化

3. 下面是map类的官方文本介绍,里面有详细的用法讲解。

- C++ Referencehttps://legacy.cplusplus.com/reference/map/

pair类型的介绍 

1. map底层使用红黑树来存储数据,每个节点存储一个键值对,数据类型为 pair<Key,T>

template <class T1,class T2>
struct pair
{
	typedef pair<T1, T2> pair;
	T1 _first;
	T2 _second;
	pair()
		:_first(T1())
		, _second(T2())
	{}
};

map类对象的常见构造

1. map<string,string> s1,什么也不需要传入,构造一个空的map类对象

2. map<string,string> s2(s1.begin(),s1.end()),使用另一个map类对象进行迭代器构造

3. map<string,string> s3(const map<string,string>& s2),使用另一个map类对象进行拷贝构造

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <map>
using namespace std;

int main()
{
	map<string, string> m1;
	map<string, string> m2(m1.begin(),m1.end());
	map<string, string> m3(m2);
	return 0;
}

1. map类对象的初始化分为两种。 

2. 如果使用号,则为拷贝初始化;如果不使用号,则为直接初始化。 

3. map类对象拷贝初始化时,需要使用大括号包裹初始化的键值对

4. map类对象赋值初始化时,需要使用大括号包裹而非括号

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <map>
using namespace std;

int main()
{

	//map<string, string> m1 = {"1","难绷"};
	map<string, string> m1{{ "1", "难绷" }};
	auto it = m1.begin();
	while (it != m1.end())
	{
		cout << it->first << " ";
		it++;
	}
	cout << endl;
	for (auto e : m1)//e的类型和m1相同
	{
		cout << e.first << " ";
	}
	return 0;
}

map容器的修改操作 

1. map.insert({key,value})向map类对象中插入键值对如果插入map类对象已有的键则插入失败

2. map.find(key)检查map类对象中是否存在某个特定的键key效率为log(N)返回一个迭代器

3. set.count(key)检查map类对象中是否存在某个特定的键key返回1或者0

4. set.erase(key)map类对象中删除键为key的键值对如果删除map类对象没有键key则删除失败

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <map>
using namespace std;

int main()
{
	map<string, string> m1{{ "right","右边" }};
	m1.insert({ "left","左边" });
	//m1.insert({ "left","2边" });向map类对象中插入已有的键,插入失败
	m1.insert({ "front","前面" });
	m1.insert({ "back","后面" });
	if (m1.count("front"))
	{
		auto it = m1.find("front");
		cout << it->first << " : " << it->second << endl;
	}
	m1.erase("front");
	//m1.erase({ "hehe","2边" });向map类对象中删除未有的键,删除失败
	if (m1.count("front"))
	{
		auto it = m1.find("front");
		cout << it->first << " : " << it->second << endl;
	}
	return 0;
}

map类对象的遍历操作 

1. map类支持迭代器操作迭代器遍历走二叉搜索树的中序遍历因此默认为升序

2. map.begin()map.end()map.begin()获取第一个元素的迭代器,map.end()获取最后一个元素的下一个位置的迭代器。

3. map.rbegin()map.rend()map.rbegin()获取最后一个元素的迭代器,map.rend()获取第一个元素的上一个位置的迭代器。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <map>
using namespace std;

int main()
{	
	map<string, string> m1 = { {"1","难绷"},{"2","难说"},{"3","难道"} };
	auto it = m1.begin();
	while (it != m1.end())
	{
		cout << it->first << " ";
		it++;
	}
	cout << endl;
	for (auto e : m1)//e的类型和m1相同
	{
		cout << e.first << " ";
	}
	return 0;
}

map类对象的数据修改

1. map支持修改value值,不支持修改key键,如果修改关键字数据,就破坏了底层搜索树的结构。

2. map 还有⼀个非常重要的修改接口 [ ] ,但是  [ ]  不仅仅支持修改,还支持插入数据和查找数据,它是⼀个多功能复合接口。
3.  insert() 插入⼀个 pair<key,value>对象
  • 如果key已经在map中,插入失败,则返回⼀个pair<iterator,bool>对象first是key所在结点的迭代器second是false
  • 如果key不在在map中,插入成功,则返回⼀个pair<iterator,bool>对象first是新插入key所在结点的迭代器second是true
  • 无论插入成功还是失败,返回的pair<iterator,bool>对象的first都会指向key键所在的迭代器
  • 也就意味着insert插入失败时充当了查找的功能,正是因为这⼀点,insert可以用来实现 [ ]
  • 需要注意的是这里有两个pair,⼀个是map底层红黑树节点中存的pair<key,T>,另⼀个是insert返回值pair<iterator,bool>
mapped_type& operator[] (const key_type& k)
{
    pair<iterator, bool> ret = insert({ k, mapped_type() });
    iterator it = ret.first;
    return it->second;
}
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <map>
using namespace std;

int main()
{
	map<string, string> m1{ {"apple","苹果"} };
	m1["pear"] = "梨子";
	m1["left"] = "左边";
	m1["banana"] = "香蕉";
	m1["left"] = "左边、剩下";
	for (auto e : m1)
	{
		cout << e.second << endl;
	}
	return 0;
}

 

 

相关文章:

  • Vue 技术解析:从核心概念到实战应用
  • ArrayList 和 数组 的区别
  • Vue 3 + TypeScript 实现一个多语言国际化组件(支持语言切换与内容加载)
  • 【Linux系统】进程概念
  • qt designer 创建窗体选择哪种屏幕大小
  • Golang|抽奖相关
  • 路由器端口映射的意思、使用场景、及内网ip让公网访问常见问题和解决方法
  • 项目部署-(二)Linux下SpringBoot项目自动部署
  • MySQL流程控制
  • 如何管理“灰色时间”导致的成本漏洞
  • SOLID原则详解:提升软件设计质量的关键
  • 【DDR 内存学习专栏 1.3.1 -- DDR 的 Bank 及 burst 访问】
  • 空间信息可视化——WebGIS前端实例(一)
  • 基于Nacos+动态线程池的分布式系统弹性设计:投行交易与风控场景实战
  • 安当TDE透明加密技术:企业机密文件和数据库加密解决方案
  • 大数据学习栈记——Redis安装及其使用
  • MVCC是什么?MVCC的作用是什么?MVCC实现方式有哪些?
  • 批量将多个文件转成压缩包,支持批量设置压缩密码
  • CSI-external-provisioner
  • 从零开始学A2A一:A2A 协议概述与核心概念
  • 伊朗港口爆炸已造成281人受伤
  • 理想汽车副总裁刘杰:不要被竞争牵着鼻子走,也不迷信护城河
  • 今年一季度全国结婚登记181万对,较去年同期减少15.9万对
  • 破解160年基因谜题,我国科学家补上豌豆遗传研究最后拼图
  • 刘非履新浙江省委常委、杭州市委书记,曾在吉湘云多省任职
  • 政治局会议:积极维护多边主义,反对单边霸凌行径