auto commit

This commit is contained in:
CyC2018 2018-02-22 15:29:02 +08:00
parent 06a8653f87
commit bee8913883

View File

@ -74,18 +74,18 @@
* [5. 删除最小键](#5-删除最小键)
* [6. 分析](#6-分析)
* [散列表](#散列表)
* [散列函数](#散列函数)
* [基于拉链法的散列表](#基于拉链法的散列表)
* [基于线性探测法的散列表](#基于线性探测法的散列表)
* [查找](#查找)
* [插入](#插入)
* [删除](#删除)
* [调整数组大小](#调整数组大小)
* [1. 散列函数](#1-散列函数)
* [2. 基于拉链法的散列表](#2-基于拉链法的散列表)
* [3. 基于线性探测法的散列表](#3-基于线性探测法的散列表)
* [3.1 查找](#31-查找)
* [3.2 插入](#32-插入)
* [3.3 删除](#33-删除)
* [3.4 调整数组大小](#34-调整数组大小)
* [应用](#应用)
* [各种符号表实现的比较](#各种符号表实现的比较)
* [Java 的符号表实现](#java-的符号表实现)
* [集合类型](#集合类型)
* [稀疏向量乘法](#稀疏向量乘法)
* [1. 各种符号表实现的比较](#1-各种符号表实现的比较)
* [2. Java 的符号表实现](#2-java-的符号表实现)
* [3. 集合类型](#3-集合类型)
* [4. 稀疏向量乘法](#4-稀疏向量乘法)
<!-- GFM-TOC -->
# 基础
@ -1363,7 +1363,7 @@ private Node put(Node x, Key key, Value val) {
#### 5. 删除最小键
如果最小键在一个 2- 节点中,那么删除该键会留下一个空链接,就破坏了平衡性,因此要确保最小键不在 2- 节点中。将 2- 节点转换成 3- 节点或者 4- 节点有两种方法,一种是向上层节点拿一个 key或者向兄弟节点拿一个 key。如果上层节点是 2- 节点,那么就没办法从上层节点拿 key 了,因此要保证删除路径上的所有节点都不是 2- 节点。在向下删除的过程中,保证以下情况之一发生:
如果最小键在一个 2- 节点中,那么删除该键会留下一个空链接,就破坏了平衡性,因此要确保最小键不在 2- 节点中。将 2- 节点转换成 3- 节点或者 4- 节点有两种方法,一种是向上层节点拿一个 key一种是向兄弟节点拿一个 key。如果上层节点是 2- 节点,那么就没办法从上层节点拿 key 了,因此要保证删除路径上的所有节点都不是 2- 节点。在向下删除的过程中,保证以下情况之一发生:
1. 如果当前节点的左子节点不是 2- 节点,完成;
2. 如果当前节点的左子节点是 2- 节点而它的兄弟节点不是 2- 节点,向兄弟节点拿一个 key 过来;
@ -1387,7 +1387,7 @@ private Node put(Node x, Key key, Value val) {
由于无法通过散列值知道键的大小关系,因此散列表无法实现有序性操作。
### 散列函数
### 1. 散列函数
对于一个大小为 M 的散列表,散列函数能够把任意键转换为 [0, M-1] 内的正整数,该正整数即为 hash 值。
@ -1427,7 +1427,7 @@ Java
int hash = (x.hashCode() & 0x7fffffff) % M;
```
使用 Java 自带的 HashMap 等自带的哈希表实现时,只需要去实现 Key 类型的 hashCode() 函数即可,因此也就不需要考虑 M 的大小等。Java 规定 hashCode() 能够将键均匀分布于所有的 32 位整数Java 中的 String、Integer 等对象的 hashCode() 都能实现这一点。以下展示了自定义类型如何实现 hashCode()。
使用 Java 自带的 HashMap 等自带的哈希表实现时,只需要去实现 Key 类型的 hashCode() 函数即可。Java 规定 hashCode() 能够将键均匀分布于所有的 32 位整数Java 中的 String、Integer 等对象的 hashCode() 都能实现这一点。以下展示了自定义类型如何实现 hashCode()。
```java
public class Transaction{
@ -1445,7 +1445,7 @@ public class Transaction{
}
```
### 基于拉链法的散列表
### 2. 基于拉链法的散列表
拉链法使用链表来存储 hash 值相同的键,从而解决冲突。此时查找需要分两步,首先查找 Key 所在的链表,然后在链表中顺序查找。
@ -1453,7 +1453,7 @@ public class Transaction{
对于 N 个键M 条链表 (N>M),如果哈希函数能够满足均匀性的条件,每条链表的大小趋向于 N/M因此未命中的查找和插入操作所需要的比较次数为 \~N/M。
### 基于线性探测法的散列表
### 3. 基于线性探测法的散列表
线性探测法使用空位来解决冲突,当冲突发生时,向前探测一个空位来存储冲突的键。使用线程探测法,数组的大小 M 应当大于键的个数 NM>N)。
@ -1486,7 +1486,7 @@ public class LinearProbingHashST<Key, Value> {
}
```
#### 查找
#### 3.1 查找
```java
public Value get(Key key) {
@ -1499,7 +1499,7 @@ public Value get(Key key) {
}
```
#### 插入
#### 3.2 插入
```java
public void put(Key key, Value val) {
@ -1517,7 +1517,7 @@ public void put(Key key, Value val) {
}
```
#### 删除
#### 3.3 删除
删除操作应当将右侧所有相邻的键值重新插入散列表中。
@ -1545,7 +1545,7 @@ public void delete(Key key) {
}
```
#### 调整数组大小
#### 3.4 调整数组大小
线性探测法的成本取决于连续条目的长度,连续条目也叫聚簇。当聚簇很长时,在查找和插入时也需要进行很多次探测。
@ -1580,23 +1580,23 @@ private void resize(int cap) {
## 应用
### 各种符号表实现的比较
### 1. 各种符号表实现的比较
![](https://github.com/CyC2018/InterviewNotes/blob/master/pics/9ee83c8c-1165-476c-85a6-e6e434e5307a.jpg)
应当优先考虑散列表,当需要有序性操作时使用红黑树。
### Java 的符号表实现
### 2. Java 的符号表实现
Java 的 java.util.TreeMap 和 java.util.HashMap 分别是基于红黑树和拉链法的散列表的符号表实现。
### 集合类型
### 3. 集合类型
除了符号表,集合类型也经常使用,它只有键没有值,可以用集合类型来存储一系列的键然后判断一个键是否在集合中。
### 稀疏向量乘法
### 4. 稀疏向量乘法
向量运算涉及到 N 次乘法,当向量为稀疏向量时,可以使用符号表来存储向量中的非 0 索引和值,使得乘法运算只需要对那些非 0 元素进行即可。
当向量为稀疏向量时,可以使用符号表来存储向量中的非 0 索引和值,使得乘法运算只需要对那些非 0 元素进行即可。
```java
import java.util.HashMap;