C++ map 和 multimap 容器

map/multimap的简介
map是标准的关联式容器,一个map里存储的元素是一个键值对序列,叫做(key,value)键值对。它提供基于key快速检索数据的能力。

  1. map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
  2. map底层的具体实现是采用红黑树变体的平衡二叉树的数据结构。在插入操作、删除和检索操作上比vector快很多。
  3. map可以直接存取key所对应的value,支持[]操作符,如map[key]=value。
  4. 使用时必须包含头文件#include <map>

multimap与map的区别:
map支持唯一键值,每个键只能出现一次;而multimap中相同键可以出现多次。multimap不支持[]操作符。

map/multimap容器 和 set/multiset容器都是差不多的,只是map/mulitmap比他们多了一个键值!

如果不懂set/multiset容器的可以点下面链接:
https://blog.csdn.net/cpp_learner/article/details/104751672

当然,map/multimap容器也有仿函数,因为在之前的文章中,已经详细讲过了,所以这里就不在讲了,如果不懂的可以点下面链接去学习:
https://blog.csdn.net/cpp_learner/article/details/104730577


定义
	// 无参
	map<int, string> m1;
	map<int, int> m2;
	map<string, float> m3;
	map<char, string> m4;

	// 带参
	map<int, string> m5(m1.begin(), m1.end());	// 迭代器
	map<string, float> m6(m3);	// 调用拷贝构造函数
	map<char, string> m7 = m4;	// 调用了赋值构造函数

还可以用各种指针类型或自定义类型


插入

// 方式一 构造一个pair,然后插入,如果键存在,则插入失败
m1.insert(pair<int, string>(1, “张三”));

// 方式二 使用make_pair
m1.insert(make_pair(2, “李四”));

// 方式三 使用value_type,相当于pair<int, string>
m1.insert(map<int, string>::value_type(3, “王五”));

// 方式四 使用 [] 重载,如果键值对已经存在,则覆盖原值
m1[4] = “赵六”;
m1[4] = “韩七”;

注意:

  1. 方式一 至 方式三的返回值类型都是一样的,都是
    pair<iterator,bool> 类型

  2. 第四种方法非常直观,但碰到相同的键时会进行覆盖操作。比如插入key 为4的键值时,先在mapStu中查找主键为4的项,若不存在,则将一个键为4,值为默认初始化值的对组插入到mapStu中,然后再将值修改成“赵六”。若发现已存在4这个键,则修改这个键对应的value。

  3. string strName = mapStu[8]; //取值操作或插入操作

  4. 只有当mapStu存在8这个键时才是正确的取操作,否则会自动插入一个实例,键为8,值为默认构造时的初始化值。

下面测试代码 函数 test1 中会有详细案例


迭代器

// 返回容器中第一个数据的迭代器
m1.begin();

// 返回容器中最后一个数据之后的迭代器
m1.end();

// 返回容器中倒数第一个元素的迭代器
m1.rbegin();

// 返回容器中倒数最后一个元素的后面的迭代器
m1.rend();

// 使用迭代器方式输出容器里的值

for (map<int, string>::iterator it = m1.begin(); it != m1.end(); it++) {
	cout << "key:" << (*it).first << "  value:" << (*it).second << endl;
}

排序

map 和 multimap 容器默认存储时是顺序存储的,即
map<int, string> m1; 相等于: map<int, string, less<int>> m1;

也可以使用greater定义一个容器,使其默认逆序存储,即
map<int, string, greater<int>> m2;

在此条链接中会有详细解析:
https://blog.csdn.net/cpp_learner/article/details/104730577

// 交换容器中的元素
m3.swap(m2);


// 返回容器中元素的个数
m1.size();

// 判断容器是否为空
m1.empty(); // 为空返回真,不为空返回假

//删除迭代器所指的元素,返回下一个元素的迭代器
m1.erase(m1.begin());

//删除区间[beg,end)的所有元素,返回下一个元素的迭代器
m1.erase(beg, end);

//删除容器中key为key的对组,返回删除的对组个数
m1.erase(8);

// 删除容器中所有的元素
m1.clear();


查找

map方式
// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();

/*---map---*/
// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
map<int, string>::iterator it = m1.find(5);
if (it != m1.end()) {
	cout << "m1.find(5) = " << (*it).second << endl;
} else {
	cout << "没找到!!!" << endl;
}

multimap方式
// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();

/*---multimap---*/
// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
multimap<int, string>::iterator mit = m2.find(111);
if (mit != m2.end()) {
	for (; mit != m2.end(); mit++) {
		if ((*mit).first == 111) {
			cout << "m2.find(111) = " << (*mit).second << endl;
		} else {
			break;
		}
	}
}

