C++STL set/multiset容器

6 篇文章 0 订阅

1、set/multiset容器简介

  • set元素的特性是所有元素都会根据元素的键值自动排序。set的元素不像map可以同时拥有实值和键值,set的元素既是实值也是键值。set不允许两个元素有相同的键值不能通过set的迭代器改变set元素的值,因为set的元素值就是键值,关系到set元素的排序规则,如果任意改变set元素值,会严重破坏set组织。
  • set的迭代器是一种const_iterator(常量迭代器)。set拥有和list某些相同的性质,当对容器中的元素进行插入或删除操作时,除了被删除的那个元素不会造成其他元素的迭代器失效
  • multiset特性及用法和set完全相同,唯一的差别在于它允许键值重复。 set和multiset的底层实现是红黑树(一种平衡二叉树)。

2、API

/*******************************set构造函数******************************/
set<T> st;//set默认构造函数
multiset<T> mst;//multiset默认构造函数
set(const set &st);//拷贝构造函数
/************************赋值操作*************************************/
set& operator=(cosnt set& st);重载=运算符
swap(st);//交换两个集合容器
/****************************大小操作*******************************/
size();//返回容器中元素的数目
empty();//判断容器是否为空
/*************************插入和删除操作***************************/
insert(elem);//在容器中插入元素
clear();清除所有元素
erase(pos);//删除pos迭代器所指向的元素,返回下一个元素的迭代器
erase(beg,end);//删除区间[beg,end)的所有元素,返回下一个元素的迭代器
erase(elem);//删除容器中值为elem的元素
/**********************查找操作******************************/
find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end()
cout(key);//返回键key的元素个数
lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器
uppper_bound(keyElem);//返回第一个key>keyElem元素的迭代器
equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个

3、使用

insert、erase

  • set会对插入的元素按照指定的排序规则进行自动排序,对于基本数据类型,默认按照从小到大排序。
  • set不允许插入相同的键值,insert()函数返回值为对组pair<iterator,bool>,即返回插入位置的迭代器和插入的结果,如果插入了相同的键值,则根据返回值可知插入失败。
void test()
{
    set<int> s;    
    s.insert(20);
    s.insert(40);
    s.insert(30);
    s.insert(40);
    s.insert(10);
    for_each(s.begin(),s.end(),[](int val){
        cout<<val<<" ";
    });//10、20、30、40
    //set容器提供的是只读迭代器const_iterator
    //用户不可以修改set容器的元素
    set<int>::const_iterator it=s.begin();
    //*it=100;//error
    cout<<"size="<<s.size()<<endl;//4
    //删除起始位置的元素
    s.erase(s.begin());
    for_each(s.begin(),s.end(),[](int val){
        cout<<val<<" ";
    });//20 30 40
    //根据元素删除
    s.erase(40);
    for_each(s.begin(),s.end(),[](int val){
        cout<<val<<" ";
    });//20 30
    //count(key)查找键key的元素个数
    //set容器的键值是不重复的,那么count(key)只能是1或0
    cout << s.count(40) << endl;//0   
}

对组(pair)

这里对对组进行简要介绍。对组将一对值合成一个值,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个公有属性first和second访问。
类模板:template<class T1,class T2>struct pair

//第一种创建对组的方法
pair<string,int> pair1(string("name"),20);
cout<<pair1.first<<endl;//访问pair第一个值
cout<<pair1.second<<endl;//访问pair第二个值
//第二种
pair<string,int> pair2=make_pair("name",20);
cout<<pair2.first<<endl;//访问pair第一个值
cout<<pair2.second<<endl;//访问pair第二个值
//第三种=赋值
pair<string,int> pair3=pair2;
cout<<pair3.first<<endl;//访问pair第一个值
cout<<pair3.second<<endl;//访问pair第二个值
void test()
{
    //10086--移动   10010--联通
    //定义对组方式1:
    pair<int,string> pair1(10086,"移动");
    cout<<"编号:"<<pair1.first<<",名称:"<<pair1.second<<endl;
    
    //定义对组方式2(推荐):
    pair<int,string> pair2=make_pair(10010,"联通");
    cout<<"编号:"<<pair2.first<<",名称:"<<pair2.second<<endl;
}

