C++map基本概念和接口

目录

一、map中实际的数据类型pair以及对应的数据打印

1、pair数据类型

2、数据打印

二、map的插入insert

1、插入数据时,数据的几种写法

2、插入的几种写法 

 3、插入单个值的返回值

三、map的构造

四、map的删除查找以及其他常用接口

1、删除erase

2、查找find

3、count

4、lower_bound和upper_bound

五、map中的[]重载

六、multimap和map的差异

 


###map和set很多地方相似,最大的不同就是map中存放的不仅仅是key,还有value;使用map时,一般都是通过key去寻找value;

  • map的第二个参数需要时我们自己写仿函数,第三个参数写了内存池需要我们自己写,默认表示内存从空间适配器上面申请;一般来说后面两个参数不需要我们自己写;
  • map底层是红黑树,增删查改的时间复杂度是O(logN);
  • map迭代器是按中序遍历的,所以按照key来排序是升序排列的。

一、map中实际的数据类型pair以及对应的数据打印

1、pair数据类型

key_type就是key,mapped_type就是value,而value_type才是底层每个数据的类型,这个value_type就是pair(对),这个对就是一个类,类里面有两个成员变量,就是key和value;

typedef pair<const Key, T> value_type;
template <class T1, class T2>
struct pair
{
	typedef T1 first_type;
	typedef T2 second_type;
	T1 first;
	T2 second;
	pair() : first(T1()), second(T2())
	{}
	pair(const T1& a, const T2& b) : first(a), second(b)
	{}
	template<class U, class V>
	pair(const pair<U, V>& pr) : first(pr.first), second(pr.second)
	{}
};
template <class T1, class T2>
inline pair<T1, T2> make_pair(T1 x, T2 y)
{
	return (pair<T1, T2>(x, y));
}

key就是first不可改变,否则会破坏底层构建规则;value(second)可以改变;

2、数据打印

由于map数据类型是pair,而这个类类型中没有实现流插入和流提取的重载,所以不能直接输出;所以这里使用到 . 和 -> ,key被重命名为first,value被重命名为second;用迭代器输出时迭代器重载了->和*,可以找到pair类型的对象指针和对象,然后再解引用;

###代码示例:

void test4()
{
	map<string, string> m1;
	m1.insert({ {"apple","苹果"},{"banana","香蕉"},{"pear","梨子"} });
	map<string, string>::iterator i = m1.begin();
	//1、* 解引用迭代器获得pair对象,通过pair的.去获取key和value
	while (i != m1.end())
	{
		cout << (*i).first << " : " << (*i).second << endl;
		i++;
	}
	cout << endl;
	//2、-> 解引用获得获得pair对象指针,通过pair的-> 去获取key和value
	i = m1.begin();
	while (i != m1.end())
	{
		//->在迭代器中被重载,实际上是这样:
		//i.operator->()->first
		cout << i.operator->()->first << " : " << i->second << endl;
		i++;
	}
}

 

二、map的插入insert

1、插入数据时,数据的几种写法

void test1()
{
	map<string, string> m1;
	//map中数据类型就是pair
	//插入
	//1、可以插入一个 pair 的有名对象
	pair<string, string> p1("auto", "自动");
	m1.insert(p1);
	//2、插入 pair 的匿名对象
	m1.insert(pair<string, string>("left", "左"));
	//3、插入pair的两个参数,插入过程中会发生隐式类型转换,先构造一个pair再插入
	m1.insert({ "right","右" });
}

2、插入的几种写法 

插入数据是按照key值是否相同插入的,有重复的就不会插入;

single element (1)
pair<iterator,bool> insert (const value_type& val);
template <class P> pair<iterator,bool> insert (P&& val);
with hint (2)
iterator insert (const_iterator position, const value_type& val);
template <class P> iterator insert (const_iterator position, P&& val);
range (3)
template <class InputIterator>
  void insert (InputIterator first, InputIterator last);
initializer list (4)
void insert (initializer_list<value_type> il);

 

  1. 插入单个数据 ;
  2. 在指定的迭代器位置插入数据;
  3. 插入一段迭代器区间,插入会按照key排序;
  4. 插入一段列表;

###代码示例:

