STL容器与算法 (八)C++ map知识点

C++ map

Map是STL [1] 的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。

map容器属于关联容器中的有序容器。之前所写的srting、vector、list、queue、deque都属于顺序容器;我们接下来所学的map,set都是关联容器。
关联容器的特点是:键—值 对,key—value;顺序容器直接是实值,没有代表性的键值。例如,1—1号学生个人信息,我们在容器中查找1号学生信息,我们只需要找到1的位置就能查询到1号学生信息。

定义

map是键值保存,高效访问,通过键值排序,通过键值查找。
特点:

  • 高效访问,比如容器中有一百万个数据量,map是1~20次找到,而list则是O(log(n))次。缺点:插入效率低于链表,因为涉及到排序
  • 键值不能重复

map和multimap十分相似,区别在于mao容器中元素的关键字不能重复。multimap有的成员函数,map都有。此外,mao还有成员函数operator[]:T & operator[] (Key k);
该成员函数返回 first 值为 k 的元素的 second 部分的引用。如果容器中没有元素的 first 值等于 k,则自动添加一个 first 值为 k 的元素。如果该元素的 second 成员变量是一个对象,则用无参构造函数对其初始化。


头文件

需要引用一个头文件#include<map>

#include<iostream>
#include<map>
using namespace std;

构造函数

  • 无参构造

  • insert()插入元素

语法一:

pair<iterator, bool> insert( const pair<KEY_TYPE,VALUE_TYPE> &val );
只有在val不存在时插入val。返回值是一个指向被插入元素的迭代器和一个描述是否插入的bool值。

pair<键,值>
键值不能重复,实值可以重复;
输出键值用first,实值用second;

void fun(pair<int,char> pr)
{
	cout << pr.first << " " << pr.second << endl;
}

void MapConstruct()
{
	typedef pair<int,char> in_pair;
	
	map<int , char> mp; // < / >  
	mp.insert(pair<int,char>(1,'a'));//插入方法一
	mp.insert(in_pair(2,'b'));//插入方法二

	
	for_each(mp.begin(),mp.end(),fun);
}

输出结果为:
在这里插入图片描述

我们知道在map容器中键值不能有重复的,那我们实验一下,如果有重复的,输出结果会是什么?怎样才能报错;

typedef pair<int,char> in_pair;
	
	map<int , char> mp; // < / >  
	mp.insert(pair<int,char>(1,'a'));
	mp.insert(in_pair(2,'a'));
	mp.insert(in_pair(2,'b'));  //此处,存在两个键值为2的元素
	
	for_each(mp.begin(),mp.end(),fun);//遍历输出

输出结果:
在这里插入图片描述
我们不难发现只有第一个键值为2 的成功输出出来,那么另一个我们怎么判定是map容器内存在重复元素;我们通过定义pair<map<int,char>::iterator,bool>pr;,通过输出bool的真假去判断键值是否重复

typedef pair<int,char> in_pair;
	pair<map<int,char>::iterator,bool>pr;
	
	map<int , char> mp; // < / >  
	mp.insert(pair<int,char>(1,'a'));

	pr = mp.insert(in_pair(2,'a'));
	cout << pr.second << endl;
	
	pr = mp.insert(in_pair(2,'b'));
	cout << pr.second << endl;

输出结果:
在这里插入图片描述
由此我们看到,第一个插入成功bool为1,第二个因为键值重复导致失败所以为0.

语法二:

iterator insert( iterator pos, const pair<KEY_TYPE,VALUE_TYPE> &val );
插入val到pos的后面,然后返回一个指向这个元素的迭代器。

使用迭代器进行插入,迭代器可以++,但是不可以+2,+3之类的;由于map内部会自动排序,不管用迭代器插入到任意位置,map容器也会将其排序,插入到其应有的序列中去

	typedef pair<int,char> in_pair;
	pair<map<int,char>::iterator,bool>pr;
	
	map<int , char> mp; // < / >  
	mp.insert(pair<int,char>(1,'a'));
	pr = mp.insert(in_pair(3,'a'));
//	cout << pr.second << endl;	
	pr = mp.insert(in_pair(4,'b'));
//	cout << pr.second << endl;
	pr = mp.insert(in_pair(5,'b'));
	pr = mp.insert(in_pair(6,'b'));
	pr = mp.insert(in_pair(7,'b'));
	pr = mp.insert(in_pair(9,'b'));
	
	map<int,char>::iterator ite = mp.begin();
	ite++;
	ite++;
	ite++;
	ite++;  //插入第4个位置
	mp.insert(ite, in_pair(2,'b'));
	
	for_each(mp.begin(),mp.end(),fun);

输出结果:

