但是我们想想为什么会有这种问题?因为我们给每一个单词都分配了一个数组单元,而类似aaaa,zzzz这样的
单词显然是不存在的,因此我们有了一个最常用的哈希化的方法,“取余法”。50000个单词,但我们给它分
配一个容量为100000的数组,我们先将单词转化为10进制数字largeNumber,则 arrayIndex = hugeNumber
% arraySize;
哈希化其实是一种压缩,是压缩就必定要付出代价,也就是不能保证每个单词都能有自己的空白数组单元,
这也就是我们所说的“哈希冲突”。我们有两种方法解决冲突,一种是给冲突的数据再找一个空白数组单元,
叫做“开放地址法”,第二种是创建一个存放链表的数组,将所有冲突数据放到对应位置的链表中,这叫做
“链地址法”。
而开放地址法又有线性探测、二次探测和再哈希法。线性探测比较简单,就是依次向下寻找空白数组单元。
简单写一下线性探测的插入数据的java代码:
public int hashFunc(int key){
return key % arraySize;
}
public void insert(DataItem item){
int key = item.getkey();
int hashVal = hashFunc(key);
while(hashArray[hashVal] != null && hashArray[hashVal] != -1){ //-1指的是被删除过数据
hashVal ++; 项的数组单元
hashVal %= arraySize; //如果有必要则返回数组初始部位继续查询
}
hashArray[hashVal] = item;
}
当哈希表的数据项接近于填满哈希表时,会产生一种不好的现象“聚集”,这会使得哈希表处理数据的速度大大
下降,二次探测能有效避免聚集,假如线性探测的过程是x+1,x+2,x+3....那么二次探测的过程就是x+1,x+4,x+9.....
但是这样具有相同的哈希化后的值的数据又会产生“二次聚集”,因此我们又有了再哈希法,也就是将关键字用不同的
哈希函数再哈希化一边将结果作为探测的“步长”。现在已知一个哈希函数能很好满足这个想法:stepSize = constant - (key % constant);
其中constant是小于数组容量的一个质数。下面我简单写下代码来体现这一方法如何插入数据:
public void insert(DataItem item){
int key = item.getKey();
int hashVal = hashFunc1(key);
int stepSize = hashFunc2(key); //hashFunc2为再哈希化的哈希函数
while(hashArray[hashVal] != null && hashArray[hashVal] != -1){
hashVal += stepSize;
hashVal %= arraySize;
}
hashArray[hashVal] = item;
}
“链地址法”的意思就是让数组里面存储的不是数据项而是链表下面用一个图来展示:
public void insert(Link theLink){
int key = theLink.getKey();
Link previous = null;
Link currunt = first;
while(currunt != null && key > current.getKey()){
previous = current;
current = current.next;
}
if(previous == null)
first = theLink
else
previous.next = theLink;
theLink.next = current;
}
相关推荐
也叫哈希表)。是依据关键码值(Keyvalue)而直接进行訪问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来訪问记录。以加快查找的速度。这个映射函数叫做散列函数。存放记录的数组叫做散列表。散列函数能...
Hash Join 算法会将驱动表 R 中的记录导入内存并创建一张哈希表,然后遍历被驱动表 S 的每一条记录,逐一在哈希表中判断当前记录是否满足连接条件。 Hash Join 的优点在于可以大幅度提高连接速度,特别是在被驱动...
地址学习通过记录MAC地址与端口的映射关系,动态更新哈希表,而STP则用于构建无环的网络拓扑,避免广播风暴和数据包循环。 总的来说,Linux内核中的桥接机制是通过虚拟网桥设备和相关的数据结构实现网络接口之间的...
例如,如果内存有限,那么使用数组或链表可能会比使用哈希表更合适,因为哈希表通常需要更多的内存空间。 总的来说,理解并合理选择数据存储结构是提升程序运行效率的关键。在计算阶乘这样的问题上,我们可以看到,...
MySQL 中的数据都是按照表存储的,更微观地看,这些表都是按照行存储的。每执行一次 select 查询,MySQL 都会返回一个结果集,该结果集由若干行组成。因此需要在 Redis 中找到一种对应于 MySQL 行的数据结构。Redis ...
而结构化P2P网络使用分布式哈希表(Distributed Hash Table,DHT)方法来组织网络,使得每个节点负责存储一部分全局信息,可以通过高效的算法快速定位资源,提高了搜索的效率。 3. P2P网络的关键技术 文中提到了...
- **`HashMap`**:基于哈希表实现的映射,提供了快速的添加、删除和查找操作,但不保证键的顺序。可以包含一个null键和多个null值。 - **`Hashtable`**:与`HashMap`相似,但支持同步操作,即线程安全。不允许null...
- **数据结构选择**:根据问题的需求选择合适的数据结构,如数组、链表、树、图、哈希表等。不同的数据结构对算法性能有很大影响,如快速查找通常使用哈希表,有序数据则使用二分查找。 - **内存管理**:合理分配...
1、列表(list) list是处理一组有序项目的数据结构,即你可以在一个列表中存储一个序列的项目。 列表中的项目应该包括在方括号中,这样Python就知道你是指明一个列表。一旦你创建了一个列表,就可以添加、删除...
这可能通过使用哈希表或集合数据结构来存储已访问过的厂家,确保只打印一次。 4. **用户界面**:程序需提供一个友好的用户界面,包括菜单选项如“读取数据”、“统计价值总量”、“厂家清单”和“退出”。这涉及到...
### MySQL查询优化浅析 #### 一、查询优化概述 查询优化是数据库管理系统(DBMS)中的一个重要组成部分,其主要目标是在接收到一个SQL查询后,寻找最高效的执行计划,以尽可能快的速度返回查询结果。这一过程涉及到...
### MySQL核心Innodb存储引擎浅析—事务系统 #### 存储引擎介绍 在MySQL中,存储引擎是处理表的存储方式的核心组件之一。不同的存储引擎提供了不同的特性,如事务支持、锁定粒度等。其中,MyISAM和InnoDB是最常用...
golang中的map是一种数据类型,将键与值绑定到一起,底层是用哈希表实现的,可以快速的通过键找到对应的值。 类型表示:map[keyType][valueType] key一定要是可比较的类型(可以理解为支持==的操作),value可以是...
哈希表是一种数据结构,它使用哈希函数来计算一个键值的索引,然后存储该键值对应的值。这种数据结构能够快速地插入、删除和查找数据。Java中的`HashMap`、`HashSet`等集合就是基于哈希表实现的。 ##### `hashCode...
MySQL 数据表分区技术是一种优化大型数据库性能的有效方法,它通过将大表逻辑上分为多个部分,使得查询操作能更高效地处理数据。分区技术在 MySQL 5.1 及以后的版本中得到了支持,提供了四种主要的分区类型:RANGE、...
哈希表(Hashtable)类是基于键值对的数据结构,允许快速查找、插入和删除元素。哈希表利用键的哈希码来定位元素,提高了操作效率。它不支持null键和值,并且是线程安全的。在实际应用中,如果不需要线程安全,通常...
PostgreSQL支持多种类型的索引,包括B树(B-Tree)、哈希(Hash)、GiST(Generalized Search Tree)、SP-GiST(Spatial Indexes)、GIN(Generalized Inverted Indexes)和BRIN(Bitmap Range Indexes)。...