STL容器(2)-set

      大家好,继上次为大家介绍完vector容器之后,今天再来为大家介绍stl另一个著名容器-set

目录

set

1.set的简单介绍

2.set的用法

1.set容器的声明

2.set的常用函数

3.set的并,交,差,对称差

 后话


set

1.set的简单介绍

set的中文翻译为“集合”,实际上,c++中的set的确实现了集合的功用,与vector不同的是,set是一种关联容器

在set容器中,元素保有其互异性,其中的每个元素都是互不相同的。(这里的互不相同是指,假如set容器中已经包含了一个数字a,那么无论之后再向set中加入多少次a,set中仍然只会有这一个元素a,不会出现很多a的情况)在某种程度上。这也意味着set具有去重功能

我们所熟知的“集合”,还有一个特性:无序性。而set中的元素并不是无序的,而是升序排列的,在一个数据插入set时,set能够根据数据的值自动进行排序。

而且set的插入删除效率比用其他序列容器高。

之所以set容器能够自动有序,快速添加、删除,是由他的内部实现的:set容器的内部采用了一种非常高效的平衡检索二叉树黑树。关于红黑树,我只能说介于我现在的水平与时间,难以完全展开解释,而且红黑树在数据结构中也是比较复杂高深的,我这里就不做过多介绍,感兴趣的朋友可以自行了解~。


2.set的用法

1.set容器的声明

set容器的声明与之前我们了解过的vector类似。

#include<iostream>
#include<set>

using namespace std;
struct node
{
	...
}

int main()
{
	set<int> st;//整型 
	set<pair<int,int>> st;//pair 
	set<char> st;//字符型 
	set<node> st;//结构体 
 } 

2.set的常用函数

首先要介绍的就是:

st.insert( )   在st中插入元素。

st.begin()    返回指向第一个元素的迭代器.

st.end()      返回指向最后一个元素下一个位置(注意不是最后一个元素)的迭代器.

有了这三个函数,我们就可以实现set容器的一些基本功能。

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

int main()
{
	set<int> st;
	
	st.insert(4);//将4插入st中,
	int n;
	for(int i=1;i<5;i++)//下面我们利用循环来插入多个数。如1,2,3,4 
	{
		cin>>n;
		st.insert(n); 
	 } 
	for(auto it=st.begin();it!=st.end();it++)//set容器的遍历 
	{
		cout<<*it<<" ";
	}
	//最后的输出为1 2 3 4,而不是4 1 2 3 4,可见set容器相同的元素只会储存一次。 
	return 0;
 } 

上面的代码中,我们使用auto关键字定义的迭代器it,当然我们也可以用

     set<int> ::iterator it=st.begin();的方式来定义一个迭代器


st.find(value)   返回set中值为value的元素的迭代器。

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

int main()
{
	set<int> st;
	
	st.insert(4);
	int n;
	for(int i=1;i<5;i++)//1 2 3 4
	{
		cin>>n;
		st.insert(n); 
	 } 
	 auto it=st.begin();
	 it=st.find(2);
	for(;it!=st.end();it++)
	{
		cout<<*it<<" ";
	}//输出结果为2 3 4
	return 0;
 } 

st.erase(it)    删除一个元素,it为需要被删除的元素的迭代器。

st.erase(value)    删除值为value的元素。

st.erase(it1,it2)     it1,it2均为迭代器,删除[it1,it2)内的元素(注意前闭后开);

在刚刚代码的基础上:

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

int main()
{
	set<int> st;
	
	st.insert(4);
	int n;
	for(int i=1;i<5;i++)
	{
		cin>>n;
		st.insert(n); 
	 } 
	st.erase(4);//删除元素值为4的元素。
	for(auto it=st.begin();it!=st.end();it++)
	{
		cout<<*it<<" ";
	}//输出结果为1 2 3
	return 0;

 } 

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

