c++ STL容器 --- 单映射map、多重映射multimap

包含头文件<map>

映射代表的是一种关系,有点类似哈希结构(数据的一个抽象地址和这个元素的一个关系)

也可以把它叫做关联式容器

map<int, string> mapData;    //创建一个map容器

map 里面存储的数据是一个数对类型

在 c++ 当中有一个数对类型的结构体,pair 类型:两种类型的模板类,把两个类型强制关联在一起,第一个 first,第二个  second,要用两个类型去做实例化

#include <map>
#include <iostream>
#include <graphics.h>
using namespace std;
//模板类 第一个类型 第二个类型
template <class _Ty1, class _Ty2>
struct MyPair 
{
	_Ty1 first;
	_Ty2 second;
	MyPair(_Ty1 first, _Ty2 second) :first(first), second(second) {}
};

void testPair() 
{
    //构建一个pair对象-> 两个类型的未知类型
    //用 int 对应 string-> 对应关系
	pair<int, string> pData(1, "string");
	MyPair<int, string> myPData(1, "string");
    //访问数据
	cout << pData.first << " " << pData.second << endl;
}

int main() 
{
	testMap();
	testUserData();
	testmultimap();
	return 0;
}

map 的创建与使用

自带排序,默认从小到大

数据唯一性(单映射可以避免出现重复现象)

map 有 3 种插入方式:

要把数据插入到 map 当中,一定是把数据构建成一个数对类型,才能插到 map 容器中

1.用 insert 函数做插入

2.用make_pair外部的(模板函数,需要传参)函数构建数对插入

3.单映射(自己独特的插入方式),可以直接采用数组下标的方式进行插入,map 相比数组来说,这个下标是没有任何要求(因为内部做了重载)

下标可以是负数,并且一般不好用 for 循环去做打印(由于下标可以没有规律,避免用 for 循环去做打印)

mapData[键] = 值; 

mapData[-1] = string( "string - 1"(构建一个 string 类型的对象));

-1 是键(first),"string - 1" 是值 (second)

map[ first ] = second;就是 first 对应 second

数组在一定程度上来说可以算是一种映射

相同的键采用的是覆盖方式(如果存在相同的键,会保留最后一次插入的值),由于比较是根据键去比较的,和值没有关系(把第一个数据叫做键,第二个数据叫做值)

实际使用中更多是用键去存储一些东西:Easyx-----c++实现推箱子_小雪菜本菜的博客-CSDN博客_easyx推箱子

map<string, IMAGE*> img;
img["墙"] = new IMAGE;   直接用墙对应一个 IMAGE 类型的数据,使用的时候,直接用img["墙"]即可,img["墙"]等效于键的值
img["路"] = new IMAGE;   加载资源
putimage(0, 0, img["墙"]); 在某一个位置贴一张图片,直接使用 img["墙"]
putimage(0, 0, img["路"]);
music["开始"] = "./res/game_mudic.mp3";  每一个音乐文件对应一个路径

Easyx-----c++实现飞机大战_小雪菜本菜的博客-CSDN博客_飞机大战掩码图

在做一些游戏的时候,这个游戏可能比较大,它里面有很多音乐文件,每一种音乐文件的操作方式可能不太一样。用 map 管理资源是极其合适的,因为我们可以直接去操作资源,存储图片也是一样的,map 可以存在任何对应关系,例如可以用 string 对应一个函数指针,可以用 string 对应一个图片资源. . .

在图形库中,可能会因为资源太多,分不清楚哪一个变量名表示哪一个资源,用 map 操作就可以避免这个尴尬的情况(使用 map,关联性比较强)

之前可能是数组去存储,数组的弊端就是下标是一个整数,可区分性太低,在写项目的时候可能写着写着就忘记某一个下标代表的是什么,用映射关系就不存在这种问题

map 的特性:可以通过键的方式去访问值,因为就是一个键对应一个值,用对象 + 下标的方式就是访问值

参数:数据类型、数据类型、比较准则、分配器

