一 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。
}