声明:本文是在学习C++ STL–标准模板库的笔记,方便以后复习;主要参考《C++ Prime》、《C++标准库》、《黑马程序员匠心之作|C++教程从0到1入门编程》等。
简介:
pair
pair
中第一个元素为key
(键值),起到索引作用,第二个元素为value
(实值)本质:
map/multimap
属于关联式容器,底层结构是基于红黑树实现。优点:
key
值快速找到value
值map和multimap区别:
map
不允许容器中有重复key值元素multimap
允许容器中有重复key值元素使用map前要包含头文件:
#include
功能描述:
map
容器进行构造和赋值操作函数原型:
构造:
map mp;
//map默认构造函数:map(const map &mp);
//拷贝构造函数赋值:
map& operator=(const map &mp);
//重载等号操作符示例:
#include
#include
using namespace std;
void printMap(map<int,int>&m)
{
for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
{
cout << "key = " << it->first << " value = " << it->second << endl;
}
cout << endl;
}
void test01()
{
map<int,int>m; //默认构造
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
printMap(m);
map<int, int>m2(m); //拷贝构造
printMap(m2);
map<int, int>m3;
m3 = m2; //赋值
printMap(m3);
}
int main() {
test01();
system("pause");
return 0;
}
输出:
key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
总结: map中所有元素都是成对出现,插入数据时候要使用对组
功能描述:
函数原型:
size();
//返回容器中元素的数目empty();
//判断容器是否为空swap(st);
//交换两个集合容器示例:
#include
#include
using namespace std;
void printMap(map<int,int>&m)
{
for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
{
cout << "key = " << it->first << " value = " << it->second << endl;
}
cout << endl;
}
void test01()
{
map<int, int>m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
if (m.empty())
{
cout << "m为空" << endl;
}
else
{
cout << "m不为空" << endl;
cout << "m的大小为: " << m.size() << endl;
}
}
//交换
void test02()
{
map<int, int>m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
map<int, int>m2;
m2.insert(pair<int, int>(4, 100));
m2.insert(pair<int, int>(5, 200));
m2.insert(pair<int, int>(6, 300));
cout << "交换前" << endl;
printMap(m);
printMap(m2);
cout << "交换后" << endl;
m.swap(m2);
printMap(m);
printMap(m2);
}
int main() {
test01();
test02();
system("pause");
return 0;
}
输出:
m不为空
m的大小为: 3
交换前
key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
key = 4 value = 100
key = 5 value = 200
key = 6 value = 300
交换后
key = 4 value = 100
key = 5 value = 200
key = 6 value = 300
key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
总结:
功能描述:
函数原型:
insert(elem);
//在容器中插入元素。clear();
//清除所有元素erase(pos);
//删除pos迭代器所指的元素,返回下一个元素的迭代器。erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。erase(key);
//删除容器中值为key的元素。示例:
#include
#include
using namespace std;
void printMap(map<int,int>&m)
{
for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
{
cout << "key = " << it->first << " value = " << it->second << endl;
}
cout << endl;
}
void test01()
{
//插入
map<int, int> m;
//第一种插入方式
m.insert(pair<int, int>(1, 10));
//第二种插入方式
m.insert(make_pair(2, 20));
//第三种插入方式
m.insert(map<int, int>::value_type(3, 30));
//第四种插入方式
m[4] = 40;
printMap(m);
//删除
m.erase(m.begin());
printMap(m);
m.erase(3);
printMap(m);
//清空
m.erase(m.begin(),m.end());
m.clear();
printMap(m);
}
int main() {
test01();
system("pause");
return 0;
}
输出:
key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
key = 4 value = 40
key = 2 value = 20
key = 3 value = 30
key = 4 value = 40
key = 2 value = 20
key = 4 value = 40
总结:
功能描述:
函数原型:
find(key);
//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();count(key);
//统计key的元素个数示例:
#include
#include
using namespace std;
//查找和统计
void test01()
{
map<int, int>m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
//查找
map<int, int>::iterator pos = m.find(3);
if (pos != m.end())
{
cout << "找到了元素 key = " << (*pos).first << " value = " << (*pos).second << endl;
}
else
{
cout << "未找到元素" << endl;
}
//统计
int num = m.count(3);
cout << "num = " << num << endl;
}
int main() {
test01();
system("pause");
return 0;
}
输出:
找到了元素 key = 3 value = 30
num = 1
总结:
学习目标:
主要技术点:
示例:
#include
class MyCompare {
public:
bool operator()(int v1, int v2) {
return v1 > v2;
}
};
void test01()
{
//默认从小到大排序
//利用仿函数实现从大到小排序
map<int, int, MyCompare> m;
m.insert(make_pair(1, 10));
m.insert(make_pair(2, 20));
m.insert(make_pair(3, 30));
m.insert(make_pair(4, 40));
m.insert(make_pair(5, 50));
for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++) {
cout << "key:" << it->first << " value:" << it->second << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}
输出:
key:5 value:50
key:4 value:40
key:3 value:30
key:2 value:20
key:1 value:1
总结:
map的优点及缺点:
优点:
①、map
基于红黑树实现,红黑树具有自动排序的功能,因此map内部所有的数据,在任何时候,都是有序的;
②、map
内部实现基于红黑树,使得map的很多操作在lgn
的时间复杂度下就可以实现,因此效率非常的高。
缺点:
空间占用率高,因为map内部基于红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间。
应用场景:适用于有顺序要求的问题,使用map会更高效一些;
unordered_map的优点及缺点:
优点:
unordered_map
内部基于哈希表,所以数据插入和查找的时间复杂度很低,几乎是常数时间缺点:
代价是消耗比较多的内存,无自动排序功能。 底层实现上,使用一个下标范围比较大的数组来存储元素,形成很多的桶,利用hash
函数对key
进行映射到不同区域进行保存。
应用场景:对于查找问题,unordered_map
会更加高效一些。
map和unordered_map的使用
unordered_map
的用法和map
是一样的,提供了 insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。
#include
#include
#include
using namespace std;
int main()
{
// 声明unordered_map对象
unordered_map<string, int> M;
// 插入数据的三种方式
M.insert(pair<string, int>("A", 1));
M.insert(unordered_map<string, int>::value_type("B", 2));
M["C"] = 3;
// 判断是否有元素
if (M.empty())
cout << "无元素" << endl;
else
cout << "有" << M.size() << "个元素" << endl;
// 遍历
unordered_map<string, int>::iterator iter;
for (iter = M.begin(); iter != M.end(); iter++)
cout << iter->first << ends << iter->second << endl;
// 查找
if (M.count("A") == 0)
cout << "can't find A!" << endl;
else
cout << "find A!" << endl;
if ((iter = M.find("B")) != M.end())
cout << "B=" << iter->second << endl;
else
cout << "can't find B!" << endl;
return 0;
}
输出:
有3个元素
A1
B2
C3
find A!
B=2
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
#include
#include
#include
#include
#include
using namespace std;
class Solution
{
public:
int lengthOfLongestSubstring(vector<char>& s)
{
int res = 0; // res记录最长无重复子串的长度
size_t left = 0; // left表示最左边的位置
unordered_map<char, size_t> m; // 无序的哈希表
for (int i = 0; i < s.size(); i++)
{
left = max(left, m[s[i]]);//left只能往前移动,不能后移
m[s[i]] = i + 1;//更新字符对应的下标为:当前字符串最新出现该字符的下标
res = max(res, int(i - left + 1)); //求出最大值
}
return res;
}
};
int main()
{
vector<char> str;
string s = "abcdabcdbb";
for (int i = 0; i < s.size(); i++)
{
str.push_back(s[i]);
}
Solution S1;
int nums = S1.lengthOfLongestSubstring(str);
cout << "最长无重复子串的长度为: " << nums << endl;
return 0;
}
输出:
字符串最的长无重复子串的长度为: 4
欢迎各位大佬关注我的公众号:Kevin的学习站,整理不易,但您的点赞、关注、收藏就是对我最大的鼓励!