c++:刷题必备 容器map的使用


map的概念

map是一个关联容器,里面的每一个位置pair,会存储两个值,一个是key,另一个是value.
我们可以通过搜索key得到value.

比如英语翻译的软件:输入一个英语单词 left(key),就能得到翻译 左边(value).
事实上,英语翻译软件底层也就是这样.

map的使用

构造在这里插入图片描述

	map<string, string> dict;

首先,map的构造需要我们传至少两种类型.
比如上面Key是string,T是string.

insert

	//构造有名对象
	pair<string, string> kv1 = { "left","左边" };
	dict.insert(kv1);
	//构造匿名对象
	dict.insert(pair<string, string>("right", "右边"));
	//函数传参
	dict.insert(make_pair("sort", "排序"));
	//隐式类型转化
	dict.insert({ "string", "字符串" });

map中为了使得两个值key-value关联到一起,会把它们绑定成一个类.
map的插入推荐用最后一种,隐式类型转化.
隐式类型转化本质是就是在传参时构造一个pair的临时对象,与上面构造匿名对象等类似.

迭代器+遍历

void test_map1()
{
	map<string, string> dict;
	//构造有名对象
	pair<string, string> kv1 = { "left","左边" };
	dict.insert(kv1);
	//构造匿名对象
	dict.insert(pair<string, string>("right", "右边"));
	//函数传参
	dict.insert(make_pair("sort", "排序"));
	//隐式类型转化
	dict.insert({ "string", "字符串" });

	map<string, string>::iterator it = dict.begin();
	while (it != dict.end())
	{

		cout << it->first << ":" << it->second << endl;
		//cout << it.operator->()->first << ":" << it.operator->()->second << endl;
		it++;
	}
}

map的迭代器使用和vector等容器类似.但是因为map里面存储的是键值对<key,value>,所有打印起来比较麻烦.

		cout << it->first << ":" << it->second << endl;
		//cout << it.operator->()->first << ":" << it.operator->()->second << endl;

这两行代码可能理解起来稍微复杂一点.
key是first,value是second,这里是按照存储顺序排列.
我们一个键值对<key,value>和其他一堆东西的组合想象成一个节点.it是一个指针,指向这个节点.
map类里面写的运算符重载it.operator->()会返回键值对<key,value>的指针,用这个指针可以指向key和value
.我们在使用可以直接省略.operator->().

理解了这个,就能更好的理解下面的范围for

	for (auto& e : dict)
	{
		cout << e.first << ":" << e.second << endl;
	}

e相当于键值对<key,value>的引用.这个的底层和上面类似.只不过在书写方面简单一些.
在这里插入图片描述

find

	//map<string, string>::iterator pos = dict.find("left");
	auto pos = dict.find("left");
	if (pos != dict.end())
	{
		cout << pos->first << ":" << pos->second << endl;
	}

find输入key值,找到会返回该节点的迭代器,找不到会返回迭代器的终点dict.end().

operator[]

operator[]是map里面内置的最强的函数,在我们刷题时帮助巨大.
首先看看operator的底层

//V& operator[](const K& key)
//{
//	pair<iterator, bool> ret = insert({ key ,V() });
//	iterator it = ret.first;
//	return it.second;
//}

operator[]会调用insert函数,insert函数里面传key值和value的默认构造.
不管插入是否成功,都会返回键值对pair<iterator, bool>,
bool里面表示插入成功与否,
iterator则返回key值所在的节点的迭代器.我们取得这个迭代器,然后返回value的引用.

void test_map2()
{
	//string可以直接构造字符串数组
	string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "香蕉","苹果","草莓", "苹果","草莓" };
	map<string, int> kv;
	//按字典序排序
	for (auto& e : arr)
	{
		//V& value=kv[e] value++;
		kv[e]++;
	}
	for (auto& e : kv)
	{
		cout << e.first << ":" << e.second << endl;
	}
}

在这里插入图片描述

举例

leetcode: 692. 前K个高频单词
在这里插入图片描述
在计算单词出现次数时,要把单词和出现次数链接起来,就得用到map.

class Solution {
public:
//仿函数,控制比较逻辑
struct Com
{
     //出现次数大的在前面,一样按照字典序小的在前面.
    bool operator()(pair<string,int>& p1,pair<string,int>&p2)
    {
        return p1.second>p2.second 
        || (p1.second==p2.second && p1.first<p2.first);
    }
};
    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string,int> m;
        for(auto& e:words)
        {
            //map里面的[]调用insert函数,这个函数会返回第二个值的引用
            m[e]++;
        }
        //把map里面的键值对存到vector进行排序
       
        vector<pair<string,int>> vp(m.begin(),m.end());

        //函数模板要传对象
        sort(vp.begin(),vp.end(),Com());
        vector<string> ret;
        for(size_t i=0; i<k; i++)
        {
            ret.push_back(vp[i].first);
        }
        return ret;
    }
};
  • 30
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

海的宇宙

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

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

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

打赏作者

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

抵扣说明:

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

余额充值