加粗样式
看出我们本应该在第四个位置插入2,b,却被其自动插入到第二个位置,并以键值按照升序排列。

语法三:

void insert( input_iterator start, input_iterator end );
插入start到end的元素到map中。

	map<int,char> mp1;
	mp1.insert(in_pair(8,'d'));
	mp1.insert(in_pair(10,'d'));
	mp.insert(mp1.begin(),mp1.end());
	

输出结果:
在这里插入图片描述

  • 一个参数

用另一个map容器,定义一个新的容器

	map<int,char>mp2(mp1); //将mp1的值初始化给mp2
  • 另一个对象的一段

	map<int,char> mp3(mp2.begin()++,mp2.end()--);
	//将mp2从第二个到倒数第二个初始化给mp3

属性

  • size()返回map中元素的个数

语法:

size_type size();

size()函数返回map中保存的元素个数。

	typedef pair<int,char> in_pair;
	map<int,char> mp;
	mp.insert(in_pair(1,'a'));
	mp.insert(in_pair(2,'b'));
	mp.insert(in_pair(3,'c'));
	mp.insert(in_pair(4,'d'));
	mp.insert(in_pair(5,'e'));
	
	cout << mp.size() << endl;

输出结果:
在这里插入图片描述

  • count() 返回指定元素出现的次数

语法:

size_type count( const KEY_TYPE &key );

我们常用count()判断map中是否存在目标键值。

typedef pair<int,char> in_pair;
	map<int,char> mp;
	mp.insert(in_pair(1,'a'));
	mp.insert(in_pair(2,'b'));
	mp.insert(in_pair(3,'c'));
	mp.insert(in_pair(4,'d'));
	mp.insert(in_pair(5,'e'));
	
	cout << mp.count(2) << endl;//存在键值2
	cout << mp.count(7) << endl;//不存在键值7

输出结果:
在这里插入图片描述
由此可知,mp里存在键值为2的元素,不存在键值为7的元素。

  • empty() 判断是否为空

语法:

bool empty();

empty()函数返回真(true)如果map为空,否则返回假(false)。

 cout << empty() << endl;
  • 头尾迭代器

  • begin() 头

语法:

iterator begin();

begin()函数返回一个迭代器指向map的第一个元素。

  • end()尾

语法:

iterator end();

end()函数返回一个迭代器指向map的尾部。


输出

  • 循环 for_each

需要加头文件#include<algorithm>

  • 迭代器输出

    ite->first 键值
    ite->second 实值
	typedef pair<int,char> in_pair;
	map<int,char> mp;
	mp.insert(in_pair(1,'a'));
	mp.insert(in_pair(2,'b'));
	mp.insert(in_pair(3,'c'));
	mp.insert(in_pair(4,'d'));
	mp.insert(in_pair(5,'e'));
		
	map<int ,char>::iterator ite = mp.begin();
	for(ite; ite != mp.end(); ite++)
	{
		cout << ite->first << " " << ite->second << endl;
		
	}

遍历结果:
在这里插入图片描述


操作

1.增

  • insert()前面有写到

2.改

键值不能改,实值可以改

3.查

  • count()可以用来查询键值是否存在

关于count()前面有写道。

  • find()查找一个元素

语法:

iterator find( const KEY_TYPE &key );

find()函数返回一个迭代器指向键值为key的元素,如果没找到就返回指向map尾部的迭代器。
尾部迭代器 == end(),我们可以判断说法是否正确,如下:

	typedef pair<int,char> in_pair;
	map<int,char> mp;
	mp.insert(in_pair(1,'a'));
	mp.insert(in_pair(2,'b'));
	map<int,char>::iterator ite1 = mp.find(2);
	cout << ite1->first << " " << ite1->second << endl;
	if( mp.end() == mp.find(7))
	{
		cout << "判断正确" << endl;
	}	

输出结果:
在这里插入图片描述

4.删

  • erase () 删除元素

语法:

void erase( iterator pos );
void erase( iterator start, iterator end );
size_type erase( const KEY_TYPE &key );

erase()函数

  • 删除在pos位置的元素
  • 删除在start和end之间的元素
  • 删除那些值为key的所有元素。
