高级关联结构 --- 哈希表
来源:互联网 发布:mysql update in 批量 编辑:程序博客网 时间:2024/06/07 10:04
哈希表根据元素的值,把他们分布到各个簇中。哈希函数是一种关联函数,她把数据项映射到一个簇中,于是哈希表可以在该簇里进行添加,更新和删除数据的操作。与二叉搜索树一样,哈希表也可以用来实现集合和映射。但与二叉搜索树不同的是,哈希表的迭代器不能按元素的大小顺序访问他们。因此,用哈希表实现的集合与映射是无序的关联容器。
STL中没有哈希表类,也没有提供无序关联容器。
12.1 哈希表
哈希表:表中的每个元素都有唯一的键与之对应。这种关联结构的主要特征是哈希函数,她用键作为参数,并返回表中的某项的入口。可以把哈希表看做是一个有下标索引的数据序列,就像数组和向量一样。哈稀函数是个定位函数,她用键作为参数,返回表中的索引值。哈希的模型就是数组和向量的内存访问函数。哈希函数提供了另外一种不同的访问方式。她不是直接使用索引值,而是根据键求出一个索引,并用该索引来定位表中的某项数据。
12.2设计哈希函数:实际哈希函数不可能达到不产生冲突,应当能够产生均匀分布的哈希值。这样就可以使哈希表的索引散布在表中,从而尽可能的少发生冲突情况。
我们将哈希容器的声明中用到哈希函数,所以必须要有某种机制把哈希函数和容器类联系起来。C++语法允许一个函数把另外一个函数当做参数来用。这种方法效率很低,更好的途径是把函数当成一个函数对象类型的对象来处理。我们把哈希函数定义成函数对象,并扩充模板的语法,使之可以把函数对象类型作为模板参数,就像我们把普通数据类型传递给模板参数一样。
12.2.1 函数对象:
函数对象也就是类的对象,其行为类似于函数。但与普通函数不同的是,象其他类型的对象一样,可以创建,存储和销毁函数对象,他们也可以拥有相关的数据成员和操作。定义函数对象的第一步是声明一个类模板,其中包含了重载函数调用运算符()的成员函数。运算符()的参数表就是函数对象的参数表。
函数对象的类声明:
template<typename T>
class functionObject
{public:
returnType operator() (arguments) const
{ //根据 参数计算返回值
return returnValue ;
}
} ;
程序员可以使用函数对象的匿名对象,只需在类型名称的后面加上运算符(),并在一对括号中列出参数表即可。
例如:greaterThan<int>() ; //这个是greaterThan<int> 类型的匿名对象。
greaterThan<int>() (x,y ) ;
STL在头文件<functional>中定义了函数对象类型
greater 和less。
12.2.3 整型哈希函数:对于整型键,如果所有数字或者部分数字是随机出现的,那么恒等函数就是一个不错的哈希函数。我们用函数对象类型hFintID来实现恒等函数。运算符()用一个整数作为键,并返回与之对应的无符号整数值。
using namespace std;
class hFintID
{
public:
unsigned int operator() (int item) const
{
return (unsigned int) item ;
}
};
平方中值技术提供了一种哈希算法,她使用中间计算结果来产生随机值。该技术使用一个整型参数,把她转换为无符号整数,然后平方,从平方数的中间截取某几个连续位,作为哈希值返回。
class hFint
{
public:
unsigned int operator() (int item ) const
{
unsigned int value = (unsigned int ) item ;
value *= value ;
value /= 256 ; //舍低8位
return value % 65536 ; // 返回0--65535之间的整数
}
};
12.2.4 字符串哈希函数
字符串 中的字符序列必须要联合起来构造一个无符号整数。我们同事使用乘法和加法来描述该算法。开始时,n=0 , 对于字符串中的每个字符,先用n*8,再加上该字符的值(ASCII码)。对字符串中的每个字符都进行了上述的乘法加法混合计算后,整数n的值可能为负,这是因为发生了整数溢出现象。这种情况下,只需对n取负号即可。用n去除一个很大的素数,返回其余数,这样做的效果是使整型哈希值的分布更加随机。这里,我们取的素数是2049 982 463 ;
class hFstring
{
public:
unsigned int operator() (const string& item) const
{
unsigned int prime = 2049982463 ;
int n = 0 , i ;
for (i = 0 ; i <item.length() ; i ++ )
{
n = n*8 +item[i] ;
}
return n > 0 ? (n % prime) : (-n % prime) ;
}
};
12.2.5 实数哈希函数
class hFreal
{
public:
unsigned int operator()(double item) const
{
int exp;
double mant;
unsigned int hashval;
if (item == 0)
hashval = 0;
else
{
mant = frexp(item,&exp);
hashval = (unsigned int)((2 * fabs(mant) -1) * (unsigned int)~0);
}
return hashval;
}
};
12.3.2 独立表链地址法
把哈希表定义成容器(如向量和链表)的索引序列。每个容器(称作桶),用来保存映射到同一位置上的数据集合。这种解决冲突的方法叫做独立表链地址法。
假设每个桶都是一个表。哈希表就是一个包含list对象的向量。
12.4 哈希类(hash)类
hash类有两个模板参数,而stree类只有一个模板参数。由于表的大小对构建hash对象是必须的,所以构造函数需要把表长(桶的个数)作为他的一个参数。
哈希迭代器有3个部分组成:指向哈希表的指针,当前桶的索引和元素在桶中的list迭代器 。
- 高级关联结构 --- 哈希表
- 关联block_device结构
- 关联block_device结构
- LOADRUNNER关联的高级应用
- LoadRunner关联的高级应用
- LOADRUNNER关联的高级应用
- hive 高级结构
- 高级结构化
- 结构体高级话题
- 结构体高级
- ffmpeg里的结构关联
- ffmpeg里的结构关联
- loadrunner 关联函数的高级应用
- 关联分析(从基础到高级)
- Mybatis高级查询之关联查询
- C# 高级编程 - .NET结构
- C高级(1)--文件结构
- 结构体的高级话题
- 关于会议
- Poj 2996 Help Me with the Game
- Poj 2993 Emag eht htiw Em Pleh
- linux文件结构【转】
- Java中接口的实现与简单登陆界面的设计
- 高级关联结构 --- 哈希表
- Hibernate五个主要接口
- iPhone4陷“天线门”联通苹果合作不合时宜
- 短信网关在短信信息服务中的作用
- Oracle性能参数调整
- js 小数点计算 BUG 解决办法
- 【转】数码影像为什么要锐化,什么叫锐化,如何锐化图片
- word list 3
- PC低迷英特尔并购求脱困 win7受累恐重挫微软