⑴ 数据结构 哈希表建立
国防部和发短信
⑵ 哈希表—什么是哈希表
哈希表是一种数据结构~
哈希表可以存储各种类型的数据,当我们从哈希表中查找所需要的数据时,理想情况是不经过任何比较,一次存取便能得到所查记录, 那就必须在记录的存储位置和它的关键字之间建立一个确定的对应关系 f,使每个关键字和结构中一个唯一的存储位置相对应。 (关键字就是所要存储的数据,存储位置相当于数组的索引)
当然,可以把哈希表理解为一个数组,每个索引对应一个存储位置,哈希表的索引并不像普通数组的索引那样,从0到length-1,而是由关键字(数据本身)通过哈希函数得到
eg1. 将26个小写字母存储到数组 int [26] a。
a对应a[0],b对应a[1],c对应a[3]……以此类推。
那么,数组 int [26] a 就是一个哈希表!
例1中,关键字(小写字母)是如何得到自己对应的索引(存储位置)的呢?
关键字的ASCII值减去a的ASCII值!
上面说过,关键字通过哈希函数得到索引,所以,f(ch)就是本例题的哈希函数。
这样,我们就在关键字和数字(存储位置)之间建立了一个确定的对应关系f。
关键字与数字是一一对应的,由于数组本身支持随机访问,所以,当查找关键字时,只需要O(1)的查找操作,也就是实现了不经过任何比较,一次便能得到所查记录。
哈希表中 哈希函数的设计 是相当重要的,这也是建哈希表过程中的关键问题之一。
假如,我们所要存储的数据其关键字是一个人的身份证号(18位数字),这个时候我们该怎么计算关键字对应的索引呢?
比如一个人的身份证号是 411697199702076425,我们很难像例1那样直接让关键字与数字建立一一对应的关系,并且保证数字适合作为数组的索引。
在这种情况下,通过哈希函数计算出的索引,即使关键字不同,索引也会有可能相同。这就是 哈希冲突
当索引相同时,我们该怎么存储数据呢?如何解决哈希冲突,是我们建哈希表的另一个关键问题。
哈希表充分体现了空间换时间这种经典的算法思想。
关键字是大整数时,比如上面我们举的身份证号例子,411697199702076425
假如我们能开辟一个 999999999999999999 大的空间,这样就能直接把身份证号作为关键字存储到数组中,这样可以用O(1)时间完成各项操作
假如我们只有 1 的空间,我们需要把所有信息存储到这个空间中(也就是所有数据都会产生哈希冲突),我们只能用O(n)时间完成各项操作
事实上,我们不可能开辟一个如此大的空间,也不可会开辟如此小的空间
无限空间时,时间为O(1)
1的空间时,时间为O(n)
而哈希表就是在二者之间产生一个平衡,即 空间和时间的平衡 。
1.哈希函数的设计
2.解决哈希冲突
3.哈希表实现时间和空间的平衡
后续会详细说明这三个关键问题~
⑶ java中hashtable怎样存储数据和读取数据
Hashtable-哈希表类
以哈希表的形式存储数据,数据的形式是键值对.
特点:
查找速度快,遍历相对慢
键值不能有空指针和重复数据
创建
Hashtable<Integer,String> ht=new
Hashtable<Integer,String>();
添值
ht.put(1,"Andy");
ht.put(2,"Bill");
ht.put(3,"Cindy");
ht.put(4,"Dell");
ht.put(5,"Felex");
ht.put(6,"Edinburg");
ht.put(7,"Green");
取值
String str=ht.get(1);
System.out.println(str);// Andy
对键进行遍历
Iterator it = ht.keySet().iterator();
while (it.hasNext()) {
Integer key = (Integer)it.next();
System.out.println(key);
}
对值进行遍历
Iterator it = ht.values().iterator();
while (it.hasNext()) {
String value =(String) it.next();
System.out.println(value);
}
取Hashtable记录数
Hashtable<Integer,String> ht=new Hashtable<Integer,String>();
ht.put(1,"Andy");
ht.put(2,"Bill");
ht.put(3,"Cindy");
ht.put(4,"Dell");
ht.put(5,"Felex");
ht.put(6,"Edinburg");
ht.put(7,"Green");
int i=ht.size();// 7
删除元素
Hashtable<Integer,String> ht=new Hashtable<Integer,String>();
ht.put(1,"Andy");
ht.put(2,"Bill");
ht.put(3,"Cindy");
ht.put(4,"Dell");
ht.put(5,"Felex");
ht.put(6,"Edinburg");
ht.put(7,"Green");
ht.remove(1);
ht.remove(2);
ht.remove(3);
ht.remove(4);
System.out.println(ht.size());// 3
Iterator it = ht.values().iterator();
while (it.hasNext()) {
// Get value
String value =(String)
it.next();
System.out.println(value);
}
⑷ 哈希值是什么
哈希表类Hashtable
哈希表是一种重要的存储方式,也是一种常见的检索方法。其基本思想是将关系码的值作为自变量,通过一定的函数关系计算出对应的函数值,把这个数值解释为结点的存储地址,将结点存入计算得到存储地址所对应的存储单元。检索时采用检索关键码的方法。现在哈希表有一套完整的算法来进行插入、删除和解决冲突。在Java中哈希表用于存储对象,实现快速检索。
Java.util.Hashtable提供了种方法让用户使用哈希表,而不需要考虑其哈希表真正如何工作。
哈希表类中提供了三种构造方法,分别是:
public Hashtable()
public Hashtable(int initialcapacity)
public Hashtable(int initialCapacity,float loadFactor)
参数initialCapacity是Hashtable的初始容量,它的值应大于0。loadFactor又称装载因子,是一个0.0到1之间的float型的浮点数。它是一个百分比,表明了哈希表何时需要扩充,例如,有一哈希表,容量为100,而装载因子为0.9,那么当哈希表90%的容量已被使用时,此哈希表会自动扩充成一个更大的哈希表。如果用户不赋这些参数,系统会自动进行处理,而不需要用户操心。
Hashtable提供了基本的插入、检索等方法。
■插入
public synchronized void put(Object key,Object value)
给对象value设定一关键字key,并将其加到Hashtable中。若此关键字已经存在,则将此关键字对应的旧对象更新为新的对象Value。这表明在哈希表中相同的关键字不可能对应不同的对象(从哈希表的基本思想来看,这也是显而易见的)。
■检索
public synchronized Object get(Object key)
根据给定关键字key获取相对应的对象。
public synchronized boolean containsKey(Object key)
判断哈希表中是否包含关键字key。
public synchronized boolean contains(Object value)
判断value是否是哈希表中的一个元素。
■删除
public synchronized object remove(object key)
从哈希表中删除关键字key所对应的对象。
public synchronized void clear()
清除哈希表
另外,Hashtalbe还提供方法获取相对应的枚举集合:
public synchronized Enumeration keys()
返回关键字对应的枚举对象。
public synchronized Enumeration elements()
返回元素对应的枚举对象。
例1.5 Hashtable.java给出了使用Hashtable的例子。
例1.5 Hashtalbe.java。
//import java.lang.*;
import java.util.Hashtable;
import java.util.Enumeration;
public class HashApp{
public static void main(String args[]){
Hashtable hash=new Hashtable(2,(float)0.8);
//创建了一个哈希表的对象hash,初始容量为2,装载因子为0.8
hash.put("Jiangsu","Nanjing");
//将字符串对象“Jiangsu”给定一关键字“Nanjing”,并将它加入hash
hash.put("Beijing","Beijing");
hash.put("Zhejiang","Hangzhou");
System.out.println("The hashtable hash1 is: "+hash);
System.out.println("The size of this hash table is "+hash.size());
//打印hash的内容和大小
Enumeration enum1=hash.elements();
System.out.print("The element of hash is: ");
while(enum1.hasMoreElements())
System.out.print(enum1.nextElement()+" ");
System.out.println();
//依次打印hash中的内容
if(hash.containsKey("Jiangsu"))
System.out.println("The capatial of Jiangsu is "+hash.get("Jiangsu"));
hash.remove("Beijing");
//删除关键字Beijing对应对象
System.out.println("The hashtable hash2 is: "+hash);
System.out.println("The size of this hash table is "+hash.size());
}
}
运行结果:
The hashtable hash1 is: {Beijing=Beijing, Zhejiang=Hangzhou, Jiangsu=Nanjing}
The size of this hash table is 3
The element of hash is: Beijing Hangzhou Nanjing
The capatial of Jiangsu is Nanjing
The hashtable hash2 is: {Zhejiang=Hangzhou, Jiangsu=Nanjing}
The size of this hash table is 2
Hashtable是Dictionary(字典)类的子类。在字典类中就把关键字对应到数据值。字典类是一个抽象类。在java.util中还有一个类Properties,它是Hashtable的子类。用它可以进行与对象属性相关的操作。
⑸ 哈希函数的哈希表的概念及作用
哈希表中元素是由哈希函数确定的。将数据元素的关键字K作为自变量,通过一定的函数关系(称为哈希函数),计算出的值,即为该元素的存储地址。表示为:
Addr = H(key)
为此在建立一个哈希表之前需要解决两个主要问题:
⑴构造一个合适的哈希函数
均匀性 H(key)的值均匀分布在哈希表中;
简单以提高地址计算的速度
⑵冲突的处理
冲突:在哈希表中,不同的关键字值对应到同一个存储位置的现象。即关键字K1≠K2,但H(K1)= H(K2)。均匀的哈希函数可以减少冲突,但不能避免冲突。发生冲突后,必须解决;也即必须寻找下一个可用地址。
解决冲突的方法:
⑴链接法(拉链法)。将具有同一散列地址的记录存储在一条线性链表中。例,除留余数法中,设关键字为 (18,14,01,68,27,55,79),除数为13。散列地址为 (5,1,1,3,1,3,1),哈希散列表如图。
⑵开放寻址法。如果h(k)已经被占用,按如下序列探查:(h(k)+p⑴)%TSize,(h(k)+p⑵)%TSize,…,(h(k)+p(i))%TSize,…
其中,h(k)为哈希函数,TSize为哈希表长,p(i)为探查函数。在 h(k)+p(i-1))%TSize的基础上,若发现冲突,则使用增量 p(i) 进行新的探测,直至无冲突出现为止。其中,根据探查函数p(i)的不同,开放寻址法又分为线性探查法(p(i) = i : 1,2,3,…),二次探查法(p(i)=(-1)^(i-1)*((i+1)/2)^2,探查序列依次为:1, -1,4, -4, 9 …),随机探查法(p(i): 随机数),双散列函数法(双散列函数h(key) ,hp (key)若h(key)出现冲突,则再使用hp (key)求取散列地址。探查序列为:h(k),h(k)+ hp(k),…,h(k)+ i*hp(k))。
⑶桶寻址法。桶:一片足够大的存储空间。桶寻址:为表中的每个地址关联一个桶。如果桶已经满了,可以使用开放寻址法来处理。例如,插入A5,A2,A3,B5,A9,B2,B9,C2,采用线性探查法解决冲突。如图。
⑹ 哈希表详解
哈希表:即散列存储结构。
散列法存储的基本思想:建立记录关键码字与其存储位置的对应关系,或者说,由关键码的值决定数据的存储地址。
这样,不经过比较,一次存取就能得到所查元素的查找方法
优点:查找速度极快(O(1)),查找效率与元素个数n无关!
哈希方法(杂凑法)
选取某个函数,依该函数按关键字计算元素的存储位置并按此存放;查找时也由同一个函数对给定值k计算地址,将k与地址中内容进行比较,确定查找是否成功。
哈希函数(杂凑函数)
哈希方法中使用的转换函数称为哈希函数(杂凑函数).在记录的关键码与记录的存储地址之间建立的一种对应关系
有数据元素序列(14,23,39,9,25,11),若规定每个元素k的存储地址H(k)=k , H(k)称为散列函数,画出存储结构图。
根据散列函数H(k)=k ,可知元素14应当存入地址为14的单元,元素23应当存入地址为23的单元,……,
根据存储时用到的散列函数H(k)表达式,迅即可查到结果!
例如,查找key=9,则访问H(9)=9号地址,若内容为9则成功;
若查不到,应当设法返回一个特殊值,例如空指针或空记录。
很显然这种搜索方式空间效率过低。
哈希函数可写成:addr(ai)=H(ki)
选取某个函数,依该函数按关键字计算元素的存储位置并按此存放;查找时也由同一个函数对给定值k计算地址,将k与地址中内容进行比较,确定查找是否成功。哈希方法中使用的转换函数称为哈希函数(杂凑函数).在记录的关键码与记录的存储地址之间建立的一种对应关系。
通常关键码的集合比哈希地址集合大得多,因而经过哈希函数变换后,可能将不同的关键码映射到同一个哈希地址上,这种现象称为冲突。
有6个元素的关键码分别为:(14,23,39,9,25,11)。
选取关键码与元素位置间的函数为H(k)=k mod 7
根据哈希函数算出来发现同一个地址放了多个关键码,也就是冲突了。
在哈希查找方法中,冲突是不可能避免的,只能尽可能减少。
所以,哈希方法必须解决以下两个问题:
1)构造好的哈希函数
(a)所选函数尽可能简单,以便提高转换速度;
(b)所选函数对关键码计算出的地址,应在哈希地址内集中并大致均匀分布,以减少空间浪费。
2)制定一个好的解决冲突的方案
查找时,如果从哈希函数计算出的地址中查不到关键码,则应当依据解决冲突的规则,有规律地查询其它相关单元。
从上面两个例子可以得出如下结论:
哈希函数只是一种映象,所以哈希函数的设定很灵活,只要使任何关键码的哈希函数值都落在表长允许的范围之内即可
冲突:key1≠key2,但H(key1)=H(key2)
同义词:具有相同函数值的两个关键码
哈希函数冲突不可避免,只能尽量减少。所以,哈希方法解决两个问题:
构造好的哈希函数;
制定解决冲突基本要求:
要求一:n个数据原仅占用n个地址,虽然散列查找是以空间换时间,但仍希望散列的地址空间尽量小。
要求二:无论用什么方法存储,目的都是尽量均匀地存放元素,以避免冲突。
Hash(key) = a·key + b (a、b为常数)
优点:以关键码key的某个线性函数值为哈希地址,不会产生冲突.
缺点:要占用连续地址空间,空间效率低。
例.关键码集合为{100,300,500,700,800,900},
选取哈希函数为Hash(key)=key/100,
则存储结构(哈希表)如下:
Hash(key)=key mod p (p是一个整数)
特点:以关键码除以p的余数作为哈希地址。
关键:如何选取合适的p?p选的不好,容易产生同义词
技巧:若设计的哈希表长为m,则一般取p≤m且为质数
(也可以是合数,但不能包含小于20的质因子)。
Hash(key)= ⎣ B ( A key mod 1 ) ⎦
(A、B均为常数,且0<A<1,B为整数)
特点:以关键码key乘以A,取其小数部分,然后再放大B倍并取整,作为哈希地址。
例:欲以学号最后两位作为地址,则哈希函数应为:
H(k)=100 (0.01 k % 1 )
其实也可以用法2实现: H(k)=k % 100
特点:选用关键字的某几位组合成哈希地址。选用原则应当是:各种符号在该位上出现的频率大致相同。
例:有一组(例如80个)关键码,其样式如下:
讨论:
① 第1、2位均是“3和4”,第3位也只有“ 7、8、9”,因此,这几位不能用,余下四位分布较均匀,可作为哈希地址选用。
② 若哈希地址取两位(因元素仅80个),则可取这四位中的任意两位组合成哈希地址,也可以取其中两位与其它两位叠加求和后,取低两位作哈希地址。
特点:对关键码平方后,按哈希表大小,取中间的若干位作为哈希地址。(适于不知道全部关键码情况)
理由:因为中间几位与数据的每一位都相关。
例:2589的平方值为6702921,可以取中间的029为地址。
特点:将关键码自左到右分成位数相等的几部分(最后一部分位数可以短些),然后将这几部分叠加求和,并按哈希表表长,取后几位作为哈希地址。
适用于:关键码位数很多,且每一位上各符号出现概率大致相同的情况。
法1:移位法 ── 将各部分的最后一位对齐相加。
法2:间界叠加法──从一端向另一端沿分割界来回折叠后,最后一位对齐相加。
例:元素42751896,
用法1: 427+518+96=1041
用法2: 427 518 96—> 724+518+69 =1311
7、随机数法
Hash(key) = random ( key ) (random为伪随机函数)
适用于:关键字长度不等的情况。造表和查找都很方便。
小结:构造哈希函数的原则:
① 执行速度(即计算哈希函数所需时间);
② 关键字的长度;
③ 哈希表的大小;
④ 关键字的分布情况;
⑤ 查找频率。
设计思路:有冲突时就去寻找下一个空的哈希地址,只要哈希表足够大,空的哈希地址总能找到,并将数据元素存入。
1)线性探测法
Hi=(Hash(key)+di) mod m ( 1≤i < m )
其中:
Hash(key)为哈希函数
m为哈希表长度
di 为增量序列 1,2,…m-1,且di=i
关键码集为 {47,7,29,11,16,92,22,8,3},
设:哈希表表长为m=11;
哈希函数为Hash(key)=key mod 11;
拟用线性探测法处理冲突。建哈希表如下:
解释:
① 47、7是由哈希函数得到的没有冲突的哈希地址;
② Hash(29)=7,哈希地址有冲突,需寻找下一个空的哈希地址:由H1=(Hash(29)+1) mod 11=8,哈希地址8为空,因此将29存入。
③ 另外,22、8、3同样在哈希地址上有冲突,也是由H1找到空的哈希地址的。
其中3 还连续移动了(二次聚集)
线性探测法的优点:只要哈希表未被填满,保证能找到一个空地址单元存放有冲突的元素;
线性探测法的缺点:可能使第i个哈希地址的同义词存入第i+1个哈希地址,这样本应存入第i+1个哈希地址的元素变成了第i+2个哈希地址的同义词,……,
因此,可能出现很多元素在相邻的哈希地址上“堆积”起来,大大降低了查找效率。
解决方案:可采用二次探测法或伪随机探测法,以改善“堆积”问题。
2) 二次探测法
仍举上例,改用二次探测法处理冲突,建表如下:
Hi=(Hash(key)±di) mod m
其中:Hash(key)为哈希函数
m为哈希表长度,m要求是某个4k+3的质数;
di为增量序列 1^2,-1 ^2,2 ^2,-2 ^2,…,q ^2
注:只有3这个关键码的冲突处理与上例不同,
Hash(3)=3,哈希地址上冲突,由
H1=(Hash(3)+1 ^2) mod 11=4,仍然冲突;
H2=(Hash(3)-1 ^2) mod 11=2,找到空的哈希地址,存入。
3) 若di=伪随机序列,就称为伪随机探测法
基本思想:将具有相同哈希地址的记录(所有关键码为同义词)链成一个单链表,m个哈希地址就设m个单链表,然后用一个数组将m个单链表的表头指针存储起来,形成一个动态的结构。
设{ 47, 7, 29, 11, 16, 92, 22, 8, 3, 50, 37, 89 }的哈希函数为:
Hash(key)=key mod 11,
用拉链法处理冲突,则建表如图所示。
Hi=RHi(key) i=1, 2, …,k
RHi均是不同的哈希函数,当产生冲突时就计算另一个哈希函数,直到冲突不再发生。
优点:不易产生聚集;
缺点:增加了计算时间。
思路:除设立哈希基本表外,另设立一个溢出向量表。
所有关键字和基本表中关键字为同义词的记录,不管它们由哈希函数得到的地址是什么,一旦发生冲突,都填入溢出表。
明确:散列函数没有“万能”通式(杂凑法),要根据元素集合的特性而分别构造。
讨论:哈希查找的速度是否为真正的O(1)?
不是。由于冲突的产生,使得哈希表的查找过程仍然要进行比较,仍然要以平均查找长度ASL来衡量。
一般地,ASL依赖于哈希表的装填因子α,它标志着哈希表的装满程度。
0≤α≤1
α 越大,表中记录数越多,说明表装得越满,发生冲突的可能性就越大,查找时比较次数就越多。
例 已知一组关键字(19,14,23,1,68,20,84,27,55,11,10,79)
哈希函数为:H(key)=key MOD 13, 哈希表长为m=16,
设每个记录的查找概率相等
(1) 用线性探测再散列处理冲突,即Hi=(H(key)+di) MOD m
(2) 用二次探测再散列处理冲突,即Hi=(H(key)+di) MOD m
(3) 用链地址法处理冲突
1) 散列存储的查找效率到底是多少?
答:ASL与装填因子α有关!既不是严格的O(1),也不是O(n)
2)“冲突”是不是特别讨厌?
答:不一定!正因为有冲突,使得文件加密后无法破译!(单向散列函数不可逆,常用于数字签名和间接加密)。
利用了哈希表性质:源文件稍稍改动,会导致哈希表变动很大。
⑺ 哈希表存储元素大于函数怎么办
首先什么是 哈希表,哈希表(英文名字为Hash table,也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。
哈希表是根据关键码的值而直接进行访问的数据结构。
在讨论哈希表之前,我们先大概了解下其他数据结构在新增,查找等基础操作执行性能
数组:采用一段连续的存储单元来存储数据。对于指定下标的查找,时间复杂度为O(1);通过给定值进行查找,需要遍历数组,逐一比对给定关键字和数组元素,时间复杂度为O(n),当然,对于有序数组,则可采用二分查找,插值查找,斐波那契查找等方式,可将查找复杂度提高为O(logn);对于一般的插入删除操作,涉及到数组元素的移动,其平均复杂度也为O(n)
线性链表:对于链表的新增,删除等操作(在找到指定操作位置后),仅需处理结点间的引用即可,时间复杂度为O(1),而查找操作需要遍历链表逐一进行比对,复杂度为O(n)
二叉树:对一棵相对平衡的有序二叉树,对其进行插入,查找,删除等操作,平均复杂度均为O(logn)。
哈希表:相比上述几种数据结构,在哈希表中进行添加,删除,查找等操作,性能十分之高,不考虑哈希冲突的情况下(后面会探讨下哈希冲突的情况),仅需一次定位即可完成,时间复杂度为O(1),接下来我们就来看看哈希表是如何实现达到惊艳的常数阶O(1)的。
我们知道,数据结构的物理存储结构只有两种:顺序存储结构和链式存储结构(像栈,队列,树,图等是从逻辑结构去抽象的,映射到内存中,也这两种物理组织形式),而在上面我们提到过,在数组中根据下标查找某个元素,一次定位就可以达到,哈希表利用了这种特性,哈希表的主干就是数组。
比如我们要新增或查找某个元素,我们通过把当前元素的关键字 通过某个函数映射到数组中的某个位置,通过数组下标一次定位就可完成操作。
这个函数可以简单描述为:存储位置 = f(关键字) ,这个函数f一般称为哈希函数,这个函数的设计好坏会直接影响到哈希表的优劣
其实直白来讲其实数组就是一张哈希表。
哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:
那么哈希表能解决什么问题呢,一般哈希表都是用来快速判断一个元素是否出现集合里。
例如要查询一个名字是否在这所学校里。
要枚举的话时间复杂度是O(n),但如果使用哈希表的话, 只需要O(1)
⑻ 哈希表概念以及哈希冲突的处理
哈希表(散列表 Hash)是相对于线性表、树形结构的一种数据结构,它能在元素的存储位置和其关键字直接建立某种之间关系,那么在进行查找时,就无需做或者做很少次的比较,就能通过这个关系直接由关键字找到对对应的记录。这就是散列查找法(Hase Search)的思想,它通过对元素的关键字值进行某种运算,直接求出元素的地址。即使用关键字到地址的直接转换方法,而不需要反复比较。因此,散列查找法又叫杂凑法或者散列法。
选择一个好的散列函数可以在一定程度上减少冲突,但在实际应用中,很难完全避免发生冲突,所以选择一个有效的处理冲突的方法是散列表的另一个关键问题。
处理冲突的方法与散列表本身的组织形式有关。按组织形式的不同,通常分为两大类:开放地址法和链地址法。
开放地址法的基本思想是:把记录都存储在散列表数组中,当某一记录关键字key的初始散列地址H0=H(key)发生冲突时,以H0为基础,采取合适方法计算得到另一地址H1,如果H1仍然发生冲突,已H1位基础再求下一个地址H2,若H2仍然冲突,再求得H3,以此类推,直至Hk不发生冲突为止,则Hk为该记录在表中的散列地址。
根据计算方法,可以分为以下三种探测方法:
线性探测法会在出现在处理过程中发生冲突的发生第一个散列地址不同的记录争夺同一个后继散列地址的现象,称为二次聚集或者堆积。即在处理同义词的冲突过程中,又添加了非同义词的冲突。
它的优点是,只要散列表未满,就一定能找到一个不发生冲突的地址
而二次探测法和伪随机数探测法可以避免出现二次聚集现象,但是不保证一定能找到不发生冲突的地址。
链地址法的基本思想是:把具有相同散列地址的记录放在同一个单链表中,称为同义词链表。有m个散列地址就有m个单链表,同时用数组HT[0..m-1]存放各个链表的头指针,凡是散列地址为i的记录都以结点的方式插入已HT[i]为头结点的单链表中。
⑼ 请问怎么用Hashset存储多种数据.
这些数据应该是相关的吧,所以应该用个对象存储起来,比如城市降雨量对象,它有三个属性:年份,城市,每月降雨量。
然后用hashset来存储这个对象。
至于查找,可以转化为迭代器,对当前对象进行判断,直到找到满足条件的即可;如果数据在数据库中,直接通过SQL来查找。
⑽ 数据结构——哈希表
哈希表(hash table)又称为散列表,或者散列映射、映射、字典和关联数组等。是一种根据键(key)直接访问在内存存储位置的数据结构,也就是我们常说的键值对。
在之前我们讲过数组,链表,栈,这些数据结构,都是不包含默认逻辑的,可以直接反应数据在内存中的存储位置以及状态。而相较于其他的数据结构,哈希表是一种包含默认逻辑的数据结构,默认逻辑即为需要使用散列函数才能够确定键对应的元素的地址。
而什么是散列表呢?
散列表是一个数组,其中储存有通过散列函数返回的结果。如图,需要保证的是不同的输入返回不同的索引,同样的输入返回相同的索引。
如果出现两个key返回同样的地址,就是所谓的冲突。一般我们使用语言都有很好的解决,并不需要我们自己来设计,不需要过多关注,如果有兴趣的话无非就是考虑一下降低填装因子和使用更加优良的散列函数。