C++之set/multiset容器

电子说

1.3w人已加入

描述

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");
}
字符串

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元素个数:" < ()< <>
字符串

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");
}
字符串

     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");
}< 
字符串

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");
}
字符串

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");
}
字符串

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");
}
字符串

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");
}
字符串

  

 审核编辑:汤梓红

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

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分