散列表: 本章介绍了散列表的各种问题。
散列函数:除法散列,乘法散列,全域散列。 其中除法散列是简单的mod. 乘法散列为h(k) = m(kA mod 1). 即关键字k乘常数A, 然后取小数部分, 乘以m. 全域散列是一组散列函数,这些函数都可以将关键字域U映射到相同的集合中, 同时对k, l 属于U. 满足h(k) = h(l)的散列函数的个数最多是: 散列函数的数目/集合的大小. 散列表的2种解决冲突的办法: 链接法和开放寻址法。链接法比较简单, 开发寻址法解决冲突的探查函数有几种: 线形探察, 二次探察, 双重散列。 其中双重探察的探察序列最多,所以相应散列效果更好。最后介绍了完全散列, 这节难度较大, 没有看太明白, 主要是对于全域散列的证明很头疼阿。我自己的链接法的实现: 因为很少用到散列, 所以只是做了少量的测试。 而且散列函数的返回值一定是int_type. 对于散列的应用了解少了点,所以模板参数的定义可能不是很合理。template <class Key, class Value, class Hash = HashDivide<Key> >class LinkHash{public: typedef Key key_type; typedef Value data_type; typedef std::pair<Key, Value> value_type; typedef value_type& value_reference; typedef const value_type& value_const_reference; typedef key_type& key_reference; typedef const key_type& key_const_reference; typedef value_type* value_pointer; typedef const value_type* value_const_pointer;
typedef LinkNode<value_type>* node_type;
LinkHash(int size) { m_container.assign(size, 0); m_size = 0; } ~LinkHash() { for (std::vector< node_type >::iterator it = m_container.begin(); it != m_container.end(); ++it) { node_type node = *it; while (node) { *it = node->next(); delete node; node = *it; } } }
size_t size() const {return m_size;}
data_type get(const key_type& key) { node_type node = find(key); if (node) { return node->value().second; } else { throw std::out_of_range("no key"); } }
bool insert(const key_type& key, const data_type& value) { return insert(value_type(key, value)); } bool insert(value_const_reference data) { node_type node = find(data.first); if (node) { node->value().second = data.second; return false; } else { node_type node = new LinkNode<value_type>(); node->m_data = data; node->m_next = m_container[hash(data.first)]; m_container[hash(data.first)] = node; ++m_size; return true; } }
bool has_key(const key_type& key) { node_type node = find(key); if (node) return true; else return false; }
bool erase(const key_type& key) { assert(hash(key)); int index = hash(key); if (index >= m_container.size()) { throw bucketNotEnough("bucket not enough"); } LinkNode<value_type> nodeImp; node_type node = &nodeImp; node->m_next = m_container[index]; while(node->next()) { if (node->next()->value().first == key) { node_type eraseNode = node->next(); node->m_next = node->next()->next(); delete eraseNode; --m_size; m_container[index] = node->m_next; return true; } node = node->next(); } return false; }
private:
node_type find(const key_type& key) { int index = hash(key); if (index >= m_container.size()) { throw bucketNotEnough("bucket not enough"); } node_type node = m_container[index]; while(node) { if (node->value().first == key) { return node; } node = node->next(); } return 0; }
int hash(const key_type& key) { return m_function(key) % m_container.size(); }
private: LinkHash(const LinkHash&); LinkHash& operator=(const LinkHash&); std::vector< node_type > m_container; Hash m_function; size_t m_size;};