哈希表的java实现
时间:2019-10-31
本文章向大家介绍哈希表的java实现,主要包括哈希表的java实现使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
哈希表的java实现
什么是哈希表?
1.哈希表是通过关键码key来直接进行访问的一种数据结构
2.也就是它通过关键码来值映射到表中的一个位置来访问记录,进而加快访问的速度
3.存放记录的数组叫做散列表(哈希表)
哈希表的根据解决冲突方式不同分为的两种样式
1.分离链接法
2.线性探测法
散列函数
1.什么是散列函数?
简单的说,就是已知一个值value,通过将value代入散列函数就可以知道其在散列表中所存放的位置。
2.散列函数的例子
1.一般情况下如果输入的数字是整数,那么合理的方法就是直接返回key mod tablesize,也就是散列函数是f(x)=x%tablesize
2.其中x是数值,而tablesize则是整个表的大小
3.假如x=13,tablesize=4,那么通过将x代入散列函数可以得到13 mod 4=1,那么由此可以得出13应当放在散列表的1这个下标的位置
冲突的问题
为什么会产生冲突?
1.假如同时又两个值13,和17,tablesize=4,那么将这两个值都代入散列函数,分别得到他们的下标分别是1,1。
2.你会发现他们放的位置是一样的,但是table[1]这个位置只能放一个值,咋办?如果硬放的话一个值会把另外一个值覆盖掉,肯定不行
解决冲突的方法
1.分离链接法
这种方法,比较符合直接的思路,既然冲突,我们都将这两个元素放到这个位置,摞起来不就行了,的确这是一种好方法,其实现是建立一张比较大的索引表,每一个
位置存放一个指向单链表的指针,冲突的元素依次插入这个单链表的末尾
2.开放寻址法
因为开放定址法必须放在表内,所以开放定址法所需要的表要比分离链接散列用表大。
代码的实现
分离链接法
# include <iostream>
using namespace std;
int MAXSIZE=20000;
int Max=19999;
typedef struct node{
int elem;
struct node* next;
}NODE,*PNODE;//定义节点
typedef struct hash{
struct node** hash_table;//哈希表
}HASH;
void Init_Hash(HASH &HS);//初始化哈希表
int Hash_function(int n);//哈希函数
void print_Hash(HASH &HS);//打印哈希表
int main(void)
{
HASH HS;
Init_Hash(HS);
print_Hash(HS);
return 0;
}
void Init_Hash(HASH& HS)//将散列表输入数据
{
int num;
int site;
cout<<"请输入"<<MAXSIZE<<"个介于0-19999的整数"<<endl;
HS.hash_table=new PNODE[MAXSIZE];
//初始化散列表
for(int i=0;i<MAXSIZE;i++)
{
HS.hash_table[i]=NULL;
}
//依次输入相应的值
for(int i=0;i<MAXSIZE;i++)
{
cout<<"请输入第"<<i+1<<"个数字:"<<endl;
cin>>num;
site=Hash_function(num);
//cout<<site<<endl;
if(HS.hash_table[site]==NULL)//不冲突的条件之下
{
PNODE pnew=new NODE;
pnew->elem=num;
pnew->next=NULL;
HS.hash_table[site]=pnew;
}
else
{
PNODE visit=HS.hash_table[site];
while(visit->next!=NULL)
{
// cout<<"1"<<" ";
visit=visit->next;
}
PNODE pnew=new NODE;
pnew->elem=num;
pnew->next=NULL;
visit->next=pnew;
}
}
}
int Hash_function(int n)
{
return n/2;
}
void print_Hash(HASH &HS)
{
cout<<"打印的哈希表为:"<<endl;
for(int i=0;i<Max/2;i++)
{
if(HS.hash_table[i]!=NULL)
{
cout<<"下标为 "<<i+1<<" ";
PNODE visit=HS.hash_table[i];
while(visit!=NULL)
{
cout<<visit->elem<<" ";
visit=visit->next;
}
cout<<"\n";
}
}
}
开放寻址法
DateItem类
package hash;
public class DateItem {
private int iData;
public DateItem(int iData)
{
this.iData = iData;
}
public int getKey() {
// TODO Auto-generated method stub
return this.iData;
}
}
OpenAdressHashtable类
package hash;
public class OpenAdressHashtable {
private DateItem[] hashArray;
private int arraySize;
private DateItem nonItem;
public OpenAdressHashtable(int size)
{
arraySize=size;
hashArray=new DateItem[arraySize];
nonItem=new DateItem(-1);
}
public void showTable()//显示哈希表
{
System.out.println("Table:");
for(int j=0;j<arraySize;j++)
{
if(hashArray[j]!=null)
{
System.out.print(hashArray[j].getKey()+"");
}
else
{
System.out.print("*");
}
}
System.out.println();
}
public int hashFunc(int key)//哈希函数
{
return key%arraySize;
}
public void insertIntoTable(DateItem item)//插入哈希表
{
int key=item.getKey();
int hashVal=hashFunc(key);
while(hashArray[hashVal]!=null&&hashArray[hashVal].getKey()!=-1)
{
hashVal++;//被占了,探测下一个位置
hashVal%=arraySize;//防止越界
}
hashArray[hashVal]=item;//插入
}
//哈希表删除
public DateItem deleteItem(int key)
{
int hashVal=hashFunc(key);
while(hashArray[hashVal]!=null)
{
if(hashArray[hashVal].getKey()==key)
{
DateItem temp=hashArray[hashVal];
hashArray[hashVal]=nonItem;//删除它
return temp;
}
++hashVal;
hashVal%=arraySize;
}
return null;
}
//哈希表查找
public DateItem findItem(int key)
{
int hashVal=hashFunc(key);
while(hashArray[hashVal]!=null)
{
if(hashArray[hashVal].getKey()==key)
{
return hashArray[hashVal];
}
hashVal++;
hashVal%=arraySize;
}
return null;
}
}
原文地址:https://www.cnblogs.com/mengxiaoleng/p/11758107.html
- Android 开发中如何动态加载 so 库文件
- 良心推荐:总结 Android 开发中必备的代码 Review 清单
- 强烈推荐:基于Java反射实现一个 Android ORM 框架
- Android 高效安全的本地广播 LocalBroadcast 完全解析
- Android的编译打包流程详解
- Android 仿京东、拼多多商品分类页
- 简单高效的实现 Android App 全局字体替换
- 基于 RxJava2+Retrofit2 精心打造的 Android 基础框架 XSnow
- Android 图片选择到裁剪之步步深坑
- Android自定义 View 实战之 StickerView
- 十分钟搞定酷炫动画,Android自定义 View 入门
- 基础篇章:关于 React Native 之 Switch 和 ProgressBarAndroid 组件的讲解
- Android 实现视屏播放器、边播边缓存功能、外加铲屎(IJKPlayer)
- 基础篇章:关于 React Native 之 ToolbarAndroid 组件的讲解
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- java之springboot之快速入门(一)- maven方式创建项目
- java之springboot之快速入门-Spring Initializr方式创建项目
- springboot之Web综合开发
- springboot之mybatis
- springboot之mybatis多数据源最简解决方案
- 蓝桥杯突击复习准备——部分算法汇总
- 小解c# foreach原理
- 多包依赖管理--Lerna
- Flume概述
- Flume中常见的组件
- 程序员进阶之算法练习(四十八)LeetCode
- [C#]不通过事件方式获取键盘按钮按下的状态
- 15.深入k8s:Event事件处理及其源码分析
- SwiftUI:使用计时器重复触发事件
- SwiftUI:获取应用进入后台的通知