目录
关联容器和顺序容器的区别
我们知道顺序容器和关联容器有根本性的不同,关联容器的元素是按照关键字来保存和访问的,顺序容器是按照它们在容器中的位置来访问的。这与这些容器的底层存储方式有关,也导致了它们索引、插入和删除效率也由区别。底层原理在这里就不介绍。
关联容器
标准库定义了8个关联容器:
- 是一个map或一个set,map保存关键字-值对,set只保存关键字
- 要求关键字值唯一或不唯一
- 关键字有序或无序
1.map
1.1定义map
类似于顺序容器,关联容器也是一个模板。定义一个map,我们需要一个指定的关键字和值的类型。关联容器不支持顺序容器的位置相关操作。与关联容器存储方式有关。
1.2关联容器迭代器遍历
访问map中的元素我们可以使用first成员函数来访问键,second来访问键所对应的值。对于想快速查找某个键对应的值可以使用find成员函数,返回值类型为当前键的迭代器。
示例:
#include<iostream>
#include<map>
using namespace std;
int main(int argc, char** argv)
{
map<string, int> words;
words = { {"Hello",1},{"world",2},{"!",3} };
auto v1 = words.begin();
while (v1 != words.end())
{
cout << v1->first << " is the " << v1->second << "th string.\n";
v1++;
}
for (int cir = 0; cir < 3; cir++)
cout << words.find("Hello")->first;//find返回指向查找键值的迭代器
return 0;
}
示例结果:
!is the 3th string.
Hello is the 1th string.
Hi is the 2th string.
HelloHelloHello
1.3map元素的添加
向map中进行insert操作时,必须记住元素类型是pair,如果插入的数据没有现成的pair,会在insert参数列表里创建一个。对于pair类型在另外一篇总结。
//向words插入的四种方法
words.insert({word,1});
words.insert(make_pair(word,1));
words.insert(pair<string,size_t>(word,1));
words.insert(map<string,size_t>::value_type(word,1));
最简单的是第一种插入方式,直接创建pair,第二种方式是用调用make_pair构造。第三种方式是显示的使用pair来构造对象。最后一种是构造一种pair类型,并且构造该类型的一个新对象,并且插入到map中去。
#include<iostream>
#include<map>
using namespace std;
int main(int argc, char** argv)
{
map<string, int> words;
words.insert({"Nice to meet you!",1});
words.insert(make_pair("Nice to meet you too !",2));
words.insert(pair<string, int>("How are you ?",3));
words.insert(map<string, int>::value_type("I am fine !", 4));
auto v2 = words.begin();
while (v2 != words.end())
{
cout <<"#"<<v2->second<<" "<< v2->first << endl;
v2++;
}
return 0;
}
结果:
#3 How are you ?
#4 I am fine !
#2 Nice to meet you too !
# 1 Nice to meet you !
从结果可以看出,map容器并没有按照插入的顺序输出,因为map会按照key顺序重新排列。上面的例子可以看出是按照字母顺序进行排列。
1.4map元素删除
关联容器定义了3个版本erase:
c.erase(k) | 从c中删除关键字为k的元素,并返回一个size_type值,指出删除元素数量 |
c.erase(p) | 从C中删除迭代器p指定元素,返回一个p之后元素的迭代器,若p指向尾元素,则返回c.end() |
c.erase(b,e) | 删除迭代器b和e中所有元素 |
示例:
#include<iostream>
#include<map>
using namespace std;
int main(int argc, char** argv)
{
map<string, int> words;
words.insert({"Nice to meet you!",1});
words.insert(make_pair("Nice to meet you too !",2));
words.insert(pair<string, int>("How are you ?",3));
words.insert(map<string, int>::value_type("I am fine !", 4));
auto v2 = words.begin();
while (v2 != words.end())
{
cout <<"#"<<v2->second<<" "<< v2->first << endl;
v2++;
}
int value = words.erase("I am fine !");
cout <<"you have erase "<< value <<" word"<< endl;
words.erase(words.find("Nice to meet you!"));
auto v3 = words.begin();
while (v3 != words.end())
{
cout << "#" << v3->second << " " << v3->first << endl;
v3++;
}
words.erase(words.begin(), words.end());//删除迭代器word.begin()到word.end()之间的元素内容
if (words.empty())//如果容器内元素为空
{
cout << "Null element !" << endl;
}
return 0;
}
示例结果:
注意当erase方法的参数为迭代器时,迭代器所指的值必须是真实值,否则将引发异常!