hash表简单实现
1、什么是哈希表?
哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
2、如何实现实现哈希表
哈希表的做法其实很简单,就是把Key通过一个固定的算法函数即所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。当然,不同的数据可能会出现相同的下标,那么就把这些数据用链表“连”起来放入对应下标数组。
当使用哈希表进行查询等操作的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间便利数组存放的链表获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位
3、简单实现
因为只是为了实现一体现这种思想的哈希表,所以写了一个简单的hashForUI实现方法,以下是具体的代码:
用户类:这里没有使用泛型,只是简单的希望哈希表能够存储用户类的数据,并且以用户的ID来作为索引,进行添加和查找
/**
* 用户信息类
*/
public class UserInfo {
private String userName;
private int id;
//构造函数
public UserInfo(String userName,int id){
this.userName = userName;
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
节点类:这是用来作为存放在数组中的链表结点,每个节点存放的数据类型是UserInfo,有一个后继指向下一个链表节点
/**
* 结点类,作为存放在数组中的链表结点
*
*/
public class Node {
private UserInfo user;
private Node next;
//构造函数
public Node(UserInfo user ,Node next){
this.user = user;
this.next = next;
}
public UserInfo getUser() {
return user;
}
public void setUser(UserInfo user) {
this.user = user;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
这是具体的实现方法:
这里关键码值使用的是UserInfo的ID,哈希函数也只是简单的
/**
* 构建hashForUI表,实现insert,delete,rehash等方法
*/
public class hashForUI{
private static int length = 10;//创建哈希表的数组,初始化长度是length;
public static Node[] array = new Node[length];
private int count = 0;//表长
private double loadFactor = 0.5;//装载因子
//插入元素
public void insert(UserInfo user){
int index = calculate(user.getId());
Node node = new Node(user,null);
node.setNext(array[index]);
array[index] = node;
count ++;
//判断是否需要rehash
rehash();
}
}
//删除元素
public boolean delete(UserInfo user){
int index = calculate(user.getId());
if(array[index] == null){//数组为空
return false;
}else if(array[index].getUser().getId() == user.getId()){//第一个元素就是所找
array[index] = array[index].getNext();
}else{//第一个不是
Node currentFirst = array[index];
Node currentSecond = currentFirst.getNext();
while(currentSecond != null){
if(currentSecond.getUser().getId() == user.getId()){//第二个即所找
currentFirst.setNext(currentSecond.getNext());
count --;
return true;
}else{//后移
currentFirst = currentSecond;
currentSecond = currentSecond.getNext();
}
}
}
return false;
}
//查找元素
public UserInfo find(int id){
int index = calculate(id);
//System.out.println(index+" "+id);
for(Node current = array[index] ;current != null;current = current.getNext()){
if(current.getUser().getId() == id){
return current.getUser();
}
}
return null;
}
//重新构建哈希表,每次增加数组长度100
public void rehash(){
//System.out.println((double)length/(double)count);
if(((double)length/(double)count) < loadFactor){
length = length*2;
System.out.println(length);
Node[] arrayCopy = new Node[length];
//直接重新插入
for(int i = 0;i < array.length;i++){
Node node = array[i];
while(node != null){
//System.out.println("&&&");
UserInfo user = node.getUser();
int index = calculate(user.getId());
Node n = new Node(user,null);
n.setNext(arrayCopy[index]);
arrayCopy[index] = n;
node = node.getNext();
}
}
array = arrayCopy;
}
}
//哈希表长
public int length(){
return count;
}
//哈希函数
public int calculate(int x){
return x%length;
//return x.hashCode();
}
}
/**
* 测试类
*/
public class test {
public static void main(String [] args){
hashForUIh = new hashForUI();
Long startTime1=System.currentTimeMillis();//记录开始时间
for(int i = 0;i<650000;i++){
UserInfo user = new UserInfo("User"+i,i);
h.insert(user);
}
Long endTime1=System.currentTimeMillis();//记录结束时间
System.out.println("hash插入元素所用时间"+(endTime1-startTime1));
UserInfo user1 = new UserInfo("User"+1299,1299);
boolean state = h.delete(user1);
System.out.println(state);
Long startTime2=System.currentTimeMillis();//记录开始时间
user1 = h.find(1333);
Long endTime2=System.currentTimeMillis();//记录结束时间
System.out.println(user1.getUserName()+" "+user1.getId());
System.out.println("hash查找元素所用时间"+(endTime2-startTime2));
}
}
运行结果:
hash插入元素所用时间1310
true
User1333 1333
hash查找元素所用时间0
如果输出每一次reHash后数组长度的改变,会发现当数据达到65W时,建立的数组大小是32W,也是相当巨大的………………
总之,只是简单实现了hash的思想,至于算法方面,有待提高~~~
分享到:
相关推荐
Hash表是一种数据结构,它通过使用哈希函数将键(key)映射到数组的索引位置,从而实现快速的查找、插入和删除操作。在C语言中,我们可以利用结构体和指针来构建一个简单的Hash表。下面将详细介绍Hash表的概念、哈希...
在编程领域,哈希表(Hash Table)是一种高效的数据结构,它通过特定的哈希函数将数据映射到一个固定大小的数组中,以实现快速的查找、插入和删除操作。哈希表的关键在于设计良好的哈希函数,该函数能够尽可能均匀地...
### 无锁Hash表的实现方式 在计算机科学领域,数据结构的设计对于提高程序效率至关重要。其中,哈希表作为一种高效的数据结构,在多种场景下都有着广泛的应用。传统的哈希表通常依赖于锁定机制来保证多线程环境下的...
UTHASH 是一个开源的 C 语言库,提供了一种简单且高效的哈希表实现,用于在 C 代码中快速查找和管理数据结构。这个库的主要功能是提供一个宏定义的集合,可以方便地将结构体转化为哈希表,进而进行添加、删除、查找...
以下是一个简单的C++实现哈希表的例子: ```cpp #include #include struct HashTable { int size; std::list, std::string>>* table; HashTable(int sz) : size(sz) { table = new std::list, std::string>...
在本项目中,“avl树实现hash表”可能是为了利用avl树的特性来优化哈希表的冲突处理。一种可能的实现方式是,每个桶不再是一个简单的链表,而是一个avl树。这样,当冲突发生时,所有映射到同一桶的键会被存储在avl树...
总结文档`hash表.doc`和`hash总结.doc`可能涵盖了哈希表的基本概念、原理、哈希函数的设计、冲突解决策略以及哈希表在实际应用中的案例分析。深入阅读这些文档将有助于进一步理解哈希表的工作机制及其在软件开发中的...
- 编写`ConsistentHash`类,实现哈希环的逻辑,包括添加节点、删除节点、查找节点等方法。 - 实现查找算法,可以使用`TreeMap`的`lowerKey()`或`ceilingKey()`方法找到环上最近的虚拟节点。 4. **优化策略** - *...
- 在这个C语言实现中,哈希函数可能是一个简单的模运算,例如`hash(key) = key % size`,其中`size`是哈希表的大小。 3. **冲突解决:链地址法**: - 链地址法是为每个数组元素创建一个链表,当新键映射到已有的...
哈希(Hash)算法在计算机科学中扮演着重要的角色,特别...同时,为了处理碰撞,可以结合链地址法、开放寻址法或者双重哈希等方法实现哈希表。在压缩包中的`hash`文件可能包含了更多不同哈希函数的实现,供学习和参考。
哈希表(Hash Table)是一种数据结构,它通过哈希函数将关键字映射到数组的索引位置,以此实现快速的查找、插入和删除操作。在C语言中实现哈希表,我们需要理解哈希函数的设计、冲突解决策略以及动态扩容等核心概念...
### 经典Hash算法概述与实现 #### 一、引言 哈希算法在计算机科学领域扮演着极其重要的角色,特别是在数据检索、信息安全以及数据完整性校验等方面。它能够将任意长度的数据转换成一个固定长度的哈希值,这一过程在...
总结来说,aHash算法是一种快速且简单的图像相似度比较方法,特别适合于大量图像的预筛选。在Delphi中实现aHash,需要理解算法的基本流程,并能够利用Delphi的图像处理和二进制操作功能。通过这个压缩包,你可以学习...
在这个框架中,`createHashTable`用于初始化哈希表,`hashFunction`用于计算哈希码,`insert`、`search`和`deleteEntry`分别对应插入、查找和删除操作。为了实现高效且无冲突的哈希索引,你需要仔细设计哈希函数以...
在描述中提到的“根据函数名获取简单的HASH值”,通常是指为了快速比较或查找函数名的一种方法。HASH函数将一个字符串转换为固定长度的数值,相同的字符串会产生相同的HASH值,不同字符串则有非常小的概率产生相同...
Hash索引的设计和实现简单,通常比其他类型的索引(如B树索引)更节省空间,但其缺点在于不支持范围查询和排序操作,因为哈希函数可能导致键值的顺序不可预测。 在内存数据库中设计和实现Hash索引,需要考虑到内存...
在Java编程语言中,实现哈希算法可以方便地用于数据验证、查找表以及密码存储等多种用途。本篇文章将详细讨论几种常见的哈希算法及其在Java中的实现。 1. **MD5(Message-Digest Algorithm 5)** MD5是一种广泛...
base64加解密, hash表, fnmatch的windows下的实现简单实现版本。是从mosquitto的auth_plug中copy和https://blog.csdn.net/tttmt/article/details/24824291?utm_source=blogxgwz8 看到的 c语言代码。在qt上测试了
C语言实现的一个结构十分清晰的hash表的构建,包括了对hash表进行操作的几个基本函数(新建,插入,删除,展示,销毁),简单易懂,希望对大家有用。
这个C++实现的哈希表虽然简单,但它展示了哈希表的基本操作。实际应用中,哈希函数通常会更复杂,以减少冲突概率。另外,为了适应动态增长的需求,哈希表的大小可能需要动态调整。此外,解决冲突的方法也有很多,如...