算法导论十一章

散列表: 本章介绍了散列表的各种问题。

散列函数:除法散列,乘法散列,全域散列。 其中除法散列是简单的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;
}; 

点赞