set和map都是泛型库对二叉树的一个泛化。
一、map的相关原理
map映照容器所处理的元素数据,与数据库中的具有键值的记录非常相似,由一个键值和其它若干个数据(映照数据组成),键值和映照数据之间,可建立一个数学上的映照关系。容器的数据结构是采用红黑树进行管理,元素值不允许重复,所使用的节点元素的比较函数,只对元素的键值进行比较,元素的各个数据项可通过键值检索。
数据构成如图所示:
如图所示为map容器的一个元素的数据组成,可通过pair封装成一个结构对象。map容器所要做的,就是将这个pair对象插入到红黑树中,完成一个元素的添加,同时,也要提供一个仅使用键值进行比较的函数对象,将它传递给红黑树。由此,就可以利用红黑树的操作,map元素数据插入到二叉树的正确位置,也可以根据键值进行元素的删除和检索。
map通过内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在std map内部所有的数据都是有序的。
二、map的应用
1、创建
(2)map()
利用默认的less<T>函数对象和内存分配器,创建一个没有任何元素的map对象。
map<char,int,greater<char> >m; //创建空map对象,元素的键值类型为char,元素的映照数据类型为int,键值的比较函数对象为greater<char>.
(2)map(const key_compare& comp);
//指定个函数对象来创建map对象,内存分配器为默认值。
//定义字符串比较函数对象strLess
struct strLess{
bool operator()(const char* s1,const char* s2) const
{
return strcmp(s1,s2)<0;
}
};
//创建map容器对象m
map<const char*, int> m(strLess());
(3)map(const map&)
拷贝构造函数,用一个map容器的元素和比较函数,拷贝生成一个新的map容器对象。
//map<int,char*> m1;
map<int,char*> m2(m1);
(4)map(InputIterator first, InputIterator last);
用迭代器区间[first, last)所指的数据,作为map容器的元素(包括键值和映照数据),创建一个map容器对象。例如,下面代码使用数组pairArray的5个pair对象,创建map容器对象m。
pair<const int,char> p1(1,'a');
pair<const int,char> p1(2,'b');
pair<const int,char> p1(3,'c');
pair<const int,char> p1(4,'d');
pair<const int,char> p1(5,'e');
pair<const int,char> pairArray[]={p1,p2,p3,p4,p5};
map<const int,char> m(pairArray,pairArray+5)
(5)map(InputIterator first, InputIterator last, const key_compare& comp);
用迭代器区间[first, last)所指的数据和comp函数对象,创建一个map对象。例如,下面代码使用greater<int>函数对象,取代默认的less<int>,创建一个map对象m。
map<const int, char,greater<const int> > m(pairArray, pairArray+5, greater<const int>());
2、元素的插入
(1)用insert函数
pair<iterator, bool> insert(const value_type& v)
将元素v(包括键值和映照数据)插入 map 容器,重复的v值不被插入。返回一个pair配对对象,提供所插入元素的迭代器位置和true/false插入成功标志。
iterator insert(iterator position, const value_type& v)
将元素 v(包括键值和映照数据)插入 map 容器,参数 position 只是提示可在 position位置之前插入v,所返回的插入位置视实际情况而定,不一定能在position位置前插入。
void insert(InputIterator first, InputIterator last)
将迭代器区间[first, last)所指的数据作为容器元素(包括键值和映照数据),插入到map容器中。
(2)还可用以map容器的数据操作[]显示地为不同键值赋予内容(映照数据),不过此时无法检测是否插入成功。
#include "map"
#include "iostream"
int main()
{
using namespace std;
map<const char*,float> m;
m["apple"]=3.6f;
m["orange"]=3.2f;
m["banana"]=1.8f;
cout<<"苹果是:"<<m["apple"]<<"yuan/jin\n";
cout<<"桔子是:"<<m["orange"]<<"yuan/jin\n";
cout<<"香蕉是:"<<m["banana"]<<"yuan/jin\n";
return 1;
}
3、元素的删除
(1)与 set 集合容器一样,map 映照容器的删除函数,可删除某个迭代器位置上的元素、等于某键值的元素、一个迭代器区间上的元素和容器中的所有元素。
(1)void erase(iterator position)
删除position所指的元素。
(2)size_type erase(const key_type& k)
删除键值为k的元素。对map容器来说,此函数总是返回值1,因为map容器不会出现键值重复的元素值。
(3)void erase(iterator first, iterator last)
删除map迭代器区间[first, last)上的所有元素。
(4)void clear()
删除map容器的所有元素。
4、元素的遍历访问
除了利用键值的数组方式来访问元素外,更一般可使用map容器的迭代器进行访问,通常需要用 begin 和 end 函数找出遍历开始的首元素和结束元素,然后通过迭代器的“++”和“*”操作,读取容器元素。以下是map容器的begin和end函数原型,分别返回指向首尾元素的迭代器位置。
(1)iterator begin()
(2)iterator end()
#include "map"
#include "string"
#include "iostream"
using namespace std;
struct StudentInfo{
string name;
int year;
string addr;
};
struct StudentRecord{
int id;
StudentInfo sf;
};
int main()
{
StudentRecord srArray[]={
{1,"Ia",21,"BeiJing"},
{2,"Ya",22,"ShangHai"},
{3,"Ta",23,"GuangXhou"}
};
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<<"S_Id "<<"Name "<<"Age "<<"Addr "<<endl;
for(i=m.begin();i!=iend;i++)
cout<<(*i).first<<" "
<<(*i).second.name<<" "
<<(*i).second.year<<" "
<<(*i).second.addr<<" "
<<endl;
return 1;
}
5、反向遍历
利用map容器定义的反向迭代器reverse_iterator和const_reverse_iterator,及获取反向首尾元素的rbegin和rend函数,可完成map容器元素的反向遍历。
(1)reverse_iterator rbegin()
(2)reverse_iterator rend()
6、元素的搜索
利用map容器提供的find函数,可搜索出具有某一键值的元素。map容器的元素键值是唯一的。find函数返回的迭代器值为搜索到的元素位置,如果该元素不存在,则返回一个end结束元素位置。
iterator find(const key_type& k) const
7、其它诸如size,swap,lower_bound等,可参见前面的总论部分:
http://blog.163.com/zhoumhan_0351/blog/static/39954227201022644534780
8、下面一个例子
#include "map"
#include "string"
#include "iostream"
using namespace std;
class StudentRecord{
public:
struct StudentInfo{
string name;
int year;
string addr;
};
StudentRecord(int id_,string name_,int year_,string addr_){
id=id_;
sf.name=name_;
sf.year=year_;
sf.addr=addr_;
}
int id;
StudentInfo sf;
};
int main()
{
typedef map<int,StudentRecord::StudentInfo> studentmap;
studentmap m;
pair<studentmap::iterator,bool> p;
StudentRecord student1=StudentRecord(1,"JH",21,"BJ");
pair<int,StudentRecord::StudentInfo> pairStudent1(student1.id,student1.sf);
p=m.insert(pairStudent1);
//pair<iterator, bool> insert(const value_type& x);
if(!p.second)
cout<<"Failed"<<endl
<<student1.id<<" "
<<student1.sf.name<<" "
<<student1.sf.year<<" "
<<student1.sf.addr<<" "
<<endl;
StudentRecord student2=StudentRecord(2,"JH2",22,"TJ");
pair<int,StudentRecord::StudentInfo> pairStudent2(student2.id,student2.sf);
p=m.insert(pairStudent2);
if(!p.second)
cout<<"Failed"<<endl
<<student2.id<<" "
<<student2.sf.name<<" "
<<student2.sf.year<<" "
<<student2.sf.addr<<" "
<<endl;
studentmap::iterator i=m.find(2);
cout<<"class ID 2's record is:\n"
<<(*i).first<<" "
<<(*i).second.name<<" "
<<(*i).second.year<<" "
<<(*i).second.addr<<" "
<<endl;
return 1;
}
来源:CSDN
作者:hopegrace
链接:https://blog.csdn.net/hopegrace/article/details/104152825