map和set

在这里插入图片描述

set就是key模型的搜索树
map就是key_value模型的搜索树
但是他们的底层不是搜索二叉树,是AVL树和红黑树!

map和set insert不会迭代器失效
erase会迭代器失效

1.set

1.1 set及使用

在这里插入图片描述
T: set中存放元素的类型,实际在底层存储<value, value>的键值对。
Compare:set中元素默认按照小于来比较
Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

  1. set是按照一定次序存储元素的容器
  2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。
    set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
  3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行 排序。
  4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对 子集进行直接迭代。
  5. set在底层是用二叉搜索树(红黑树)实现的
  6. 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放
    value,但在底层实际存放的是由<value, value>构成的键值对。
  7. set中插入元素时,只需要插入value即可,不需要构造键值对。
  8. set中的元素不可以重复(因此可以使用set进行去重)。

set的一些使用如下:
在这里插入图片描述

1.2 multiset及使用

multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。这就是和set最大的区别!
在这里插入图片描述

2.map

2.1 map及使用

在这里插入图片描述

  1. map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元 素。
  2. 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的 内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型
    value_type绑定在一起,为其取别名称为pair: typedef pair<const key, T> value_type;
  3. 在内部,map中的元素总是按照键值key进行比较排序的。
  4. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序 对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
  5. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
  6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

map允许修改迭代器,如下图value_type就是一个pair!所以pair<k,v>相当于这样存!
在这里插入图片描述
所以insert的时候就要注意,其使用如下:

#include<iostream>
#include<map>
#include<vector>
using namespace std;

void test_map1()
{
	map<string, string> dict;
	pair<string, string> kv1("sort", "排序");
	dict.insert(kv1);//1.定义有名对象

	dict.insert(pair<string, string>("left", "左边"));//2.定义匿名对象

	dict.insert(make_pair("right", "右边"));//3.make_pair定义(函数模板)
	dict.insert(make_pair("right", "xxxx"));

	//pair<string, string> kv2 = { "string", "字符串" };	// 4.隐式类型转换
	dict.insert({ "string", "字符串" });

	//map<string, string>::iterator it = dict.begin();
	auto it = dict.begin();
	while (it != dict.end())
	{
		// iterator key不能修改 value可以修改
		// const_iterator key不能修改 value不能修改
		//it->first += 'x';//first不能修改,second可以修改
		it->second += 'x';

		//cout << *it << " ";//这样是不行的,因为有一个key有一个value!
		//cout << (*it).first << ":" << (*it).second << endl;//可以
		cout << it->first << ":" << it->second << endl;//写全如下↓
		//cout << it.operator->()->first << ":" << it.operator->()->second << endl;
		++it;
	}
	cout << endl;

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

	//map<string, string> dict2 = { {"string", "字符串"}, {"left", "左边"},{"right", "右边"} };
	map<string, string> dict2 = { kv1, {"left", "左边"},{"right", "右边"} };
}

int main()
{
	test_map1();

	return 0;
}

在这里插入图片描述

void test_map2()
{
	string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "香蕉","苹果","草莓", "苹果","草莓" };
	map<string, int> countMap;
	for (auto& e : arr)
	{
		//统计方法1
		countMap[e]++;
		
		//统计方法2
		//auto it = countMap.find(e);
		//if (it != countMap.end())
		//{
		//	it->second++;
		//}
		//else
		//{
		//	//const pair<string, int>& val = { e, 1 };
		//	countMap.insert({ e, 1 });
		//}
	}

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

	//对次数排序
	multimap<int, string> sortMap;//使用multimap是因为其可以冗余,map不能冗余会发生数据丢失
	for (auto& kv : countMap)
	{
		//sortMap[kv.second] = kv.first;
		sortMap.insert({ kv.second, kv.first });
	}
	cout << endl;

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


int main()
{
	test_map2();

	return 0;
}

在这里插入图片描述

void test_map3()
{
	map<string, string> dict;
	dict.insert({ "string", "字符串" });

	// 插入(一般不会这么用)
	dict["right"];

	// 插入+修改
	dict["left"] = "左边";

	// "查找"
	cout << dict["string"] << endl;

	// 修改
	dict["right"] = "右边";

	string str;
	cin >> str;
	if (dict.count(str))
	{
		cout << "在" << endl;
	}
	else
	{
		cout << "不在" << endl;
	}
}

在这里插入图片描述

2.2 multimap及使用

与map最大区别就是可以有数据冗余!其中元素是可以重复的!
见上面的排序!
在这里插入图片描述

3.关于operator[]

在这里插入图片描述

对于其使用可以来看下面两道例题:

3.1 例一

在这里插入图片描述

class Solution {
public:
    struct kvcom
    {
        bool operator()(const pair<string,int>&kv1,const pair<string,int>&kv2)
        {
            //降序排列,从大到小排列
            return kv1.second > kv2.second || 
            (kv1.second==kv2.second && kv1.first < kv2.first);
        }
    };

    vector<string> topKFrequent(vector<string>& words, int k) 
    {
        map<string,int> countMap;
        for(auto& e:words)
        {
            countMap[e]++;
        }

        vector<pair<string,int>> v(countMap.begin(),countMap.end());
        sort(v.begin(),v.end(),kvcom());

        vector<string> res;
        for(size_t i=0;i<k;i++)
        {
            cout<<v[i].first<<":"<<v[i].second<<endl;
            res.push_back(v[i].first);
        }
        return res;
    }
};

3.2 例二

在这里插入图片描述

#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;

//仿函数控制比较
struct comp
{
    bool operator()(const pair<string, int>& kv1, const pair<string, int>& kv2)
    {
        return kv1.second > kv2.second || (kv1.second == kv2.second && kv1.first < kv2.first);
    }
 
};

int main() 
{
    string s;
    getline(cin,s);

    for(auto& e:s)
    {
        if(e>='A' && e<='Z')
        e += 32;
    }
    
    vector<string> v;
    for(int i=0;i<s.size();i++)
    {
        string tmp;
        while(s[i]!=' ' && s[i]!='.')
        {
            tmp += s[i];
            i++;
        }
        v.push_back(tmp);
    }

    map<string,int> m;
    for(auto& e:v)
    {
        m[e]++;
    }

     //sort+仿函数排序
    vector<pair<string, int>> vv(m.begin(), m.end());
    sort(vv.begin(), vv.end(), comp());

    for (int i = 0; i < vv.size(); ++i)
    {
        cout << vv[i].first << ":" << vv[i].second << endl;
    }
    return 0;
}

  • 29
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Chris·Bosh

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

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

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

打赏作者

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

抵扣说明:

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

余额充值