数据结构 哈希表 c++

什么是哈希表

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

哈希函数是一个映像,因而哈希函数的设定很灵活,只要让任何关键字由哈希函数得到的哈希数值都在表长的允许范围内即可

对不同的关键字可能得到相同的哈希值,这种现象称为冲突, 有相同哈希值的关键词称为同义词, 冲突不能完全避免,只能尽可能的减少

哈希函数的构造

如果一个哈希函数能把一个关键字集合中的任意一个关键字,经哈希函数映像得到地址集合中的任何一个地址的概率是相等的,则称这个哈希函数的均匀的,这样的哈希函数才是“好”的哈希函数

常见的构建哈希函数的方法:

1.直接定址法:取关键字或者关键字的某个线性函数值作为哈希地址。即H(key) = a*key + b; 这种哈希函数叫做自身函数。我操,为啥寝室突然出现小强?可怕。  这种方法得到的地址集合和关键字集合的大小相同,因此不会发生冲突,但实际中用的比较少

2.平方取中间法:取关键字平方后的中间几位作为哈希地址。通常在不能知道全部关键词的情况下,用这种方法比较合适。平方后的中间几位数和数的每一位都相关,由此得到的哈希地址也是随机的,取的位数由表长决定

3.折叠法:把关键词分割为位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和作为哈希地址(舍去最高位的进位)。这种方法实用与关键字位数很多且关键字中每一位上数字分布大致均匀的时候。列如一个关键词为0442205864,当地址集合的大小不超过10000的时候, 这个时候可以构造一个四位数的哈希函数。分为以下两种情况

  位移叠加:将分割后的每一部分的最低位对齐,然后相加,5864+4220+04=10088, 舍去最高位得到的哈希函数值是0088;

  移位叠加:从一端向另一端沿分割界来回折叠,然后对齐最低位相加,5864+0224+04=6092, 相当于把每一部分之字型相加;

4.除留余数法:H(key) = key MOD p;  p<=m, m是哈希表表长;最常用的一种方法,用这种方法的时候,对除数p的选择很重要,直接决定哈希函数的好坏;若除数p有质数因子pf,则所有含有pf因子的关键字的哈希地址均为pf的整数倍。 一般情况下选p为质数或不包含小于20的质因数的合数

5.随机数法:选择一个随机函数,取关键字的随机函数值作为哈希地址;

采取不同哈希函数的时候,应该考虑以下因素:计算哈希地址的时间,关键字长度,哈希表大小,关键字分布情况,记录的查找频率

冲突处理方法

冲突是指由关键字得到的哈希地址为j的位置上已存在记录,则处理冲突就是为该关键字的记录找到另一个“空”的哈希地址。在处理哈希冲突的时候,如果得到的另一个哈希地址任然冲突,则求下一个哈希地址,直到找到不发生冲突的哈希地址

1.开放地址法:Hi = (H(key) + di) MOD m, i=1,2,3,...m-1;di为曾量序列, m为哈希表长, H(key)为哈希函数;di的取值有以下几种

  • di = 1,2,3,...,m-1,称为线性再探测散列
  • di = 1*1,-1*1,2*2,-2*2,...,(m/2)*(m/2),-(m/2)*(m/2),称为二次再探测散列
  • di = 伪随机数序列, 称为伪随机探测再散列

比如:取H(key) = key MOD 11, 哈希表已经如下

0 1 2 3 4 5 6 7 8 9 10
          60 17 29      

现在求38的哈希地址,会发现H(38) = 38 MOD 11 = 6 ,这个位置上已经有17了,所以要找下一个空的哈希地址H = (6+1) MOD 11 = 7, 依然被占据, 继续查找H = (6+2) MOD 11 = 8, 此时为空,则38的哈希地址为8. 由此可见关键字的哈希地址除了与关键字有关外,还与求哈希地址的先后顺序有关

2.再哈希法:Hi = RHi(key), RHi是不同的哈希函数,即在同义词产生地址冲突的时候,用另外一个哈希函数求哈希地址,直到冲突不再发生,这种方法不容易出产生聚集现象,但是会增加计算时间

3.链地址法:把所有关键字为同义词的记录储存在同一线性链表中。假设某哈希函数产生的哈希地址在[0,m-1]上,则设立一个指针型向量 Chain ChainHash[m]; 每一个分量的初始状态都是空指针,再链表中插入的位置可以在表头,或者表尾,或者中间,来保持同义词在同一链表中按关键词有序;

用该方法对{19,14,23,01,68,20,84,27,55,11,10,79}求哈希地址,取哈希函数为H(key) = key MOD 13

0        
1 1 14 27 79
2        
3 55 68    
4        
5        
6 19 84    
7 20      
8        
9        
10 10 23    
11 11      
12        

可以看出,对关键词除以13, 模相同的都在同一链表中,且链表中按照关键词排序;查找记录的时候,只需要找到关键词所在的链表,再遍历该链表就能找到关键词所在位置

原文地址:https://www.cnblogs.com/mr-stn/p/9048880.html

时间: 2024-10-03 22:42:08

数据结构 哈希表 c++的相关文章

数据结构哈希表(转)

数据结构哈希表 参考代码如下: [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(关键字可能出现的范围)比较小时,直接寻址是一种简单而有效的方法 存

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

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

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

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 中哈希表的源码