您的位置:首页 > 其它

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

2017-09-19 10:50 405 查看

前言

在上几节中我们分析了
hashtable
以及
hash_set
还有
hash_map
的实现,
hash_set
以及
hash_map
都不允许有重复的key存在,而
hashtable
提供了允许插入重复元素的操作
insert_equal
,对应实现的则是
hash_multiset
以及
hash_multimap


接下来我们先看看
hash_multiset
的实现,它和
hash_set
的实现很类似。

hash_multiset的实现

定义及数据结构

#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
template <class Value, class HashFcn = hash<Value>,
class EqualKey = equal_to<Value>,
class Alloc = alloc>
#else
template <class Value, class HashFcn, class EqualKey, class Alloc = alloc>
#endif
class hash_multiset
{
private:
/* 这些都与hash_set类似 */
typedef hashtable<Value, Value, HashFcn, identity<Value>,
EqualKey, Alloc> ht;
ht rep;

public:
/* 不管是hash_set还是hash_multiset
* 它们的key_type和value_type都是key
*/
typedef typename ht::key_type key_type;
typedef typename ht::value_type value_type;
typedef typename ht::hasher hasher;
typedef typename ht::key_equal key_equal;

typedef typename ht::size_type size_type;
typedef typename ht::difference_type difference_type;
typedef typename ht::const_pointer pointer;
typedef typename ht::const_pointer const_pointer;
typedef typename ht::const_reference reference;
typedef typename ht::const_reference const_reference;

//常量迭代器
typedef typename ht::const_iterator iterator;
typedef typename ht::const_iterator const_iterator;

hasher hash_funct() const { return rep.hash_funct(); }
key_equal key_eq() const { return rep.key_eq(); }


构造函数

public:
/* 多个版本,指定大小或者哈希函数以及比较key大小的函数,不指定时都有其默认值 */
hash_multiset() : rep(100, hasher(), key_equal()) {}
explicit hash_multiset(size_type n) : rep(n, hasher(), key_equal()) {}
hash_multiset(size_type n, const hasher& hf) : rep(n, hf, key_equal()) {}
hash_multiset(size_type n, const hasher& hf, const key_equal& eql)
: rep(n, hf, eql) {}

/* 这里是首个和hash_set不同的地方
* hash_set中实现迭代器构造时,内部调用的是insert_unique(不允许重复key)
* 而在hash_multiset中实现时调用的是insert_equal(允许重复key)
*/
#ifdef __STL_MEMBER_TEMPLATES
template <class InputIterator>
hash_multiset(InputIterator f, InputIterator l)
: rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); }
template <class InputIterator>
hash_multiset(InputIterator f, InputIterator l, size_type n)
: rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); }
template <class InputIterator>
hash_multiset(InputIterator f, InputIterator l, size_type n,
const hasher& hf)
: rep(n, hf, key_equal()) { rep.insert_equal(f, l); }
template <class InputIterator>
hash_multiset(InputIterator f, InputIterator l, size_type n,
const hasher& hf, const key_equal& eql)
: rep(n, hf, eql) { rep.insert_equal(f, l); }
#else

hash_multiset(const value_type* f, const value_type* l)
: rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); }
hash_multiset(const value_type* f, const value_type* l, size_type n)
: rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); }
hash_multiset(const value_type* f, const value_type* l, size_type n,
const hasher& hf)
: rep(n, hf, key_equal()) { rep.insert_equal(f, l); }
hash_multiset(const value_type* f, const value_type* l, size_type n,
const hasher& hf, const key_equal& eql)
: rep(n, hf, eql) { rep.insert_equal(f, l); }

hash_multiset(const_iterator f, const_iterator l)
: rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); }
hash_multiset(const_iterator f, const_iterator l, size_type n)
: rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); }
hash_multiset(const_iterator f, const_iterator l, size_type n,
const hasher& hf)
: rep(n, hf, key_equal()) { rep.insert_equal(f, l); }
hash_multiset(const_iterator f, const_iterator l, size_type n,
const hasher& hf, const key_equal& eql)
: rep(n, hf, eql) { rep.insert_equal(f, l); }
#endif /*__STL_MEMBER_TEMPLATES */


常用操作

public:
/* 这部分的实现都与hash_set相同 */
size_type size() const { return rep.size(); }
size_type max_size() const { return rep.max_size(); }
bool empty() const { return rep.empty(); }
void swap(hash_multiset& hs) { rep.swap(hs.rep); }
friend bool operator== __STL_NULL_TMPL_ARGS (const hash_multiset&,
const hash_multiset&);

iterator begin() const { return rep.begin(); }
iterator end() const { return rep.end(); }

public:
/* 插入操作调用的是insert_equal函数 */
iterator insert(const value_type& obj) { return rep.insert_equal(obj); }
#ifdef __STL_MEMBER_TEMPLATES
template <class InputIterator>
void insert(InputIterator f, InputIterator l) { rep.insert_equal(f,l); }
#else
void insert(const value_type* f, const value_type* l) {
rep.insert_equal(f,l);
}
void insert(const_iterator f, const_iterator l) { rep.insert_equal(f, l); }
#endif /*__STL_MEMBER_TEMPLATES */
iterator insert_noresize(const value_type& obj)
{ return rep.insert_equal_noresize(obj); }

iterator find(const key_type& key) const { return rep.find(key); }

size_type count(const key_type& key) const { return rep.count(key); }

pair<iterator, iterator> equal_range(const key_type& key) const
{ return rep.equal_range(key); }

//删除操作
size_type erase(const key_type& key) {return rep.erase(key); }
void erase(iterator it) { rep.erase(it); }
void erase(iterator f, iterator l) { rep.erase(f, l); }
void clear() { rep.clear(); }

public:
/* 这些操作也与hash_set一致 */
void resize(size_type hint) { rep.resize(hint); }
size_type bucket_count() const { return rep.bucket_count(); }
size_type max_bucket_count() const { return rep.max_bucket_count(); }
size_type elems_in_bucket(size_type n) const
{ return rep.elems_in_bucket(n); }
};

template <class Val, class HashFcn, class EqualKey, class Alloc>
inline bool operator==(const hash_multiset<Val, HashFcn, EqualKey, Alloc>& hs1,
const hash_multiset<Val, HashFcn, EqualKey, Alloc>& hs2)
{
return hs1.rep == hs2.rep;
}

#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER

template <class Val, class HashFcn, class EqualKey, class Alloc>
inline void swap(hash_multiset<Val, HashFcn, EqualKey, Alloc>& hs1,
hash_multiset<Val, HashFcn, EqualKey, Alloc>& hs2)
{
hs1.swap(hs2);
}

#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */


小结

关于
hash_multiset
,它的实现和
hash_set
及其类似,只是几个需要插入元素的地方都换成了
insert_equal
而已。这个区别和
set
multiset
的区别一样。

下一小节我们将看到关于
hash_multimap
的实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: