JAVA数据结构--哈希表的实现(分离链接法)
哈希表(散列)的定义
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
哈希表的特点是采用以常数平均时间执行插入、删除和查找。
一个通俗的例子是,为了查找电话簿中某人的号码,可以创建一个按照人名首字母顺序排列的表(即建立人名
到首字母
的一个函数关系),在首字母为W的表中查找“王”姓的电话号码,显然比直接查找就要快得多。这里使用人名作为关键字,“取首字母”是这个例子中散列函数的函数法则
,存放首字母的表对应散列表。关键字和函数法则理论上可以任意确定。
分离链接法定义
将散列到同一个值得所有元素保留到一个表中。
基本思想是采用N个链表组成链表数组,N为哈希表的长度。

哈希表构造实现
public SeparateChainingHashTable() {
this(DEFAULT_TABLE_SIZE);
}
public SeparateChainingHashTable(int size) {
theLists=new LinkedList[nextPrime(size)];
for(int i=0;i<theLists.length;i++) {
theLists[i]=new LinkedList<>();//初始化链表数组
}
}
基本操作实现
/*
* 哈希表插入元素
* */
public void insert(T x) {
List<T> whichList=theLists[myhash(x)];
/*
* 如果当前哈希地址的链表不含有元素,则链表中添加该元素
* */
if(!whichList.contains(x)) {
whichList.add(x);
if(++currentSize>theLists.length)//如果表长度不够,则扩容
rehash();
}
}
public void remove(T x) {
List<T> whichList=theLists[myhash(x)];
if(whichList.contains(x)) {
whichList.remove(x);
currentSize--;
}
}
public boolean contains(T x) {
List<T> whilchList=theLists[myhash(x)];
return whilchList.contains(x);
}
public void makeEmpty() {
for(int i=0;i<theLists.length;i++)
theLists[i].clear();
currentSize=0;
}
哈希表相关实现
private void rehash() {
List<T>[] oldLists=theLists;
theLists=new List[nextPrime(2*theLists.length)];
for(int j=0;j<theLists.length;j++)
theLists[j]=new LinkedList<>();
currentSize=0;
/*
* 更新哈希表
* */
for(List<T> list:oldLists)
for(T item:list)
insert(item);
}
/*
* myhash()方法获得哈希表的地址
* */
private int myhash(T x) {
int hashVal=x.hashCode();//hashCode()方法返回该对象的哈希码值
hashVal%=theLists.length;//对哈希表长度取余数
if(hashVal<0)
hashVal+=theLists.length;
return hashVal;
}
全部代码
import java.util.LinkedList;
import java.util.List; public class SeparateChainingHashTable<T>{
public SeparateChainingHashTable() {
this(DEFAULT_TABLE_SIZE);
}
public SeparateChainingHashTable(int size) {
theLists=new LinkedList[nextPrime(size)];
for(int i=0;i<theLists.length;i++) {
theLists[i]=new LinkedList<>();//初始化链表数组
}
} /*
* 哈希表插入元素
* */
public void insert(T x) {
List<T> whichList=theLists[myhash(x)];
/*
* 如果当前哈希地址的链表不含有元素,则链表中添加该元素
* */
if(!whichList.contains(x)) {
whichList.add(x);
if(++currentSize>theLists.length)//如果表长度不够,则扩容
rehash();
}
}
public void remove(T x) {
List<T> whichList=theLists[myhash(x)];
if(whichList.contains(x)) {
whichList.remove(x);
currentSize--;
}
}
public boolean contains(T x) {
List<T> whilchList=theLists[myhash(x)];
return whilchList.contains(x);
}
public void makeEmpty() {
for(int i=0;i<theLists.length;i++)
theLists[i].clear();
currentSize=0;
} private static final int DEFAULT_TABLE_SIZE=101; private List<T> [] theLists;
private int currentSize; /*
* 哈希表扩容,表长度为下一个素数
* */
private void rehash() {
List<T>[] oldLists=theLists;
theLists=new List[nextPrime(2*theLists.length)];
for(int j=0;j<theLists.length;j++)
theLists[j]=new LinkedList<>(); currentSize=0;
/*
* 更新哈希表
* */
for(List<T> list:oldLists)
for(T item:list)
insert(item);
}
/*
* myhash()方法获得哈希表的地址
* */
private int myhash(T x) {
int hashVal=x.hashCode();//hashCode()方法返回该对象的哈希码值
hashVal%=theLists.length;//对哈希表长度取余数
if(hashVal<0)
hashVal+=theLists.length;
return hashVal;
}
//下一个素数
private static int nextPrime(int n) {
if( n % 2 == 0 )
n++; for( ; !isPrime( n ); n += 2 )
; return n;
}
//判断是否是素数
private static boolean isPrime(int n) {
if( n == 2 || n == 3 )
return true; if( n == 1 || n % 2 == 0 )
return false; for( int i = 3; i * i <= n; i += 2 )
if( n % i == 0 )
return false; return true;
}
}
JAVA数据结构--哈希表的实现(分离链接法)的更多相关文章
- java数据结构----哈希表
1.哈希表:它是一种数据结构,可以提供快速的插入操作和查找操作.如果哈希表中有多少数据项,插入和删除操作只需要接近常量的时间.即O(1)的时间级.在计算机中如果需要一秒内查找上千条记录,通常使用哈希表 ...
- java数据结构——哈希表(HashTable)
哈希表提供了快速的插入操作和查找操作,每一个元素是一个key-value对,其基于数组来实现. 一.Java中HashMap与Hashtable的区别: HashMap可以接受null键值和值,而Ha ...
- Java数据结构——哈希表
- Java中哈希表(Hashtable)是如何实现的
Java中哈希表(Hashtable)是如何实现的 Hashtable中有一个内部类Entry,用来保存单元数据,我们用来构建哈希表的每一个数据是Entry的一个实例.假设我们保存下面一组数据,第一列 ...
- (js描述的)数据结构[哈希表1.1](8)
(js描述的)数据结构[哈希表1.1](8) 一.数组的缺点 1.数组进行插入操作时,效率比较低. 2.数组基于索引去查找的操作效率非常高,基于内容去查找效率很低. 3.数组进行删除操作,效率也不高. ...
- Python与数据结构[4] -> 散列表[1] -> 分离链接法的 Python 实现
分离链接法 / Separate Chain Hashing 前面完成了一个基本散列表的实现,但是还存在一个问题,当散列表插入元素冲突时,散列表将返回异常,这一问题的解决方式之一为使用链表进行元素的存 ...
- 解决hash冲突之分离链接法
解决hash冲突之分离链接法 分离链接法:其做法就是将散列到同一个值的所有元素保存到一个表中. 这样讲可能比较抽象,下面看一个图就会很清楚,图如下 相应的实现可以用分离链接散列表来实现(其实就是一个l ...
- 分离链接法(Separate Chaining)
之前我们说过,对于需要动态维护的散列表 冲突是不可避免的,无论你的散列函数设计的有多么精妙.因此我们解决的重要问题就是:一旦发生冲突,我们该如何加以排解? 我们在这里讨论最常见的两种方法:分离链接法和 ...
- POJ2549【hash分离链接法】
题意: 给n个不同的数,求一个4个数(a,b,c,d)的组合满足a+b+c=d;求最大的d. 思路: 没想到可以用hash搞/ 这个就是数据结构里的分离链接法~ 解决hash冲突的方法:将所有关键字为 ...
随机推荐
- [模板]单源最短路径(Dijkstra)
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 主要还是再打一遍最短路,这种算法我用的不多... #include<bits/stdc++.h> using namesp ...
- 出现命令提示apt-get -f install的解决方法
提示apt-get -f install这个信息,然后查看其他的提示信息发现时缺少了一些以依赖库. 解决办法为执行:sudo apt-get -f install命令. 该命令的含义是去补全那些缺少的 ...
- Ubuntu14.04-LTS 从系统安装到配置可用
1.安装Ubuntu14.04LTS-64bit 使用U盘安装很方便快捷,可以使用老毛桃使用iso模式制作一个U盘启动盘,然后分区安装. 如果使用硬盘安装的话需要注意的问题是: 如果电脑上以前有Lin ...
- Ceph介绍
1. 介绍 云硬盘是IaaS云平台的重要组成部分,云硬盘给虚拟机提供了持久的块存储设备.目前的AWS 的EBS(Elastic Block store)给Amazon的EC2实例提供了高可用高可靠的块 ...
- YII2 全局设定 默认参数
$gridviewSettings = [ 'export' => false, 'responsive' => true, 'floatHeader' => true, 'floa ...
- 【Windows】ASP.NET Core 部署到 IIS
如果你的系统环境没有 .NET CORE SDK,请到官网进行下载: https://www.microsoft.com/net/download/windows 接下来我们开始进行环境的部署,首先在 ...
- 编写高质量代码改善C#程序的157个建议——建议148:不重复代码
建议148:不重复代码 如果发现重复的代码,则意味着我们需要整顿一下,在继续前进. 重复的代码让我们的软件行为不一致.举例来说,如果存在两处相同的加密代码.结果在某一天,我们发现加密代码有个小Bug, ...
- C++ 动态分配二维和三维数组
目的:熟悉c++动态内存分配 描述:使用c++程序定义动态数组类,使用new和delete操作符实现动态二维数组和三维数组的定义 //main.cpp //主程序类 #include <iost ...
- Javascript与数据结构系列(一)——栈的实现
栈的实现 实现一个栈,当务之急是决定存储数据的底层数据结构.这里采用的是数组. 我们的实现以定义 Stack 类的构造函数开始: function Stack() { this.dataStore = ...
- Win7 家庭普通版开启超级管理员
将以下内容copy保存为admin.reg文件 Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ ...