既上篇,这篇继续讲述set。
set:
(1)set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所 以不能指定插入位置。
(2)set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比vector快。
(3)set不可以直接存取元素。(不可以使用at.(pos)与[]操作符)。
(4)multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;而multiset中同一值可以出现多次。
(5)不可以直接修改set或multiset容器中的元素值,因为该类容器是自动排序的。如果希望修改一个元素值,必须先删除原有 的元素,再插入新的元素。
(6)set 默认构造对象:
如:set<int> setInt; //一个存放int的set容器。
(7)set的相关用法:
set.insert(elem); //在容器中插入元素。
set.begin(); //返回容器中第一个数据的迭代器。
set.end(); //返回容器中最后一个数据之后的迭代器。
set.rbegin(); //返回容器中倒数第一个元素的迭代器。
set.rend(); //返回容器中倒数最后一个元素的后面的迭代器。
set<int,less<int> > setIntA; //该容器是按升序方式排列元素。
set<int,greater<int>> setIntB; //该容器是按降序方式排列元素。
set(const set &st); //拷贝构造函数
set& operator=(const set &st); //重载等号操作符
set.swap(st); //交换两个集合容器
set.size(); //返回容器中元素的数目
set.empty(); //判断容器是否为空
set.clear(); //清除所有元素
set.erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
set.erase(beg,end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
set.erase(elem); //删除容器中值为elem的元素。
set.find(elem); //查找elem元素,返回指向elem元素的迭代器。
set.count(elem); //返回容器中值为elem的元素个数。对set来说,要么是0,要么是1。对multiset来说,值可能大于1。
set.lower_bound(elem); //返回第一个>=elem元素的迭代器。
set.upper_bound(elem); //返回第一个>elem元素的迭代器。
set.equal_range(elem); //返回容器中与elem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end)。
(8)set<int>相当于 set<int,less<int>>。
less<int>与greater<int>中的int可以改成其它类型,该类型主要要跟set容纳的数据类型一致。
疑问1:less<>与greater<>是什么?
疑问2:如果set<>不包含int类型,而是包含自定义类型,set容器如何排序?
要解决如上两个问题,需要了解容器的函数对象,也叫伪函数,英文名叫functor。
下面将讲解什么是functor,functor的用法:
解答:尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数的方法,那就是函数对象。
functor,翻译成函数对象,伪函数,算符,是重载了“()”操作符的普通类对象。从语法上讲,它与普通函数行为类似。
greater<>与less<>就是函数对象。
(9)pair:
1、pair译为对组,可以将两个值视为一个单元。
2、pair<T1,T2>存放的两个值的类型,可以不一样,如T1为int,T2为float。T1,T2也可以是自定义类型。
3、pair.first是pair里面的第一个值,是T1类型。
4、pair.second是pair里面的第二个值,是T2类型。
举例:注意注释
#include<set>
#include<iostream>
#include<cstring>
using namespace std;
class Student
{
friend class Cmp;
private:
char m_name[20];
int m_age;
public:
Student(char *n,int a);
void print() const;
bool operator > (const Student &s) const;
bool operator < (const Student &s) const;
};
Student::Student(char *n,int a) //有参构造函数
{
strcpy(m_name , n);
m_age = a;
}
void Student::print() const //输出信息
{
cout<< m_name << " " << m_age <<endl;
}
bool Student::operator > (const Student &s) const
{
//return (this->m_age > s.m_age); //利用年龄来比较大小
return (strcmp(this->m_name , s.m_name)> 0); //利用名字来比较大小
}
bool Student::operator < (const Student &s) const
{
//return (this->m_age < s.m_age); //利用年龄来比较大小
return (strcmp(this->m_name , s.m_name)< 0); //利用名字来比较大小
}
int main()
{
//srand(time(NULL)); //随机抽样
//less函数对象,默认是less,从大到小排序
//priority_queue< Student , deque<Student> , less<Student> > q;
//greater函数对象,默认是greater,从小到大排序
//priority_queue< int , deque<int> , greater<int> > q;
//Cmp函数对象,作用与greater相同
//priority_queue< Student , deque<Student> , Cmp > q;
set<Student , less<Student> > s;
Student s1("aa" ,24);
Student s2("bb" ,19);
//Student s6("bb" ,21); //如果根据名字比较 s2把s6覆盖掉
Student s3("cc" ,22);
Student s4("dd" ,23);
Student s5("ee" ,28);
Student s6("ff" ,30);
Student s7("gg" ,8);
Student s8("mm" ,40);
Student s9("zz" ,25);
s.insert(s1);
s.insert(s2);
s.insert(s3);
s.insert(s4);
s.insert(s5);
s.insert(s6);
s.insert(s7);
s.insert(s8);
for(set<Student , less<Student> >::iterator it = s.begin(); it!=s.end(); it++)
{
it->print(); //打印信息
}
cout<< "size: " << s.size() <<endl;
if(s.empty()) //判断容器是否为空
{
cout<< "Set is empty!" <<endl;
}
else
{
cout<< "Set is not empty!" <<endl;
}
cout<< "--------------erase iterator---------------" <<endl; //根据迭代器删除信息
set<Student , less<Student> >::iterator it = s.begin();
it++;
s.erase(it);
for(it = s.begin(); it!=s.end(); it++)
{
it->print();
}
cout<< "--------------erase element--------------" <<endl; //根据元素删除信息
Student ss("cc",22);
s.erase(ss);
for(it = s.begin(); it!=s.end(); it++)
{
it->print();
}
cout<< "--------------find--------------" <<endl; //查找元素
Student sss("zz",100);
it = s.find(sss);
if(it == s.end())
{
cout<< "not exist" <<endl;
}
else
{
it->print();
}
cout<< "--------------count--------------" <<endl; //计数
int num = s.count(sss);
cout<< num <<endl;
cout<< "--------------lower_bound--------------" <<endl; //返回第一个>=元素的迭代器
Student ssss("zz",100);
it = s.lower_bound(ssss);
if(it != s.end())
{
it->print();
}
else
{
cout<< "failure!" <<endl;
}
cout<< "--------------upper_bound--------------" <<endl; //返回第一个>元素的迭代器
Student xx("gg",0);
it = s.upper_bound(xx);
if(it != s.end())
{
it->print();
}
else
{
cout<< "failure!" <<endl;
}
return 0;
}