map与set的基本应用
来源:互联网 发布:沈航网络自助 编辑:程序博客网 时间:2024/06/16 12:14
map与set的使用与原理
set
一种底层为二叉搜索树中红黑树的C++标准容器,其模板参数有三个: T(存储在容器中的关键词的数据类型)、Compare((提供比较元素的函数决定元素在容器中的相对位置)、Alloc(存储管理设备)。
成员变量
成员函数
这里对set的部分函数功能进行测试说明
首先,进行基本的 添加数据、迭代器的建立与使用。
#include<iostream>using namespace std;#include<set>void TestSet(){ set<int> s1; s1.insert(5); s1.insert(2); s1.insert(0); s1.insert(1); s1.insert(6); set<int>::iterator it1 = s1.begin(); while (it1 != s1.end()) { cout << *it1 << " "; ++ it1; } cout << endl;}int main(){ Test(); return 0;}
调试运行后结果显示为:
set中迭代器的++与–重载使用的是 中序遍历 进行移动,从而我们打印时得到一个顺序的结果,而当我们改变Compare,进行一个greater的重载并手动调用时,可实现降序的打印
typedef set<int,greater<int>> Set;void TestSet(){ Set s1; s1.insert(5); s1.insert(2); s1.insert(0); s1.insert(1); s1.insert(6); Set::iterator it1 = s1.begin(); while (it1 != s1.end()) { cout << *it1 << " "; ++ it1; } cout << endl;}
并且,set还具有 防冗余功能,当对6进行重复插入时
Set s1; s1.insert(5); s1.insert(2); s1.insert(0); s1.insert(1); s1.insert(6); s1.insert(6); s1.insert(6); s1.insert(6);
仍然只有一个6被记录,这里是由于Insert的返回值为 pair类型
pair为一个具有两个模板参数的结构体
在进行插入时,若在原容器中查到了当前添加内容,则pair中第二个参数会返回false表示已经存在一个当前内容。
而我们也可以看到Insert中也存在两个重载,分别 可以进行指定位置插入并返回一个指向位置的定位器、特定区间插入,将两哥迭代器中的内容插入;
int pos = 10; for (int pos = 0; pos < 14; pos++) s1.insert(s1.end()--, pos);
Set s1; s1.insert(5); s1.insert(2); s1.insert(0); s1.insert(1); s1.insert(6); vector<int> v1; v1.insert(v1.begin(),99); v1.insert(v1.begin(), 98); v1.insert(v1.begin(), 97); s1.insert(v1.begin(), v1.end());
map
map与set有很多相同之处,因此这里着重介绍两者的差异
map存储的为一对数据K,V,而set为一个数据K。
void TestMap(){ map<string, int> m1; m1.insert(pair<string, int>("const", 0)); m1.insert(pair<string, int>("set", 0)); m1.insert(pair<string, int>("air", 0)); m1.insert(pair<string, int>("map", 0)); map<string, int>::iterator it1 = m1.begin(); while (it1 != m1.end()) { cout << it1->first << ":" << it1->second << endl; ++it1; }}int main(){ TestMap(); return 0;}
也因此map在使用是可以重复输入,将 多次出现的数据次数记以进第二个参数位置 ,我们可以进行一些统计工作,譬如单词出现的次数:
①使用find函数,当发现已经存在数据时进行加一
string str[] = { "one", "two", "four", "four", "two", "four", "four" }; map<string, int> CountMap; for (size_t i = 0; i < sizeof(str) / sizeof(str[0]); i++) { map<string, int>::iterator it = CountMap.find(str[i]); if (it != CountMap.end()) (*it).second++; }
当然我们在set中曾提过,Insert的返回值也为一对数据切插入失败时会在第二个数据返回false,由此进行优化:
②利用Insert的返回值
void TestMap(){ string str[] = { "one", "two", "four", "four", "two", "four", "four" }; map<string, int> CountMap; pair<map<string, int>::iterator, bool> ret; for (size_t i = 0; i < sizeof(str) / sizeof(str[0]);i++) { ret = CountMap.insert(pair<string,int>((str[i]), 1)); if (ret.second == false) ret.first->second++; } map<string, int>::iterator it1 = CountMap.begin(); while (it1 != CountMap.end()) { cout << it1->first << ":" << it1->second << endl; ++it1; }}int main(){ TestMap(); return 0;}
然而在map中,已经对这种操作进行了整理,放在了 [ ]的重载中,其底层实现与我们的第二种方法完全一致
③使用[ ]的重载
string str[] = { "one", "two", "four", "four", "two", "four", "four" }; map<string, int> CountMap; for (size_t i = 0; i < sizeof(str) / sizeof(str[0]);i++) { CountMap[str[i]]++; }
如此也可以得到与②同样的结果
简单应用
eg:求水果出现的次数且求出前N个最多的
首先由上述map中的方法,可以进行次数统计
int main(){ map<string, int> map1; vector<map<string, int>::iterator> v; string strs[] = { "葡萄", "梨", "桃", "西瓜", "菠萝", "西瓜", "梨", "橘子", "香蕉", "梨", "香蕉","椰子", "梨", "苹果", "菠萝", "香蕉", "橘子", "桃子", "苹果", "桃", "橘子", "葡萄", "橘子", "荔枝", "苹果", "荔枝", "橘子" }; for (size_t i = 0; i < sizeof(strs)/sizeof(strs[0]); i++) { map1[strs[i]]++; } return 0;}
接下来只需要将map1中的水果根据value,即第二个参数进行排序即可,方法众多,下文使用堆排序进行处理
typedef struct Compare{ bool operator()(map<string, int>::iterator l, map<string, int>::iterator r) { return l->second > r->second; }}Compare;void GetTopN(map<string, int>& m, size_t n, vector<map<string, int>::iterator>& v){ map<string, int> ::iterator it = m.begin(); for (size_t i = 0; i < n; ++i) { v.push_back(it); it++; } make_heap(v.begin(), v.end(), Compare()); while (it != m.end()) { if (it->second > v.front()->second) { pop_heap(v.begin(), v.end(), Compare()); v.pop_back(); v.push_back(it); push_heap(v.begin(), v.end(), Compare()); } it++; }}
使用堆排序将前N种水果插入,最后打印vector容器中的元素即可
在主函数中调用并打印
GetBeginOfNFruits(map1, 5, v); for (size_t i = 0; i < v.size(); ++i) { cout << v[i]->first << "-" << v[i]->second << endl; }
最终结果
- map与set的基本应用
- Set与Map的基本用法
- java list set map的区别与应用
- Java Set,List,Map的区别与应用
- Java Set,List,Map的区别与应用
- map与set的简单综合应用,统计单词词频
- Map的基本应用
- set容器与map容器基本操作
- set与map的比较
- map与set的使用
- 【STL】set map的基本用法
- 【STL】map和set的基本用法
- 十四、符号表Map(Set)的应用
- list、set、map集合的综合应用
- java Set List 和 Map的区别与应用(转载)
- hibernate Set与Map的排序
- List, Map, Set与Iterator的使用
- list set与map的异同
- codeforces 730 A Toda 2
- mybatis解决insert时候空值问题
- C++抽象工厂模式(abstract factory patterns)实现
- 最长上升子序列
- Android listView 的使用
- map与set的基本应用
- HDU 1109 Run Away 模拟退火算法
- mysql int,datetime,timestamp时间戳、时间日期相关总结分析
- Spring MVC学习
- 380. Insert Delete GetRandom O(1)
- FEA大数据实践之亿级数据量处理
- 1078. Hashing (25)
- 数据库
- if __name__ == '__main__' 如何正确理解?