上海网站开发运营,网站工作室模板,wordpress 360收录,东莞寮步网站建设文章目录 set1.关联式容器2.键值对3. set3.1 set介绍3.2 set的使用3.2.1 pair3.2.2 find3.2.3 lower_bound 3.3 multiset3.3.1 multiset的介绍3.3.2 multiset的使用3.3.3 find3.3.4 equal_range3.3.5 erase set
1.关联式容器
在初阶阶段#xff0c;我们已经接触过STL中的部分… 文章目录 set1.关联式容器2.键值对3. set3.1 set介绍3.2 set的使用3.2.1 pair3.2.2 find3.2.3 lower_bound 3.3 multiset3.3.1 multiset的介绍3.3.2 multiset的使用3.3.3 find3.3.4 equal_range3.3.5 erase set
1.关联式容器
在初阶阶段我们已经接触过STL中的部分容器比如vector、list、deque、forward_list(C11)等这些容器统称为 序列式容器 因为其底层为线性序列的数据结构里面存储的是元素本身。
那什么是关联式容器它与序列式容器有什么区别
关联式容器也是用来存储数据的与序列式容器不同的是其里面存储的是 key, value 结构的键值对在数据检索时比序列式容器效率更高。
2.键值对
用来表示具有一一对应关系的一种结构该结构中一般只包含两个成员变量key和valuekey代表键值value表示与key对应的信息。比如现在要建立一个英汉互译的字典那该字典中必然有英文单词与其对应的中文含义而且英文单词与其中文含义是一一对应的关系即通过该应该单词在词典中就可以找到与其对应的中文含义
3. set
3.1 set介绍
set文档介绍
翻译 set是按照一定次序存储元素的容器 在set中元素的value也标识它(value就是key类型为T)并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const)但是可以从容器中插入或删除它们。 在内部set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。 set容器通过key访问单个元素的速度通常比unordered_set容器慢但它们允许根据顺序对子集进行直接迭代。 set在底层是用二叉搜索树(红黑树)实现的。
注意
与map/multimap不同map/multimap中存储的是真正的键值对key, valueset中只放value但在底层实际存放的是由value, value构成的键值对。set中插入元素时只需要插入value即可不需要构造键值对。set中的元素不可以重复(因此可以使用set进行去重)。使用set的迭代器遍历set中的元素可以得到有序序列set中的元素默认按照小于来比较set中查找某个元素时间复杂度为 l o g 2 n log_2 n log2nset中的元素不允许修改(为什么?)set中的底层使用二叉搜索树(红黑树)来实现
3.2 set的使用
set的模板参数列表 T: set中存放元素的类型实际在底层存储value, value的键值对。
Compareset中元素默认按照小于来比较
Allocset中元素空间的管理方式使用STL提供的空间配置器管理
#include iostream
using namespace std;
#include setvoid test_set()
{setint s;s.insert(5);s.insert(2);s.insert(6);s.insert(3);s.insert(1);s.insert(3);s.insert(3);s.insert(3);s.insert(5);s.insert(6);setint::iterator it s.begin();while(it ! s.end()){cout *it ;it;}
}int main()
{test_set();return 0;
}验证结果 当然遍历set值也可以使用范围for
#include iostream
using namespace std;
#include setvoid test_set()
{setint s;s.insert(5);s.insert(2);s.insert(6);s.insert(3);s.insert(1);s.insert(3);s.insert(3);s.insert(3);s.insert(5);s.insert(6);setint::iterator it s.begin();while(it ! s.end()){cout *it ;it;}cout endl;for(auto e : s){cout e ;}
}int main()
{test_set();return 0;
}运行结果对比 正所谓只要支持迭代器就一定支持范围for
可以发现有相同的值只返回了一次而且走的是中序遍历。
注set的底层是红黑树本质也是一个二叉搜索树当有相同的值时便不会再插入了返回的是false
这是就一个问题了查找到相同值时布尔值是如何返回接受的呢
答通过pair接受返回值
3.2.1 pair
这里来查看pair接口 SGI-STL中关于键值对的定义
template class T1, class T2
struct pair
{typedef T1 first_type;typedef T2 second_type;T1 first;T2 second;pair() : first(T1()), second(T2()){}pair(const T1 a, const T2 b) : first(a), second(b){}
};下面用pair接受返回值示例
#include iostream
using namespace std;
#include setvoid test_set()
{setint s;s.insert(5);s.insert(2);s.insert(6);s.insert(3);s.insert(1);s.insert(3);s.insert(3);s.insert(3);s.insert(5);s.insert(6);auto ret1 s.insert(5);cout ret1.second endl;pairsetint::iterator, bool ret2 s.insert(5);cout ret2.second endl;pairsetint::iterator, bool ret3 s.insert(4);cout ret3.second endl;
}int main()
{test_set();return 0;
}接收结果 从结果可以看出插入成功返回 1 插入失败返回 0 。
3.2.2 find
find接口简介 返回值介绍 find返回的就是迭代器
当想在set中删除值时也可以通过find来删除
#include iostream
using namespace std;
#include setvoid test_set()
{setint s;s.insert(5);s.insert(2);s.insert(6);s.insert(3);s.insert(1);s.erase(1); //直接删除setint::iterator it s.find(2); //find函数删除if (it ! s.end()){s.erase(it);}for (auto e : s){cout e ;}
}int main()
{test_set();return 0;
}删除结果 如果查找的不存在则程序会崩溃掉
#include iostream
using namespace std;
#include setvoid test_set()
{setint s;s.insert(5);s.insert(2);s.insert(6);s.insert(3);s.insert(1);setint::iterator it s.find(30);s.erase(it);for (auto e : s){cout e ;}
}int main()
{test_set();return 0;
}结果 这里用的是vscode为显示任何效果如果用vs则会显示程序崩溃窗口
当夜也有解决方法
#include iostream
using namespace std;
#include setvoid test_set()
{setint s;s.insert(5);s.insert(2);s.insert(6);s.insert(3);s.insert(1);setint::iterator it s.find(30);if (it ! s.end()){s.erase(it);}for (auto e : s){cout e ;}
}int main()
{test_set();return 0;
}3.2.3 lower_bound
给一个值返回一个迭代器
#include iostream
using namespace std;
#include setvoid test_set()
{setint myset;setint::iterator itlow, itup;for (int i 1; i 10; i){myset.insert(i * 10); //10 20 30 40 50 60 70 80 90}itlow myset.lower_bound(25); // val值的位置的iteratoritup myset.upper_bound(60); // val值的位置的iteratormyset.erase(itlow, itup); //取值范围[25,60]for(auto e : myset){cout e ;}cout endl;
}int main()
{test_set();return 0;
}返回结果 注意 set不支持修改其余的功能就是迭代器的正常调用
3.3 multiset
3.3.1 multiset的介绍
multiset文档介绍 [翻译] multiset是按照特定顺序存储元素的容器其中元素是可以重复的。 在multiset中元素的value也会识别它(因为multiset中本身存储的就是value, value组成的键值对因此value本身就是keykey就是value类型为T). multiset元素的值不能在容器中进行修改(因为元素总是const的)但可以从容器中插入或删除。 在内部multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序。 multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢但当使用迭代器遍历时会得到一个有序序列。 multiset底层结构为二叉搜索树(红黑树)。
注意 multiset中再底层中存储的是value, value的键值对 mtltiset的插入接口中只需要插入即可 与set的区别是multiset中的元素可以重复set是中value是唯一的 使用迭代器对multiset中的元素进行遍历可以得到有序的序列
3.3.2 multiset的使用
此处只简单演示set与multiset的不同其他接口接口与set相同
#include iostream
using namespace std;
#include setvoid test_set()
{setint s;s.insert(5);s.insert(2);s.insert(6);s.insert(3);s.insert(1);multisetint::iterator it s.begin();while(it ! s.end()){cout *it ;it;}cout endl;
}int main()
{test_set();return 0;
}运行结果 从结果看来multiset的功能排序 去重
3.3.3 find
#include iostream
using namespace std;
#include setvoid test_set()
{multisetint s;s.insert(5);s.insert(2);s.insert(6);s.insert(3);s.insert(1);s.insert(2);s.insert(5);s.insert(2);s.insert(5);multisetint::iterator it s.begin();while(it ! s.end()){cout *it ;it;}cout endl;//如果有多个值find返回中序第一个valit s.find(2);while(it ! s.end()){cout *it ;it;}cout endl;
}int main()
{test_set();return 0;
}调用结果 3.3.4 equal_range
实例
#include iostream
using namespace std;
#include setvoid test_set()
{multisetint s;s.insert(5);s.insert(2);s.insert(6);s.insert(3);s.insert(1);s.insert(2);s.insert(5);s.insert(2);s.insert(5);cout 原序列: ;for (auto e : s){cout e ;}cout endl;cout 现序列: ;auto ret s.equal_range(2);s.erase(ret.first, ret.second);for(auto e : s){cout e ;}cout endl;
}int main()
{test_set();return 0;
}调用结果 其中first 和 second 的意义就是
firstval值secondval值
由此可见其功能就是删除所指定查找的所有重复的val值。
3.3.5 erase
在multiset中的使用
#include iostream
using namespace std;
#include setvoid test_set()
{multisetint s;s.insert(5);s.insert(2);s.insert(6);s.insert(3);s.insert(1);s.insert(2);s.insert(5);s.insert(2);s.insert(5);cout 原序列: ;for (auto e : s){cout e ;}cout endl;cout 删除个数: ;size_t n s.erase(2);cout n endl;cout 现序列: ;for(auto e : s){cout e ;}cout endl;
}int main()
{test_set();return 0;
}删除结果