added cactus theme files
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
---
|
||||
title: java散列知识点总结
|
||||
date: 2017-02-18 19:19:01
|
||||
category: notes
|
||||
tags:
|
||||
- Algorithms
|
||||
keywords:
|
||||
- hash
|
||||
- 散列
|
||||
- 哈希
|
||||
- java
|
||||
---
|
||||
|
||||
java 的根类 `Object` 具有 `hashcode` 方法。当 `equal` 方法被重写时也应当重写 `hashcode` 方法。
|
||||
|
||||
## 基本数据类型的散列码
|
||||
|
||||
* `byte` `short` `int` `char` 类型的搜索键将会转换为 `int`。
|
||||
* `float` 类型的搜索键使用 `Float.floatToIntBits(key)` 作为散列码。
|
||||
* `long` 类型的搜索键会进行折叠操作,如下:
|
||||
|
||||
```java
|
||||
iny hashCode = (int) (key ^ (key >> 32));
|
||||
```
|
||||
|
||||
* `double` 类型的搜索键会使用 `Double.doubleToLongBits(key)` 方法转换为 `long` 类型然后再进行折叠。
|
||||
|
||||
## 字符串类型的散列码
|
||||
|
||||
对于字符串一般使用多项式散列码进行计算,
|
||||
|
||||
~~这里放个公式的图~~
|
||||
|
||||
b的较好取值为31,33,37,39,41。在 java String 类中 `b` 取31。
|
||||
|
||||
```java
|
||||
public static int hash(String key, int tableSize)
|
||||
{
|
||||
int hashVal = 0;
|
||||
|
||||
for (int i = 0; i < key.length(); i++)
|
||||
hashVal = 37*hashVal + key.charAt(i);
|
||||
|
||||
hashVal %= tableSize;
|
||||
if (hashVal < 0)
|
||||
hashVal += tableSize;
|
||||
|
||||
return hashVal;
|
||||
}
|
||||
```
|
||||
|
||||
## 压缩散列码
|
||||
|
||||
由于散列码可能是很大的正数,通常应该对其进行压缩以防止超出索引的范围。若索引范围为 `0 ~ n - 1` ,通常的做法是 `h(hashCode) = hashCode % N` ,选择N为大于2的素数。
|
||||
`java.util.HashMap` 的实现中,将N设置为2的幂值,这样可以使用位运算代替上述的取模:`h(hashCode) = hashCode & (N - 1)` ,两者是完全等价的。
|
||||
|
||||
## 处理冲突
|
||||
|
||||
### 开放地址法
|
||||
|
||||
开放地址法是在冲突发生时,在散列表中找到一个开放位置的过程。
|
||||
|
||||
* 线性探测,存在成簇问题
|
||||
* 二次探测,存在二次成簇问题,并且不能保证一个开放的单元总是可以被找到。
|
||||
* 再哈希法
|
||||
|
||||
### 链地址法
|
||||
|
||||
链地址法是将具有同样索引的条目放在同一位置,每个位置使用一个桶(ArrayList or LinkedList)来放置多个条目。
|
||||
|
||||
## 装填因子
|
||||
|
||||
装填因子衡量一个散列表有多满。`lamda = n / N` 。对于开放地址法,装填因子介于 0 ~ 1,对于链地址法,装填因子可能为任意值。通常开放地址法需要将装填因子维持在0.5以下,而链地址法为0.9以下。`java.util.HashMap` 采用了阈值0.75。
|
||||
Reference in New Issue
Block a user