void MapDel()
{
	typedef pair<int,char> in_pair;
	map<int,char> mp;
	mp.insert(in_pair(1,'a'));
	mp.insert(in_pair(2,'b'));
	mp.insert(in_pair(3,'c'));
	mp.insert(in_pair(4,'d'));
	mp.insert(in_pair(5,'e'));
	mp.insert(in_pair(6,'f'));
	
	map<int,char>::iterator ite = mp.begin();
	map<int,char>::iterator ite1 = mp.begin();
	ite++;
	ite++;  //指向第三个元素; 
	mp.erase(ite);  //删除迭代器指向的元素 
	//第一次删除后,有:
	//1 a
	//2 b
	//4 d
	//5 e
	//6 f  
	
	ite1++;
	ite1++;
	ite1++; //指向第四个元素; 
	mp.erase(ite1,mp.end());//删除第四个到最后一个之间的元素
	
	mp.erase(1);  //删除键值为1的元素
		
	ite = mp.begin();
	
	for(ite;ite != mp.end(); ite++)
	{
		cout << ite ->first << " " << ite->second << endl;
	}
	 
}

输出结果:
在这里插入图片描述

  • clear()

语法:

void clear();

clear()函数删除map中的所有元素。

	mp.clear();

其他函数

  • swap() 交换

语法:

void swap( map &obj );

swap()交换obj和现map中的元素。

  • 规定从小到大排序

    map容器默认按照键值大小从小到大排序
typedef pair<int,char> in_pair;
	map<int,char> mp;
	mp.insert(in_pair(1,'a'));
	mp.insert(in_pair(5,'e'));
	mp.insert(in_pair(3,'c'));
	mp.insert(in_pair(4,'d'));
	mp.insert(in_pair(2,'b'));	
	mp.insert(in_pair(6,'f'));

	map<int,char>::iterator ite = mp.begin();
	for(ite;ite != mp.end(); ite++)
	{
		cout << ite ->first << " " << ite->second << endl;
	}

输出结果:
在这里插入图片描述

  • 规定从大到小排序

需要头文件#include<functional>以及模板参数列表 greater< int>从而改变map排序顺序

typedef pair<int,char> in_pair;
	map<int,char> mp;
	mp.insert(in_pair(1,'a'));
	mp.insert(in_pair(5,'e'));
	mp.insert(in_pair(3,'c'));
	mp.insert(in_pair(4,'d'));
	mp.insert(in_pair(2,'b'));	
	mp.insert(in_pair(6,'f'));

	map<int,char>::iterator ite = mp.begin();
	for(ite;ite != mp.end(); ite++)
	{
		cout << ite ->first << " " << ite->second << endl;
	}
	cout << endl;
	
	map<int,char,greater<int> > mp1;//模板参数列表,是个类型 
	mp1.insert(in_pair(1,'a'));
	mp1.insert(in_pair(5,'e'));
	mp1.insert(in_pair(3,'c'));
	mp1.insert(in_pair(4,'d'));
	mp1.insert(in_pair(2,'b'));	
	mp1.insert(in_pair(6,'f'));
	
	map<int,char,greater<int> >::iterator ite1 = mp1.begin();
	//注意此处的双>>一定要分开 > >
	for(ite1;ite1 != mp1.end(); ite1++)
	{
		cout << ite1 ->first << " " << ite1->second << endl;
	}

输出:
在这里插入图片描述

  • lower_bound (key)

语法:

iterator lower_bound( const KEY_TYPE &key );

lower_bound()函数返回一个迭代器,指向map中键值>=key的第一个元素。

在这里插入图片描述
比如:我在上面这一列中寻找键值为9的元素,发现没有目标键值,由于lower_bound()函数中定义返回>=key的第一个元素,因此迭代器返回的是键值为10 的元素;若寻找键值为6的元素,那么直接返回6.

  • upper_bound(key)

语法:

iterator upper_bound( const KEY_TYPE &key );

upper_bound()函数返回一个迭代器,指向map中键值>key的第一个元素。
根据上图,返回键值都大于其目标键值。若寻找键值为6的元素,那么直接返回8.

typedef pair<int,char> in_pair;
	map<int,char> mp2;
	mp2.insert(in_pair(1,'a'));
	mp2.insert(in_pair(3,'c'));
	mp2.insert(in_pair(5,'e'));
	
	cout << mp2.lower_bound(3)->first << endl;
	cout << mp2.upper_bound(3)->first << endl;

输出结果:
在这里插入图片描述



#include<iostream>
#include<map>
#include<algorithm>
#include<functional> 
using namespace std;

void fun(pair<int,char> pr)
{
	cout << pr.first << " " << pr.second << endl;
}

