STL hash table, Unordered Contains

STL hash table, Unordered Contain

 

C++11加入使用hash table实现的Unordered Containers。容器中元素是不排序的,同时我们也不能指定某个元素的位置。

头文件:#include <unordered_set>   unordered_set; unordered_multiset;

          #include <unordered_map> unordered_map; unordered_multimap;

操作基本类似于关联容器,只是底层使用hash table。主要不同是理解bucket的概念。

namespace std {

    template <typename T,

                   typaname Hash = hash<T>,

                    typename EqPred = equal_to<T>,

                    typename Allocator = allocator<T> >

    class unordered_set;

    template <typename Key, typename T,

                  typanem Hash = hash<T>,

                  typename EqPred = equal_to<T>,

                  typanema Allocator = allocator<pair<const Key, T> > >

class unordered_ma;
}

注意点:

(1) hash函数为hash<T>

(2) 比较准则 equal_to<T>

 

1.特点

标准没有指定实现,vs和g++都使用开链法实现。

指定迭代器至少为forward_iterator,但是具体实现一般都是forward_iterator。

插入,删除,查找元素保证分摊的常数时间。rehashing可能发生,这是一个线性复杂度的操作。

相对于普通关联容器的不利:

(1) 不提供<, >, <=,>=去排序元素,since c++11提供了==, !=。

(2)不提供lower_bound(), upper_bound()

(3) 不提供反向迭代器,forward_iterator

(4)不能直接访问元素

(5) 可以通过iterator访问元素,key值是const。

(6) 可以指定min 桶数。

(7) 可以提供自定义的hash function。

(8)可以指定查找元素时的相等准则。重载operator=。

(9) 可以指定max 负载因子,当超过时可以自动重排。

(9) 可以强制rehashing。

 

rehashing发生的时机:只有在insert(), rehash(), reserve(), clear()之后才可能。

这保证了erase()从来都不会使iterator,reference,和指针失效。

因此,当你删除很多元素是,桶的大小不会改变。但是当你insert()一个元素时,桶的大小可能压缩(rehash)。

相等key是相邻的,rehashing时保证key的相对顺序不变。

 

2.构造,复制,赋值

unordered c([bnum], [hf], [cmp]);     //桶数目,hash function, 比较谓词都是可选

unordered c(beg, end, [bnum][hf][cmp]);

unordered c = initlist;

unordered c(initlist);

复制和移动复制

c.~Unord();

主要的特点是可以指定:bucket num,hash function, cmp

 

3.容器内部布局的操作

c.hash_function()

c.key_eq()

c.bucket(val): 返回val所在的桶的索引

c.bucket_count():返回桶的数目,size()返回所有元素的数目。

c.size():返回元素的数目

c.bucket_size(buckidx): 返回桶buckidx的元素数目

c.[c]begin(buckdx):返回桶buckdx的第一个元素forward iter

c.[c]end(buckdx):返回桶buckdx的最后一个元素之后位置

c.max_bucket_count(): 最大桶的数目

c.load_factor():返回当前的负载因子,0.7..0.8之间速度和内存消耗是最平均的。

c.max_load_factor:返回当前最大负载因此,<=1。

c.max_load_factor(val):设置最大负载因子为val,当当前的负载因子 > val时rehashing。若是比较关心速度,可以设置这个。

c.rehashi(bnum); 再散列容器,桶的大小至少为bnum。但是还要考虑到此时的负载因子, 可以存的元素数量为 load_factor * bunm <= bnum; 当前元素数量可能大于此值,可能会进一步的再散列。

c.reserve(num);再散列容器,元素数量至少为num。已考虑了负载因子,能够至少存num个元素而不会再散列。桶的数量为num / load_factor。保证可以存下num元素而不会再散列。

4. 定义自己的hash function

hash function映射元素的值到一个指定的桶,自定义hash function只需映射不同元素值相等的分布在[0, size_t)。

#include <functional>

class  customer

{

     …
}

class CustomerHash

{

      public:

            std::size_t operator() (const Customer &c) const

           {

                     return…
           }

}

std::unordered_set<Customer, CustomerHash> custset;

 

也可以使用函数:

std::size_t customer_hash_func(const Customer &c)

{

     return …
}

std::unordered_set<Customer, std:size_t(*)(const Customer&)>

custset(20, customer_hash_func);

对于hash_val的选择:

可以使用boost的hash_combine()。

5.定义自己的Equivalence Criterion

可以作为我们查找值的相等准则,默认使用equal_to()使用operator==比较元素。

可以使用普通函数或者函数对象。

注意:带着非默认相等谓词的unordered 容器通常也需要一个非默认的hash function。

6. 查找

主要在快速查找时用

c.count(val);

c.find(val);

c.equal_range(val);

 

posted on 2014-08-10 18:19  hancmhi  阅读(450)  评论(0编辑  收藏  举报