STL | Map(映射)的使用(一)

2019-06-11  本文已影响0人  0与1的邂逅

写在前面:

Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力。由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。

Map

图片来源:https://www.cnblogs.com/empty16/p/6395813.html

这里说下map内部数据的组织,map内部自建一颗红黑树(一 种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的。

这里略过红黑树,感兴趣的童鞋自行百度,可以先从二叉排序树入手。(后面有时间我再来总结)



进入正题:

一. 定义一个Map(映射)

map共提供了6个构造函数,这块涉及到内存分配器这些东西,我也没深入去了解。因此,我们就来介绍最常见的一种构造方法:

#include<map>// 头文件
map<char,int>Map;// 定义一个从char类型到int类型的映射Map

构造函数包含了两个参数,第一个参数是关键字Key,第二个参数是关键字的值Key_Value。这两个参数可以是任意类型

通常,我们习惯用typedef来定义Map,为什么呢?因为在定义迭代器的时候,我们可以不用多写多余的重复代码,而且要修改Map的时候,也不需要修改多处地方。

#include<map>
typedef map<char,int> m;// 自定义一种类型——m
m Map;

二. 插入数据

定义好了映射Map,接下来就需要向Map插入数据。插入数据主要有以下三种方法。

#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
typedef map<char,int>m;
m Map;

int main()
{
    char ch;
    for(int i=0;i<10;i++)
    {
        cout<<"input character:";
        cin>>ch;
        // 方法一:用insert函数插入pair数据
        Map.insert(pair<char,int>(ch,i));
    }
}
#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
typedef map<char,int>m;
m Map;

int main()
{
    char ch;
    for(int i=0;i<10;i++)
    {
        cout<<"input character:";
        cin>>ch;
        // 方法二:用insert函数插入value_type数据
        // 这里就可以看出用typedef定义Map的好处
        Map.insert(m::value_type(ch,i));
    }
}
#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
typedef map<char,int>m;
m Map;

int main()
{
    char ch;
    for(int i=0;i<10;i++)
    {
        cout<<"input character:";
        cin>>ch;
        // 方法三:用数组方式插入数据
        Map[ch]=i;
    }
}

以上三种插入方法,虽然都可以实现数据的插入,但是它们是有区别的。当然,第一种和第二种在效果上是完成一样的。

insert函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,想要再次插入该关键字,insert操作是插入不了的。

但是用数组方式就不同了,它可以覆盖以前该关键字对应的值。

下面用一个程序来验证。

#include<iostream>
#include<map>
using namespace std;

typedef map<char,int> m;
m Map_1;// 数组方式插入 
m Map_2;// insert函数插入 

int main()
{
    char ch;
    for(int i=0;i<4;i++)
    {
        cout<<"input the character:";
        cin>>ch;
        Map_1[ch]=i;
        Map_2.insert(pair<char,int>(ch,i));
    }
    m::iterator iter_1,iter_2;// 前向迭代器 
    cout<<"--------------------------\n";
    cout<<"数组:\n";
    for(iter_1=Map_1.begin();iter_1!=Map_1.end();iter_1++)
    {
        cout<<iter_1->first<<"->"<<iter_1->second<<endl;
    }
    cout<<"--------------------------\n";
    cout<<"insert:\n";
    for(iter_2=Map_2.begin();iter_2!=Map_2.end();iter_2++)
    {
        cout<<iter_2->first<<"->"<<iter_2->second<<endl;
    }
    cout<<"\n";
    
    // 重新插入已经存在的关键字Key
    // 尝试将其Key_Value值改为520 
    cout<<"重新插入character:\n";
    cin>>ch;
    Map_1[ch]=520;
    Map_2.insert(pair<char,int>(ch,520));
    
    cout<<"--------------------------\n";
    cout<<"数组:\n";
    for(iter_1=Map_1.begin();iter_1!=Map_1.end();iter_1++)
    {
        cout<<iter_1->first<<"->"<<iter_1->second<<endl;
    }
    cout<<"--------------------------\n";
    cout<<"insert:\n";
    for(iter_2=Map_2.begin();iter_2!=Map_2.end();iter_2++)
    {
        cout<<iter_2->first<<"->"<<iter_2->second<<endl;
    }
}
验证结果
三. Map容器的大小:

Map容器已经插入了数据,那么Map容器的大小(目前)是多大呢?或者说插入了多少组数据呢?

我们可以用size函数,这跟STL中其他容器(如vector)用法一致。


四. 遍历Map容器:

既然插入了数据,那么我们怎么去遍历呢?(借此也看看是不是插入成功)同样的,也有三种方法可以对Map容器进行遍历。

map<char,int>::iterator iter;// 前向迭代器 
for(iter=Map.begin();iter!=Map.end();iter++)
{
    cout<<iter->first<<" "<<iter->second<<endl;
}
map<char,int>::reverse_iterator r_iter;// 反向迭代器
for(r_iter=Map.rbegin();r_iter!=Map.rend();r_iter++)
{
    cout<<r_iter->first<<" "<<r_iter->second<<endl;
} 

判定关键字是否在Map中:

这里有三种判断关键字是否在Map中的方法。

map<char,int>Map;
map<char,int>::iterator iter=Map.find(Key);
if(iter==Map.end())cout<<"can't find"<<endl;
else cout<<"find"<<endl;
  1. lower_bound():返回键值>=给定元素的第一个位置(下界)
  2. upper_bound():返回键值>给定元素的第一个位置(上界)
  3. equal_range():返回特殊条目的迭代器对。具体表现为:
    返回一个pair,pair里面第一个变量是lower_bound返回的迭代器,pair里面第二个迭代器是upper_bound返回的迭代器。

如果这两个迭代器(上、下界)相等的话,则说明Map中不存在这个关键字。

if(iter_1!=iter_2)cout<<"find"<<endl;
else cout<<"can't find"<<endl;

完整代码,测试lower_bound、upper_bound、equal_value函数 👇👇👇

#include<iostream>
#include<cstdio>
#include<map>
using namespace std;

typedef map<char,int>m;
m Map;

int main()
{
    char ch;
    for(int i=0;i<5;i++)
    {
        cout<<"input character:";
        cin>>ch;
        Map[ch]=i;
    }
    m::iterator iter_1,iter_2;
    iter_1=Map.lower_bound('C');
    iter_2=Map.upper_bound('C');
    cout<<"lower_bound:\n";
    cout<<iter_1->first<<"->"<<iter_1->second<<endl;
    cout<<"upper_bound:\n";
    cout<<iter_2->first<<"->"<<iter_2->second<<endl;
    cout<<"*********************\n";
    cout<<"queal_value:\n";
    pair<m::iterator,m::iterator> p=Map.equal_range('C');
    iter_1=p.first;
    iter_2=p.second;
    cout<<iter_1->first<<"->"<<iter_1->second<<endl;
    cout<<iter_2->first<<"->"<<iter_2->second<<endl;
} 

查找关键字:

find函数:返回一个pair对象,pair->first表示Key的值,pair->second表示Key_Value的值。

result = Map.find(Key);
cout << result->first << "->" << result->second << endl;


Map总结:

为什么选择Map?/ Map的功能作用?

Map的基本操作函数:
*begin() 返回指向Map头部的迭代器
*clear() 删除所有元素
*count() 返回指定元素出现的次数,Map中只有0和1两个值
*empty() 如果Map为空,则返回true
*end() 返回指向Map末尾的迭代器
equal_range() 返回特殊条目的迭代器对
*erase() 删除一个元素
*find() 查找一个元素
get_allocator() 返回Map的配置器
*insert() 插入元素
key_comp() 返回比较元素Key的函数
lower_bound() 返回键值>=给定元素的第一个位置
max_size() 返回可以容纳的最大元素个数
*rbegin() 返回一个指向Map尾部的反向迭代器
*rend() 返回一个指向Map头部的反向迭代器
*size() 返回map中元素的个数
*swap() 交换两个Map容器
upper_bound() 返回键值>给定元素的第一个位置
value_comp() 返回比较元素Key_Value的函数

PS:带*的函数:表示我比较常用的函数。



写在最后:

参考资料:

因为文章篇幅原因,剩下一些内容(删除和排序)就留着下次再讲。

其实,对于STL,很多容器都具有功能相同的函数、迭代器。前面讲过vector容器,也是经常需要被用到的。就我而言,vector可能比map用的频率还大一些。

关于vector容器的文章:

上一篇下一篇

猜你喜欢

热点阅读