map和set的使用(基于STL库)

前言

        map和set是STL模板库中重要的关联式容器,与序列式容器不同的是,关联式容器里面存储的是<key,value>结构的键值对,在数据检索时比序列式容器效率更高。让我们一起来看看吧!

目录

1.set

        1.1键值对

        1.2set的介绍

        1.3set的使用 

        1.3.1set的模版参数列表

        1.3.2set的构造函数

        1.3.3set的迭代器

        1.3.4与容量相关的

        1.3.5set的增删查

2.map 

        2.1map的介绍

        2.2map的使用 

        2.2.1 map的模版参数说明

        2.2.2map的构造

        2.2.3map的迭代器

        2.2.4增删查

        2.2.5容量相关

        2.2.6例子

3.multiset

4.multimap


1.set

        和其他容器一样set可以进行增删查,但是不能改变它的值,因为它的底层是用平衡搜索树来实现的额,如果将节点的值改变,就会破坏平衡搜索树的性质,因此改变它是非法的。 

        1.1键值对

        键值对是用来表示一一对应关系的一种结构,该结构中包含两个变量成员,key和value,key代表键值,value表示与key一一对应的信息。比如,现在有一本英汉词典,英语单词和其对于的汉语意思构成键值对。

SGI-STL中关于键值对的定义: 

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)
    {}
};

        1.2set的介绍

        set的介绍 

        关于set使注意事项:

        1.与map/multimap不同,map/multimap中储存的是真正的键值对<key,value>,set中只放value,但是底层实际上是由<value,value>构成的键值对。

        2.set中插入元素时,只需要插入value即可,不需要重构键值对。

        3.set中的元素不可重复。

        4.使用set迭代器遍历set中的元素实际上平衡树的中序遍历。

        5.set中的元素默认是按照小于来比较的。

        6.set查找某个元素,时间复杂度为:logN。

        7.set的元素不允许修改

        8.set底层是由红黑色来实现的

        1.3set的使用 

        1.3.1set的模版参数列表

        

        1.T中存放存放元素的类型,底层实际上存储的<value,value>键值对。

        2. Compare:set中的默认元素按照小于来比较的

        3.Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

        1.3.2set的构造函数

        

函数声明表
函数声明 功能介绍
set (const Compare& comp = Compare(), const Allocator&
= Allocator() );
构造空的set
set (InputIterator first, InputIterator last, const
Compare& comp = Compare(), const Allocator& =
Allocator() );
用[first,last]区间的元素构造set
set ( const set<Key,Compare,Allocator>& x); set的拷贝构造

        1.3.3set的迭代器

        与其他容器一样set也可以使用迭代器遍历,并且set只能使用迭代器遍历。         

        

迭代器函数声明表
函数声明 功能
iterator begin() 返回set起始位置的元素的迭代器
iterator end() 返回set最后一个位置后面的迭代器
const_iterator cbegin()
const
返回set起始位置的const迭代器
const_iterator cend() const 返回set最后一个位置后面的const迭代器
reverse_iterator rbegin() 返回set起始位置的反向迭代器,即end
reverse_iterator rend() 返回set最后一个元素下一个位置的迭代器,即rbegin
const_reverse_iterator
crbegin() const
返回set起始位置的反向const迭代器,即cend
const_reverse_iterator
crend() const
 返回set最后一个元素下一个位置的反向const      迭代器,即crbegin

        1.3.4与容量相关的

函数声明表
函数声明 功能介绍
bool empty ( ) const 检测set是否为空,返回值是bool值,为空返回true
size_type size() const 返回set中有效元素的个数

        1.3.5set的增删查

函数声明表
函数声明 功能介绍
void erase ( iterator position ) 删除迭代器position位置的元素
size_type erase ( const
key_type& x )
删除值为x的元素
void erase ( iterator first,
iterator last )

删除set中[first,last)区间的元素

