【经典数据结构】哈希表

哈希表的基本概念

  哈希表,也叫散列表,它是基于快速存取的角度设计的,是一种典型的“空间换时间”的做法。哈希表是普通数组的一种推广,因为数组可以直接寻址,故可在O(1)时间内访问数组的任意元素。

  哈希表是根据关键字(Key Value)而直接进行访问的数据结构。也就是说,它将关键字通过某种规则映射到数组中的某个位置,以加快查找的速度。这个映射规则称为哈希函数(散列函数),存放记录的数组称为哈希表。哈希表建立了关键字和存储地址之间的一种直接映射关系。

  若多个不同的关键字通过哈希函数计算得到相同的数组下标,称其发生了冲突,这些发生冲突的不同关键字称为同义词。一方面,设计好的HASH函数应尽量减少这这样的冲突;另一方面,由于这样的冲突总是不可避免的,所以还要设计好处理冲突的方法。

哈希函数

  所有散列都有如下一个基本特性:如果两个散列值是不相同的(根据同一函数),那么这两个散列值的原始输入也是不相同的(根据同一函数)。那么这两个散列值的原始输入也是不相同的。这个特性使散列函数具有确定性的结果,具有这种性质的散列函数称为单向散列函数。

  典型的散列函数都有无限定义域,比如任意长度的字节字符串,和有限的值域,比如固定的比特串。

常用哈希函数

  我们在数据结构这门课程,曾经学习这几种简单常用的散列函数,如直接定址法、数字分析法、平方取中法、除留余数法,折叠法等。

  以下我们介绍工业界比较著名的哈希函数(哈希算法),这些算法通常应用于信息安全领域)。

  典型的哈希算法包括MD4,MD5和SHA-1,MD5和SHA-1(安全哈希算法)可以说是目前应用最为广泛的Hash算法,而它们都是以MD4为基础设计的。

处理冲突的方法

  任何哈希函数都不可能绝对地避免冲突,为此必须考虑冲突发生时应如何进行处理,即为产生冲突的关键字寻找下一个“空”的Hash地址,于是提出了处理冲突的各种方法。

  1) 链地址法

    链地址法是指所有的冲突关键字(同义词)存储在一个线性链表中,这个链表由其散列地址唯一标识。

  2)开放定址法

    开放定址法是指可存放新表项的空闲地址。既向它的同义词表项开放,又向它的非同义词表项开放。其数学递推公式为(Hi表示冲突发生后第i次探测的散列地址):

          Hi=(H(key)+di)%m

式中,i=1,2,...,k(k<=m-1),m为散列表表长,di为增量序列,di通常有以下几种取法:

  当di=1,2,..,m-1时称为线性探测法。其特点是,冲突发生时顺序查看表中下一个单元,直到找出一个空单元或查遍全表。

  当di=12,-12,22,-22,...,k2,-k2时,其中k<=m/2,又为二次探测法。

  当di是伪随机序列时,称为伪随机探测法。

  3)再散列法

  当冲突发生时,利用另一个哈希函数再次计算一个地址,直到冲突不再发生,这种方法称为再哈希法。

  4)建立一个公共溢出区

  一旦由哈希函数得到的地址冲突,就都填入溢出表。

  有以下两点需要说明: 

  1)在开放定址的情形下,不能随便删除表中已有的元素,因为若删除元素将会截断其他具有相同散列地址的元素的查找地址。所以若想删除一个元素时,给它做一个删除标记,进行逻辑删除。但这样做的副作用是,在执行多次删除后,表面上看起来散列表很满,实际上有许多位置没有利用,因此需要定期维护散列表,要把做删除标记的元素物理删除。

  2)计算查找的平均查找长度ASL时,平均的概念是对表终当前非空元素而言的,并非是整个表长。计算查找失败的平均查找长度ASL时,平均的概念是针对表长。

时间: 2024-10-12 17:45:14

【经典数据结构】哈希表的相关文章

数据结构哈希表(转)

数据结构哈希表 参考代码如下: [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;// 

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

我们在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(关键字可能出现的范围)比较小时,直接寻址是一种简单而有效的方法 存

Java数据结构——哈希表

什么是哈希表?哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地方. 哈希表充分体现了算法设计领域的经典思想:空间换时间.哈希表是时间和空间之间的平衡.其中的哈希函数是最重要的,“键”通过哈希函数得到的“索引”分布越均匀越好.但是哈希表会失去顺序性. 哈希函数的设计对于整型 小范围正整数直接使用 小范围负整数进行偏移 -100~100 ----> 0~200 大整数:模一个素数 对于浮点型转成整型处理 对于字符串也是转成整型处理 int hash=0: f

数据结构 哈希表 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

java数据结构——哈希表(HashTable)

哈希表提供了快速的插入操作和查找操作,每一个元素是一个key-value对,其基于数组来实现. 一.Java中HashMap与Hashtable的区别: HashMap可以接受null键值和值,而Hashtable则不能. Hashtable是线程安全的,通过synchronized实现线程同步.而HashMap是非线程安全的,但是速度比Hashtable快. 这两个类有许多不同的地方,下面列出了一部分: a) Hashtable 是 JDK 1 遗留下来的类,而 HashMap 是后来增加的.

数据结构哈希表的闭散列基本实现

#pragma once #include<string> using namespace std; enum Status//表示当前位置的状态 { EXITS, DELETE, EMPTY, }; template<class K,class V> struct KeyValueNode//KV键值对 { K _key; V _value; KeyValueNode(const K& key=K(), const V& value=V()) :_key(key)

数据结构---哈希表(KV模式)(除留余数法)

可以实现快速定位查找数据 思想一:开一个适当大小的数组,讲需要存入的数据%上数组的_capacity的到的数作为他存放的位置,如果这个位置被占了,则在他的下一个位置存放数据(不会找不到空位置,下面会说到). 思想二:存放在数组上的是一个结构体,结构体包含一个索引值Key,存储值Value,和一个存储状态(枚举类型,EXIST,EMPTY,DELETE)可以使用这三种状态进行判断和懒人删除法(不用清除数据,设置为DELETE状态即可). 思想三:开辟空间的问题,初始空间经过资料查询,开一个大小为5

Nginx 哈希表结构 ngx_hash_t

概述 关于哈希表的基本知识在前面的文章<数据结构-哈希表>已作介绍.哈希表结合了数组和链表的特点,使其寻址.插入以及删除操作更加方便.哈希表的过程是将关键字通过某种哈希函数映射到相应的哈希表位置,即对应的哈希值所在哈希表的位置.但是会出现多个关键字映射相同位置的情况导致冲突问题,为了解决这种情况,哈希表使用两个可选择的方法:拉链法 和 开放寻址法. Nginx 的哈希表中使用开放寻址来解决冲突问题,为了处理字符串,Nginx 还实现了支持通配符操作的相关函数,下面对 Nginx 中哈希表的源码