0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C++之set/multiset容器

wang123a 来源:wang123a 作者:wang123a 2023-07-17 09:43 次阅读

1.set/multiset容器简介

set/multiset容器又称为关联式容器,底层是通过二叉树实现。set/multiset容器在插入数据时就会做排序处理,默认是从小到大的顺序。其中set容器允许插入重复数据,multiset则不做此限制。

在前面介绍的string(字符串)、vector(单端数组)、deque(双端数组)、statck(栈)、queue(队列)、list(链表)都属于顺序容器。而set/multiset则是数组关联式容器。

2.set/multiset构造函数和赋值

set容器支持默认构造、有参构造、拷贝构造三种方式。

set容器插入数据使用insert()函数。

set/multiset是一个关联式容器,在插入数据时就会自动排序,底层实现原理是二叉树
set不允许插入重复数据(插入重复数据会忽略)
multiset则可以插入重复数据

set/multiset构造函数
	默认构造:set< T > t;
	有参构造:set(begin,end);
	拷贝构造函数set(const set &p);
set/multiset赋值:
	重载=: set &operator=(const set &p);
#include < iostream >
using namespace std;
#include < set >
void PrintSet(const set< int >& p)
{
	for (set< int >::const_iterator ptr = p.begin(); ptr != p.end(); ptr++)
	{	
		cout < < *ptr < < " ";
	}
	cout < < endl;
}
void PrintMultiset(multiset< int >& p)
{
	for (multiset< int >::const_iterator ptr = p.begin(); ptr != p.end(); ptr++)
	{
		cout < < *ptr < < " ";
	}
	cout < < endl;
}
void test()
{
	set< int > t1;
	//插入数据
	t1.insert(10);
	t1.insert(5);
	t1.insert(7);
	t1.insert(8);
	t1.insert(10);
	PrintSet(t1);
	cout < < "有参构造:" < < endl;
	set< int >t2(t1.begin(), t1.end());
	PrintSet(t2);
	cout < < "拷贝构造:" < < endl;
	set< int >t3(t2);
	PrintSet(t3);

	multiset< int >mt1;
	mt1.insert(10);
	mt1.insert(5);
	mt1.insert(7);
	mt1.insert(8);
	mt1.insert(10);
	cout < < "multiset容器示例:" < < endl;
	PrintMultiset(mt1);
	cout < < "=赋值示例:" < < endl;
	multiset< int >mt2 = mt1;//等号赋值
	PrintMultiset(mt2);
	
}
int main()
{ 
	test();
	system("pause");
}
wKgZomSyZGGAcYuBAANtACAfiRo987.png

3.set容器设置大小和互换元素


set/multiset大小设置:
	获取元素个数:size()
	判断容器是否为空empty();
	互换元素:swap()

