C++总结(6):STL关联容器之set、map、multiset、multimap详解

C++中有多种种类的容器,包括:顺序容器(Sequence Containers)、关联容器(Associative Containers)、无序容器(Unordered Containers)和容器适配器(Container Adapters)。

上一篇文章介绍了顺序容器,这篇文章就来详细一下关联容器。关联容器实现了可以快速搜索的排序数据结构,具有O(log n)的复杂度。它包括setmapmultisetmultimap

1 Set

集合(Set)是一种关联容器类型,它有如下特点:

  • 存储顺序:按排序顺序存储元素。
  • 值特征:每个元素必须是唯一的
  • 值性质:元素的值一旦添加到集合中就不能被修改,尽管可以删除再添加
  • 原理:二叉搜索树
  • 排列顺序:集合中的值没有索引

下面来看一下Set的声明方式:

#include <set>
std::set <data_type> set_name;
例:
set<int> val; // defining an empty set
set<int> val = {6, 10, 5, 1}; // defining a set with values

Set中的元素是唯一的,下面看一个例子:

#include <iostream>
#include <set>

int main()
{
	std::set<char> a;
	a.insert('G');
	a.insert('F');
	a.insert('G');
	for (auto& str : a) {
		std::cout << str << ' '; //F G
	}
	return 0;
}

设置Set降序排列(不指名的话默认为升序):

std::set <data_type, greater<data_type>> set_name;

来看一个例子:

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

int main()
{
	set<int, greater<int> > s1;
	s1.insert(10);
	s1.insert(5);
	s1.insert(12);
	s1.insert(4);
	for (auto i : s1) {
		cout << i << ' ';
	}
	return 0;
}

基本方法

  • begin():返回一个迭代器,指向集合中的第一个元素
  • end():返回一个迭代器,指向集合中最后一个元素后的理论元素
  • size():返回集合中的元素数量
  • max_size():返回集合可以容纳的最大元素数量
  • empty():返回集合是否为空
#include <iostream>
#include <iterator>
#include <set>
using namespace std;

int main()
{
	set<int, greater<int> > s1;
	s1.insert(40);
	s1.insert(30);
	s1.insert(60);
	s1.insert(20);
	s1.insert(50);
	s1.insert(50);
	s1.insert(10);

	set<int, greater<int> >::iterator itr;
	cout << "\nThe set s1 is : \n";
	for (itr = s1.begin(); itr != s1.end(); itr++) {
		cout << *itr << " ";  //60 50 40 30 20 10
	}
	cout << endl;

	set<int> s2(s1.begin(), s1.end());
	cout << "\nThe set s2 after assign from s1 is : \n";
	for (itr = s2.begin(); itr != s2.end(); itr++) {
		cout << *itr << " ";  //10 20 30 40 50 60
	}
	cout << endl;

	cout << "\ns2 after removal of elements less than 30 :\n";
	s2.erase(s2.begin(), s2.find(30));
	for (itr = s2.begin(); itr != s2.end(); itr++) {
		cout << *itr << " ";  //30 40 50 60
	}

	int num;
	num = s2.erase(50);
	cout << "\ns2.erase(50) : " << num << " removed\n";  //1
	for (itr = s2.begin(); itr != s2.end(); itr++) {
		cout << *itr << " ";  //30 40 60
	}
	cout << endl;

	cout << "s1.lower_bound(40) : " << *s1.lower_bound(40) << endl;  //40(第一个不小于40的元素)
	cout << "s1.upper_bound(40) : " << *s1.upper_bound(40) << endl;  //30(第一个不大于40的元素)

	cout << "s2.lower_bound(40) : " << *s2.lower_bound(40) << endl;  //40
	cout << "s2.upper_bound(40) : " << *s2.upper_bound(40) << endl;  //60
	
	return 0;
}

其它方法