// 返回容器中键值为key的对组个数。对map来说,要么是0,要么是1;对multimap来说,值>=0
m1.count(222);

// 返回第一个 >= key 元素的迭代器
m1.lower_bound(2);

// 返回第一个 > key 元素的迭代器
m1.upper_bound(2);

//返回容器中key与keyElem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end)
//m1.equal_range(keyElem);
m1.equal_range(7);

返回值是: pair<iterator, iterator> 类型

在下面测试代码函数 test7 中会有详细案例。


测试代码:

#include <map>
#include <iostream>
#include <Windows.h>
#include <string>

using namespace std;

// 定义
void test1(void) {
	// 无参
	map<int, string> m1;
	map<int, int> m2;
	map<string, float> m3;
	map<char, string> m4;

	m1.insert(pair<int, string>(1, "张三"));
	m1.insert(pair<int, string>(2, "李四"));

	// 带参
	map<int, string> m5(m1.begin(), m1.end());	// 迭代器
	map<string, float> m6(m3);	// 调用拷贝构造函数
	map<char, string> m7 = m4;	// 调用了赋值构造函数

	for (map<int, string>::iterator it = m1.begin(); it != m1.end(); it++) {
		cout << "key:" << (*it).first << "  value:" << (*it).second << endl;
	}
}

// insert插入
void test2(void) {
	map<int, string> m1;

	// 方式一 构造一个pair,然后插入,如果键存在,则插入失败
	m1.insert(pair<int, string>(1, "张三"));

	// 方式二 使用make_pair
	m1.insert(make_pair(2, "李四"));

	// 方式三 使用value_type,相当于pair<int, string>
	m1.insert(map<int, string>::value_type(3, "王五"));

	// 方式四 使用 [] 重载,如果键值对已经存在,则覆盖原值
	m1[4] = "赵六";
	m1[4] = "韩七";

	m1[5] = m1[6];	// 应为两个都是新值,所以他们创建键后,值默认为空

	m1[7] = m1[4];	// 将键值为4里的值赋值给键值为7的值

	m1[0] = m1[8];	// 新键赋值给旧键,它两的值都为空

	


	// 方式一 至 方式三的返回值类型都是一样的
	pair<map<int, string>::iterator, bool> ret1 = m1.insert(pair<int, string>(9, "刘八"));
	pair<map<int, string>::iterator, bool> ret2 = m1.insert(make_pair(10, "杨九"));
	pair<map<int, string>::iterator, bool> ret3 = m1.insert(map<int, string>::value_type(11, "吴十"));
	if (ret1.second == true) {
		cout << "插入成功!value:" << (*(ret1.first)).second << endl;
	} else {
		cout << "插入失败!" << endl;
	}


	for (map<int, string>::iterator it = m1.begin(); it != m1.end(); it++) {
		cout << "key:" << (*it).first << "  value:" << (*it).second << endl;
	}
}

// 迭代器
void test3(void) {
	map<int, int> m1;

	m1.begin();		// 返回容器中第一个数据的迭代器。
	m1.end();		// 返回容器中最后一个数据之后的迭代器。
	m1.rbegin();  // 返回容器中倒数第一个元素的迭代器。
	m1.rend();   // 返回容器中倒数最后一个元素的后面的迭代器。
}

// 排序
void test4(void) {
	map<int, string> m1;	// 默认是less顺序排序
	//map<int, string, less<int>> m1;

	m1.insert(pair<int, string>(1, "张三"));
	m1.insert(pair<int, string>(2, "李四"));
	m1.insert(pair<int, string>(3, "王五"));
	m1.insert(pair<int, string>(4, "赵六"));

	
	// 可以使用greater逆序排序
	map<int, string, greater<int>> m2;
	m2.insert(pair<int, string>(1, "韩七"));
	m2.insert(pair<int, string>(2, "刘八"));
	m2.insert(pair<int, string>(3, "杨九"));

	map<int, string, greater<int>> m3;

	// 交换容器中的元素
	m3.swap(m2);

	
	cout << "m1 ==> less<int>:" << endl;
	for (map<int, string>::iterator it = m1.begin(); it != m1.end(); it++) {
		cout << "key:" << (*it).first << "  value:" << (*it).second << endl;
	}

	cout << "m3 ==> greater<int>:" << endl;
	for (map<int, string>::iterator it = m3.begin(); it != m3.end(); it++) {
		cout << "key:" << (*it).first << "  value:" << (*it).second << endl;
	}
}

