三 关联式容器(三)hashtable

一  hashtable概述:

(0)hashtable:在查找、插入和删除操作上有常数平均时间。hashtable的优点:

*hashtable把数据的查询、插入和删除时间大大降低,几乎是常数时间;代价是消耗比较多的内存(用空间换时间)。

*例如:100万条记录,用map需要20次比较,但是频繁进行搜索时,20次比较也会成为瓶颈;所以使用hash_map可以做到,并且其使用方式和map一样。



(1)SGI STL特性:

*采用链地址法来解决碰撞问题。表格使用vector来实现(如下图)


*hash table的迭代器是forward迭代器,没有后退操作。

*如果元素个数大于bucket vector的大小时(即装载因子大于1时),需要再散列。


*hashtable内置了28个质数作为bucket大小的数目(初始化和再散列时使用),需要时调用函数__str_next_prime(unsighed long n),返回最接近并大于等于n的那个指数。如下:

// Note: assumes long is at least 32 bits.
enum { _S_num_primes = 28 };


static const unsigned long __stl_prime_list[_S_num_primes] =
{
  53ul,         97ul,         193ul,       389ul,       769ul,
  1543ul,       3079ul,       6151ul,      12289ul,     24593ul,
  49157ul,      98317ul,      196613ul,    393241ul,    786433ul,
  1572869ul,    3145739ul,    6291469ul,   12582917ul,  25165843ul,
  50331653ul,   100663319ul,  201326611ul, 402653189ul, 805306457ul,
  1610612741ul, 3221225473ul, 4294967291ul
};


(2)hashtable的数据结构:


hashtable的模板参数相当多,包括:

Value:节点的实值类型。

Key:节点的键值类型。

//以下三个都是函数对象。

HashFcn:hash function的函数型别。

ExtractKey:从节点中取出键值的方法。

EqualKey:判断键值是否相同的方法。

Alloc:空间配置器。


如下图:


(3)hash function

1.对于一些hashtable无法处理的类型,需要用户自己定义hash function。

2.<hash_fun.h>定义了数个现成的hash functions,全部都是函数对象。

hash functions是计算元素位置的函数,SGI将这项任务赋予bkt_num(),由它调用hash function,取得一个可以对hashtable进行模运算的值。


//hash_fun.h头文件的内容

#ifndef _HASH_FUN_H
#define _HASH_FUN_H 1


#include <cstddef>


namespace __gnu_cxx
{
  using std::size_t;


  template <class _Key> struct hash { };


  inline size_t
  __stl_hash_string(const char* __s)
  {
    unsigned long __h = 0;
    for ( ; *__s; ++__s)
      __h = 5*__h + *__s;
    return size_t(__h);
  }


  template<> struct hash<char*>
  {
    size_t operator()(const char* __s) const
    { return __stl_hash_string(__s); }
  };


  template<> struct hash<const char*>
  {
    size_t operator()(const char* __s) const
    { return __stl_hash_string(__s); }
  };


  template<> struct hash<char>
  { size_t operator()(char __x) const { return __x; } };


  template<> struct hash<unsigned char>
  { size_t operator()(unsigned char __x) const { return __x; } };


  template<> struct hash<signed char>
  { size_t operator()(unsigned char __x) const { return __x; } };


  template<> struct hash<short>
  { size_t operator()(short __x) const { return __x; } };


  template<> struct hash<unsigned short>
  { size_t operator()(unsigned short __x) const { return __x; } };


  template<> struct hash<int>
  { size_t operator()(int __x) const { return __x; } };


  template<> struct hash<unsigned int>
  { size_t operator()(unsigned int __x) const { return __x; } };


  template<> struct hash<long>
  { size_t operator()(long __x) const { return __x; } };


  template<> struct hash<unsigned long>
  { size_t operator()(unsigned long __x) const { return __x; } };
} // namespace __gnu_cxx


#endif


二 hashtable的相关操作(见源代码)


三 实例:


//hashtable的实现文件hashtable.h位于ext文件夹中。
#include<iostream>
#include<ext/hash_set>//or include<ext/hashtable.h>
#include<ext/functional>//包含identity
using namespace std;
using namespace __gnu_cxx;
int main()
{
//identity和equal_to都是函数对象。identity定义于<ext/functional>,equal定义于stl_function.h中。
hashtable<int,int,hash<int>,identity<int>,equal_to<int> >ht(50,hash<int>(),equal_to<int>());


cout<<ht.bucket_count()<<endl;//返回bucket个数,即buckets vector的大小,输出53.
cout<<ht.max_bucket_count()<<endl;//返回最大buckets的个数.vector的大小被设计为28个质数计算好,以备随时访问。
int data=100;
while(data-->0)
ht.insert_unique(data);
cout<<ht.bucket_count()<<endl;//输出193。
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值