FunctionDescription
begin()/end()返回指向第一个/最后一个元素的迭代器
rbegin()/rend()返回指向最后一个元素/集合开始之前位置的反向迭代器
crbegin()/crend()返回一个指向集合的最后一个/第一个元素的常量反向迭代器
cbegin()/cend()返回一个指向集合开始/结束的常量随机访问迭代器
size()返回集合中元素的数量
max_size()返回集合可以容纳的最大元素数量。
empty()判断集合是否为空
insert()在集合中添加一个新元素
insert (iterator position, const g)在迭代器指向的位置添加一个新元素‘g’
erase(iterator position)删除迭代器指向的元素
erase(const g)删除值为‘g’的元素
clear()删除集合中的所有元素
key_comp() / value_comp()比较两个元素的大小以确定它们的排列顺序/比较元素大小(不常用)
find(const g)如果找到元素’g’,则返回指向它的迭代器,否则返回指向集合末尾的迭代器。
count(const g)根据元素’g’是否存在于集合中返回1或0
lower_bound(const g)返回指向集合中第一个与’g’等价或肯定在’g’之前的元素的迭代器
upper_bound(const g)返回指向集合中第一个在’g’之后的元素的迭代器。
equal_range()查找一个键值,并返回一个迭代器分别指向该键值的最小和最大元素(可用此迭代器遍历)
emplace()将新元素插入set容器中,当且仅当插入的元素是不存在于集合中时
emplace_hint()在已知的位置插入一个值并返回一个迭代器,指向插入位置。如果参数中传递的元素已经存在,则返回一个指向现有元素位置的迭代器。
swap()交换两个集合的内容,但两个集合的类型必须相同,尽管大小可能不同
get_allocator()获取与容器关联的分配器对象的副本,以便进行自定义的内存管理

2 Map

Map是以映射方式存储元素的关联容器。每个元素都有一个键值和一个映射值。

基本方法

  • begin():返回映射中第一个元素的迭代器
  • end():返回一个迭代器,指向映射中最后一个元素后面的理论元素
  • size():返回映射中的元素数量
  • max_size():返回映射可以容纳的最大元素数量
  • empty():返回映射是否为空
  • insert(keyvalue, mapvalue):向映射添加新元素
  • erase(iterator position):删除迭代器指向的位置处的元素
  • erase(const g):从映射中删除键值“g”
  • clear():从映射中删除所有元素

例1:begin(),end()size()

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

int main()
{
	map<string, int> mp;

	mp["one"] = 1;
	mp["two"] = 2;
	mp["three"] = 3;

	map<string, int>::iterator it = mp.begin();
	while (it != mp.end()) {
	    //[one]=1 [three]=3 [two]=2
		cout << "[" << it->first << "]=" << it->second << endl;
		++it;
	}
	cout << "Size of map: " << mp.size() << endl; //3
	return 0;
}

例2:Map的使用

#include <iostream>
#include <iterator>
#include <map>
using namespace std;
 
int main()
{
    map<int, int> gquiz1;

    gquiz1.insert(pair<int, int>(1, 40));
    gquiz1.insert(pair<int, int>(2, 30));
    gquiz1.insert(pair<int, int>(3, 60));
    gquiz1.insert(pair<int, int>(4, 20));
    gquiz1.insert(pair<int, int>(5, 50));
    gquiz1.insert(pair<int, int>(6, 50));
 
    gquiz1[7] = 10;// another way of inserting a value in a map
 
    map<int, int>::iterator itr;
    cout << "\nThe map gquiz1 is : \n";
    for (itr = gquiz1.begin(); itr != gquiz1.end(); ++itr) {
        //[1,40][2,30][3,60][4,20][5,50][6,50][7,10]
        cout << '[' << itr->first << ',' << itr->second << ']';
    }
    cout << endl;
 
    map<int, int> gquiz2(gquiz1.begin(), gquiz1.end());
    cout << "\nThe map gquiz2 after" << " assign from gquiz1 is : \n";
    for (itr = gquiz2.begin(); itr != gquiz2.end(); ++itr) {
        //[1,40][2,30][3,60][4,20][5,50][6,50][7,10]
        cout << '[' << itr->first << ',' << itr->second << ']';
    }
    cout << endl;
 
    cout << "\ngquiz2 after removal of elements less than key=3 : \n";
    gquiz2.erase(gquiz2.begin(), gquiz2.find(3));
    for (itr = gquiz2.begin(); itr != gquiz2.end(); ++itr) {
        //[3,60][4,20][5,50][6,50][7,10]
        cout << '[' << itr->first << ',' << itr->second << ']';
    }
 
    int num;
    num = gquiz2.erase(4);
    cout << "\ngquiz2.erase(4) : " << num << " removed \n";
    for (itr = gquiz2.begin(); itr != gquiz2.end(); ++itr) {
        //[3,60][5,50][6,50][7,10]
        cout << '[' << itr->first << ',' << itr->second << ']';
    }
    cout << endl;
    
    cout << "gquiz1.lower_bound(5) : " << " KEY = " << gquiz1.lower_bound(5)->first << ' ';
    cout << " ELEMENT = " << gquiz1.lower_bound(5)->second << endl;//KEY = 5  ELEMENT = 50
    cout << "gquiz1.upper_bound(5) : " << " KEY = " << gquiz1.upper_bound(5)->first << ' ';
    cout << " ELEMENT = " << gquiz1.upper_bound(5)->second << endl;//KEY = 6  ELEMENT = 50
 
    return 0;
}

