SGISTL源码探究-关联式容器:set

昆仑通态,自由串口通讯 软件默认无该功能,需要问客服索要扩展包。 阅读详情

前言

在本小节中,我们将分析set容器,它的特性是,所有的元素会根据键值自动在set内部排序,set的键值就是实值,并且不允许两个相同值的元素在set中存在。并且set的元素值不能通过迭代器进行改变,因为一旦改变,就意味着set内部有序就被打破了。
set实现的机制和map一样,同样以红黑树作为底部实现,而关于set的操作,也只用调用红黑树提供的接口就行了。

set的实现

定义部分
#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
template <class Key, class Compare = less<Key>, class Alloc = alloc>
#else
template <class Key, class Compare, class Alloc = alloc>
#endif
class set {
public:
  // typedefs:
  //一些定义
  typedef Key key_type;
  typedef Key value_type;
  typedef Compare key_compare;
  typedef Compare value_compare;
private:
  typedef rb_tree<key_type, value_type,
                  identity<value_type>, key_compare, Alloc> rep_type;
  //红黑树
  rep_type t;  // red-black tree representing set
public:
  typedef typename rep_type::const_pointer pointer;
  typedef typename rep_type::const_pointer const_pointer;
  typedef typename rep_type::const_reference reference;
  typedef typename rep_type::const_reference const_reference;
  typedef typename rep_type::const_iterator iterator;
  typedef typename rep_type::const_iterator const_iterator;
  typedef typename rep_type::size_type size_type;
  typedef typename rep_type::difference_type difference_type;
构造函数
  // allocation/deallocation
  //设置默认的大小比较标准
  set() : t(Compare()) {}
  //设置大小比较标准
  explicit set(const Compare& comp) : t(comp) {}

#ifdef __STL_MEMBER_TEMPLATES
  //调用红黑树的insert_unique进行范围构造
  template <class InputIterator>
  set(InputIterator first, InputIterator last)
    : t(Compare()) { t.insert_unique(first, last); }

  template <class InputIterator>
  set(InputIterator first, InputIterator last, const Compare& comp)
    : t(comp) { t.insert_unique(first, last); }
  //重载操作符=  
  set(const set<Key, Compare, Alloc>& x) : t(x.t) {}
  set<Key, Compare, Alloc>& operator=(const set<Key, Compare, Alloc>& x) {
    t = x.t;
    return *this;
  }
常用操作
  // accessors:
  //返回键值的比较标准
  key_compare key_comp() const { return t.key_comp(); }
  //由于set中key和value是同一个,所以这里也调用key_comp
  value_compare value_comp() const { return t.key_comp(); }
  //返回起始迭代器(STL中红黑树中返回的是最左节点)
  iterator begin() const { return t.begin(); }
  //返回末尾迭代器(STL中红黑树中返回的是header)
  iterator end() const { return t.end(); }
  bool empty() const { return t.empty(); }
  size_type size() const { return t.size(); }
  size_type max_size() const { return t.max_size(); }
插入/删除操作
  // insert/erase
  //有了红黑树提供的接口,完成插入/删除操作很方便
  typedef  pair<iterator, bool> pair_iterator_bool;
  pair<iterator,bool> insert(const value_type& x) {
    //insert_unique,不允许重复的值
    pair<typename rep_type::iterator, bool> p = t.insert_unique(x);
    //返回pair,第一个代表指向插入节点的迭代器,第二个代表插入是否成功
    return pair<iterator, bool>(p.first, p.second);
  }
  iterator insert(iterator position, const value_type& x) {
    typedef typename rep_type::iterator rep_iterator;
    return t.insert_unique((rep_iterator&)position, x);
  }
#ifdef __STL_MEMBER_TEMPLATES
  template <class InputIterator>
  void insert(InputIterator first, InputIterator last) {
    t.insert_unique(first, last);
  }
#else
  void insert(const_iterator first, const_iterator last) {
    t.insert_unique(first, last);
  }
  void insert(const value_type* first, const value_type* last) {
    t.insert_unique(first, last);
  }
#endif /* __STL_MEMBER_TEMPLATES */
  /* 删除操作,也调用红黑树提供的erase即可
   * 根据指定位置删除、指定值删除、范围删除重载了不同的版本
   */
  void erase(iterator position) {
    typedef typename rep_type::iterator rep_iterator;
    t.erase((rep_iterator&)position);
  }
  size_type erase(const key_type& x) {
    return t.erase(x);
  }
  void erase(iterator first, iterator last) {
    typedef typename rep_type::iterator rep_iterator;
    t.erase((rep_iterator&)first, (rep_iterator&)last);
  }
  //这里也直接调用红黑树的clear函数,记住header没有被清除
  void clear() { t.clear(); }
其他
  // set operations:
  //以下也都是调用的红黑树提供的接口
  iterator find(const key_type& x) const { return t.find(x); }
  size_type count(const key_type& x) const { return t.count(x); }
  iterator lower_bound(const key_type& x) const {
    return t.lower_bound(x);
  }
  iterator upper_bound(const key_type& x) const {
    return t.upper_bound(x);
  }
  pair<iterator,iterator> equal_range(const key_type& x) const {
    return t.equal_range(x);
  }
  friend bool operator== __STL_NULL_TMPL_ARGS (const set&, const set&);
  friend bool operator< __STL_NULL_TMPL_ARGS (const set&, const set&);
};

