P211map映照容器所处理的元素数据,与数据库表的具有键值的记录非常相似,由一个键值和其他若干数据(映照数据)组成,键值和映照数据之间,可建立一个数学上的映照关系,由此而得映照容器的名称。容器的数据结构同样是采用红黑树进行管理,插入的元素键值不允许重复,所使用的节点元素的比较函数,只对元素的键值进行比较,元素的各项数据可通过检索出来。
一、map技术原理
键值,映照数据是map容器的一个元素的数据组成,可通过pair封装成一个结构对象。map容器所要做的,就是将这个pair对象插入到红黑树,完成一个元素的添加。同时,也要提供一个权使用键值进行比较的函数对象,将它传递给红黑树。由此,就可利用红黑树的操作,将map元素数据插入到二叉树中的正确位置,也可以根据键值进行元素的删除和检索。
如下是SGI C++ STL的map容器的实现代码。首先,内部定义了一个红黑树对象M_t。由于红黑树的节点比较函数是直接对节点元素进行的,因此,还要将传入的键值比较函数Compare转换为元素的比较函数value_compare。当然,这样的元素比较仍然是元素键值的一个比较。至于元素的唯一插入、删除和检索,都是调用红黑树的操作函数实现,代码十分简单。为应用上的方便,map还定义了一个数组“[]“操作符,不仅可用键值的数组方式访问元素的映照数据,还可用来添加map容器的元素。
二、map应用基础
#include <map>
1、创建map对象
map()
map(const key_compare &comp)
map(const map&)
map(InputIterator first, InputIterator last)
map(InputIterator first, InputIterator last, const key_compare &comp)
2、元素的插入
元素数据(包括键值和映照数据)的二叉树装入
pair<iterator, bool> insert(const value_type &v):重复的v值不被插入。返回一个pair配对对象,提供所插入元素的迭代器位置和true/false插入成功标志。
iterator insert(iterator position, const value_type &v):参数position只是提示可在position位置之前插入v,所返回的插入位置视实际情况而定,不一定能在position位置前插入。
void insert(InputIterator first, InputIterator last):将迭代器区间[first, last]所指的数据作为容器元素(包括键值和映照数据),插入到map容器中。
#include <map>
#include <iostream>
using namespace std;
int main(void) {
map<const char*, float> m;
//
m["apple"] = 3.6f;
m["orange"] = 3.2f;
m["banana"] = 1.8f;
m["pear"] = 2.3f;
m["lichee"] = 6.3f;
//
cout << "apple price: " << m["apple"] << endl;
cout << "orange price: " << m["orange"] << endl;
cout << "banana price: " << m["banana"] << endl;
cout << "pear price: " << m["pear"] << endl;
cout << "lichee price: " << m["lichee"] << endl;
return 0;
}
3、元素的删除
void erase(iterator position)
size_type erase(const key_type &k)
void erase(iterator first, iterator last)
void clear()
4、元素的遍历访问
iterator begin()
iterator end()
5、元素的反向遍历
reverse_iterator rbegin()
reverse_iterator rend();
6、元素的搜索
iterator find(const key_type &k) const
#include <map> #include <iostream> struct StudentRecord { //学生记录结构体 struct StudentInfo { char *name; int year; char *addr; }; StudentRecord(int id_, char *name_, int year_, char *addr_) { id = id_; sf.name = name_; sf.year = year_; sf.addr = addr_; } int id; //学号,作键值 StudentInfo sf; //其他信息 }; int main(void) { using namespace std; // typedef map<int, StudentRecord::StudentInfo> studentmap; studentmap m; pair<studentmap::iterator, bool> p; //插入第一条学生记录 StudentRecord student1 = StudentRecord(1, "焦焦", 21, "北京"); pair<int, StudentRecord::StudentInfo> pairStudent1(student1.id, student1.sf); p = m.insert(pairStudent1); if (!p.second) { cout << "插入学生记录失败:\n" << student1.id << ' ' << student1.sf.name << ' ' << student1.sf.year << ' ' << student1.sf.addr << ' ' << endl << endl; }
//插入第二条学生记录 StudentRecord student2 = StudentRecord(2, "软介", 18, "上海"); pair<int, StudentRecord::StudentInfo> pairStudent2(student2.id, student2.sf); p = m.insert(pairStudent2); if (!p.second) { cout << "插入学生记录失败:\n" << student2.id << ' ' << student2.sf.name << ' ' << student2.sf.year << ' ' << student2.sf.addr << ' ' << endl << endl; }
//插入第三条学生记录 StudentRecord student3 = StudentRecord(3, "译尹", 20, "深圳"); pair<int, StudentRecord::StudentInfo> pairStudent3(student3.id, student3.sf); p = m.insert(pairStudent3); if (!p.second) { cout << "插入学生记录失败:\n" << student3.id << ' ' << student3.sf.name << ' ' << student3.sf.year << ' ' << student3.sf.addr << ' ' << endl << endl; }//插入第四条学生记录,失败 StudentRecord student4 = StudentRecord(3, "辛强", 26, "天津"); pair<int, StudentRecord::StudentInfo> pairStudent4(student4.id, student4.sf); p = m.insert(pairStudent4); if (!p.second) { cout << "插入学生记录失败:\n" << student4.id << ' ' << student4.sf.name << ' ' << student4.sf.year << ' ' << student4.sf.addr << ' ' << endl << endl; }//记录搜索
studentmap::iterator i = m.find(2);
cout << "搜索出学号为2的记录:\n" << (*i).first << ' ' << (*i).second.name << ' ' << (*i).second.year << ' ' << (*i).second.addr << ' ' << endl << endl; return 0;
}
7、其他的常用函数