// 大小
void test5(void) {
	map<int, string> m1;

	m1.insert(pair<int, string>(1, "张三"));
	m1.insert(pair<int, string>(2, "李四"));
	m1.insert(pair<int, string>(3, "王五"));
	m1.insert(pair<int, string>(4, "赵六"));

	// 返回容器中元素的个数
	m1.size();

	// 判断容器是否为空
	m1.empty();	// 为空返回真,不为空返回假


	if (!m1.empty()) {
		cout << "容器元素个数为:" << m1.size() << endl;

	} else {
		cout << "容器为空!" << endl;
	}
}

// 删除
void test6(void) {
	map<int, string> m1;

	m1.insert(pair<int, string>(1, "张三"));
	m1.insert(pair<int, string>(2, "李四"));
	m1.insert(pair<int, string>(3, "王五"));
	m1.insert(pair<int, string>(4, "赵六"));
	m1.insert(pair<int, string>(5, "韩七"));
	m1.insert(pair<int, string>(6, "刘八"));
	m1.insert(pair<int, string>(7, "杨九"));
	m1.insert(pair<int, string>(8, "吴十"));

	//删除迭代器所指的元素,返回下一个元素的迭代器
	m1.erase(m1.begin());	// 李四,王五,赵六,韩七,刘八,杨九,吴十


	map<int, string>::iterator beg = m1.begin();
	beg++;
	map<int, string>::iterator end = m1.begin();
	end++;
	end++;
	end++;

	//删除区间[beg,end)的所有元素,返回下一个元素的迭代器
	m1.erase(beg, end);	// 李四,韩七,刘八,杨九,吴十

	//删除容器中key为key的对组,返回删除的对组个数
	m1.erase(8);   // 李四,韩七,刘八,杨九


	for (map<int, string>::iterator it = m1.begin(); it != m1.end(); it++) {
		cout << "key:" << (*it).first << "  value:" << (*it).second << endl;
	}

	// 删除容器中所有的元素
	m1.clear();
}

// 查找
void test7(void) {
	map<int, string> m1;
	multimap<int, string> m2;

	m1.insert(pair<int, string>(1, "张三"));
	m1.insert(pair<int, string>(2, "李四"));
	m1.insert(pair<int, string>(3, "王五"));
	m1.insert(pair<int, string>(4, "赵六"));
	m1.insert(pair<int, string>(5, "韩七"));
	m1.insert(pair<int, string>(6, "刘八"));
	m1.insert(pair<int, string>(7, "杨九"));
	m1.insert(pair<int, string>(8, "吴十"));

	m2.insert(pair<int, string>(111, "张三"));
	m2.insert(pair<int, string>(111, "李四"));
	m2.insert(pair<int, string>(222, "王五"));
	m2.insert(pair<int, string>(222, "赵六"));
	

	/*---map---*/
	// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
	map<int, string>::iterator it = m1.find(5);
	if (it != m1.end()) {
		cout << "m1.find(5) = " << (*it).second << endl;
	} else {
		cout << "没找到!!!" << endl;
	}

	/*---multimap---*/
	// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
	multimap<int, string>::iterator mit = m2.find(111);
	if (mit != m2.end()) {
		for (; mit != m2.end(); mit++) {
			if ((*mit).first == 111) {
				cout << "m2.find(111) = " << (*mit).second << endl;
			} else {
				break;
			}
		}
	}

	//返回容器中键值为key的对组个数。对map来说,要么是0,要么是1;对multimap来说,值>=0
	m1.count(222);   

	//返回第一个 >= key 元素的迭代器
	it = m1.lower_bound(2);  
	if (it != m1.end()) {
		cout << "找到啦!==> " << (*it).second << endl;
	} else {
		cout << "没找到!" << endl;
	}

	//  返回第一个 > key 元素的迭代器
	it = m1.upper_bound(2);
	if (it != m1.end()) {
		cout << "找到啦!==> " << (*it).second << endl;
	} else {
		cout << "没找到!" << endl;
	}

	//返回容器中key与keyElem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end)
	//m1.equal_range(keyElem);
	pair<map<int, string>::iterator, map<int, string>::iterator> iit = m1.equal_range(7);
	
	// 第一个迭代器
	if (iit.first != m1.end()) {
		cout << "begin ==> " << (*iit.first).second << endl;
	} else {
		cout << "没找到!" << endl;
	}

	// 第二个迭代器
	if (iit.second != m1.end()) {
		cout << "end ==> " << (*iit.second).second << endl;
	}
	else {
		cout << "没找到!" << endl;
	}

}

int main(void) {
	//test1();

	//test2();

	//test3();

	//test4();

	//test5();

	//test6();

	//test7();

	system("pause");
	return 0;
}

总结:
STL容器中,所有容器的接口用法都是差不多的,所以说其实并不难,只要理解了一种,其他的容器用法都全会了。

发布了47 篇原创文章 · 获赞 37 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/cpp_learner/article/details/104795704
今日推荐