int main()
{
	set<int> st;
	
	st.insert(4);
	int n;
	for(int i=1;i<5;i++)
	{
		cin>>n;
		st.insert(n); 
	 } 
	 auto it=st.begin();//定义it为首元素。 
	 st.erase(it);//删除首元素 
	for(auto it=st.begin();it!=st.end();it++)
	{
		cout<<*it<<" ";
	}//输出结果为2 3 4 
	return 0;

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

int main()
{
	set<int> st;
	
	st.insert(4);
	int n;
	for(int i=1;i<5;i++)//1 2 3 4
	{
		cin>>n;
		st.insert(n); 
	 } 
	 auto it=st.begin();
	 st.erase(it,st.find(3));//删除1~2个元素 
	for(auto it=st.begin();it!=st.end();it++)
	{
		cout<<*it<<" ";
	}//输出结果为3 4
	return 0;
 } 

st.count(value)    判断值为value的元素是否在容器中。

st.empty()    判断是否为空,若为空返回true。

st.clear()      清空set中所有元素。

st.size()    set中元素的个数。

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

int main()
{
	set<int> st;
	int n;
	for(int i=1;i<5;i++)//1 2 3 4
	{
		cin>>n;
		st.insert(n); 
	 } 
	 cout<<st.size()<<endl;//结果为4 
	 if(st.empty()) cout<<"容器为空"<<endl;
	 else cout<<"容器不为空"<<endl;
	 if(st.count(3))  cout<<"容器内有3"<<endl;
	 else cout<<"容器内没有3"<<endl;
	 //输出结果为:容器不为空 容器内有3 
	 st.clear();//清空数组再进行判断 
	 if(st.empty()) cout<<"容器为空"<<endl;
	 else cout<<"容器不为空"<<endl;
	 if(st.count(3))  cout<<"容器内有3"<<endl;
	 else cout<<"容器内没有3"<<endl;
	 //输出结果为:容器为空 容器内没有3	  
	return 0;
 } 

lower_bound(key_value) ,返回第一个大于等于key_value的定位器。

upper_bound(key_value),返回第一个大于key_value的定位器。

这两位也有其用法,在这里我不赘述,先举一个简单的例子,在下篇文章中我会以一道题来详细说明。

#include <iostream>
#include <set>
using namespace std;
int main ()
{
    set<int> st;
    st.insert(3);
    st.insert(4);
    st.insert(5);
    cout<<*st.lower_bound(3)<<endl;//3
    cout<<*st.upper_bound(3)<<endl;//4
    return 0;
}

3.set的并,交,差,对称差

使用以下函数均需要包含头文件#include <algorithm>

set_intersection(取集合交集)

set_union(取集合并集)

set_difference(取集合差集)

set_symmetric_difference(取集合对称差集)

并不是只有set容器可以使用这四个函数,但两个集合必须是有序序列。

使用方法:(四个函数使用方法相似,这里以取并集为例)

1.set_union(A.begin(),A.end(),B.begin(),B.end(),inserter(C1,C1.end()));

将a的第一项至最后一项与b的第一项至最后一项取交集,并将结果储存在c1中。

或:前四项不变,inserter(C1,C1.end()) 改为ostream_iterator<int>(cout," ")。其功能为直接输出其并集。

ostream_iterator<int>(cout," ")是一个输出流迭代器,使用时需要头文件#include <iterator>

第一个参数是输出流std::out,第二个参数可以是字符串,也可以是字符串常量,他表示各个元素被输出时的分隔符。

下面来进行一个总结:

#include <iostream>
#include <algorithm>
#include <set>
#include <iterator>
using namespace std;
int main(){
	set<int>A;
	set<int>B;
	set<int>C1;//存交集 
	set<int>C2;//存差集 
	set<int>C3;//存对称差集 
	int n;
	for(int i=0;i<4;i++){//输入集合A的元素1 2 3 4 
		cin>>n;
		A.insert(n);
	}
	for(int i=0;i<4;i++){//输入集合B的元素2 3 4 5
		cin>>n;
		B.insert(n);
	}
	cout<<endl; 
	
	cout<<"并集:"<<endl; 
	set_union(A.begin(),A.end(),B.begin(),B.end(),ostream_iterator<int>(cout," "));//这里我们不存并集,直接输出。
	 
	set_intersection(A.begin(),A.end(),B.begin(),B.end(),inserter(C1,C1.end()));//之后我们采用先储存,再遍历的方式输出。 
	cout<<endl<<"交集:"<<endl; 
	for(auto pos=C1.begin();pos!=C1.end();pos++){
		cout<<*pos<<" ";
    }
    
	set_difference(A.begin(),A.end(),B.begin(),B.end(),inserter(C2,C2.end()));
	cout<<endl<<"差集:"<<endl; 
	for(auto pos=C2.begin();pos!=C2.end();pos++){
		cout<<*pos<<" ";
	} 
	
	 set_symmetric_difference(A.begin(),A.end(),B.begin(),B.end(),inserter(C3,C3.end()));
	cout<<endl<<"对称差集:"<<endl;
	for(auto pos=C3.begin();pos!=C3.end();pos++){
		cout<<*pos<<" ";
	} 
	return 0;
} 

输出结果为:

~完~


 后话

写到这里,这篇文章已经将近5000字了,也是尽我所能整理了一些set容器的相关知识,当然有一些知识比如set的自定义比较函数没有进行整理,感兴趣的朋友可以自行搜索了解一下qwq~,

话说整理stl容器的篇幅感觉会越来越长,下次我准备整理map,感觉可写的内容更多呢,有点违背这个专栏浅学的初衷,hhh。

就写到这吧,如果您喜欢可以点个赞,如果能得到您的关注支持那更是感激不尽。

下次见,bye。

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值