//重载操作符,都是调用的红黑树重载的操作符
template <class Key, class Compare, class Alloc>
inline bool operator==(const set<Key, Compare, Alloc>& x,
                       const set<Key, Compare, Alloc>& y) {
  return x.t == y.t;
}

template <class Key, class Compare, class Alloc>
inline bool operator<(const set<Key, Compare, Alloc>& x,
                      const set<Key, Compare, Alloc>& y) {
  return x.t < y.t;
}

例子

#include <iostream>
#include <set>
using namespace std;
int main()
{
    set<int> s{1, 2, 3, 4, 5};

    set<int>::iterator first = s.begin();
    set<int>::iterator last = s.end();
    while(first != last)
    {
        cout << *first << endl;
        first++;
    }
    s.erase(s.begin(), s.end());
    cout << "size:" << s.size() << endl;

    s.insert(10);
    s.insert(9);


    set<int>::iterator ite1 = s.find(10);
    if(ite1 != s.end())
    {
        //*ite1 = 20;
        cout << "i find it" << endl;
    }
    else
        cout << "not found" << endl;
    return 0;
}

针对关联式容器,我们应当使用其提供的find函数,而不应该使用stl中算法部分提供的find函数(顺序查找)。
当我们试图改变set的值时,编译会出错并提示向只读位置‘ite1.std::_Rb_tree_const_iterator<_Tp>::operator*<int>()’赋值。

小结

本小节中我们阅读了set容器的几乎全部源码,可以发现它只是将STL中的红黑树进行了一层封装,然后加上了自己的特性,所以实现的很简单,就连迭代器也是使用的红黑树中的。

FPGA控制AD5754实现模数转换Verilog代码与测试激励 本文提供了使用FPGA控制AD5754芯片实现数字信号转模拟信号的Verilog代码和测试激励。AD5754芯片简介:AD5754是一款16位数字信号转模拟信号的芯片。通信方式:FPGA与AD5754之间通过SPI接口进行通信,SPI时钟clk的最大频率为30MHz。模拟输出:AD5754提供了四路模拟输出。工作方式:当前AD5754采用单极性工作方式。指令刷新:根据现有理解,同轴的速度和电流指令应同时刷新。利用LDAC引脚控制模拟信号的刷新,但需实际验证。CLR信号验证。 阅读详情

相关推荐

V93000 SmarTest 8入门:从零搭建你的第一个半导体测试程序

