zoukankan      html  css  js  c++  java
  • C++ STL——map和multimap


    注:原创不易,转载请务必注明原作者和出处,感谢支持!

    一 map和multimap

    map相对于set的区别:map具有键值和实值,所有元素根据键值自动排序。pair的第一元素被称为键值,第二元素被称为实值。map也是以红黑树为底层实现机制。

    我们不能通过map的迭代器来修改map的键值,因为键值关系关系到容器内元素的排列规则,任意改变键值会破坏容器的排列规则,但是你可以改变实值。

    map和multimap的区别在于,map不允许相同key值存在,multimap则允许相同的key值存在。

    构造函数

    map<T1 T2> mp;		// 默认构造函数
    map(const map &mp);	// 拷贝构造函数
    

    赋值操作

    map &operator-(const map &mp);	// 重载等号运算符
    swap(mp);						// 交换两个集合容器
    

    大小操作

    size();		// 返回容器中元素的数目
    empty();	// 判断容器是否为空
    

    插入数据元素操作

    map<int, string> mp;
    
    // 第一种,通过pair的方式插入对象
    mp.insert(pair<int, string>(3, "小张"));
    
    // 第二种,通过pair的方式插入对象
    mp.insert(make_pair(-1, "小张"));
    
    // 第三种,通过value_type的方式插入对象
    mp.insert(map<int, string>::value_type(1, "小李"));
    
    // 第四重,通过数组的方式插入
    mp[3] = "小刘";
    mp[5] = "小王";
    

    (1)前面三种方法,采用的是insert()方法,该方法的返回值为pair<iterator, bool>

    (2)第四种方法非常直观,但存在一个性能的问题。插入3时,先在mp中查找主键为3的项,若没有发现,则将一个键为3,值为初始化值的对组插入到mp中,然后再将值修改为"小刘"。若发现已存在3这个键,则修改这个键对应的value。

    (3)string strName = mp[2];只有当mp存在2这个键时才是正确的取值操作,否在会自动插入一个实例,键为2,值为初始化值。

    删除操作

    clear();			// 删除所有元素
    erase(pos);			// 删除pos迭代器所指的元素,返回下一个元素的迭代器
    erase(beg, end);	// 删除区间[beg, end)的所有元素,返回下一个元素的迭代器
    erase(keyElem);		// 删除容器中key为keyElem的对组
    

    查找操作

    find(key);				// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回mp.end()
    count(keyElem);			// 返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对于multimap来说,值可能大于1
    lower_bound(keyElem);	// 返回第一个key <= keyElem元素的迭代器
    upper_bound(keyElem);	// 返回第一个key > keyElem元素的迭代器
    equal_range(keyElem);	// 返回容器中key与keyElem相等的上下限的两个迭代器
    

    这是map的应用案例。

    // 初始化和插入数据
    void Test1()
    {
    	// 第一个为key的类型,第二个为value的类型
    	map<int, string> mp;
    
    	// 插入数据
    	typedef pair<int, string> itemType;
    
    	itemType i1;
    	i1.first = 1;
    	i1.second = "ZHAO";
    	mp.insert(i1);
    
    	// 判断是否插入成功
    	pair<map<int, string>::iterator, bool> r1 = mp.insert(itemType(2, "QIAN"));
    	if (r1.second)
    	{
    		cout << "插入成功!" << endl;
    	}
    	else
    	{
    		cout << "插入失败!" << endl;
    	}
    
    	// key如果相等,则插入失败
    	pair<map<int, string>::iterator, bool> r2 = mp.insert(itemType(2, "KKK"));
    	if (r2.second)
    	{
    		cout << "插入成功!" << endl;
    	}
    	else
    	{
    		cout << "插入失败!" << endl;
    	}
    
    	mp.insert(make_pair(3, "SUN"));
    	mp.insert(map<int, string>::value_type(4, "LI"));
    
    	// 与使用insert()不同的时,使用数组的方式,即使插入相同的key值元素
    	// 也不会报插入失败的错误。而是会把key对应的value值给更新成新的value值
    	mp[5] = "ZHOU";
    	mp[5] = "WU";
    	// 总结:使用数组的插入方式。如果key不存在,则插入新的键值对;如果key存在,则将旧的value修改成新的value
    
    	// 注意:map存储的是pair
    	decltype(mp.begin()) it;
    	for (it = mp.begin(); it != mp.end(); ++it)
    	{
    		cout << it->first << " : " << it->second << endl << endl;
    	}
    
    	// 如果尝试打印不存在的key,则value会输出value类型的默认值
    	// 对于string类型,其默认值为空字符串,所以value输出值为空
    	// 并且新的键值对“-1 : 空”会被插入到map中!!!
    	cout << "mp[-1] = " << mp[-1] << endl;
    
    	for (it = mp.begin(); it != mp.end(); ++it)
    	{
    		cout << it->first << " : " << it->second << endl;
    	}
    
    }
    

    下面是一个multimap的综合应用案例。

    #define SALE_DEPARTMENT 1
    #define DEVELOP_DEPARTMENT 2
    #define FINACIAL_DEPARTMENT 3
    
    class Worker
    {
    public:
    	string mName;
    	string mTel;
    	int mAge;
    	int mSalary;
    };
    
    void CreateWorker(vector<Worker> &worker)
    {
    	string seedName = "ABCDE";
    	for (int i = 0; i < 5; ++i)
    	{
    		Worker w;
    		w.mName = "员工";
    		w.mName += seedName[i];
    		w.mAge = 20 + rand() % 10;
    		w.mTel = "010-88888888";
    		w.mSalary = rand() % 1000 + 10000;
    
    		worker.push_back(w);
    	}
    }
    
    void WorkerByGroup(vector<Worker> &worker, multimap<int, Worker> &workerGroup)
    {
    	// 随机分配到不同部门
    	for (vector<Worker>::iterator it = worker.begin(); it != worker.end(); ++it)
    	{
    		int departID = rand() % 3 + 1;
    		switch (departID)
    		{
    		case SALE_DEPARTMENT:
    			workerGroup.insert(make_pair(SALE_DEPARTMENT, *it));
    			break;
    		case DEVELOP_DEPARTMENT:
    			workerGroup.insert(make_pair(DEVELOP_DEPARTMENT, *it));
    			break;
    		case FINACIAL_DEPARTMENT:
    			workerGroup.insert(make_pair(FINACIAL_DEPARTMENT, *it));
    			break;
    		default:
    			break;
    		}
    	}
    }
    
    void PrintWorkerByGroup(multimap<int, Worker> &workerGroup)
    {
    	// 打印所有员工信息
    	cout << "所有员工信息:" << endl;
    	multimap<int, Worker>::iterator it;
    	for (it = workerGroup.begin(); it != workerGroup.end(); ++it)
    	{
    		cout << "Name = " << it->second.mName << endl;
    		cout << "Age = " << it->second.mAge << endl;
    		cout << "Tel = " << it->second.mTel << endl;
    		cout << "Salary = " << it->second.mSalary << endl;
    		switch (it->first)
    		{
    		case SALE_DEPARTMENT:
    			cout << "Department = SALE_DEPARTMENT" << endl;
    			break;
    		case DEVELOP_DEPARTMENT:
    			cout << "Department = DEVELOP_DEPARTMENT" << endl;
    			break;
    		case FINACIAL_DEPARTMENT:
    			cout << "Department = FINACIAL_DEPARTMENT" << endl;
    			break;
    		default:
    			break;
    		}
    		cout << endl;
    	}
    
    	// 打印销售部门信息
    	cout << "销售部门信息:" << endl;
    	multimap<int, Worker>::iterator ret = workerGroup.find(SALE_DEPARTMENT);
    	int departCount = workerGroup.count(SALE_DEPARTMENT);
    	int num = 0;
    	for (it = ret; it != workerGroup.end() && num < departCount; ++it, ++num)
    	{
    		cout << (it->second).mName << endl;
    	}
    }
    

    map和set一样,当你使用map来存储自定义类型时,需要使用仿函数来指定自定义类型的排序规则。

    class MyKey
    {
    public:
    	MyKey(int index, int id) : mIndex(index), mID(id) {}
    public:
    	int mIndex;
    	int mID;
    };
    
    class mycmp
    {
    public:
    	bool operator()(const MyKey &k1, const MyKey &k2)
    	{
    		return k1.mIndex > k2.mIndex;
    	}
    };
    int main(int argc, char **argv)
    {
    	// 以下的写法无法通过编译
    	// map<MyKey, int> mp;
    	// mp.insert(make_pair(MyKey(1, 2), 10));
    	// mp.insert(make_pair(MyKey(4, 5), 20));
    
    	map<MyKey, int, mycmp> mp;
    	mp.insert(make_pair(MyKey(1, 2), 10));
    	mp.insert(make_pair(MyKey(4, 5), 20));
    	for (map<MyKey, int, mycmp>::iterator it = mp.begin(); it != mp.end(); ++it)
    	{
    		cout << "Index = " << it->first.mIndex << endl;
    		cout << "ID = " << it->first.mID << endl;
    		cout << "second = " << it->second << endl;
    		cout << endl;
    	}
    
    
    	getchar();
    	return 0;
    }
    
  • 相关阅读:
    app版本升级的测试点
    APP测试完整测试用例设计方法
    多条件组合查询---测试用例设计
    上传文件和导出的测试用例设计
    需求评审时,测试应该做什么?
    什么是PRD?
    什么是测试计划?
    由谁来编写测试计划?
    测试计划模板
    无法预览图片
  • 原文地址:https://www.cnblogs.com/laizhenghong2012/p/11785877.html
Copyright © 2011-2022 走看看