小言_互联网的博客

【总结】C++ 数据结构 —— STL之集合(set)用法详解

286人阅读  评论(0)



一、set 的概念

       set 的含义是集合,它是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找等操作,就像一个集合一样。所有的操作的都是严格在logn时间之内完成,效率非常高。set 和 multiset 的区别是:set 插入的元素不能相同,但是 multiset 可以相同。其特点如下:

  1. 每个元素的键值都唯一,不允许两个元素有相同的键值。
  2. 所有元素都会根据元素的键值自动排序。
  3. set 中的元素不像 map 那样可以同时拥有实值(value)和键值(key),只能存储键,是单纯的键的集合。
  4. set 中元素的值不能直接被改变。
  5. set 支持大部分的map的操作,但是 set 不支持下标的操作,而且没有定义mapped_type类型。


二、set 的基本操作

使用STL标准库的 set 时,应包含头文件:#include <set>

1、set 的定义及初始化

set<Type> s						      //定义一个set容器
set<Type> s(s1)			              //定义一个set容器,并用容器s1来初始化
set<Type> s(b, e)					  //b和e分别为迭代器的开始和结束的标记
set<Type> s(s1.begin(), s1.begin()+3) //用容器s1的第0个到第2个值初始化s
set<Type> s(a, a + 5)      		      //将a数组的元素初始化vec向量,不包括a[4]
set<Type> s(&a[1], &a[4]) 			  //将a[1]~a[4]范围内的元素作为s的初始值


2、set 的基本操作

s.begin()					//返回指向第一个元素的迭代器
s.end()						//返回指向最后一个元素的迭代器
s.clear()					//清除所有元素
s.count()					//返回某个值元素的个数
s.empty()					//如果集合为空,返回true,否则返回false
s.equal_range()				//返回集合中与给定值相等的上下限的两个迭代器
s.erase()					//删除集合中的元素
s.find(k)					//返回一个指向被查找到元素的迭代器
s.insert()					//在集合中插入元素
s.lower_bound(k)			//返回一个迭代器,指向键值大于等于k的第一个元素
s.upper_bound(k)			//返回一个迭代器,指向键值大于k的第一个元素
s.max_size()				//返回集合能容纳的元素的最大限值
s.rbegin()					//返回指向集合中最后一个元素的反向迭代器
s.rend()					//返回指向集合中第一个元素的反向迭代器
s.size()					//集合中元素的数目


三、set 的用法


1、基本用法:

#include <iostream>
#include <set>
using namespace std;
int main(){
     set<int> s;
     s.insert(1);
     s.insert(2);
     s.insert(3);
     s.insert(1);
     cout<<"set的size值为 :"<<s.size()<<endl;
     cout<<"set的maxsize的值为 :"<<s.max_size()<<endl;
     cout<<"set中的第一个元素是 :"<<*s.begin()<<endl;
     cout<<"set中的最后一个元素是:"<<*s.end()<<endl;
     s.clear();
     if(s.empty())
         cout<<"set为空"<<endl;
     cout<<"set的size值为 :"<<s.size()<<endl;
     cout<<"set的maxsize的值为 :"<<s.max_size()<<endl;
     return 0;
}

输出结果:

总结:

  1. 插入3之后虽然插入了一个1,但set中最后一个值仍然是3 。一共插入了4个数,但是集合中只有3个数并且是有序的,说明了set集合的两个特点,有序和不重复。
  2. begin() 和 end()函数是不检查set是否为空的,使用前最好使用empty()检验一下set是否为空。

2、count() 的用法

//返回某个值元素的个数
#include <iostream>
#include <set>
using namespace std;
int main(){
     set<int> s;
     s.insert(1);
     s.insert(2);
     s.insert(3);
     s.insert(1);
     cout<<"set 中 1 出现的次数是 :"<<s.count(1)<<endl;
     cout<<"set 中 4 出现的次数是 :"<<s.count(4)<<endl;
     return 0;
}

输出结果:

总结: count() 用来查找set中某个键值出现的次数,但因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了,所以这个函数在set中并不是很实用。

3、erase() 的用法

  1. erase(iterator) :删除定位器iterator指向的值

  2. erase(first,second):删除定位器first和second之间的值

  3. erase(key_value):删除键值key_value的值