半导体测试是芯片从设计走向量产的关键环节,而ATE(自动化测试设备)正是支撑这一环节的核心工具。理解ATE测试程序开发的基本原理,不仅需要掌握测试机台的硬件架构,还要熟悉其软件环境中的管脚映射、电平时序、测试流程等底层逻辑。V93000作为爱德万的主力平台,其SmarTest 8环境通过对象化与流程化设计,将复杂的芯片测试任务拆解为可配置、可复用的模块,极大提升了并行测试效率与调试的便利性。无论是数字逻辑芯片的功能验证,还是模拟混合信号器件的参数测量,掌握SmarTest 8的核心操作都能帮助你快速搭建出可

weixin_31476015的博客 240

SGISTL源码阅读十九 set关联式容器

SGISTL源码阅读十九 set容器 前言 之前我们已经分析了vector,list,deque三个容器。如果按照“数据在容器中的排列”特性,容器可以分为序列式(sequence)和关联式(associative)两种,前面学习过的三种容器都是序列式容器。 接下来我们将学习关联式容器。标准的STL关联式容器分为set(集合)和map(映射表)两大类,以及这两大类的衍生体muiltiset(多键集合...

Lyn&Xx 321

避坑指南:CesiumLab+ENVI处理Sentinel-2影像数据的完整流程

本文提供了一份详细的避坑指南,完整介绍了如何利用CesiumLab和ENVI工具链,将Sentinel-2卫星影像处理成可供Cesium三维地球引擎加载的离线瓦片数据。内容涵盖数据获取、SNAP预处理、ENVI影像增强合成以及CesiumLab切片配置等全流程实战步骤与关键参数优化,旨在帮助工程师高效构建自主可控的高精度离线地图服务。

weixin_29248653的博客 289

c++ stl之关联式容器 set

关联式容器 1.什么是关联式容器 关联式容器依据特定的排序法则,自动对容器内的数据元素进行排序。排序的准则是以函数的形式呈现出来的,用来比较数据元素的值(value)或者键(key)。在默认的缺省状态下是以 operator 2.关联式容器的底层实现 关联式容器是由二叉树(binary tree)实现出来的。 3.关联式容器的类别: 关联式容器的差别主要在于数据元素的类

tianxiaolu1175的专栏 956

HLM(多层线性模型)在stata中语句

在阅读CEPS中发现有些研究采用的是HLM模型,HLM简单来说用一个方程跑两个回归。举例,对学习成绩影响因素,不同层有不同的影响,如在个体层面上个体特征会对成绩产生影响,在学校层面学校排名等因素会对成绩产生影响,两种因素不在一个层面,每层造成的差异都不相同。 在找相关语句时候发现操作这个语句的软件大多是SPSS和HLM,对于stata操作者并不友好。因此,在有限资料中总结了HLM在stata中的语句,后面会附上学习视频和链接。 先放语句,后面对方程式一个大致解析。由于针对HLM有一本书的介绍,可能一篇文章无

weixin_44652251的博客 1万+

【脚本篇】---spyglass lint脚本

【代码】【脚本篇】---spyglass lint脚本。

冬瓜 6355

qt中setGeometry()函数与move()函数

setGeometry()函数是对窗体的综合设置,有四个参数,分别是坐标和长宽,但是注意,如果窗体是顶级窗体,例如Qwidget类设置的窗体时,设置的坐标只是窗体内灰色框的坐标,这是如果加上move()函数,就可以对窗体外部的边框进行位置的设定。 ...

s15810751918的博客 6915

一文详解声码器

声码器(Vocoder)是语音信号处理领域的核心技术,其本质是通过“分析 - 参数化 - 合成” 的闭环流程,实现语音的高效编码、转换或生成。它不仅是早期语音通信的关键工具,更是现代 AI 语音技术(如 TTS、语音转换)的核心组件。以下从原理、技术分类、关键模块、应用及发展趋势展开详细解析。

weixin_41413777的博客 1351

STL关联容器—set

set 容器与 map 非常类似。区别在于,集合不存储键/值对,在 set 中,值本身就是键。如果要存储没有显示键的信息,但是又希望对元素以便快速插入、查找和删除,此时 set 就很有用。   set 提供的接口与 map 的接口几乎相同。主要区别是 set 没有提供 operator [ ]。另外,尽管标准中没有明确指出来,但是大多数实现指令都令 set iterator 等同于 const_

chaoyuan899的专栏 1766

QGC二次开发实战指南(一):从零构建自定义地面站界面

本文详细介绍了QGC二次开发实战指南,从零开始构建自定义地面站界面。通过QT和QML技术结合MAVLINK协议,开发者可以打造适合特定业务场景的无人机监控系统,提升操作效率与用户体验。文章包含环境搭建、界面设计、数据绑定等完整开发流程,是QGC二次开发的实用教程。

weixin_28693683的博客 496

Pytorch实现之SRGAN+CBAM的结构设计

在SRGAN的残差连接中加入了CBAM注意力机制,同时设计了四类损失来训练。

LJ1147517021的博客 569

map和set

关于容器我们知道的在STL中有关联容器和顺序容器,那么所谓的关联容器是什么?所谓的顺序容器又是什么呢?在STL中的哪些属于关联容器,哪些属于顺序容器呢?下面来做一个简单的介绍:关联容器中的元素是按照关键字来保存和访问的,C++中的关联容器重要就是map和set。而顺序容器是按照元素在容器中的位置来进行保存和访问的,在C++中的顺序容器是Vector、List、Deque。今天我就关联容器来给大家做

Payshent的博客 7707

FPGA实现LVDS接口(1)--IBUFDS原语、OBUFDS原语和IOBUFDS原语的介绍及使用(仿真/源码)

通过本文您会学到:Xinlix的源语IBUFDS、OBUFDS和IOBUFDS是什么?

孤独的单刀 2万+

SGISTL源码探究-关联式容器:hash_set

前言在上小节中,我们已经分析了hashtable的实现,它只是hash_set和hash_map的预备知识。在本小节中,我们将进入到关联式容器hash_set的源码中,一窥究竟。hash_set的实现由于hash_set并没有自己定义的迭代器,所以接下来我们先对它的定义部分以及数据结构进行分析,然后是它的构造函数以及常用操作等。定义部分及数据结构#ifndef __STL_LIMITED_DEFAU

Move_now的博客 876

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

SGISTL源码探究-关联式容器:multiset

前言multiset和set的实现十分相似,除了允许键值重复之外,几乎一样。而实现允许键值重复这一功能的是红黑树中提供的操作insert_equal,接下来我们就进入到它的源码,顺便也复习一下set,看看到底和set有什么不同。multiset的实现#ifndef __STL_LIMITED_DEFAULT_TEMPLATES template <class Key, class Compare =

Move_now的博客 846

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

SGISTL源码-容器 笔记

本文是在阅读SGI STL v3.3源码中,遇到的一些问题及有意思的点。本文建立在已经观看过侯捷老师STL源码剖析课程的基础上。是在阅读源码过程中,对其中的内容进行补充、修饰。

weixin_46065476的博客 596

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

SGISTL源码探究-关联式容器:hash_multiset

前言在上几节中我们分析了hashtable以及hash_set还有hash_map的实现,hash_set以及hash_map都不允许有重复的key存在,而hashtable提供了允许插入重复元素的操作insert_equal,对应实现的则是hash_multiset以及hash_multimap。 接下来我们先看看hash_multiset的实现,它和hash_set的实现很类似。hash_mu

Move_now的博客 1090

SGISTL源码探究-关联式容器:map

前言在本小节中,我们将分析map容器,它与set最大的不同就是,它是key-value型的,而set的key和value是同一个。map和set底层都由红黑树实现,map上存储的都是pair,即键值对,存储到红黑树中时,排序依据的就是pair的第一个元素。 之前提到在set中,不允许更改元素的值,而在map中,key值同样不允许修改,但是value可以修改,因为value不涉及到map整体内部结构

Move_now的博客 913

STL源码剖析 - 第5章 关联式容器 - hash_set

5.8 hash_set    hash_set以hashtable为底层机制。和set类似,hast_set的键值就是实值,实值就是键值,但是不同点是hash_set容器中的元素是没有排序的,因为hash table没有提供排序功能。hash_set的使用方式与set完全相同。本文源码出自SGISTL的文件。 hash_set容器源码剖析 #ifndef __SGI_STL_INTERNA

灯火阑珊处 532

SGISTL源码阅读二十四 hash_set 关联式容器

SGISTL源码阅读二十四 hash_set 关联式容器 前言 前面我们已经分析了set和hashtable,set的底层容器是红黑树,而接下来我们要分析的hash_set,是底层为hashtable的集合。 深入源码 hash_set的定义部分 #ifndef __STL_LIMITED_DEFAULT_TEMPLATES template &lt;class Value, class Has...

Lyn&Xx 207

STL源码剖析 - 第5章 关联式容器 - RB-tree(红黑树)

5.1 树的导览      标准的STL关联式容器分为set(集合)和map(映射表)两大类,以及这两大类的衍生体multiset(多键集合)和multimap(多键映射表)。这些容器的底层机制均以RB-tree(红黑树)完成。RB-tree也是一个独立的容器,但并不开放给外界使用。 此外,SGI STL还提供了一个不在标准规格之列的关联式容器:hash table(散列表),以及以此hash

灯火阑珊处 758

SGISTL源码探究-关联式容器:hash_map

前言在上一小节,我们分析了hash_set的实现,本小节我们将针对hash_map进行分析。它大部分也是调用的hashtable,不过它与map的区别也是因为底层的实现不同,所以map具有自动排序功能,而hash_map没有。 接下来我们来看看hash_map是如何实现的。hash_map的实现还是分为定义部分及其数据结构、构造函数、常用操作这三部分。关于hash_map的迭代器,是使用的hash

Move_now的博客 835

《STL源码剖析》——第五、六章:关联容器与算法

第五章、关联容器 5.0、关联容器 标准的STL关联式容器分为set(集合)和map(映射表)两大类,以及这两大类的衍生体multiset(多键集合)和multimap(多键映射表)。这些容器的底层机制均以RB-tree(红黑树)完成。RB-tree也是一个独立容器,但并不开放给外界使用。 SGISTL还提供了一个不在标准规格之列的关联式容器:hash_table(散列表),以及以此has...

weixin_42637495的博客 350

STL源码分析之RB-tree结构简析

所谓关联容器:          每笔数据(每个元素)都有一个键值(key)和一个实值(value)。当元素被插入到关联式容器中时,容器内部结构(可能是RB-Tree 也可能是hash-table)便依照其键值大小,以某种特定规则将这个元素置放于适当的位置。          关联容器没有所谓的头尾(只有最大元素和最小元素),所以不会有所谓的push_back(), push_front(),

博客 795

【STL源码剖析】第五章 关联式容器 之 树的导览

第五章 关联式容器标准的STL关联式容器分为set(集合)和map(映射表)两大类,以及这两大类的衍生体multiset(多建集合)和multimap(多键映射表)。这些容器的底层实现极值均以RB-tree(红黑树)完成。RB-tree也是一个独立容器,但并不开放给外界使用。此外,SGI STL还提供了一个不在标准规格之列的关联式容器:hash table(散列表),以及以此hash table为...

stt2019 462

STL工具库使用解析系列之二:自定义比较函数的两种方式(重载和仿函数)

C++比C不仅多了面向对象支持class类编程,还支持泛型编程,以及提供丰富的STL开发工具库。泛型是一种在编译期间动态具体化的技术,使得一些通用算法或数据结构的封装变得十分方便。在C++标准中指出,当一个模板不被使用时,它就不应该被具体化。对于模板在编译期间如何特化,其实用到的概念诸多,比如“惰性求值”和“模式匹配”,两点关键: 1.对于函数模板: 确定特化的参数类型是隐式传进去的,编译器将根

墨篙和小奶猫 1052
上一篇: SGISTL源码探究-STL中的红黑树(下)
下一篇: SGISTL源码探究-pair的实现
UKey_
博客等级 码龄10年 258粉丝 186原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值