map映照容器所处理的元素数据,与数据库的具有键值的记录非常相似,由一个键值和其他若干数据(映照数据)组成,键值和映照数据之间,可建立一个数学上的映照关系,由此而得映照容器的名称。**容器的数据结构同样是采用红黑树进行管理,插入的键值不允许重复,**所使用的节点元素的比较函数只对元素的键值进行比较,元素的各项数据可通过键值检索出来。
- map技术原理
下图所示是map容器的一个元素的数据组成,可通过pair封装成一个结构对象。map容器做的,就是将这个pair对象插入到红黑树,完成一个元素的添加。同时,也要提供一个仅使用键值进行比较的函数对象,将它传递给红黑树。由此,可利用红黑树的操作,将map元素数据插入到二叉树中的正确位置,也可以根据键值进行元素的删除和检索。
- map应用基础
2.1创建map对象
利用默认的less<T>函数对象和内存分配器,创建一个没有任何元素的map对象。例如下面一行代码创建了一个空的map对象m,m的键值类型为char,元素的映照数据类型为int,键值的比较函数对象为greater<char>。ps:greater是按照键值将映照数据从大到小排列,没写就默认从小到大,即比较函数对象为less。
map<char,int,greater<char>> m;
还有几种方式,后面有遇到再提
2.2元素的插入和删除
除了可以用insert函数将整个元素数据进行插入外,常用map容器的数组 “[]” ,显示地为不同键值赋予内容(映照数据)
不多说直接上代码:
#include <map>
#include <QCoreApplication>
#include <iostream>
#include<QString>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
map<string,float> m1;
map<string,float>::iterator i;
m1["apple"] = 3.6f;
m1["orange"] = 3.2f;
m1["banana"] = 1.8f;
cout << "苹果价格:" << m1["apple"] << endl;
cout << "橘子价格:" << m1["orange"] << endl;
cout << "香蕉价格:" << m1["banana"] << endl;
m1.erase("apple"); //删除键值为apple的映照数据
cout << "苹果价格:" << m1["apple"] << endl;
return a.exec();
}
运行结果:
2.2元素的遍历访问和反向遍历
除了利用键值的数组方式来访问元素外,经常使用map容器的迭代器进行访问或反向遍历。
#include <map>
#include <QCoreApplication>
#include <iostream>
#include<QString>
using namespace std;
struct StudentInfo{ //定义学生信息的结构体
char *name;
int age;
char *addr;
};
struct StudentRecord{ //学生记录结构体
int id; //学号作为键值
StudentInfo sf; //学生信息作为映照数据
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
StudentRecord srArray[] = { //插入三条数据
{1,"李强",21,"北京"},
{2,"王文",26,"上海"},
{3,"张三",19,"深圳"}
};
map<int,StudentInfo> m;
for(int j=0;j<3;j++)
{
m[srArray[j].id] = srArray[j].sf;
}
map<int,StudentInfo>::iterator i,iend;
iend=m.end();
cout << "学号 " << "名字 " << "年龄 " << "地址 " << endl;
for(i=m.begin();i!=iend;i++)
{
cout << (*i).first <<" " << (*i).second.name << " " << (*i).second.age << " " << (*i).second.addr << endl;
}
cout << "反向遍历后:" << endl;
map<int,StudentInfo>::reverse_iterator ri,rend;
rend=m.rend();
for(ri=m.rbegin();ri!=rend;ri++)
{
cout << (*ri).first <<" " << (*ri).second.name << " " << (*ri).second.age << " " << (*ri).second.addr << endl;
}
return a.exec();
运行结果:
2.3元素的搜索
利用map提供的find函数,可搜索出具有某一键值的元素。
#include <map>
#include <QCoreApplication>
#include <iostream>
#include<QString>
using namespace std;
struct StudentRecord{ //定义学生记录结构体
struct StudentInfo{
char *name;
int age;
char *addr;
};
StudentRecord(int id_,char *name_,int age_,char *addr_)
{
id=id_;
sf.name = name_;
sf.age = age_;
sf.addr = addr_;
}
int id;
StudentInfo sf;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
typedef map<int,StudentRecord::StudentInfo> studentmap; //定义一个map的对象m
studentmap m;
pair<studentmap::iterator,bool> p; //p用来判断是否插入成功
//插入第一条数据
StudentRecord student1 =StudentRecord(1,"娇娇",18,"上海");
pair<int,StudentRecord::StudentInfo> pairStudent1(student1.id,student1.sf);
p=m.insert(pairStudent1);
if(!p.second)
{
cout << "插入学生失败:" << endl
<< student1.id << " "
<< student1.sf.name << " "
<< student1.sf.age << " "
<< student1.sf.addr << endl;
}
//插入第二条数据
StudentRecord student2 =StudentRecord(2,"阿明",16,"北京");
pair<int,StudentRecord::StudentInfo> pairStudent2(student2.id,student2.sf);
p=m.insert(pairStudent2);
if(!p.second)
{
cout << "插入学生失败:" << endl
<< student2.id << " "
<< student2.sf.name << " "
<< student2.sf.age << " "
<< student2.sf.addr << endl;
}
//插入第三条数据
StudentRecord student3 =StudentRecord(3,"啊亮",21,"深圳");
pair<int,StudentRecord::StudentInfo> pairStudent3(student3.id,student3.sf);
p=m.insert(pairStudent3);
if(!p.second)
{
cout << "插入学生失败:" << endl
<< student3.id << " "
<< student3.sf.name << " "
<< student3.sf.age << " "
<< student3.sf.addr << endl;
}
//插入键值重复的学生记录,则插入失败
StudentRecord student4 =StudentRecord(3,"多多",23,"广州");
pair<int,StudentRecord::StudentInfo> pairStudent4(student4.id,student4.sf);
p=m.insert(pairStudent4);
if(!p.second)
{
cout << "插入学生失败:" << endl
<< student4.id << " "
<< student4.sf.name << " "
<< student4.sf.age << " "
<< student4.sf.addr << endl;
}
//记录搜索
studentmap::iterator i=m.find(2);
cout << "搜索出学号为2的记录:" << endl
<< (*i).first << " "
<< (*i).second.name << " "
<< (*i).second.age << " "
<< (*i).second.addr << endl;
return a.exec();
}
运行结果:
2.4补充
multimap多重映照容器,和map一样都是使用红黑树对元素进行插入等操作,但是multimap允许具有重复键值的元素插入容器。正是由于元素键值的重复插入,使得数组操作符“[]”利用键值来访问失去意义,因此multimap没有定义数组方式的"[]"操作运算。