在初阶阶段,我们已经接触过STL中的部分容器,比如:vector、list、deque、forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。那什么是关联式容器?它与序列式容器有什么区别?
关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是
用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。
比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义。
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)
{}
};
根据应用场景的不桶,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结构的关联式容器主要有四种:map、set、multimap、multiset。
这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。下面一依次介绍每一个容器。
set文档
void test_set3()
{
set<int> s;
s.insert(5);
s.insert(4);
s.insert(3);
s.insert(6);
s.insert(7);
s.insert(4);
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
set<int> copy(s);
for (auto e : copy)
{
cout << e << " ";
}
cout << endl;
}
void test_set2()
{
set<int> s;
s.insert(5);
s.insert(4);
s.insert(3);
s.insert(6);
s.insert(7);
s.insert(4);
cout << s.size() << endl;
cout << s.empty() << endl;
}
STL中六大组件中算法的find算法效率是O(N),而set的find接口效率是二叉搜索树,效率为logN。
void test_set1()
{
set<int> s;
s.insert(5);
s.insert(4);
s.insert(3);
s.insert(6);
s.insert(7);
s.insert(4);
set<int>::iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
it++;
}
cout << endl;
set<int>::iterator pos1 = s.find(3);
if (pos1 != s.end()) //有元素才删除
{
s.erase(pos1);
}
s.erase(5);
//s.erase(100);
set<int>::iterator pos2 = find(s.begin(), s.end(), 7);
s.erase(pos2);
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
s.erase(s.begin(), s.end());
}
map文档
void test_map1()
{
map<int, int> m;
m.insert(pair<int, int>(1, 1));
m.insert(pair<int, int>(2, 2));
m.insert(pair<int, int>(3, 3));
m.insert(make_pair(4, 4));
map<int, int>::iterator it = m.begin();
while (it != m.end())
{
cout << (*it).first << ":" << (*it).second << endl;
cout << it->first << ":" << it->second << endl;
it++;
}
for (auto e : m)
{
cout << e.first << ":" << e.second << endl;
}
}
函数声明 | 功能简介 |
---|---|
bool empty ( ) const | 检测map中的元素是否为空,是返回true,否则返回false |
size_type size() const | size_type size() const |
– | – |
mapped_type& operator[] (constkey_type& k) | 返回去key对应的value |
void test_map3() //第一种方法
{
string str[] = { "西瓜", "西瓜", "菠萝", "西瓜", "西瓜", "西瓜", "苹果", "苹果" };
map<string, int>countMap;
for (auto& e : str)
{
map<string, int>::iterator pos = countMap.find(e);
if (pos != countMap.end())
{
pos->second++;
}
else
{
countMap.insert(pair<string, int>(e, 1));
}
}
for (auto e : countMap)
{
cout << e.first << ":" << e.second << endl;
}
}
void test_map4()
{
string str[] = { "西瓜", "西瓜", "菠萝", "西瓜", "西瓜", "西瓜", "苹果", "苹果" };
map<string, int>countMap;
for (auto e : str)
{
countMap[e]++;
}
for (auto e : countMap)
{
cout << e.first << ":" << e.second << endl;
}
}
void test_map2()
{
map<string, string> m;
m.insert(pair<string, string>("water", "水"));
m.insert(pair<string, string>("apple", "苹果"));
m.insert(make_pair("banan", "香蕉"));
map<string, string>::iterator it = m.begin();
while (it != m.end())
{
cout << it->first << ":" << it->second << endl;
it++;
}
cout << m.size() << endl;
cout << m.empty() << endl;
m.erase("apple");
for (auto e : m)
{
cout << e.first << ":" << e.second << endl;
}
cout << m.size() << endl;
map<string, string>::iterator pos1 = m.find("banan");
if (pos1 != m.end())
{
m.erase(pos1);
}
for (auto e : m)
{
cout << e.first << ":" << e.second << endl;
}
cout << m.size() << endl;
//map::iterator pos2 = find(m.begin(), m.end(),"water");
//m.erase(pos2);
for (auto e : m)
{
cout << e.first << ":" << e.second << endl;
}
cout << m.size() << endl;
}
multiset的接口与set相同。
multimap文档
multimap中没有重载operator[]操作(可思考下为什么?)。
因为有多个相同的key值,所以不知道返回key值的哪个value。
以上就是今天要讲的内容,本文介绍了关联式容器map、set的使用,而关联式容器存储键值数据方便查找匹配数据,提供了大量能使我们快速便捷地处理数据的函数和方法,我们务必掌握。另外如果上述有任何问题,请懂哥指教,不过没关系,主要是自己能坚持,更希望有一起学习的同学可以帮我指正,但是如果可以请温柔一点跟我讲,爱与和平是永远的主题,爱各位了。