2020-10-10

vs-stl实现中 std::unordered_map计算哈希值:

class unordered_map
        : public _Hash<_Umap_traits<_Kty, _Ty,
            _Uhash_compare<_Kty, _Hasher, _Keyeq>, _Alloc, false>>

{}

 

template<class _Traits>
    class _Hash
    {    // hash table -- list with vector of iterators for quick access
public:
    using key_type = typename _Traits::key_type;
    using key_compare = typename _Traits::key_compare;
    using value_compare = typename _Traits::value_compare;
    enum
        {    // various constants
        _Bucket_size = key_compare::bucket_size,
        _Min_buckets = 8,    // min_buckets = 2 ^^ N, 0 < N
        _Multi = _Traits::_Multi};
    using _Mylist = list<typename _Traits::value_type, typename _Traits::allocator_type>; // using value_type = pair<const _Kty, _Ty>;
    using _Alnode = typename _Mylist::_Alnode;
    using _Alnode_traits = typename _Mylist::_Alnode_traits;

    using value_type = typename _Mylist::value_type;
    using allocator_type = typename _Mylist::allocator_type;
    using size_type = typename _Mylist::size_type;
    using difference_type = typename _Mylist::difference_type;
    using pointer = typename _Mylist::pointer;
    using const_pointer = typename _Mylist::const_pointer;
    using reference = value_type&;
    using const_reference = const value_type&;

    using iterator = conditional_t<is_same_v<key_type, value_type>,
        typename _Mylist::const_iterator,
        typename _Mylist::iterator>;
    using const_iterator = typename _Mylist::const_iterator;

    using _Unchecked_iterator = conditional_t<is_same_v<key_type, value_type>,
        typename _Mylist::_Unchecked_const_iterator,
        typename _Mylist::_Unchecked_iterator>;
    using _Unchecked_const_iterator = typename _Mylist::_Unchecked_const_iterator;

    using _Aliter = _Rebind_alloc_t<_Alnode, _Unchecked_iterator>;
    using _Myvec = vector<_Unchecked_iterator, _Aliter>;

    void _Init(size_type _Buckets = _Min_buckets)
        {    // initialize hash table with _Buckets buckets, leave list alone
        _Vec.reserve(2 * _Buckets);    // avoid curdling _Vec if exception occurs
        _Vec.assign(2 * _Buckets, _Unchecked_end());
        _Mask = _Buckets - 1;
        _Maxidx = _Buckets;

        }

    _Traits _Traitsobj;    // traits to customize behavior
    _Mylist _List;    // list of elements, must initialize before _Vec 
// 实际的pair<k,v>保存在链表_List里, unordered_map.find/begin/end返回的迭代器其实就是该_List的迭代器
    _Myvec _Vec;    // vector of list iterators, begin() then end()-1 // _Vec里保存着_List的迭代器, 用于快速查询访问
    size_type _Mask;    // the key mask
    size_type _Maxidx;    // current maximum key value

 };

size_type _Hashval(const key_type& _Keyval) const
{    // return hash value, masked to current table size
        return (_Traitsobj(_Keyval) & _Mask);   // size_type _Mask;    // the key mask : _Mask = _Buckets - 1;
                                                                                                                                     _Maxidx = _Buckets;

// _Maxidx 桶数; _Mask 桶数 - 1, 用于哈希掩码。_Min_buckets = 8,    // min_buckets = 2 ^^ N, 0 < N
}

......

->

template<class _Kty>
    struct hash
        : _Conditionally_enabled_hash<_Kty, !is_const_v<_Kty> && !is_volatile_v<_Kty>
            && (is_enum_v<_Kty> || is_integral_v<_Kty> || is_pointer_v<_Kty>)>
    {    // hash functor primary template (handles enums, integrals, and pointers)
    static size_t _Do_hash(const _Kty& _Keyval) noexcept
        {    // hash _Keyval to size_t value by pseudorandomizing transform
        return (_Hash_representation(_Keyval));
        }
    };

->

template<class _Kty>
    _NODISCARD inline size_t _Hash_representation(const _Kty& _Keyval) noexcept
    {    // bitwise hashes the representation of a key
    return (_Fnv1a_append_value(_FNV_offset_basis, _Keyval));
    }

->

#if defined(_WIN64)
_INLINE_VAR constexpr size_t _FNV_offset_basis = 14695981039346656037ULL;
_INLINE_VAR constexpr size_t _FNV_prime = 1099511628211ULL;  // prime: 一个很大的素数
#else /* defined(_WIN64) */
_INLINE_VAR constexpr size_t _FNV_offset_basis = 2166136261U;
_INLINE_VAR constexpr size_t _FNV_prime = 16777619U;
#endif /* defined(_WIN64) */

template<class _Kty>
    _NODISCARD inline size_t _Fnv1a_append_value(const size_t _Val, const _Kty& _Keyval) noexcept
    {    // accumulate _Keyval into partial FNV-1a hash _Val
    static_assert(is_trivial_v<_Kty>, "Only trivial types can be directly hashed.");
    return (_Fnv1a_append_bytes(_Val,
        &reinterpret_cast<const unsigned char&>(_Keyval), sizeof(_Kty)));   // 将值重解释为长度为sizeof(_Kty)的"二进制字符串"
    }

->

_NODISCARD inline size_t _Fnv1a_append_bytes(size_t _Val,
    const unsigned char * const _First, const size_t _Count) noexcept
    {    // accumulate range [_First, _First + _Count) into partial FNV-1a hash _Val
    for (size_t _Idx = 0; _Idx < _Count; ++_Idx)
        {
        _Val ^= static_cast<size_t>(_First[_Idx]); // 异或 1^1=0;  0^0=0;  1^0=1;  0^1=1
        _Val *= _FNV_prime// 再乘以一个很大的素数
        }

    return (_Val);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值