#include < iostream >
using namespace std;
#include < set >
#if 1
void PrintSet(const set< int >& p)
{
	for (set< int >::const_iterator ptr = p.begin(); ptr != p.end(); ptr++)
	{
		cout < < *ptr < < " ";
	}
	cout < < endl;
}
void test()
{
	set< int > t1;
	for (int i = 0; i < 5; i++)
	{
		int temp = rand() % 100;
		t1.insert(temp);
	}
	cout < < "元素个数:" < < t1.size() < < endl;
	cout < < "t1数据信息:" < < endl;
	PrintSet(t1);
	set< int > t2;
	if (t2.empty())
	{
		cout < < "t2容器为空" < < endl;
	}
	cout < < "t2赋值" < < endl;
	t2 = t1;
	cout < < "t2数据信息:" < < endl;
	PrintSet(t2);
	cout < < "swap数据互换:" < < endl;
	set< int >t3;
	t3.swap(t2);
	cout < < "t3数据信息:" < < endl;
	PrintSet(t3);
	cout < < "t2数据信息:" < < endl;
	PrintSet(t2);
	cout < < "t2元素个数:" < ()< <>
wKgaomSyZMmAIPwcAAQ6UpWmRZs135.png

4.set容器设置大小和互换元素

insert()插入元素,可以插入单端数据,也可以插入一个区间数据。

erase()删除元素,可以指定位置删除,可以删除所以相同的元素,也可以删除一个区间范围。

clear()清空容器。

set容器插入:
	insert(elem)  -->插入数据elem
	insert(begin,endl)--->插入区间
注意:set容器没有push_back、push_front函数
set容器删除:
	erase(elem);//删除成员,相当于list容器的remove
	erase(begin,end);//删除区间
	erase(pos);//指定位置删除
	clear();//清空
#include < iostream >
using namespace std;
#include < set >
class Person
{
public:
	Person(string name, int age) :name(name), age(age) {
	}
	//setr容器由于插入数据时会对数据进行排序,所以需要重载"< ",而且必须为常函数
	bool operator< (const Person& p)const
	{
		if (name == p.name)return age < p.age;
		else name < p.name;
	}
	bool operator==(const Person& p)const
	{
		if (name == p.name && age == p.age)return true;
		return false;
	}
	string name;
	int age;
};
ostream& operator< <(ostream& cout, const Person& p)
{
	cout < < "姓名:" < < p.name < < "t年龄:" < < p.age;
	return cout;
}
void PrintSet(set< Person >& p)
{
	for (set< Person >::iterator ptr = p.begin(); ptr != p.end(); ptr++)
	{
		cout < < *ptr < < endl;
	}
}
void test()
{
	set< Person > t1;
	t1.insert(Person("小王",18));
	t1.insert(Person("小李", 18));
	t1.insert(Person("小李", 19));
	t1.insert(Person("小王", 18));
	PrintSet(t1);
	set< Person >t2;
	t2.insert(t1.begin(), t1.end());
	cout < < "t2数据内容:" < < endl;
	PrintSet(t2);
	cout < < "t2删除成员:" < < endl;
	t2.erase(Person("小李", 18));
	PrintSet(t2);
	cout < < "t2删除区间:" < < endl;
	t2.erase(t2.begin(), t2.end() );//相当于clear()
	PrintSet(t2);
	cout < < "t1指定位置删除:" < < endl;
	t1.erase(t1.begin());
	PrintSet(t1);

}
int main()
{
	test();
	system("pause");
}
wKgZomSyZZeAfMTiAAS7catRMzQ171.png

5.查找和统计元素个数

find()函数查找元素,查找冲个返回该元素的位置迭代器,失败返回end;

count()函数通过成员,返回个数。

set容器查找:
	set< T >::iterator &find(elem)  -->查找成功返回该成员的迭代器,若不存在返回end()
set容器统计
	count(elem)  --->统计elem的个数
#include < iostream >
using namespace std;
#include < set >
class Person
{
public:
	Person(string name, int age) :name(name), age(age) {

	}
	bool operator< (const Person& p)const
	{
		if (age == p.age)
		{
			return name < p.name;//年龄相同按姓名降序
		}
		return age < p.age;
	}
	string name;
	int age;
};
ostream& operator< <(ostream& cout, const Person& p)
{
	cout < < "姓名:" < < p.name < < "t年龄:" < < p.age;
	return cout;
}
void PrintSet(set< Person >& t)
{
	for (set< Person >::iterator ptr = t.begin(); ptr != t.end(); ptr++)
	{
		cout < < *ptr < < endl;
	}
}
void test()
{
	set< Person > t1;
	t1.insert(Person("小王", 18));
	t1.insert(Person("小李", 18));
	t1.insert(Person("小李", 19));
	t1.insert(Person("小王", 18));
	PrintSet(t1);
	
	auto ret= t1.find(Person("小李", 19));//此时auto ret等价于set< Person >::iterator ret;
	if (ret != t1.end())
	{
		cout < < "查找成功:";
		cout < < *ret < < endl;
	}
	else
	{
		cout < < "查找失败!" < < endl;
	}
	int count = t1.count(Person("小李", 19));
	cout < < "满足的成员个数:"< & t)
{
	for (multiset< Person >::iterator ptr = t.begin(); ptr != t.end(); ptr++)
	{
		cout < < *ptr < < endl;
	}
}
void test2()
{
	multiset< Person > mt;
	mt.insert(Person("小王", 18));
	mt.insert(Person("小李", 18));
	mt.insert(Person("小李", 19));
	mt.insert(Person("小王", 18));
	PrintMultiset(mt);
	cout < < "统计所有的Person("小王", 18)成员" < < endl;
	auto ret = mt.count(Person("小王", 18));
	cout < < "个数为:" < < ret < < endl;

	cout < < "删除所有的Person("小王", 18)成员" < < endl;
	for (auto ptr = mt.begin(); ptr != mt.end(); )
	{
		auto ret = mt.find(Person("小王", 18));
		if (ret != mt.end())
			ptr=mt.erase(ret);//删除该成员,成功返回下一个成员的迭代器
		else ptr++;
	}
	PrintMultiset(mt);
}

int main()
{
	test();
	cout < < "n------------------------multiset容器---------------------" < < endl;
	test2();
	system("pause");
}< 
wKgZomSyZlCAGEUXAATxDQkkc6w160.png

6.set和multiset区别

set和multiset区别:
set不可以插入重复数据,insert插入数据时有返回值。返回类型为队组pair,该返回值返回的是插入数据的位置迭代器,第二是插入的状态值;
multiset可以插入重复数据,insert插入数据返回值为插入数据的位置迭代器;,>

#include < iostream >
using namespace std;
#include < set >
#if 0
class Person
{
public:
	Person(string name, int age) :name(name), age(age) {

	}
	bool operator< (const Person& p)const
	{
		//按年龄排序,年龄相同时再按姓名升序
		if (age == p.age)return name < p.name;
		return age < p.age;
	}
	string name;
	int age;
};
ostream& operator< <(ostream& cout, const Person &p)
{
	cout < < "姓名:" < < p.name < < "t年龄:" < < p.age;
	return cout;
}
void PrintSet(set< Person >& p)
{
	for (set< Person >::iterator ptr = p.begin(); ptr != p.end(); ptr++)
	{
		cout < < *ptr < < endl;
	}

}
void test()
{
	cout < < "set容器,不允许插入重复内容" < < endl;
	set< Person > t1;
	pair < set< Person >::iterator, bool> ret=t1.insert(Person("小王", 18));
	if (ret.second)
	{
		cout < < "插入成功!" < < endl;
		cout < < "插入的值为:" < < *(ret.first) < < endl;
	}
	ret = t1.insert(Person("小王", 18));
	if (ret.second)
	{
		cout < < "第二次插入成功!" < < endl;
		cout < < "插入的值为:" < < *(ret.first) < < endl;
	}
	else
	{
		cout < < "第二次插入失败!" < < endl;
		cout < < "插入的值为:" < < *(ret.first) < < endl;
	}
	cout < < "ptr内容:" < < endl;
	PrintSet(t1);

	cout < < "multiset容器,允许插入重复内容" < < endl;
	multiset< Person > mt;
	auto point=mt.insert(Person("小王", 18));//返回当前位置迭代器iterator
	cout < < "插入数据为:" < < *point < < endl;
	point = mt.insert(Person("小王", 18));//返回当前位置迭代器iterator
	cout < < "插入数据为:" < < *point < < endl;
	cout < < "multiset容器内容:" < < endl;
	for (multiset< Person >::iterator ptr = mt.begin(); ptr != mt.end(); ptr++)
	{
		cout < < *ptr < < endl;
	}

}
int main()
{

	test();
	system("pause");
}
wKgaomSyZu-AaguDAATJkW6bC6Q402.png

7.pair对组使用

对组pair--成对出现的数据,通过队组可以返回两个数据
对组创建:
pair p(val,val2);--有参构造
pairp=make_pair(val,val2),type>,type>

#include < iostream >
using namespace std;
void test()
{
	pair< string, int > p("小王", 18);
	cout < < "第一个参数:" < < p.first < < "t第二个参数:" < < p.second < < endl;
	pair< string, int >p2 = make_pair("小李", 26);
	cout < < "第一个参数:" < < p2.first < < "t第二个参数:" < < p2.second < < endl;

}
int main()
{

	test();
	system("pause");
}
wKgaomSyZ2uAZJm9AANvHTUhop4769.png

8.set容器排序规则设置

set容器默认是升序排序,要实现降序排序则需要设置排序规则:提供一个仿函数。

#include < iostream >
using namespace std;
#include < set >
class mycompare
{
public:
	bool operator()(int v1,int v2)const //仿函数,即重载()运算符
	{
		return v1 > v2;
	}
};
void test()
{
	set< int >t1;
	t1.insert(20);
	t1.insert(10);
	t1.insert(40);
	t1.insert(30);
	t1.insert(5);
	cout < < "默认排序:" < < endl;
	for (set< int >::iterator ptr = t1.begin();ptr != t1.end(); ptr++)
	{
		cout < < *ptr< <" ";
	}
	cout < < endl;
	set< int, mycompare >t2;
	t2.insert(20);
	t2.insert(10);
	t2.insert(40);
	t2.insert(30);
	cout < < "从大到小排序:" < < endl;
	for (set< int,mycompare >::iterator ptr = t2.begin(); ptr != t2.end(); ptr++)
	{
		cout < < *ptr < <" ";
	}
	cout < < endl;
}
int main()
{
	test();
	system("pause");
}
wKgZomSyaAqAI02oAANBHHL0m84982.png

9.set容器自定义数据排序示例

对自定义数据类型进行数据排序。

#include < iostream >
using namespace std;
#include < set >
class Person
{
	friend class mycompare;//定义为友元类
	friend ostream& operator< <(ostream& cout, Person p);//友元函数
public:
	Person(string name, int age) :name(name), age(age) {
	}
private:
	string name;
	int age;
};
ostream& operator< <(ostream& cout, Person p)
{
	cout < < "姓名:" < < p.name < < "t年龄:" < < p.age;
	return cout;
}
class mycompare
{
public:
	bool operator()(const Person& p1, const Person& p2)const
	{
		//年龄按降序,名字按升序
		if (p1.age == p2.age)
		{
			return p1.name < p2.name;
		}
		return p1.age > p2.age;
	}
};
void PrintSet(set< Person, mycompare >t)
{
	for (set< Person, mycompare >::iterator ptr = t.begin(); ptr != t.end(); ptr++)
	{
		cout < < *ptr < < endl;
	}
}
void test()
{
	set< Person,mycompare >t1;
	t1.insert(Person("小王", 18));
	t1.insert(Person("小李", 18));
	t1.insert(Person("小李", 19));
	t1.insert(Person("小王", 18));
	PrintSet(t1);

}
int main()
{
	test();
	system("pause");
}
wKgaomSyaHaAUuRzAALtsANwS3c248.png



审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 字符串
    +关注

    关注

    1

    文章

    579

    浏览量

    20512
  • 函数
    +关注

    关注

    3

    文章

    4331

    浏览量

    62604
  • 容器
    +关注

    关注

    0

    文章

    495

    浏览量

    22061
  • C++
    C++
    +关注

    关注

    22

    文章

    2108

    浏览量

    73642
收藏 人收藏

    评论

    相关推荐

    c++vector容器

    1.vector容器介绍       向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为
    的头像 发表于 07-13 19:36 1429次阅读
    <b class='flag-5'>c++</b><b class='flag-5'>之</b>vector<b class='flag-5'>容器</b>

    c++list容器

    list是序列容器,允许在序列中的任何位置执行固定O(1)时间复杂度的插入和删除操作,并在两个方向进行迭代。list容器是一个双向循环链表。
    的头像 发表于 07-15 08:53 1415次阅读
    <b class='flag-5'>c++</b><b class='flag-5'>之</b>list<b class='flag-5'>容器</b>

    C++STL算法(二)

    C++STL算法(二)
    的头像 发表于 07-18 14:49 1051次阅读
    <b class='flag-5'>C++</b><b class='flag-5'>之</b>STL算法(二)

    c++STL算法(三)

    c++STL算法(三)
    的头像 发表于 07-18 15:00 1293次阅读
    <b class='flag-5'>c++</b><b class='flag-5'>之</b>STL算法(三)

    C++文件操作

    C++文件操作
    的头像 发表于 07-21 10:52 1115次阅读
    <b class='flag-5'>C++</b><b class='flag-5'>之</b>文件操作

    C++力扣刷题记盛最多的水容器,让我们从C++做题到放弃

    C++
    电路设计
    发布于 :2023年01月05日 15:49:23

    C++标准库学习笔记重点

    查找一个带某特定值的元素,其速度可能快过关联式容器。 unordered set、unordered multiset、unordered map、unordered multimap31.
    发表于 10-23 20:28

    详细剖析C++的的3种容器

    容器是随着面向对象语言的诞生而提出的,容器类在面向对象语言中特别重要,甚至它被认为是早期面向对象语言的基础。在现在几乎所有的面向对象的语言中也都伴随着一个容器集,在C++ 中,就是标准
    的头像 发表于 01-09 12:57 4963次阅读
    详细剖析<b class='flag-5'>C++</b>的的3种<b class='flag-5'>容器</b>

    C++容器的使用代码资料总结免费下载

    本文档的主要内容详细介绍的是C++容器的使用代码资料总结免费下载。
    发表于 01-29 10:52 3次下载
    <b class='flag-5'>C++</b><b class='flag-5'>容器</b>的使用代码资料总结免费下载

    C++设计新思维-泛型编程与设计应用

    C++设计新思维-泛型编程与设计应用
    发表于 11-16 15:59 3次下载

    什么是set

    set 容器,又称集合容器,即该容器的底层是以红黑树变体实现的,是典型的关联式容器。这意味着,set
    的头像 发表于 02-27 15:42 1795次阅读

    C++学习笔记c++的基本认识

    自这篇文章我们即将开始C++的奇幻之旅,其内容主要是读C++ Primer的总结和笔记,有兴趣可以找原版书看看,对于学习C++还是有很大帮助的。这篇文章将从一个经典的程序开始介绍C++
    的头像 发表于 03-17 13:57 737次阅读

    C++学习笔记顺序容器

    C++中的顺序容器是一种用于存储和管理元素序列的数据结构。它们提供了一组有序的元素,并支持在序列的任意位置插入和删除元素。C++标准库中提供了多种顺序容器,包括vector、deque
    的头像 发表于 05-11 17:05 596次阅读

    C++入门通用算法

    C++ 是一种强大的编程语言,它提供了许多通用算法,可以用于各种容器类型。这些算法是通过迭代器来操作容器中的元素,因此它们是通用的,可以用于不同类型的容器。在本篇博客中,我们将详细介绍
    的头像 发表于 05-17 09:40 670次阅读

    C++之父新作带你勾勒现代C++地图

    为了帮助大家解决这些痛点问题,让大家领略现代C++美,掌握其中的精髓,更好地使用C++C++之父Bjarne Stroustrup坐不住了,他亲自操刀写就了这本《
    的头像 发表于 10-30 16:35 853次阅读
    <b class='flag-5'>C++</b>之父新作带你勾勒现代<b class='flag-5'>C++</b>地图