其它方法

FunctionDefinition
insert()在映射容器中插入具有特定键的元素
count(g)返回与映射中键值“g”匹配的元素的数量
equal_range(k)查找一个键值,并返回一个迭代器分别指向该键值的最小和最大元素(可用此迭代器遍历)
erase()从容器中删除元素
rbegin()/rend()返回指向映射中最后一个元素/第一个键值对之前的理论元素的反向迭代器
find(g)如果找到,返回指向映射中键值“g”的元素的迭代器,否则返回指向末尾的迭代器
crbegin()/crend()返回指向映射中最后一个元素/第一个键值对之前的理论元素的常量反向迭代器
cbegin()/cend()返回指向映射容器中第一个元素/最后一个元素之后的理论元素的常量迭代器
emplace()在映射容器中插入键及其元素
max_size()返回映射容器可以容纳的最大元素数量
upper_bound()/lower_bound()返回一个迭代器,指向第一个键值大于/不小于k的元素,若没有则返回end()
=将一个容器的容量分配给另一个容器,替换其当前内容
emplace_hint()在已知的位置(迭代器)插入一个值并返回一个迭代器,指向插入位置
key_comp()/value_comp()比较两个元素的大小以确定它们的排列顺序/比较元素大小(不常用)
size()返回映射中元素的数量
empty()返回映射是否为空
begin()/end()返回映射中第一个/最后一个元素的迭代器
[]该操作符用于引用操作符中给定位置的元素
clear()从映射中删除所有元素
at(k)返回与键k关联的元素的引用
swap()交换两个映射的内容,但两个映射必须是同一类型

3 Multiset

Multiset是一种类似于Set的关联容器,不同之处在于多个元素可以具有相同的值。

基本方法

  • begin():返回Multiset中第一个元素的迭代器
  • end():返回Multiset中最后一个元素之后的迭代器
  • size():返回Multiset中的元素数
  • max_size():返回Multiset可以容纳的最大元素数
  • empty():返回Multiset是否为空
  • insert(x):在Multiset中插入元素x
  • clear():从Multiset中删除所有元素
  • erase(x):删除所有出现的x

实例

#include <iostream>
#include <iterator>
#include <set>

using namespace std;

