浅谈数据结构:哈希表

一.  基本概念

哈希表(hash table )是一种根据关键字直接访问内存存储位置的数据结构,通过哈希表,数据元素的存放位置和数据元素的关键字之间建立起某种对应关系,建立这种对应关系的函数称为哈希函数

二.哈希表的构造方法

假设要存储的数据元素个数是n,设置一个长度为m(m > n)的连续存储单元,分别以每个数据元素的关键字Ki(0<=i<=n-1)为自变量,通过哈希函数hash(Ki),把Ki映射为内存单元的某个地址hash(Ki),并将数据元素存储在内存单元中

从数学的角度看,哈希函数实际上是关键字到内存单元的映射,因此我们希望通过哈希函数通过尽量简单的运算使得哈希函数计算出的花溪地址尽量均匀的背影射到一系列的内存单元中,构造哈希函数有三个要点:(1)运算过程要尽量简单高效,以提高哈希表的插入和检索效率;(2)哈希函数应该具有较好的散列型,以降低哈希冲突的概率;第三,哈希函数应具有较大的压缩性,以节省内存。

以下有三种常用方法:

(1)直接地址法:以关键字的某个线性函数值为哈希地址,可以表示为hash(K)=aK+C;优点是不会产生冲突,缺点是空间复杂度可能会较高,适用于元素较少的情况

(2)除留余数法:它是由数据元素关键字除以某个常数所留的余数为哈希地址,该方法计算简单,适用范围广,是经常使用的一种哈希函数,可以表示为:

hash(K=K mod C;该方法的关键是常数的选取,一般要求是接近或等于哈希表本身的长度,研究理论表明,该常数选素数时效果最好

(3)数字分析法:该方法是取数据元素关键字中某些取值较均匀的数字来作为哈希地址的方法,这样可以尽量避免冲突,但是该方法只适合于所有关键字已知的情况,对于想要设计出更加通用的哈希表并不适用

三.哈希冲突的解决方案

在构造哈希表时,存在这样的问题:对于两个不同的关键字,通过我们的哈希函数计算哈希地址时却得到了相同的哈希地址,我们将这种现象称为哈希冲突

哈希冲突主要与两个因素有关,(1)填装因子,填装因子是指哈希表中已存入的数据元素个数与哈希地址空间的大小的比值,a=n/m ; a越小,冲突的可能性就越小,相反则冲突可能性较大;但是a越小空间利用率也就越小,a越大,空间利用率越高,为了兼顾哈希冲突和存储空间利用率,通常将a控制在0.6-0.9之间,而.net中的HashTable则直接将a的最大值定义为0.72 (虽然微软官方MSDN中声明HashTable默认填装因子为1.0,但实际上都是0.72的倍数),(2)与所用的哈希函数有关,如果哈希函数得当,就可以使哈希地址尽可能的均匀分布在哈希地址空间上,从而减少冲突的产生,但一个良好的哈希函数的得来很大程度上取决于大量的实践,不过幸好前人已经总结实践了很多高效的哈希函数,可以参考大神Lucifer文章:数据结构:HahTable:   http://www.cnblogs.com/lucifer1982/archive/2008/06/18/1224319.html

哈希冲突通常是很难避免的,解决哈希冲突有很多种方法,通常分为两大类:

1.开放地址法,他是一类以发生哈希冲突的哈希地址为自变量,通过某种哈希函数得到一个新的空闲内存单元地址的方法,开放地址法的哈希冲突函数通常是一组

2.链表法:当未发生冲突时,直接存放数据,当冲突产生时,把产生冲突的数据元素另外存放在单链表中

先讲这么多吧,之后找时间将哈希表实现原理再写上

时间: 2024-10-11 04:40:24

浅谈数据结构:哈希表的相关文章

浅谈数据结构之线性表顺序存储(一)

 首先,数据结构是由某一数据元素集合及该集合中所有数据元素之间的关系组成.具体来说,数据结构应当包含三方面的内容:(1).数据的逻辑结构:(2).数据的存储结构:(3).对数据所施加的操作.而数据的存储结构形式有两种:顺序存储与链式存储.在这里,先谈一谈线性表的顺序存储. 线性表:零个或多个数据元素的有限序列.第一,它是一个序列,也就是说,元素之间是有顺序的:第二,它是有限的,即元素个数是有限的.而线性表的顺序存储结构,说白了,就是在内存中找块地,通过占位的形式把一定的内存空间给占了,然后把相同

数据结构哈希表(转)

数据结构哈希表 参考代码如下: [plain] view plain copy /* 名称:哈希表 语言:数据结构C语言版 编译环境:VC++ 6.0 日期: 2014-3-26 */ #include <stdio.h> #include <malloc.h> #include <windows.h> #define NULLKEY 0   // 0为无记录标志 #define N 10        // 数据元素个数 typedef int KeyType;// 

浅谈数据结构-二叉树

浅谈数据结构-二叉树 二叉树是树的特殊一种,具有如下特点:1.每个结点最多有两颗子树,结点的度最大为2.2.左子树和右子树是有顺序的,次序不能颠倒.3.即使某结点只有一个子树,也要区分左右子树. 一.特殊的二叉树及特点 1.斜树 所有的结点都只有左子树(左斜树),或者只有右子树(右斜树).这就是斜树,应用较少 2.满二叉树 所有的分支结点都存在左子树和右子树,并且所有的叶子结点都在同一层上,这样就是满二叉树.就是完美圆满的意思,关键在于树的平衡. 根据满二叉树的定义,得到其特点为: 叶子只能出现

浅谈数据结构-树

树是一种数据结构,其中一个元素可以有两个或者多个数据元素,具有一对多的特点,用树结构来存储文件. 树的概念 结点的度:子结点的个数.例如结点1中有3个子结点,结点1的度是3. 树的度:树的度等于所有结点度中度最高的值.结点最高的度为3,树的度为3. 叶子结点:度为0的结点,即没有子结点的结点.例如:上图中3,5,6,7,9,10. 分支结点:除了叶子结点以外的结点,即度不为0的结点.例如:上面树的分支结点为1,2,4,8. 内部结点:除了根结点以及叶子结点或在分支结点的基础之上在去掉根结点.例如

数据结构---哈希表(散列表)

我们在Java容器中谈到:有哈希表(也称为散列表)支持的HashMap.LinkedHashSet等都具有非常高的查询效率.这其中就是Hash起的作用.顺序查找的时间复杂度为O(N) ,二分查找和查找树的时间复杂度为O(logN),而 哈希表的时间复杂度为O(1) .不过这只是理想状态,实际并不那么完美. 1.哈希表的概念和思想 哈希表是唯一的专用于集合的数据结构.可以以常量的平均时间实现插入.删除和查找. 哈希表的思想是:用一个与集合规模差不多大的数组来存储这个集合,将数据元素的关键字映射到数

数据结构 - 哈希表

哈希表 1. 哈希表的引入 1.1 哈希表的简单概述   哈希表一个通过哈希函数来计算数据存储位置的数据结构,通常支持如下操作 (高效的操作):python中的字典是通过哈希表实现的 insert(key, value):插入键值对(key,value) get(key):如果存在键为key的键值对则返回其value,否则返回空值 delete(key):删除键为key的键值对  1.2.直接寻址表 当关键字的key 的 全域U(关键字可能出现的范围)比较小时,直接寻址是一种简单而有效的方法 存

浅谈数据结构-查找

在上万条数据中,查找制定元素,这就是查找完成的功能. 查找表:由同一种类型元素构成的集合,由于"集合"中数据元素之间存在松散的关系,因此查找表是一种灵活应用的数据结构. 查找表的操作: 查询某个特定的数据元素是否在查找表中. 查询某个特定元素的各种属性. 在查找表中制定位置插入一条数据. 从查找表中删除特定的数据元素. 查找表中四个操作之间是紧密关联的,比如,插入一个数据:首先判断元素是否在查找表中,有,返回,没有插入.判断一个元素在查找表中,先是查找元素,然后获取属性,然后和插入的元

数据结构 哈希表 c++

什么是哈希表 理想的查找是不经过任何的比较,一次存取就能得到想要查询的记录:要达到这样的目的就需要在记录的储存位置和它的关键字之间建立一个确定的关系f , 让每个关键字和结构中的一个唯一的地址相对应.在查找的时候,只需要对应关系f找到给定值K的像f(K),若结构中存在关键字和K相等,则必定在f(K)的储存位置上,由此不需要任何比较就能得到查询: 就好像数组一样,我们要找第一个数,调用a[0]就能得到第一个数, 当我们通过关键字来找的时候,通过一定的规则,把关键字和储存位置建立一个映射,就能通过数

数据结构——哈希表的构造和查找

#include<stdio.h> #include<malloc.h> #define MAXSIZE 25 #define P 13 #define OK 1 #define ERROR 0 #define DUPLICATE -1 #define TRUE 1 #define FALSE 0 typedef struct /*哈希表元素结构*/ { int key; /*关键字值*/ int flag; /*是否存放元素*/ } ElemType; typedef struc