#include <iostream>
#include <set>
using namespace std;
int main(){
     set<int> s;
     set<int>::const_iterator it;
     set<int>::iterator first;
     set<int>::iterator second;
     for(int i=1; i<=10; ++i)
         s.insert(i);
     //第一种删除,删掉1
     s.erase(s.begin());
     //第二种删除,删掉2和3
     first = s.begin();
     second = s.begin();
     second++;
     second++;
     s.erase(first,second);
     //第三种删除,删掉8
     s.erase(8);
     cout<<"删除后 set 中元素是 :";
     for(it=s.begin(); it!=s.end(); ++it)
         cout<<*it<<" ";
     cout<<endl;
     return 0;
}

输出结果:

总结: set中的删除操作是不进行任何的错误检查的,比如定位器的是否合法等等,所以用的时候自己一定要注意。

4、find() 的用法

//返回一个指向被查找到元素的迭代器,如果没找到则返回end()
#include <iostream>
#include <set>
using namespace std;
int main(){
     int a[] = {4,5,6};
     set<int> s(a,a+3);
     set<int>::iterator it;
     if((it=s.find(4))!=s.end())
         cout<<*it<<endl;
     return 0;
}

输出结果:

4

5、insert() 的用法

  1. insert(key_value):将key_value插入到set中 ,返回值是pair<set::iterator,bool>,bool标志着插入是否成功,而iterator代表插入的位置;若key_value已经在set中,则iterator表示的key_value在set中的位置。

  2. inset(first,second);将定位器first到second之间的元素插入到set中,返回值是void.

#include <iostream>
#include <set>
using namespace std;
int main(){
     int a[] = {1,2,3};
     set<int> s;
     set<int>::iterator it;
     s.insert(a,a+3);
     for(it=s.begin(); it!=s.end(); ++it)
         cout<<*it<<" ";
     cout<<endl;
     pair<set<int>::iterator,bool> pr;
     pr=s.insert(5);
     if(pr.second)
         cout<<*pr.first<<endl;
     cout<<"插入数值之后的set中有:"<<endl;
	 for(it=s.begin(); it!=s.end(); ++it)
		cout<<*it<<" ";
	 cout<<endl;
     return 0;
}

输出结果:


6、lower_bound()、upper_bound() 的用法

  1. lower_bound(key_value) :返回第一个大于等于key_value的定位器

  2. upper_bound(key_value):返回第一个大于key_value的定位器

#include <iostream>
#include <set>
using namespace std;
int main(){
     set<int> s;
     s.insert(1);
     s.insert(3);
     s.insert(4);
     s.insert(6);
     cout<<*s.lower_bound(1)<<endl;
     cout<<*s.lower_bound(2)<<endl;
     cout<<*s.upper_bound(3)<<endl;
     return 0;
}

输出结果:

1
3
4

7、equal_range() 的用法

equal_range():返回一对定位器,分别表示第一个大于等于给定关键值的元素和第一个大于给定关键值的元素,这个返回值是一个pair类型。如果这一对定位器中哪个返回失败,就会等于end()的值。

#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
int main(){
	set<int> s;
	set<int>::iterator it;
	for(int i=1; i<=5; ++i)
		s.insert(i); //向set中加入数据
	for(it=s.begin(); it!=s.end(); ++it)
		cout<<*it<<" ";  //输出set中的数据
	cout<<endl;
	pair<set<int>::const_iterator,set<int>::const_iterator> pr;
	pr=s.equal_range(3);
	cout<<"第一个大于等于3的数是:"<<*pr.first<<endl;
	cout<<"第一个大于3的数是: "<<*pr.second<<endl;
	return 0;
}

输出结果:


8、自定义比较函数

(1)元素不是结构体:

 //自定义比较函数myComp,重载“()”操作符
struct myComp{
	bool operator()(const your_type &a,const your_type &b){
		return a.data > b.data;
	}
}
set<int,myComp>s;
set<int,myComp>::iterator it;

(2)元素是结构体:

//可以直接将比较函数写在结构体内
struct Info{
	string name;
	float score;
	//重载“<”操作符,自定义排序规则
	bool operator < (const Info &a) const{
		//按score从大到小排列
		return a.score<score;
	}
}
 
set<Info> s;
set<Info>::iterator it;

转载:https://blog.csdn.net/weixin_44668898/article/details/102089892
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场