int main()
{
	multiset<int, greater<int> > gquiz1;

	gquiz1.insert(40);
	gquiz1.insert(30);
	gquiz1.insert(60);
	gquiz1.insert(20);
	gquiz1.insert(50);
	gquiz1.insert(50);
	gquiz1.insert(10);

	multiset<int, greater<int> >::iterator itr;
	cout << "\nThe multiset gquiz1 is : \n";
	for (itr = gquiz1.begin(); itr != gquiz1.end(); ++itr) {
		cout << *itr << " ";  //60 50 50 40 30 20 10
	}
	cout << endl;


	multiset<int> gquiz2(gquiz1.begin(), gquiz1.end());
	cout << "\nThe multiset gquiz2 \nafter assign from gquiz1 is : \n";
	for (itr = gquiz2.begin(); itr != gquiz2.end(); ++itr) {
		cout << *itr << " ";  //10 20 30 40 50 50 60
	}
	cout << endl;

	cout << "\ngquiz2 after removal of elements less than 30 : \n";
	gquiz2.erase(gquiz2.begin(), gquiz2.find(30));
	for (itr = gquiz2.begin(); itr != gquiz2.end(); ++itr) {
		cout << *itr << " ";  //30 40 50 50 60
	}

	int num;
	num = gquiz2.erase(50);
	cout << "\ngquiz2.erase(50) : " << num << " removed \n";  //2
	for (itr = gquiz2.begin(); itr != gquiz2.end(); ++itr) {
		cout << *itr << " ";  //30 40 60
	}
	cout << endl;

	cout << "\ngquiz1.lower_bound(40) : " << *gquiz1.lower_bound(40) << endl;  //40
	cout << "gquiz1.upper_bound(40) : " << *gquiz1.upper_bound(40) << endl;  //30

	cout << "gquiz2.lower_bound(40) : " << *gquiz2.lower_bound(40) << endl;  //40
	cout << "gquiz2.upper_bound(40) : " << *gquiz2.upper_bound(40) << endl;  //60

	return 0;
}

移除multiset中有相同值的元素

  • a.erase(n):移除multiset中值为n的所有元素
  • a.erase(a.find(n)):移除multiset中值为n的其中一个元素
#include <bits/stdc++.h>
using namespace std;

int main()
{
	multiset<int> a;
	a.insert(10);
	a.insert(10);
	a.insert(10);

	cout << a.count(10) << endl;  //3
	a.erase(a.find(10));
	cout << a.count(10) << endl;  //2
	a.erase(10);
	cout << a.count(10) << endl;  //0

	return 0;
}

其它方法

FunctionDefinition
begin()/end()返回一个迭代器,指向multiset中的第一个元素/最后一个元素后的理论元素
size()返回multiset中的元素数量
max_size()返回multiset可以容纳的最大元素数量
empty()返回multiset是否为空
insert(const g)向multiset添加新元素g。
insert(iterator,const g)在迭代器指向的位置添加新元素“g”
erase(iterator position)删除迭代器指向位置处的元素
erase(const g)从多重集合中删除值“g”
clear()从多重集合中删除所有元素
key_comp()/value_comp()比较两个元素的大小以确定它们的排列顺序/比较元素大小(不常用)
find(const g)如果找到元素“g”,则返回指向它的迭代器,否则返回指向末尾的迭代器
count(const g)返回multiset中与元素“g”匹配的次数
lower_bound(const g)/upper_bound(const g)返回一个迭代器,指向在multiset中第一个元素,该元素不小于/大于给定的元素g。若没有则返回一个指向multiset末尾的迭代器。
swap()交换两个multiset的内容,但集合必须是同一类型
emplace()将新元素插入multiset容器中
equal_range()返回一个迭代器对,迭代器对是容器中所有键值等于k的元素的范围。
emplace_hint()在multiset中插入新元素
rbegin()/rend()返回指向multiset中最后一个元素/第一个元素之前的理论元素的反向迭代器
cbegin()/cend()返回指向multiset中第一个元素/最后一个元素之后的常量迭代器
crbegin()/crend()返回指向multiset中最后一个元素/第一个元素之前的理论元素的反向常量迭代器
get_allocator()获取与multiset关联的分配器对象的副本,以便进行自定义的内存管理

4 Multimap

MultimapMap类似,不同之处在于多个元素可以共享相同的键,它并不要求键-值对必须是唯一的。值得注意的一点是,Multimap始终保持所有键按顺序排序。

基本方法

  • begin():返回指向Multimap中第一个元素的迭代器
  • end():返回指向Multimap中最后一个元素之后理论元素的迭代器
  • size():返回Multimap中元素的数量
  • max_size():返回Multimap可以容纳的最大元素数量
  • empty():返回Multimap是否为空
  • pair<int, int> insert(keyvalue, multimapvalue):向Multimap中添加新元素

Multimap实例

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