void testMap() 
{
    //传入两个未知类型做实例化-> 数对类型
	map<int, string> mapData;
	map<int, string, less<int>> mapData1;        //和上面创建方式一样,从小到大
	map<int, string, greater<int>> mapData2;     //从大到小
	//1.用insert函数做插入-> 要插入一个数对类型 需要把数据构建成pair类型的对象
	mapData.insert(pair<int, string>(1, "string"));
	//2.make_pair构建数对插入
	mapData.insert(make_pair<int, string>(3, "string3"));
	//3.单映射,可以直接采用数组下标的方式进行插入
	mapData[-1] = string("string-1");            //等效插入一个数对类型
	//上面代码等效: mapData.insert(pair<int,string>(-1,"string-1"))  
	mapData[1] = "string1";		                 //相同键 采用的是覆盖方式
	//迭代器遍历
	for (auto iter = mapData.begin(); iter != mapData.end(); iter++) 
	{
		//*iter指的是pair类型-> 先打印它里面的键 再打印它里面的值
		cout << iter->first << " " << iter->second<<endl;
	}   
	for (auto v : mapData) 
	{
		cout << v.first << "\t" << v.second << endl;
	}
    //通过键的方式去访问值
	cout << mapData[1] << endl;                    //用的时候直接使用即可
    //用erase函数去做删除-> 通过键去做删除 传入键 删除1这个位置
	mapData.erase(1);
	for (auto v : mapData)
	{
        //v是一个结构体用.的方式访问
		cout << v.first << "\t" << v.second << endl;
	}
	cout << endl;
}
/* 输出 */

-1 string-1
1 string1
3 string3

-1      string-1
1       string1
3       string3

string1
/* 1 string1 被删除了 */
-1      string-1
3       string3

map 存储自定义类型数据

做一个匹配,一个 MM 对应一个 Boy

map 中可以任何关系相对应,只要你觉得它们之间可以形成关联

需要重载,由于整个 map 的排序是采用 MM 去排序的,MM 有两个属性,可以通过 name 的方式去排序(按照什么方式比较可以随便写),就需要重载

不是说随便重载一个,Boy 是没有排序效果的,只有键才有排序效果,所以应该是重载键里面的比较(不是说把重载随便写到哪个类里面都可以)

//MM类
class MM
{
public:
	MM() = default;
	MM(string name, int age) :name(name), age(age) {}
	void print() const /* 对象含有与成员函数"MM::print"不兼容的类型限定符 对象类型是: const MM */
	{
		cout << name << "\t" << age << endl;
	}
    //按照姓名的方式比较
	bool operator<(const MM& object)const 
	{
		return this->name < object.name;
	}
protected:
	string name;
	int age;
};
//Boy类
class Boy
{
public:
	Boy() = default; /* "Boy::Boy" 没有合适的默认构造函数可用 */
	Boy(string name, int age) :name(name), age(age) {}
	void print() const
	{
		cout << name << "\t" << age << endl;
	}
protected:
	string name;
	int age;
};
void testUserData() 
{
    //用MM对应Boy
	map<MM, Boy> mbData;
    //下标法使用
    //MM对象这个键对应一个值-> 对应一个Boy对象
	mbData[MM("小美", 19)] = Boy("小张", 29);
    //打印Boy的信息 mbData[MM("小美", 19)]等效Boy对象-> Boy对象调用成员函数print是没有什么问题的
	mbData[MM("小美", 19)].print();
    //只要类型上对应都可以采用下标法去访问
	mbData[MM("小丽", 20)] = Boy("小明", 18);
    //打印所有的信息
	cout << "配对信息:" << endl;
	for (auto v : mbData) 
	{
		//容器管理自定义类型数据
		//v代表数对类型:pair<MM,Boy> v是常属性的
		//v.frist:MM对象 应该调用成员函数去做打印
		//v.second:Boy对象
		v.first.print();
		v.second.print();
	}
}

/* 输出 */

小张    29
配对信息:
小丽    20
小明    18
小美    19
小张    29

多重映射

多重映射,没有什么限制,什么样对应关系都可以插入到这个映射容器中。只有单纯的排序功能
多重映射的弊端:因为存在相同的键,所以不能采用下标法插入(由于存在相同的键,所以在用下标法访问的时候,分不清楚把值插到哪个键里面去了)

void testmultimap() 
{
	multimap<int, string>  mulData;
    //其他操作一样
	mulData.insert(pair<int, string>(1, "string"));
	mulData.insert(pair<int, string>(1, "string1"));
	mulData.insert(pair<int, string>(2, "string"));
	mulData.insert(pair<int, string>(3, "string"));
	mulData.insert(make_pair<int, string>(3, "string"));
    //遍历
	for (auto v : mulData) 
	{
		cout << v.first << "\t" << v.second << endl;
	}
}

/* 输出 */
/* 所有的关系都会保留下来:两个1对应string */
1       string
1       string1
2       string
3       string
3       string
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

qiuqiuyaq

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

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

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

打赏作者

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

抵扣说明:

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

余额充值