void test2()
{
	map<string, int> mymap;
	//1、插入单个数据
	mymap.insert({ "one", 1 });
	//2、在指定位置插入数据
	map<string, int>::iterator it = mymap.end();
	mymap.insert(it, { "two",2 });
	//3、插入一段迭代器区间
	map<string, int> mymap2;
	mymap2.insert({ "three",3 });
	mymap2.insert({ "four" ,4 });
	mymap2.insert({ "five" ,5 });
	mymap.insert(mymap2.begin(), mymap2.end());
	//4、插入一段列表
	mymap.insert({ { "six",6 } ,{"seven",7} });
}

 3、插入单个值的返回值

插入单个值的返回值的类型是pair<iterator,bool>,这个类型的意思:

  1. iterator就是插入数据成功时数据的迭代器所在,这个key已经存在就插入失败,那么iterator就是这个已经存在的key的迭代器;
  2. bool插入成功就是true,插入失败就是false。

这个返回值是为了map的[]准备的,后面提及。

 

三、map的构造

// empty (1) ⽆参默认构造
explicit map (const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type());
// range (2) 迭代器区间构造
template <class InputIterator>
map (InputIterator first, InputIterator last,
const key_compare& comp = key_compare(),
const allocator_type& = allocator_type());
// copy (3) 拷⻉构造
map (const map& x);
// initializer list (5) initializer 列表构造
map (initializer_list<value_type> il,
const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type());
  1. 无参构造不需要传参数,后面两个参数一般不用传;
  2. 迭代器区间构造,传入一段迭代器区间进行构造,左闭右开;
  3. 拷贝构造,传入一个map的对象进行构造;
  4. 列表构造,传入一段列表

map和set一样是双向迭代器,支持加加和减减以及反向迭代器;

###代码示例:

void test3()
{
	//1、无参
	map<int, int>m1;
	//2、迭代器区间构造
	map<int, int> m2;
	m2.insert({ { 1,1 }, { 2,2 }, { 3,3 } });
	map<int, int>m3(m2.begin(), m2.end());
	//3、拷贝构造
	map<int, int> m4(m2);
	//4、列表构造
	map<int, int>m5({ {5,5},{6,6},{7,7} });
}

四、map的删除查找以及其他常用接口

1、删除erase

(1)
iterator  erase (const_iterator position);
(2)
size_type erase (const key_type& k);
(3)
iterator  erase (const_iterator first, const_iterator last);
  1. 删除迭代器指定的位置;
  2. 给定key值,删除和含相同key值的数据,返回值是删除的个数;这里删除成功只会返回1,multimap返回的值可以是其他值,因为它支持存放多个相同key值的数据; 
  3. 删除一段迭代器区间的数据

2、查找find

 iterator find (const key_type& k);
const_iterator find (const key_type& k) const;

查找成功返回查找得到数据的迭代器;

3、count

size_type count (const key_type& k) const;

 寻找含相同key值的数据,并且返回寻找到的个数;

4、lower_bound和upper_bound

      iterator lower_bound (const key_type& k);
const_iterator lower_bound (const key_type& k) const;
   iterator upper_bound (const key_type& k);
const_iterator upper_bound (const key_type& k) const;

和set相同;

lower_bound返回大于等于这个数据的迭代器;upper_bound返回大于这个数据的迭代器。

五、map中的[]重载

// operator 的内部实现
mapped_type& operator [] ( const key_type& k)
{
// 1、如果k不在map中,insert会插⼊k和mapped_type默认值,同时[]返回结点中存储
mapped_type值的引⽤,那么我们可以通过引⽤修改返映射值。所以[]具备了插⼊+修改功能
// 2、如果k在map中,insert会插⼊失败,但是insert返回pair对象的first是指向key结点的
迭代器,返回值同时[]返回结点中存储mapped_type值的引⽤,所以[]具备了查找+修改的功能
pair<iterator, bool > ret = insert ({ k, mapped_type () });
iterator it = ret.first;
return it->second;
}

前面学到的[]是通过下标获取数据,这里意义不同;

#代码示例:

void test5()
{
	string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "香蕉" };
	map<string, int> m1;
	for (const auto& i : arr)
	{
		m1[i]++;//没有就插入,并且返回value并且加加;有就返回value并且加加
	}
	for (const auto& j : m1)
	{
		cout << j.first << " 个数:" << j.second << endl;
	}
}

六、multimap和map的差异

multimap和map的使⽤基本完全类似,主要区别点在于multimap⽀持关键值key冗余,那么
insert/find/count/erase都围绕着⽀持关键值key冗余有所差异,这⾥跟set和multiset完全⼀样,⽐如
find时,有多个key,返回中序第⼀个。其次就是multimap不⽀持[],因为multimap⽀持key冗余,当返回时,不知道返回key的哪一个value。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值