参考:
- https://blog.csdn.net/shuzfan/article/details/53115922
- https://www.nhooo.com/cpp/cpp-map-swap-function.html
- https://blog.csdn.net/qq_34106574/article/details/86721916
- https://blog.csdn.net/zhongguoren666/article/details/8463249
STL是标准C++系统的一组模板类,使用STL模板类最大的好处就是在各种C++编译器上都通用。
在STL模板类中,用于线性数据存储管理的类主要有vector、 list,、map 等等。
C++中map提供的是一种键值对容器,里面的数据都是成对出现的,每一对中的第一个值称之为关键字(key),每个关键字只能在map中出现一次;第二个称之为该关键字的对应值。
//头文件
#include
//注意,STL头文件没有扩展名.h
map<int, string> ID_Name;
// 使用{}赋值是从c++11开始的,因此编译器版本过低时会报错,如visual studio 2012
map<int, string> ID_Name = {
{ 2015, "Jim" },
{ 2016, "Tom" },
{ 2017, "Bob" } };
map<int, string> ID_Name;
// 如果已经存在键值2015,则会作赋值修改操作,如果没有则插入
ID_Name[2015] = "Tom";
// 插入单个键值对,并返回插入位置和成功标志,插入位置已经存在值时,插入失败
pair<iterator,bool> insert (const value_type& val);
//在指定位置插入,在不同位置插入效率是不一样的,因为涉及到重排
iterator insert (const_iterator position, const value_type& val);
// 插入多个
void insert (InputIterator first, InputIterator last);
//c++11开始支持,使用列表插入多个
void insert (initializer_list<value_type> il);
下面是具体使用示例:
#include
#include
int main()
{
std::map<char, int> mymap;
// 插入单个值
mymap.insert(std::pair<char, int>('a', 100));
mymap.insert(std::pair<char, int>('z', 200));
//返回插入位置以及是否插入成功
std::pair<std::map<char, int>::iterator, bool> ret;
ret = mymap.insert(std::pair<char, int>('z', 500));
if (ret.second == false) {
std::cout << "element 'z' already existed";
std::cout << " with a value of " << ret.first->second << '\n';
}
//指定位置插入
std::map<char, int>::iterator it = mymap.begin();
mymap.insert(it, std::pair<char, int>('b', 300)); //效率更高
mymap.insert(it, std::pair<char, int>('c', 400)); //效率非最高
//范围多值插入
std::map<char, int> anothermap;
anothermap.insert(mymap.begin(), mymap.find('c'));
// 列表形式插入
anothermap.insert({ { 'd', 100 }, {'e', 200} });
return 0;
}
Map中元素取值主要有at和[ ]两种操作,at会作下标检查,而[]不会。
map<int, string> ID_Name;
//ID_Name中没有关键字2016,使用[]取值会导致插入
//因此,下面语句不会报错,但打印结果为空
cout<<ID_Name[2016].c_str()<<endl;
//使用at会进行关键字检查,因此下面语句会报错
ID_Name.at(2016) = "Bob";
// 查询map是否为空
bool empty();
// 查询map中键值对的数量
size_t size();
// 查询map所能包含的最大键值对数量,和系统和应用库有关。
// 此外,这并不意味着用户一定可以存这么多,很可能还没达到就已经开辟内存失败了
size_t max_size();
// 查询关键字为key的元素的个数,在map里结果非0即1
size_t count( const Key& key ) const; //
共有八个获取迭代器的函数:begin, end, rbegin, rend 以及对应的 cbegin, cend, crbegin, crend。
二者的区别在于:后者一定返回 const_iterator,而前者则根据map的类型返回iterator 或者 const_iterator。const情况下,不允许对值进行修改。如下面代码所示:
map<int,int>::iterator it;
map<int,int> mmap;
const map<int,int> const_mmap;
it = mmap.begin(); //iterator
mmap.cbegin(); //const_iterator
const_mmap.begin(); //const_iterator
const_mmap.cbegin(); //const_iterator
返回的迭代器可以进行加减操作,此外,如果map为空,则 begin = end。
// 删除迭代器指向位置的键值对,并返回一个指向下一元素的迭代器
iterator erase( iterator pos )
// 删除一定范围内的元素,并返回一个指向下一元素的迭代器
iterator erase( const_iterator first, const_iterator last );
// 根据Key来进行删除,返回删除的元素数量,在map里结果非0即1
size_t erase( const key_type& key );
// 清空map,清空后的size为0
void clear();
//clear()就相当于enumMap.erase(enumMap.begin(), enumMap.end());
示例:
enumMap.erase(1); //删掉关键字“1”对应的条目
enumMap.erase(enumMap.begin()); //删掉第一个条目
enumMap.erase(enumMap.begin(), enumMap.begin() + 1); //删掉起始的两个条目
// 就是两个map的内容互换
void swap( map& other );
示例:
1.
#include
#include
using namespace std;
int main(void) {
map<char, int> m1 = {
{'a', 1},
{'b', 2},
{'c', 3},
{'d', 4},
{'e', 5},
};
map<char, int> m2;
m2.swap(m1);
cout << "Map包含以下元素" << endl;
for (auto it = m2.begin(); it != m2.end(); ++it)
cout << it->first << " = " << it->second << endl;
return 0;
}
//输出:
Map包含以下元素
a = 1
b = 2
c = 3
d = 4
e = 5
在上面的示例中,Map m1具有五个元素,而m2为空。当您将m1交换为m2时,m1的所有元素都将交换为m2。
2.
#include
#include
#include
using namespace std;
void show(const char *msg, map<string, int> mp);
int main() {
map<string, int> m1, m2;
m1.insert(pair<string, int>("A", 100));
m1.insert(pair<string, int>("G", 300));
m1.insert(pair<string, int>("B", 200));
// 交换m1和m2的内容。
cout << "交换m1和m2。\n";
m1.swap(m2);
show("Contents of m2: ", m2);
show("Contents of m1: ", m1);
// Clear m1.
m1.clear();
if(m1.empty()) cout << "m1 为空.";
return 0;
}
// 使用迭代器显示map的内容。
void show(const char *msg, map<string, int> mp) {
map<string, int>::iterator itr;
cout << msg << endl;
for(itr=mp.begin(); itr != mp.end(); ++itr)
cout << " " << itr->first << ", " << itr->second << endl;
cout << endl;
}
//输出:
交换m1和m2。
m2内容:
A, 100
B, 200
G, 300
m1内容:
m1 为空.
在上面的示例中,Map m1的内容被交换到Map m2,并且在交换Map m1 后已被清除。
// 比较两个关键字在map中位置的先后
key_compare key_comp() const;
示例:
map<char,int> mymap;
map<char,int>::key_compare mycomp = mymap.key_comp();
mymap['a']=100;
mymap['b']=200;
mycomp('a', 'b'); // a排在b前面,因此返回结果为true
// 关键字查询,找到则返回指向该关键字的迭代器,否则返回指向end的迭代器
// 根据map的类型,返回的迭代器为 iterator 或者 const_iterator
iterator find (const key_type& k);
const_iterator find (const key_type& k) const;
示例:
std::map<char,int> mymap;
std::map<char,int>::iterator it;
mymap['a']=50;
mymap['b']=100;
mymap['c']=150;
mymap['d']=200;
it = mymap.find('b');
if (it != mymap.end())
mymap.erase (it); // b被成功删除
/*find的时候注意key的数据类型,最好用能消除数据类型差异的key,否则可能会出现强制转换后仍找不到的情况。
需要说明的是iterator, begin(), end()是STL模板类的一个通用概念,操作方法也大同小异;
通过map对象的方法获取的iterator数据类型是一个std::pair对象,包括两个数据 iterator.first 和 iterator.second 分别代表关键字和存储的数据 */
iterator map_name.equal_range(key)
equal_range
是C++ STL中的一种二分查找的算法,试图在已排序的[first,last)中寻找value,它返回一对迭代器i和j,其中i是在不破坏次序的前提下,value可插入的第一个位置(亦即lower_bound
),j则是在不破坏次序的前提下,value可插入的最后一个位置(亦即upper_bound
),因此,[i,j)内的每个元素都等同于value,而且[i,j)是[first,last)之中符合此一性质的最大子区间。
equal_range
根据键值,返回一对迭代器的pair对象。如果该键值在容器中存在,则pair对象中的第一个迭代器指向该键关联的第一个实例,第二个迭代器指向该键关联的最后一个实例的下一位置。如果找不到匹配的元素,则pair对象中的两个迭代器都将指向此键应该插入的位置。总之,equal_range
返回迭代器位置区间 [ lower_bound, upper_bound )
。
算法lower_bound
返回区间A的第一个迭代器,算法upper_bound
返回区间A的最后一个元素的下一个位置,算法equal_range
则是以pair
的形式将两者都返回。
示例:
#include
#include
using namespace std;
int main ()
{
map<char,int> mymap;
pair<map<char,int>::iterator,map<char,int>::iterator> ret;
mymap['a']=10;
mymap['b']=20;
mymap['c']=30;
ret = mymap.equal_range('b');
cout << "lower bound points to: ";
cout << ret.first->first << " => " << ret.first->second << endl;
cout << "upper bound points to: ";
cout << ret.second->first << " => " << ret.second->second << endl;
return 0;
}
//运行结果:
lower bound points to: 'b' => 20
upper bound points to: 'c' => 30
operator:==
!=
<
<=
>
>=
注意:对于==
运算符, 只有键值对以及顺序完全相等才算成立。
#include
#include
#include
using namespace std;
int main()
{
map<string,int> m;
m["a"]=1;
m["b"]=2;
m["c"]=3;
map<string,int>::iterator it;
for(it=m.begin();it!=m.end();++it)
cout<<"key: "<<it->first <<" value: "<<it->second<<endl;
return 0;
}
map<string,int>::iterator it; //定义一个迭代指针it。
// it->first 为索引键值,it->second 为值。
在对象中应用时,最好在析构函数中要调用它的clear方法,例如:
class a{
map<int,int> m;
~a(){
m.clear();
}
}
map 与 multimap 都是存储key-value(键-值 对)类型的容器。
不同之处在于:map只允许key与value一一对应;multimap一个key可对应多个value。
示例:
以下不作特别说明,适用于map的都适用于multimap:
#include
#include
#include
#include // std::sort
using namespace std;
//打印函数可写成模板
//打印函数 printfA
void printfA(map<vector<int>, int> vec_)
{
for (std::map<std::vector<int>, int>::iterator it = vec_.begin(); it != vec_.end(); it++)
{
std::cout << it->first[0] << " " << it->first[1] << " " << it->first[2] << " " << it->second << std::endl;
}
cout << "容积 = " << vec_.size() << endl;
}
//打印函数 printfB
void printfB(multimap<string, int> vec_)
{
for (multimap<string, int>::iterator it = vec_.begin(); it != vec_.end(); it++)
{
std::cout << it->first << " " << it->second << std::endl;
}
cout << "容积 = " << vec_.size() << endl;
}
int main()
{
//声明,定义
std::map<int, std::string> m;
m[3] = "h1";
m[0] = "what";
// 构建 key-value
m.insert(std::pair<int, std::string>(2, "love you"));
std::cout << m[0].c_str() << std::endl;//这里数字 不是索引值了
std::cout << m[3].c_str() << std::endl;
std::cout << m[4].c_str() << std::endl;
std::cout << m[2].c_str() << std::endl; // 会产生一个新的元素,即m[2] = ""
m[6] = string("slam2345");
std::cout << m.size() << std::endl; // 5
//遍历
for (std::map<int, std::string>::iterator it = m.begin(); it != m.end(); it++)
std::cout << it->first << ", " << it->second.c_str() << std::endl;
std::vector<int> pointTemp;
std::map<std::vector<int>, int> vecA;
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
pointTemp.push_back(y);
pointTemp.push_back(x);
pointTemp.push_back(x + y);
//插入
vecA.insert(std::pair<std::vector<int>, int>(pointTemp, (y * 4 + x + 1)));
pointTemp.clear();
}
}
printfA(vecA);
【注意】区分map与multimap:
//***************************************************************************************************
//<1>插入返回值 判定是否插入成功
//带插入数据
vector<int> pointTemp_ = { 1,2,3 };
// Insert方法不能覆盖,如果键已经存在,则插入失败;【注意插入位置,是自动排序】
int a1 = 4;
//判定插入是否成功
pair< map<vector<int>, int>::iterator, bool> isInsertOK;//注意这里声明
isInsertOK = vecA.insert(pair<vector<int>, int>(pointTemp_, a1));
cout << "插入成功? " << isInsertOK.second << endl;
//打印
printfA(vecA);
//***************************************************************************************************
//<2>map对象的拷贝构造与赋值
map<vector<int>, int> vecB(vecA); //拷贝构造
map<vector<int>, int> vecC;
vecC = vecA;
vecC.swap(vecA);
//***************************************************************************************************
//<3>查找
map<string, int> vecD;
// 你以为按照下面初始化 vecD,他的size会是5? 由于insert方法不能覆盖,所以我们将map 改成 multimap
vecD.insert(pair<string, int>((string)"china", 1));
vecD.insert(pair<string, int>((string)"china", 2));//拒绝插入
vecD.insert(pair<string, int>((string)"china", 3));//拒绝插入
vecD.insert(pair<string, int>((string)"english", 1));
vecD.insert(pair<string, int>((string)"english", 2));//拒绝插入
multimap<string, int> vecE;
vecE.insert(make_pair((string)"china", 1));
vecE.insert(make_pair((string)"china", 1));//允许插入
vecE.insert(make_pair((string)"china", 3));//允许插入
vecE.insert(make_pair((string)"china", 4));//允许插入
vecE.insert(make_pair((string)"china", 5));//允许插入
vecE.insert(make_pair((string)"english", 1));
vecE.insert(make_pair((string)"english", 2));//允许插入
vecE.insert(make_pair((string)"america", 1));
vecE.insert(make_pair((string)"america", 2));//允许插入
vecE.insert(make_pair((string)"america", 3));//允许插入
cout << "multimap 初始化" << endl;
cout << "vecE所有元素"<<endl;
printfB(vecE);
//查找区间
multimap<string, int> ::iterator it1 = vecE.lower_bound("china"); //指向vecE中第一个等于键值 “china”对应的元素
multimap<string, int> ::iterator it2 = vecE.upper_bound("china"); //指向vecE中第一个大于键值 “china”对应的元素
cout << it1->first << " " << it1->second << endl;
cout << it2->first << " " << it2->second << endl;
// 等于 = lower_bound + upper_bound
pair<multimap<string, int>::iterator, multimap<string, int>::iterator > it3 = vecE.equal_range("china");
map<string, int>::iterator it4 = it3.first;
map<string, int>::iterator it5 = it3.second;
//查找key = “china”键值对的个数
int iCount = vecE.count("china");
//查找key = “china”对应键值对
multimap<string, int>::iterator it6 = vecE.find("china");
//***************************************************************************************************
// <4>删除
multimap<string, int>::iterator itBegin = vecE.begin();
// 删除 vecE 前面三个元素 与 后面 三个元素
// 在改善特征点匹配算法中有实践
int index = 0;
int vecA_size = vecE.size();
//删除(自定义删除任何元素)
for (multimap<string, int>::iterator it_ = vecE.begin(); it_ != vecE.end(); )
{
//<1>法1
//vecE.erase(it_++);
//<2>法2
if ((0<=index)&&(index<=2))
{
it_ = vecE.erase(it_);//这样写,防止指针失效
}
else if (((vecA_size - 3) <= index) && (index <= (vecA_size - 1)))
{
it_ = vecE.erase(it_);
}
else
{
it_++;
}
++index;
}
//删除multimap中key = "english"的 所有 元素
vecE.erase("english");
cout << "vecE删除key = english的 所有 元素 " << endl;
printfB(vecE);
//删除所有元素
multimap<string, int>::iterator itBegin_ = vecE.begin();
multimap<string, int>::iterator itEnd_ = vecE.end();
vecE.erase(itBegin_, itEnd_);
//bool isEmpty = vecE.empty();
if (vecE.empty())
{
cout << "vecE已经被清空" << endl;
}
return 0;
}