set和map
Posted Y—X
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了set和map相关的知识,希望对你有一定的参考价值。
1. 键值对
用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。 比如一个英汉互译的字典,每个英文单词都对应着一个翻译val。
SGI-STL中关于键值对的定义:
template <class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair(): first(T1()), second(T2())
{}
pair(const T1& a, const T2& b): first(a), second(b)
{}
};
2. set
- set是按照一定次序存储元素的容器
- 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素
不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。 - 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。
- set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直
接迭代。 - set在底层是用二叉搜索树(红黑树)实现的
注意:1.set中的元素不可以重复(因此可以使用set进行去重)
2.set中的元素不允许修改(因为底层二叉搜索树,修改会改变结构)
2.1 set的使用
set的模板参数列表:
使用举例:
3.map的使用介绍
- map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。
- 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair: typedef pair value_type;
typedef pair<const Key, T> value_type;
- 在内部,map中的元素总是按照键值key进行比较排序的。
- map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行
直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。 - map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
- map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))
3.1map的插入
void testmap()
{
string strs[] = { "sort", "sort", "insert", "sort", "map", "sort", "map" };
map<string, int> countMap;
for (auto& s : strs)
{
auto ret = countMap.find(s);
if (ret != countMap.end())
{
ret->second++;
}
else
{
//countMap.insert(pair<string, int>(s, 1));
countMap.insert(make_pair(s, 1));
}
}
for (auto& e : strs)
{
pair<map<string, int>::iterator, bool> ret = countMap.insert(make_pair(e, 1));
if (ret.second == false)//插入失败,s已经在map中
{
ret.first->second++;
}
}
for (auto& e : countMap)
{
cout << e.first << ": " << e.second << endl;
}
}
运行结果:
3.2map的operator[]
string strs[] = { "sort", "sort", "insert", "sort", "map", "sort", "map" };
map<string, int> countMap;
for (auto& s : strs)
{
countMap[s]++;
}
for (auto& e : countMap)
{
cout << e.first << ": " << e.second << endl;
}
map[]有俩层作用:
1.如果k不在,插入pair(k,v())并且返回value的引用
2.如果k在,不插入,返回和k相等节点额value的引用
4.map的应用
问题描述:本公司现在要给公司员工发波福利,在员工工作时间会提供大量的水果供员工补充营养。由于水果种类
比较多,但是却又不知道哪种水果比较受欢迎,然后公司就让每个员工报告了自己最爱吃的k种水果,并且告知已经将所有员工喜欢吃的水果存储于一个数组中。然后让我们统计出所有水果出现的次数,并且求出大家最喜欢吃的前k种水果。
思路:利用map将所有的水果出现的次数统计起来,然后将map的迭代器放入vector之中,最后构造仿函数 ->second进行比较,利用sort进行排序。
void GetFavoriteFruit(const vector<string>& fruits, size_t k)
{
typedef map<string, int>::iterator CountMapIt;
map<string, int> countMap;
for (auto& e : fruits)
{
countMap[e]++;
}
//排序 vector + sort
vector<CountMapIt> v;
CountMapIt it = countMap.begin();//将map中迭代器放入数组之中
while (it != countMap.end())
{
v.push_back(it);
++it;
}
//仿函数
struct CountMapItCompare
{
bool operator()(const CountMapIt& it1, const CountMapIt& it2)
{
return it1->second > it2->second;
}
};
sort(v.begin(), v.end(), CountMapItCompare());//降序
for (auto& e : v)
{
cout << e->first << ": " << e->second << endl;
k--;
if (k == 0)
{
break;
}
}
}
int main()
{
const vector<string> v = { "西瓜","香蕉", "西瓜", "葡萄","葡萄","苹果", "葡萄","香蕉", "香蕉", "葡萄","西瓜", "榴莲","西瓜", "榴莲", "苹果", "葡萄", };
GetFavoriteFruit(v, 3);
return 0;
}
给一非空的单词列表,返回前 k 个出现次数最多的单词。
返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。
class Solution {
public:
vector<string> topKFrequent(vector<string>& words, int k) {
//1.用map统计单词出现的频率,map将单词按照ASCII进行了排序
map<string, int> countMap;
for(auto& e : words)
{
countMap[e]++;
}
//2.用multimap对单词出现的频率,排降序
multimap<int, string, greater<int>> sortMap;//排降序
for(auto& e : countMap)
{
sortMap.insert(make_pair(e.second, e.first));
}
vector<string> v;
auto it = sortMap.begin();
while(k--)
{
v.push_back(it->second);
it++;
}
return v;
}
};
以上是关于set和map的主要内容,如果未能解决你的问题,请参考以下文章
C++进阶第二十篇——map和set(map和set的用法+multimap+multiset+map和set代码实现)