SGISTL源码探究-关联式容器:set
来源:互联网 发布:关于域名说法正确的是 编辑:程序博客网 时间:2024/05/21 21:40
前言
在本小节中,我们将分析set
容器,它的特性是,所有的元素会根据键值自动在set
内部排序,set
的键值就是实值,并且不允许两个相同值的元素在set
中存在。并且set
的元素值不能通过迭代器进行改变,因为一旦改变,就意味着set
内部有序就被打破了。 set
实现的机制和map
一样,同样以红黑树作为底部实现,而关于set
的操作,也只用调用红黑树提供的接口就行了。
set的实现
定义部分
#ifndef __STL_LIMITED_DEFAULT_TEMPLATEStemplate <class Key, class Compare = less<Key>, class Alloc = alloc>#elsetemplate <class Key, class Compare, class Alloc = alloc>#endifclass 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 setpublic: 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
中的红黑树进行了一层封装,然后加上了自己的特性,所以实现的很简单,就连迭代器也是使用的红黑树中的。
阅读全文
0 0
- SGISTL源码探究-关联式容器:set
- SGISTL源码探究-关联式容器:map
- SGISTL源码探究-关联式容器:multiset
- SGISTL源码探究-关联式容器:multimap
- SGISTL源码探究-关联式容器:hash_set
- SGISTL源码探究-关联式容器:hash_map
- SGISTL源码探究-关联式容器:hash_multiset
- SGISTL源码探究-关联式容器:hash_multimap
- SGISTL源码探究-vector容器(上)
- SGISTL源码探究-vector容器(下)
- SGISTL源码探究-list容器(上)
- SGISTL源码探究-list容器(下)
- SGISTL源码探究-deque容器(上)
- SGISTL源码探究-deque容器(下)
- SGISTL源码探究-配接器
- SGISTL源码探究-内存池
- SGISTL源码探究-traits技法
- SGISTL源码探究-stack配接器
- 记录nginx配置php7过程
- Calico 的网络结构是什么?- 每天5分钟玩转 Docker 容器技术(68)
- 2017 ACM-ICPC 亚洲区(西安赛区)网络赛: B. Coin
- ActiveMQ(一)-消息中间件概述
- mysql— EXPLAIN命令的总结
- SGISTL源码探究-关联式容器:set
- Java语法基础练习题
- 网络编程之Winsock2 服务提供者接口(SPI)
- Java工具包之图片水印-yellowcong
- java帐号管理系统(窗体MD5加密)
- 使用C语言实现单链表
- JAVA学习笔记-序列化
- ubuntu 16.04 server版安装VirtualBox Guest Additions 的解决过程
- myBatis 传递参数源码分析