C++ STL——set和multiset
注:原创不易,转载请务必注明原作者和出处,感谢支持!
注:内容来自某培训课程,不一定完全正确!
一 set和multiset
set和multiset的特性是所有元素会根据元素的值自动进行排序。set和multiset以红黑树(平衡二叉树的一种)为底层机制。其查找效率非常好。set容器中不允许重复的元素,multiset则允许重复元素存在。
构造函数
set<T> st; // 默认构造函数
multiset<T> mst; // multiset默认构造函数
set(const set &st); // 拷贝构造函数
赋值操作
set &operator=(const set &st); // 重载等号运算符
swap(st); // 交换两个集合容器中的元素
大小操作
size(); // 返回容器中元素的数目
empty(); // 判断容器是否为空
插入和删除
insert(elem); // 在容器中插入元素
clear(); // 清空所有元素
erase(pos); // 删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg, end); // 删除区间[beg, end)的所有元素
erase(elem); // 删除容器中值为elem的元素
查找操作
find(key); // 查找键key是否存在,若存在,返回该元素的迭代器;若不存在,则返回map.end()
lower_bound(keyElem); // 返回第一个key>=keyElem元素的迭代器
upper_bound(keyElem); // 返回第一个key>keyElem元素的迭代器
equal_range(keyElem); // 返回容器中key和keyElem相等的上下限的两个迭代器
下面是set和multiset的应用案例。
void printSet(set<int> &v)
{
decltype(v.begin()) it;
for (it = v.begin(); it != v.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
}
void printMultiset(multiset<int> &mst)
{
decltype(mst.begin()) it;
for (it = mst.begin(); it != mst.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
}
void Test1()
{
// 初始化
set<int> s1;
s1.insert(7);
s1.insert(2);
s1.insert(4);
s1.insert(5);
s1.insert(1);
printSet(s1);
// 赋值
set<int> s2 = s1;
printSet(s2);
set<int> s3;
s3.swap(s1);
printSet(s1);
printSet(s3);
// 删除
s3.erase(s3.begin());
printSet(s3);
s3.erase(7);
printSet(s3);
// multiset
multiset<int> mst;
mst.insert(7);
mst.insert(6);
mst.insert(9);
mst.insert(1);
mst.insert(6);
cout << "mst = " << endl;
decltype(mst.begin()) it;
for (it = mst.begin(); it != mst.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
// 查找
set<int> st;
for (int i = 1; i <= 10; ++i)
{
st.insert(i * 10);
}
printSet(st);
set<int>::iterator itlow, itup;
// 第一个key >= 30的元素的迭代器
itlow = st.lower_bound(30);
// 第一个key > 60的元素的迭代器
itup = st.upper_bound(60);
cout << "*itlow = " << *itlow << endl;
cout << "*itup = " << *itup << endl;
st.erase(itlow, itup);
printSet(st);
// equal_range()
multiset<int> s;
s.insert(10);
s.insert(20);
s.insert(20);
s.insert(20);
s.insert(30);
s.insert(40);
printMultiset(s);
pair<decltype(s.begin()), decltype(s.begin())> iteq;
iteq = s.equal_range(20);
cout << "*iteq.first = " << *iteq.first << endl;
cout << "*iteq.second = " << *iteq.second << endl;
s.erase(iteq.first, iteq.second);
printMultiset(s);
}
使用仿函数更改set容器的默认排序方式
在上面的案例中,我们知道set容器默认是对int数据从小到大进行排序的。那么怎样才能让set从大到小排序呢?请看下面的例子。
// 仿函数
class MyCompare
{
public:
bool operator() (int v1, int v2)
{
return v1 > v2;
}
};
// 从大到小排序
void Test2()
{
set<int, MyCompare> s1;
s1.insert(7);
s1.insert(2);
s1.insert(4);
s1.insert(5);
s1.insert(1);
decltype(s1.begin()) it;
for (it = s1.begin(); it != s1.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
}
set容器当中如何放置对象
如果你直接这样写的话是不行的!
class Person
{
public:
Person(int id, int age) : id(id), age(age) {}
public:
int id;
int age;
};
void Test3()
{
// 会报错!因为set内部是需要排序的,当你往set里放置对象时,
// set是不知道如何对对象进行排序的。这与基础数据类型不同
set<Person> sp;
Person p1(1000, 20);
Person p2(1001, 21);
Person p3(1002, 22);
sp.insert(p1);
sp.insert(p2);
sp.insert(p3);
}
那这个问题如何解决?使用仿函数!如下所示。
class cmp
{
public:
bool operator() (const Person &p1, const Person &p2)
{
// 根据ID从小到大排序
return p1.id < p2.id;
}
};
void Test3()
{
// 会报错!因为set内部是需要排序的,当你往set里放置对象时,
// set是不知道如何对对象进行排序的。这与基础数据类型不同
// set<Person> sp;
// 正确的写法
set<Person, cmp> sp;
Person p1(1000, 23);
Person p2(1001, 26);
Person p3(1002, 22);
sp.insert(p1);
sp.insert(p2);
sp.insert(p3);
decltype(sp.begin()) it;
for (it = sp.begin(); it != sp.end(); ++it)
{
cout << "id = " << it->id << " " << "age = " << it->age << endl;
}
// 务必注意:因为仿函数cmp里只对Person的ID进行比较
// 所以在下面的案例中,在sp中查找p4,结果理应是p4不在
// sp中的。但是,因为cmp直对Person的ID进行比较,所以
// 下面案例的实际输出是p4在sp中!,因为p4的ID和p3的ID
// 相同。所以,it返回的实际上是p3的迭代器!!!!!!
Person p4(1002, 29);
it = sp.find(p4);
if (it != sp.end())
{
cout << "p4在sp中!" << endl;
cout << "id = " << it->id << " " << "age = " << it->age << endl;
}
else
{
cout << "p4不在sp中!" << endl;
}
}
务必注意上面案例中的查找的注意事项!
二 对组pair
对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个公有函数first和second访问。
创建对组
// 方法一
pair<string, int> p1(string("name"), 20);
cout << p1.first << endl;
cout << p1.second << endl;
// 方法二
pair<string, int> p2 = make_pair("name", 20);
cout << p2.first << endl;
cout << p2.second << endl;
// 对组的赋值
pair<string, int> p3 = p2;
cout << p3.first << endl;
cout << p3.second << endl;
C++ STL——set和multiset的更多相关文章
- C++ STL set和multiset的使用
C++ STL set和multiset的使用 std::set<int> s;那个s这个对象里面存贮的元素是从小到大排序的,(因为用std::less作为比较工具.) 1,set的含义是 ...
- STL Set和multiset 容器
STL Set和multiset 容器 set/multiset的简介 set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列. 元素插入过程是按排序规则插入,所以不能指定插入位 ...
- STL之set && multiset
一.set 在了解关联容器set之前,让我们先来看看下面这个例子,并猜测该例子输出什么: // stl/set1.cpp #include <iostream> #include < ...
- STL - set和multiset
set/multiset的简介 set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列.元素插入过程是按排序规则插入,所以不能指定插入位置. set采用红黑树变体的数据结构实现, ...
- STL之set&multiset使用简介
关于set,必须说明的是set关联式容器.set作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序.应该注 ...
- c++ STL -- set和multiset
set和multiset 1.结构 set和multiset会根据特定的排序原则将元素排序.两者不同之处在于,multisets允许元素重复,而set不允许重复. 只要是assignable.copy ...
- STL:set/multiset用法详解
集合 使用set或multiset之前,必须加入头文件<set> Set.multiset都是集合类,差别在与set中不允许有重复元素,multiset中允许有重复元素. sets和mul ...
- STL使用————SET&MULTISET
SET函数的基本用法 by hhl 使用set的好处 1. 当增加元素后,集合会自动删重并从小到大排列(时间比快排还快)2. 相当于一棵伸展树(能快速求出后继) 使用基础 #include<se ...
- 转自http://blog.sina.com.cn/daylive——C++ STL set&multiset
C++ STL set和multiset的使用 1,set的含义是集合,它是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找等操作,就 像一个集合一样.所有的操作的都是严格在logn时间 ...
随机推荐
- 【python】Logging模块
1.日志记录级别 logging.debug<logging.info<logging.warning<logging.error<logging.critical 关键是最高 ...
- Java攻城狮面试题录:笔试篇(1)
1.作用域public,private,protected,以及不写时的区别答:区别如下:不写时默认为friendly 2.ArrayList和Vector的区别,HashMap和Hashtable的 ...
- Error:Execution failed for task ':app:compileDebugJavaWithJavac'
百度一下呗 查找了各种解决方案,都不对症. 最后发现,造成这种异常的原因有很多.具体的还是要去终端编译,查看到底是什么地方出错了,然后具体问题具体分析. 终端进入项目的根目录,然后输入命令 ./gra ...
- 微信小程序开发(十)获取手机的经纬度
// succ.wxml <view>经度:{{lon}}</view> <view>纬度:{{lat}}</view> // succ.js var ...
- linux-2.6.38 input子系统(简析)
一.输入子系统简介 引入输入子系统这种机制可以对不同的输入设备进行管理.各种输入设备如:鼠标.键盘.触摸屏等有一套相同的处理机制,输入子系统将其共性提取出来, 对于驱动开发人员只用实现其差异即可,实现 ...
- 启动Tomcat报错:A child container failed during start
在之前的工作和学习当中,有碰到过很多未知的,在当时看来十分令人疑惑的问题.当时的解决手段简单粗暴,就是直接百度,搜到对应的解决方案,直接抄过来试试,不行再换,直到问题消失,程序可以正常跑了,立马就不管 ...
- PyTorch 启程&拾遗
1..Tensors are similar to NumPy’s ndarrays, with the addition being that Tensors can also be used on ...
- PAT乙级1041
题目链接 https://pintia.cn/problem-sets/994805260223102976/problems/994805281567916032 题解 简单的信息录入和查询而已. ...
- MyBatis日期用法技巧
当你想在实体类中使用Java.util.Date类型,而且还想在数据库中保存时分秒时,你可以在xml中修改为: #{xxdate,jdbcType=TIMESTAMP} 就是将#{}中的jdbcTyp ...
- 原生XMLHttpRequest (ajax)的简单使用
示例: 第一步:创建XMLHttpRequest对象 var httpxml ; if(window.XMLHttpRequest){ //大多数浏览器 httpxml = new XMLHttpRe ...