STL之set和map

STL之set和map

set和map都是关联式容器,底层实现都是红黑树,先来看红黑树的实现,明白了红黑树,set和map就很简单了。具体使用在数据结构里面列出,因为做题经常用到。。
红黑树插入和删除操作都是在O(logn)时间内完成的,其他操作建议参考数据结构和算法类的书籍。

rb_tree

一点需要声明的是一个节点中key和data加一起是value.
几个优点,也是为什么set和map要使用这个rb_tree来实现

  1. 利用平衡二叉搜索树的特性,排列规则有助于search和insert,并保持适度平衡:没有一个节点过深
  2. 提供遍历以及iterators,按照++iter遍历,能获取排序的装填
  3. 两种insertion:insert_unique()表示key一定在整个tree中独一无二,否则安插失败。insert_equal()表示节点的key可以重复。
    另外:我们不应该使用rb_tree的iterators改变元素值。但是map运行data改变,而key是不可变的。所以并未阻止我们去改变元素值。
    部分源码
template<class Key,class Value,class KeyOfValue,class Compare,class Alloc=alloc>
class rb_tree{
protected:
	typedef_rb_tree_node<Value>rb_tree_node;
	...
public:
	typedef rb_tree_node* link_type;
	....
protected://数据,红黑树的类对象本身的大小只是这个三个数据的大小
	size_type node_count;//rb_tree的大小(节点数量)
	link_type header;//虚拟头节点
	Compare key_compare;//key的大小比较准则
};

这只是一个大概,更详细的内容还是多看看源码。

set/multiset

几个需要熟记的点:

  1. set和multiset都是以rb_tree为底层结构,因此有元素自动排序特性,排序的依据是key,而set和multiset的value和key合一:value就是key。
  2. 我们无法使用set/multiset的iterators改变元素值,irerator底部是rb_tree的const-iterator,就是为了禁止user对元素赋值
  3. set和multiset的区别:set的key必须独一无二,因此insert用的是rb_tree的insert_unnique;而multiset的key可以重复,因此其insert()用的是rb_tree的insert_equal。
    部分源码
template<class Key,class Compare=less<Key>,class Alloc=alloc>
class set{
public:
	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;//红黑树变量t
public:
	typedef typename rep_type::const_iterator iterator;//迭代器是const
	....
}
//使用set
set<int>iset;//默认了一部分
set<int ,less<int>,alloc>;
tmplate<int,int,identity<int>,less<int>,alloc>class rb_tree;

map/multimap

几个需要熟记的点:

  1. map/multimap以rb_tree为底层结构,因此有自动排序的特性,排序的依据还是key
  2. 允许修改data,不允许修改key,通过将key设定为const类型
  3. map和multimap的区别:map的key必须独一无二,因此insert用的是rb_tree的insert_unnique;而multimap的key可以重复,因此其insert()用的是rb_tree的insert_equal.

源码:
区别于set。

template<class key,class T,class Compare=less<Key>,class Alloc=alloc>
class map{
public:
	typedef Key key_type;
	typedef T data_type;//区别于set
	typedef T mapped_type;
	typedef pair<const Key,T>value_type;//pari键值对,通过这里设置const key来防止修改key,但是可以修改data
	typedef Compare key_compare;
private:
	typedef rb_tree<key_type,value_type,selectlst<value_type>,key_compare,Alloc>rep_type;
	rep_type t;
public:
	typedef typename rep_type::iterator iterator;//区分set
}
//使用
map<int,string>imap;//这里是key和data的值
map<int ,string,less<int>,alloc>imap;
template<>;//其实就是使用红黑树

//map中的[]
//可以使用数组的形式来访问数据,当要访问的数据不在map中的时候,会将利用[]的数据以键值对的形式添加到map。
需要清楚的点:
  1. set,map分别和multiset,multimap的区别:在于元素可不可以重复 ,插入元素的时候是调用inset_unique还是insert_equal
  2. set的key是通过设置迭代器为const类型来使得不能改变key的值,而Map是通过利用pair类型,来设置key为const类型,使得不能改变key的值,但是可以改变data的值。
  3. 使用的时候根据具体情况选择合适的容器。

参考:侯捷老师STL讲解
《STL源码刨析》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值