void swap (
set<Key,Compare,Allocator>&
st );
交换set中的元素
void clear ( ) 将set清空
iterator find ( const
key_type& x ) const
返回值为x的迭代器
size_type count ( const
key_type& x ) const
返回值为x的元素个数

2.map 

        2.1map的介绍

        1.map是关联式容器,它按照特定的次序(按照key值来比较)存储由键值对key和值value组合而成的元素。

        2.在map中,key键值对通常用于排序和唯一的标识元素,而值value中存储与此值key关联的内容。键值对key和value的类型可能不同,并且在map内部,key与value通过成员类型value_type绑在一起,为其区别为pair:typedef pair<const key, T> value_type;

        3.在内部,map中的元素总是按照键值key进行比较排序的。

        4.map通过键值访问单个元素的速度通常比unordered_map慢,但是map允许根据顺序对元素直接迭代(即对map中的元素进行迭代可以得到一个有序序列)。

        5.map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。

        6.map通过被实现为红黑色。

        2.2map的使用 

        2.2.1 map的模版参数说明

template < class Key,                                     // map::key_type           class T,                                       // map::mapped_type           
class Compare = less<Key>,                     // map::key_compare           
class Alloc = allocator<pair<const Key,T> >    // map::allocator_type           
> class map;

 key:对应键值对中的key类型。

T:键值对中的value类型

Compare:比较器类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)不需要传递参数,如果无法比较时(自定义类型),需要用户自己显示传递比较规则(一般情况下按照函数指针或者仿函数来传递)

Allloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器。

        2.2.2map的构造

函数声明 功能介绍
map 构造一个空的map

        2.2.3map的迭代器

迭代器函数声明表
函数声明 功能介绍
begin()和end() begin:首元素的位置,end:最后一个元素下一个元素的位置
cbegin()和cend() 与begin和end的意义相同,但是cbegin和cend所指的元素不能修改
rbegin()和rend()

反向迭代器,rbegin在end位置,rend在begin位置,其++和--都是与begin和end操作相反的移动。

crbegin()和crend()

与rbegin和rend位置相同,操作相同,但是crbegin和crend所指向的不能修改

        2.2.4增删查

函数声明 功能介绍
pair<iterator,bool> insert (
const value_type& x )
在map中插入一个键值对x,注意x是一个键值对,返回值也是一个键值对,iterator代表新插入元素的位置,bool代表释放插入成功
void erase ( iterator position ) 删除迭代器position位置的元素
size_type erase ( const
key_type& x )
删除键值为x的元素
void erase ( iterator first,
iterator last )
删除[first,last)区间中的元素
void swap (
map<Key,T,Compare,Allocator>&
mp )
交换两个map中的元素
void clear ( ) 将map中的元素清空
iterator find ( const key_type& x
)
在map中查找key值为x的元素,找到返回该元素的位置的迭代器,否则返回end
const_iterator find ( const
key_type& x ) const
在map中查找key为x的元素,找到返回该元素的位置的const迭代器,否则返回cend

        2.2.5容量相关

函数声明 功能简介
bool empty ( ) const 检测map中是否为空,如果为空返回true
size_type size() const 返回map中的有效元素的个数
mapped_type& operator[] (const
key_type& k)
返回key对应的value

         如果使用operator[]时没有找到key值,即当key不存在时,operator[]用默认的value与key构造键值对然后插入,返回默认的value,at()函数抛出异常。

        2.2.6例子

#include<iostream>
#include<map>
#include<set>
#include<string>
using namespace std;
void map1()
{
	//使用map来统计水果出现的次数
	string s[] = { "西瓜", "西瓜", "菠萝", "西瓜", "苹果", "苹果", "西瓜",
		"西瓜", "菠萝", "菠萝", "哈密瓜","甜枣","甜枣","荔枝" };
	map<string, int> mp;
	for (auto& e : s)
	{
		map<string, int>::iterator it = mp.find(e);
		if (it != mp.end())
		{
			it->second++;//存在的水果次数就加加
		}
		else
		{
			mp.insert(make_pair(e,1));//不存在就插入
		}
	}
	for (auto& e : mp)
		cout << e.first << " " << e.second << endl;
}

void map2()
{
	map<string, string> m;
	//向map中插入元素
	//将键值对<"apple","苹果">插入map中,用pair来构造键值对
	m.insert(pair<string, string>("apple", "苹果"));
	//将键值对<"orange","橙子">插入到map中,用make_pair来构造键值对
	m.insert(make_pair("orange", "橙子"));
	//用operator[]向map中插入元素
	m["pear"] = "梨子";
	//key不存在时抛异常
	//
	cout << m.size();
	//遍历map
	for (auto& e : m)
		cout << e.first << ": " << e.second << endl;
	//map中的键值对key一定是唯一的
	//如果key存在将插入失败
	auto e = m.insert(make_pair("apple", "苹果"));
	if (e.second)
	{
		cout << "<apple,苹果>不在map中, 已经插入" << endl;

	}
	else
	{
		cout << "键值为peach的元素已经存在:" << endl;

	}
	auto e1 = m.erase("apple");//删除键值对为“Apple”的元素
	if (e1)
	{
		cout << "删除apple成功!" << endl;
	}
	else
	{
		cout << "删除apple失败!" << endl;
	}
}
void maps()
{
	string s[] = { "西瓜", "西瓜", "菠萝", "西瓜", "苹果", "苹果", "西瓜",
		"西瓜", "菠萝", "菠萝", "哈密瓜","甜枣","甜枣","荔枝" };
	map<string, int> m;
	for (auto& e : s)
		m[e]++;//通过调用map的operator[]来统计水果出现的次数
	for (auto& e : m)
		cout << e.first << ":" << e.second << endl;
}

        可以通过map中的operator[]来对水果出现的次数进行统计,这和其他容器的opreator[]不同,它是怎么做到的呢,这就要和它的底层实现有关系了,实际上operator[]是调用insert实现的,而且operator[]返回的是<K,V>键值对的V的引用。

return (*((this->insert(make_pair(k, mapped_type()))).first)).second 

所以当key不存在时会将key插入map对象中,operator[]用默认的value和key组成键值对,然后插入,返回该默认的value。

如果key已经存在不会插入成功,operator[]返回已经存在的<key,vaule>键值对的value的引用。

我们可以使用insert来替代operator[]的功能,如下:

void map3()
{
	string s[] = { "西瓜", "西瓜", "菠萝", "西瓜", "苹果", "苹果", "西瓜",
		"西瓜", "菠萝", "菠萝", "哈密瓜","甜枣","甜枣","荔枝" };
	map<string, int> m;
	for (auto& e : s)
	{
		std::pair<map<string,int>::iterator, bool> it = m.insert(make_pair(e, 1));
		if (it.second == false)//key存在
		{
			++ (it.first->second);
		}
		
	}
	for (auto& e : m)
		cout << e.first << ":" << e.second << endl;

}

operator[]还可以进行增查改,例如:

void func()
{
    map<string, int> m;
    m["香蕉"];//增
	cout << m["香蕉"] << endl;//查
	m["香蕉"] = 5; //插入+修改
}

3.multiset

        它和set的用法基本相同,接口也是一致的,但是它允许冗余的键值对存在。例如:

void multiset1()
{
	multiset<int> se;
	int array[] = { 1,3,3,3,4,5,6,4 };
	for (auto& e : array)
	{
		se.insert(e);
	}
	for (auto& e : se)
		cout << e << " ";
}

4.multimap

        它和map的用法也是基本相同的,唯一的区别是multimap允许冗余的键值对存在,并且它没有operator[],因为存在多个相同的key无法区分到key值,因此不提供operator[]。

猜你喜欢

转载自blog.csdn.net/m0_68641696/article/details/132039793