int main()
{
	multimap<int, int> gquiz1;

	gquiz1.insert(pair<int, int>(1, 40));
	gquiz1.insert(pair<int, int>(2, 30));
	gquiz1.insert(pair<int, int>(3, 60));
	gquiz1.insert(pair<int, int>(6, 50));
	gquiz1.insert(pair<int, int>(6, 10));

	multimap<int, int>::iterator itr;
	cout << "\nThe multimap gquiz1 is : ";
	for (itr = gquiz1.begin(); itr != gquiz1.end(); ++itr) {
        //[1,40][2,30][3,60][6,50][6,10]
		cout << '[' << itr->first << ',' << itr->second << ']';
	}
	cout << endl;

	gquiz1.insert(pair<int, int>(4, 50));
	gquiz1.insert(pair<int, int>(5, 10));

	cout << "\nThe multimap gquiz1 after adding extra elements is :";
	for (itr = gquiz1.begin(); itr != gquiz1.end(); ++itr) {
        //[1,40][2,30][3,60][4,50][5,10][6,50][6,10]
		cout << '[' << itr->first << ',' << itr->second << ']';
	}
	cout << endl;


	multimap<int, int> gquiz2(gquiz1.begin(), gquiz1.end());

	cout << "\nThe multimap gquiz2 after assign from gquiz1 is :";
	for (itr = gquiz2.begin(); itr != gquiz2.end(); ++itr) {
        //[1,40][2,30][3,60][4,50][5,10][6,50][6,10]
		cout << '[' << itr->first << ',' << itr->second << ']';
	}
	cout << endl;

	cout << "\ngquiz2 after removal of elements less than key=3 :";
	gquiz2.erase(gquiz2.begin(), gquiz2.find(3));
	for (itr = gquiz2.begin(); itr != gquiz2.end(); ++itr) {
        //[3,60][4,50][5,10][6,50][6,10]
		cout << '[' << itr->first << ',' << itr->second << ']';
	}

	int num;
	num = gquiz2.erase(4);
	cout << "\ngquiz2.erase(4) : "<< num << " removed \n ";  //1
	for (itr = gquiz2.begin(); itr != gquiz2.end(); ++itr) {
        //[3,60][5,10][6,50][6,10]
		cout << '[' << itr->first << ',' << itr->second << ']';
	}
	cout << endl;
    //[5,10]
	cout << "gquiz1.lower_bound(5) : ["<< gquiz1.lower_bound(5)->first << ','<< gquiz1.lower_bound(5)->second << ']' <<endl;
	//[6,50]
	cout << "gquiz1.lower_bound(5) : ["<< gquiz1.upper_bound(5)->first << ','<< gquiz1.upper_bound(5)->second << ']' <<endl;
	return 0;
}

其它方法

FunctionDefinition
crbegin()/crend()返回一个指向multimap中最后一个元素/第一个元素之前理论元素的常数逆向迭代器
emplace_hint()在中使用hint插入元素,hint一般是表示插入的位置的迭代器
clear()移除所有元素
multimap empty()返回multimap是否为空
maxsize()返回可以容纳的最大元素数量
key_comp()/value_comp()用于获取multimap的键/键-值的比较对象,允许自定义比较规则
rbegin()/rend()返回一个指向最后一个元素/第一个元素之前理论元素的逆向迭代器
cbegin() and cend()返回一个指向第一个元素/最后一个元素之后理论元素的常数迭代器
swap()交换两个相同类型和大小的multimap容器的内容
size()返回元素的数量
emplace()插入键和其元素
begin()/end()返回一个指向multimap中第一个元素/最后一个元素之后理论元素的迭代器
lower_bound()/upper_bound()返回指向首个不小于/大于给定键值的元素的迭代器
count(g)返回multimap中与给定键值 ‘g’ 匹配的元素数量
erase()从multimap中移除给定键值
find(g)返回multimap中键值 ‘g’ 对应的元素的迭代器,没找到返回尾迭代器。
equal_range()获取一个迭代器对,该对表示与给定键值等效的所有元素的范围
insert()插入元素
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tilblackout

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值