C++中map和set的使用详细攻略

 更新时间:2023年02月22日 09:55:00   作者:命由己造~  
set set是一种关联式容器,下面这篇文章主要给大家介绍了关于C++中map和set使用的相关资料,文中通过实例代码介绍的非常详细,对大家学习或者使用C++具有一定的参考学习价值,需要的朋友可以参考下

一、set

1.1 set的介绍

首先要知道set的底层是由红黑树(平衡二叉搜索树)实现的。

T set存放元素类型,底层是<value, value>的键值对。
Compare 仿函数,因为实现搜索树需要比较。

1.2 set的使用

1.2.1 set的构造

void test_set()
{
	// 默认构造
	set<int> s1;
	// 迭代器区间构造
	int a[] = { 1, 2, 3, 4 };
	set<int> s2(a, a + 4);
	// 拷贝构造(深拷贝)
	set<int> s3(s2);

	for (int e : s2) cout << e << " ";
	cout << endl;
	for (int e : s3) cout << e << " ";
	cout << endl;
}

1.2.2 set的迭代器

可以看到set有反向迭代器。

void test1()
{
	set<int> s;// 排序+去重
	s.insert(1);
	s.insert(2);
	s.insert(3);
	s.insert(1);
	s.insert(3);
	s.insert(4);
	// 正向迭代器
	set<int>::iterator it1 = s.begin();
	while (it1 != s.end())
	{
		cout << *it1++ << " ";
	}
	cout << endl;
	// 反向迭代器
	set<int>::reverse_iterator it2 = s.rbegin();
	while (it2 != s.rend())
	{
		cout << *it2++ << " ";
	}
	cout << endl;
}

因为set的仿函数默认参数是less<T>,所以排的是升序,如果我们想排降序就可以传递greater<T>

void test1()
{
	set<int, greater<int>> s;// 排序+去重
	s.insert(1);
	s.insert(2);
	s.insert(3);
	s.insert(1);
	s.insert(3);
	s.insert(4);
	// 正向迭代器
	set<int>::iterator it1 = s.begin();
	while (it1 != s.end())
	{
		cout << *it1++ << " ";
	}
	cout << endl;
	// 反向迭代器
	set<int>::reverse_iterator it2 = s.rbegin();
	while (it2 != s.rend())
	{
		cout << *it2++ << " ";
	}
	cout << endl;
}

1.2.3 set的修改

1.2.3.1 insert && find && erase

void test2()
{
	set<int> s;
	s.insert(1);
	s.insert(2);
	s.insert(3);
	s.insert(4);
	s.insert(5);
	set<int>::iterator it = s.find(3);
	s.erase(it);
	for (auto& e : s)
	{
		cout << e << " ";
	}
	cout << endl;
}

1.2.3.2 count

传进去一个元素数值,返回该元素的个数

void test2()
{
	set<int> s;
	s.insert(1);
	s.insert(2);
	s.insert(3);
	s.insert(4);
	s.insert(5);
	cout << s.count(2) << endl;
	cout << s.count(6) << endl;
}

因为set的元素是唯一的,所以在set这里count可以用find来代替,但是在后面的multiset可以插入重复的元素,count就可以统计该元素的个数。

1.3 multiset

multiset和set的区别是它可以插入重复的元素。其他的接口跟set一致。头文件也跟set相同

void test3()
{
	multiset<int> ms;
	ms.insert(1);
	ms.insert(1);
	ms.insert(2);
	ms.insert(3);
	ms.insert(4);
	for (auto& e : ms)
	{
		cout << e << " ";
	}
	cout << endl;
	cout << "count(1): " << ms.count(1) << endl;
}

另外使用find查找时,如果有多个值相同,find返回的值是中序的第一个。

二、map

2.1 map的介绍

key 键值对中key的类型
T 键值对中value的类型

注意:

1️⃣ map中的元素总是按照键值key进行比较排序的。
2️⃣ map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。

2.2 map的使用

构造和迭代器跟上面的set类似,就不过多阐述。

2.2.1 map的修改

2.2.1.1 insert

void test4()
{
	map<string, int> m;
	m.insert(pair<string, int>("a", 1));// 匿名对象
	m.insert(make_pair("b", 2));// 简化写法
	m.insert(make_pair("c", 2));
	m.insert(make_pair("d", 2));
	map<string, int>::iterator it = m.begin();
	while (it != m.end())
	{
		cout << (*it).first << "->" << (*it).second << endl;
		it++;
	}
}

make_pair:函数模板,不需要像pair一样显示声明类型,而是通过传参自动推导。

2.2.1.2 统计次数

1️⃣ 使用find,利用迭代器

int main()
{
	string arr[] = { "北京", "武汉", "广州", "上海", "北京", "北京", "广州",
	"上海", "上海" };
	map<string, int> cnt;
	for (auto& e : arr)
	{
		map<string, int>::iterator fd = cnt.find(e);
		if (fd == cnt.end())
		{
			cnt.insert(make_pair(e, 1));
		}
		else
		{
			fd->second++;
		}
	}
	for (auto& e : cnt)
	{
		cout << e.first << "->" << e.second << endl;
	}
	return 0;
}

2️⃣ 使用[]

int main()
{
	string arr[] = { "北京", "武汉", "广州", "上海", "北京", "北京", "广州",
	"上海", "上海" };
	map<string, int> cnt;
	for (auto& e : arr)
	{
		cnt[e]++;
	}
	for (auto& e : cnt)
	{
		cout << e.first << "->" << e.second << endl;
	}
	return 0;
}

[] 可以用来插入、修改、查找

[] -> (*((this->insert(make_pair(k,mapped_type()))).first)).second
// 等价于
V& operator[](const K& k)
{
	pair<iterator, bool> ret = insert(make_pair(k, V()));
	return ret.first->second;
}

这里就可以看出使用[]的时候要注意:如果没有它会直接插入。

所以我们想插入就可以:

int main()
{
	map<string, int> m;
	// 插入
	m["广西"];
	m["广东"] = 1;
	for (auto& e : m)
	{
		cout << e.first << "->" << e.second << endl;
	}
	return 0;
}

当我们想要修改的时候不能用insert,因为只要key相同就会插入失败

int main()
{
	map<string, int> m;
	// 插入
	m["广西"];
	m["广东"] = 1;
	m.insert(make_pair("广东", 2));// 插入失败
	for (auto& e : m)
	{
		cout << e.first << "->" << e.second << endl;
	}
	return 0;
}

先要修改可以:

m["广东"] = 2;

key不在就是插入,key在就是查找。

2.3 multimap

int main()
{
	multimap<string, int> mm;
	mm.insert(make_pair("北京", 1));
	mm.insert(make_pair("北京", 2));
	mm.insert(make_pair("北京", 1));
	mm.insert(make_pair("上海", 1));
	for (auto& e : mm)
	{
		cout << e.first << "->" << e.second << endl;
	}
	return 0;
}

multimap容器与map容器的底层实现以及成员函数的接口都是基本一致,而multimap的key可以重复注意multimap没有[]

使用multimap统计次数:

int main()
{
	multimap<string, int> mm;
	string arr[] = { "北京", "武汉", "广州", "上海", "北京", "北京", "广州",
	"上海", "上海" };
	for (auto& e : arr)
	{
		map<string, int>::iterator fd = mm.find(e);
		if (fd == mm.end())
		{
			mm.insert(make_pair(e, 1));
		}
		else
		{
			fd->second++;
		}
	}
	for (auto& e : mm)
	{
		cout << e.first << "->" << e.second << endl;
	}
	return 0;
}

补充:set和map的区别

  • map中的元素是key-value(关键字—值)对:关键字起到索引的作用,值则表示与索引相关联的数据;Set与之相对就是关键字的简单集合,set中每个元素只包含一个关键字。
  • set的迭代器是const的,不允许修改元素的值。map允许修改value,但不允许修改key。其原因是因为map和set是根据关键字排序来保证其有序性的,如果允许修改key的话,那么首先需要删除该键,然后调节平衡,再插入修改后的键值,调节平衡,如此一来,严重破坏了map和set的结构,导致iterator失效,不知道应该指向改变前的位置,还是指向改变后的位置。所以STL中将set的迭代器设置成const,不允许修改迭代器的值;而map的迭代器则不允许修改key值,允许修改value值。
  • map支持下标操作,set不支持下标操作。map可以用key做下标,map的下标运算符[ ]将关键码作为下标去执行查找,如果关键码不存在,则插入一个具有该关键码和mapped_type类型默认值的元素至map中,因此下标运算符[ ]在map应用中需要慎用,const_map不能用,只希望确定某一个关键值是否存在而不希望插入元素时也不应该使用,mapped_type类型没有默认值也不应该使用。如果find能解决需要,尽可能用find。

总结

到此这篇关于C++中map和set的使用的文章就介绍到这了,更多相关C++ map和set的使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言实现五子棋游戏

    C语言实现五子棋游戏

    这篇文章主要为大家详细介绍了C语言五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • C语言实现学生宿舍信息管理系统课程设计

    C语言实现学生宿舍信息管理系统课程设计

    这篇文章主要为大家详细介绍了C语言实现学生宿舍信息管理系统课程设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C++中cin的返回值问题

    C++中cin的返回值问题

    这篇文章主要介绍了C++中cin的返回值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • C++11新特性“=default”,“=delete”的使用

    C++11新特性“=default”,“=delete”的使用

    =default、=delete 是C++11的新特性,分别为:显式缺省(告知编译器生成函数默认的缺省版本)和显式删除(告知编译器不生成函数默认的缺省版本),本文就来介绍一下如何使用
    2021-05-05
  • C语言打印杨辉三角示例汇总

    C语言打印杨辉三角示例汇总

    本文给大家汇总了2种使用C语言实现杨辉三角的方法,不过还是给大家推荐第一种,希望大家能够喜欢。
    2016-02-02
  • C语言实现简单的扫雷功能

    C语言实现简单的扫雷功能

    这篇文章主要为大家详细介绍了C语言实现简单的扫雷功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • C++实现TCP客户端及服务器Recv数据筛选处理详解

    C++实现TCP客户端及服务器Recv数据筛选处理详解

    这篇文章主要为大家介绍了C++实现TCP客户端及服务器Recv数据筛选处理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • C++实现数组的排序/插入重新排序/以及逆置操作详解

    C++实现数组的排序/插入重新排序/以及逆置操作详解

    将新的数字与已经排序好的数组中的数字一一比较,直到找到插入点,然后将插入点以后的数字都向后移动一个单位(a[i+1]=a[i]),然后将数据插入即可
    2013-10-10
  • C++实现LeetCode(58.求末尾单词的长度)

    C++实现LeetCode(58.求末尾单词的长度)

    这篇文章主要介绍了C++实现LeetCode(58.求末尾单词的长度),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++实现双目立体匹配Census算法的示例代码

    C++实现双目立体匹配Census算法的示例代码

    这篇文章主要为大家详细介绍了如何利用C++实现双目立体匹配Census算法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-08-08

最新评论