lower_bound、upper_bound

void test()
{
    set<int> s;    
    s.insert(10);
    s.insert(20);
    s.insert(30);
    s.insert(40);
    s.insert(50);
    for_each(s.begin(),s.end(),[](int val){
        cout<<val<<" ";
    });//10、20、30、40、50
        
    //下限:lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器
    set<int>::const_iterator lower_ret;
    lower_ret =s.lower_bound(30);
    if(lower_ret==s.end()){
        cout<<"没有找到30的下限!"<<endl;
    }
    else{
        cout<<"找到30的下限:"<<*lower_ret<<endl;
    }
    //upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器
    set<int>::const_iterator up_ret;
    up_ret=s.upper_bound(30);
    if(up_ret==s.end()){
        cout<<"没有找到30的上限!"<<endl;
    }
    else{
        cout<<"找到30的上限:"<<*up_ret<<endl;
    }
    //equal_range(keyElem);//返回容器中与keyElem相等的key的上下限的两个迭代器
    //equal_range返回的是一个对组
    //first是对组中第一个值,second是队组中第二个值
    pair<set<int>::const_iterator,set<int>::const_iterator> pair_ret;
    pair_ret=s.equal_range(30);
    if(pair_ret.first==s.end()){//下限lower_bound
        cout<<"下限未找到!"<<endl;
    }
    else{
        cout<<"下限找到:"<<*(pair_ret.first)<<endl;
    }
    if(pair_ret.second==s.end()){//上限upper_bound
        cout<<"下限未找到!"<<endl;
    }
    else{
        cout<<"下限找到:"<<*(pair_ret.second)<<endl;
    }
}

在这里插入图片描述

更改set排序规则

  • set容器存放基本数据类型,由于<>中要求既是一个类型,又是一个指定排序规则函数,所以只能是仿函数,普通函数不行。
#include<iostream>
#include<set>
#include<algorithm>
using namespace std;

class MyGreater {
public:
	bool operator()(int val1,int val2) {//从大到小排序(容器中的排序逻辑都是真则不交换,假则交换)
		return val1 > val2;
	}
};
void test()
{
    //默认从小到大
    //改成从大到小
    //set<int,排序规则> s;
	set<int, MyGreater> s;
	s.insert(30);
	s.insert(10);
	s.insert(20);
	s.insert(40);
	for_each(s.begin(), s.end(), [](int val) {cout << val << " "; });
}

在这里插入图片描述

  • set存放自定义数据时有两种选择,一种是重载<运算符,一种是使用仿函数,必须从两者中选择一种,否则会定义失败。

set容器存放自定义数据时重载<运算符

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

class Person {
public:
	string name;
	int age;
	Person(string n, int a) {
		name = n;
		age = a;
	}
	//重载<运算符
	bool operator<(const Person& ob)const {//此处两个const必须加上
		return age < ob.age;
	}
};
void test()
{
    //重载<指定排序规则
	set<Person> s;
	s.insert(Person("小明",16));
	s.insert(Person("小红", 18));
	s.insert(Person("小李", 15));
	s.insert(Person("小天", 16));
	for_each(s.begin(), s.end(), [](Person val) {
		cout << val.name << " "<<val.age<<endl; 
	});
}

在这里插入图片描述

set存放自定义数据时指定排序规则(仿函数)

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

class Person {
public:
	string name;
	int age;
	Person(string n, int a) {
		name = n;
		age = a;
	}
};
class MyGreater {
public:
	bool operator()(Person val1, Person val2) {
		return val1.age < val2.age;
	}
};
void test()
{
	//使用仿函数指定排序规则
	set<Person,MyGreater> s;
	s.insert(Person("小明",16));
	s.insert(Person("小红", 18));
	s.insert(Person("小李", 15));
	s.insert(Person("小天", 16));
	for_each(s.begin(), s.end(), [](Person val) {
		cout << val.name << " "<<val.age<<endl; 
	});
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值