void MapConstruct()
{
	typedef pair<int,char> in_pair;
	pair<map<int,char>::iterator,bool>pr;
	
	map<int , char> mp; // < / >  
	mp.insert(pair<int,char>(1,'a'));
	pr = mp.insert(in_pair(3,'a'));
//	cout << pr.second << endl;	
	pr = mp.insert(in_pair(4,'b'));
//	cout << pr.second << endl;
	pr = mp.insert(in_pair(5,'b'));
	pr = mp.insert(in_pair(6,'b'));
	pr = mp.insert(in_pair(7,'b'));
	pr = mp.insert(in_pair(9,'b'));
	
	map<int,char>::iterator ite = mp.begin();
	ite++;
	ite++;
	ite++;
	ite++;
	mp.insert(ite, in_pair(2,'b'));
	
	map<int,char> mp1;
	mp1.insert(in_pair(8,'d'));
	mp1.insert(in_pair(10,'d'));
	mp.insert(mp1.begin(),mp1.end());
	
	map<int,char> mp2(mp1);
	map<int,char> mp3(mp2.begin()++,mp2.end()--);

	for_each(mp.begin(),mp.end(),fun);
}

void MapAttribute()
{
	
	
	typedef pair<int,char> in_pair;
	map<int,char> mp;
	mp.insert(in_pair(1,'a'));
	mp.insert(in_pair(2,'b'));
	mp.insert(in_pair(3,'c'));
	mp.insert(in_pair(4,'d'));
	mp.insert(in_pair(5,'e'));
	
	cout << mp.size() << endl;
	cout << mp.count(2) << endl;
	cout << mp.count(7) << endl;
	
	map<int,char>::iterator ite1 = mp.find(2);
	cout << ite1->first << " " << ite1->second << endl;

	if( mp.end() == mp.find(7))
	{
		cout << "判断正确" << endl;
	}	
	
	
//	cout << mp.empty() << endl;
//	
//	map<int ,char>::iterator ite = mp.begin();
//	
//	for(ite; ite != mp.end(); ite++)
//	{
//		cout << ite->first << " " << ite->second << endl;
//		
//	}
	
}

void MapDel()
{
	typedef pair<int,char> in_pair;
	map<int,char> mp;
	mp.insert(in_pair(1,'a'));
	mp.insert(in_pair(2,'b'));
	mp.insert(in_pair(3,'c'));
	mp.insert(in_pair(4,'d'));
	mp.insert(in_pair(5,'e'));
	mp.insert(in_pair(6,'f'));
	
	map<int,char>::iterator ite = mp.begin();
	map<int,char>::iterator ite1 = mp.begin();
	ite++;
	ite++;  //指向第三个元素; 
	mp.erase(ite);  //删除迭代器指向的元素 
	//第一次删除后,有:
	//1 a
	//2 b
	//4 d
	//5 e
	//6 f  
	
	ite1++;
	ite1++;
	ite1++; //指向第四个元素; 
	mp.erase(ite1,mp.end());//删除第四个到最后一个之间的元素
	
	mp.erase(1);  //删除键值为1的元素
		
	ite = mp.begin();
	
	for(ite;ite != mp.end(); ite++)
	{
		cout << ite ->first << " " << ite->second << endl;
	}
	 
}


void MapOther()
{
	typedef pair<int,char> in_pair;
	map<int,char> mp;
	mp.insert(in_pair(1,'a'));
	mp.insert(in_pair(5,'e'));
	mp.insert(in_pair(3,'c'));
	mp.insert(in_pair(4,'d'));
	mp.insert(in_pair(2,'b'));	
	mp.insert(in_pair(6,'f'));

	map<int,char>::iterator ite = mp.begin();
	for(ite;ite != mp.end(); ite++)
	{
		cout << ite ->first << " " << ite->second << endl;
	}
	cout << endl;
	
	map<int,char,greater<int> > mp1;//模板参数列表,是个类型 
	mp1.insert(in_pair(1,'a'));
	mp1.insert(in_pair(5,'e'));
	mp1.insert(in_pair(3,'c'));
	mp1.insert(in_pair(4,'d'));
	mp1.insert(in_pair(2,'b'));	
	mp1.insert(in_pair(6,'f'));
	
	map<int,char,greater<int> >::iterator ite1 = mp1.begin();
	for(ite1;ite1 != mp1.end(); ite1++)
	{
		cout << ite1 ->first << " " << ite1->second << endl;
	}
	
	typedef pair<int,char> in_pair;
	map<int,char> mp2;
	mp2.insert(in_pair(1,'a'));
	mp2.insert(in_pair(5,'e'));
	mp2.insert(in_pair(3,'c'));
	mp2.insert(in_pair(6,'f'));
	
	cout << mp2.lower_bound(3)->first << endl;
	cout << mp2.upper_bound(3)->first << endl;
	
}

int main()
{
	//MapConstruct();
	//MapAttribute();
	//MapDel();	
	MapOther();
	
	
	system("pause");
	return 0;
}
原创文章 50 获赞 139 访问量 2万+

猜你喜欢

转载自blog.csdn.net/diviner_s/article/details/104372268