auto commit

This commit is contained in:
CyC2018
2019-11-02 14:39:13 +08:00
parent f77756272b
commit 058e67e0ff
159 changed files with 3185 additions and 839 deletions

View File

@ -1,4 +1,38 @@
[TOC]
<!-- GFM-TOC -->
* [前言](#前言)
* [初级实现](#初级实现)
* [1. 链表实现无序符号表](#1-链表实现无序符号表)
* [2. 二分查找实现有序符号表](#2-二分查找实现有序符号表)
* [二叉查找树](#二叉查找树)
* [1. get()](#1-get)
* [2. put()](#2-put)
* [3. 分析](#3-分析)
* [4. floor()](#4-floor)
* [5. rank()](#5-rank)
* [6. min()](#6-min)
* [7. deleteMin()](#7-deletemin)
* [8. delete()](#8-delete)
* [9. keys()](#9-keys)
* [10. 分析](#10-分析)
* [2-3 查找树](#2-3-查找树)
* [1. 插入操作](#1-插入操作)
* [2. 性质](#2-性质)
* [红黑树](#红黑树)
* [1. 左旋转](#1-左旋转)
* [2. 右旋转](#2-右旋转)
* [3. 颜色转换](#3-颜色转换)
* [4. 插入](#4-插入)
* [5. 分析](#5-分析)
* [散列表](#散列表)
* [1. 散列函数](#1-散列函数)
* [2. 拉链法](#2-拉链法)
* [3. 线性探测法](#3-线性探测法)
* [小结](#小结)
* [1. 符号表算法比较](#1-符号表算法比较)
* [2. Java 的符号表实现](#2-java-的符号表实现)
* [3. 稀疏向量乘法](#3-稀疏向量乘法)
<!-- GFM-TOC -->
# 前言
@ -209,15 +243,15 @@ public class BinarySearchOrderedST<Key extends Comparable<Key>, Value> implement
# 二叉查找树
**二叉树** 是一个空链接或者是一个有左右两个链接的节点每个链接都指向一颗子二叉树
**二叉树** 是一个空链接或者是一个有左右两个链接的节点每个链接都指向一颗子二叉树
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c11528f6-fc71-4a2b-8d2f-51b8954c38f1.jpg" width="180"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c11528f6-fc71-4a2b-8d2f-51b8954c38f1.jpg" width="180"/> </div><br>
**二叉查找树** BST是一颗二叉树并且每个节点的值都大于等于其左子树中的所有节点的值而小于等于右子树的所有节点的值
**二叉查找树** BST是一颗二叉树并且每个节点的值都大于等于其左子树中的所有节点的值而小于等于右子树的所有节点的值
BST 有一个重要性质就是它的中序遍历结果递增排序
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ef552ae3-ae0d-4217-88e6-99cbe8163f0c.jpg" width="200"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ef552ae3-ae0d-4217-88e6-99cbe8163f0c.jpg" width="200"/> </div><br>
基本数据结构
@ -291,7 +325,7 @@ private Value get(Node x, Key key) {
当插入的键不存在于树中需要创建一个新节点并且更新上层节点的链接指向该节点使得该节点正确地链接到树中
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/58b70113-3876-49af-85a9-68eb00a72d59.jpg" width="200"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/58b70113-3876-49af-85a9-68eb00a72d59.jpg" width="200"/> </div><br>
```java
@Override
@ -320,11 +354,11 @@ private Node put(Node x, Key key, Value value) {
最好的情况下树是完全平衡的每条空链接和根节点的距离都为 logN
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c395a428-827c-405b-abd7-8a069316f583.jpg" width="200"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c395a428-827c-405b-abd7-8a069316f583.jpg" width="200"/> </div><br>
在最坏的情况下树的高度为 N
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/5ea609cb-8ad4-4c4c-aee6-45a40a81794a.jpg" width="200"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/5ea609cb-8ad4-4c4c-aee6-45a40a81794a.jpg" width="200"/> </div><br>
## 4. floor()
@ -402,7 +436,7 @@ private Node min(Node x) {
令指向最小节点的链接指向最小节点的右子树
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/31b7e8de-ed11-4f69-b5fd-ba454120ac31.jpg" width="450"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/31b7e8de-ed11-4f69-b5fd-ba454120ac31.jpg" width="450"/> </div><br>
```java
public void deleteMin() {
@ -423,7 +457,7 @@ public Node deleteMin(Node x) {
- 如果待删除的节点只有一个子树 那么只需要让指向待删除节点的链接指向唯一的子树即可
- 否则让右子树的最小节点替换该节点
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/23b9d625-ef28-42b5-bb22-d7aedd007e16.jpg" width="400"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/23b9d625-ef28-42b5-bb22-d7aedd007e16.jpg" width="400"/> </div><br>
```java
public void delete(Key key) {
@ -486,7 +520,7 @@ private List<Key> keys(Node x, Key l, Key h) {
2-3 查找树引入了 2- 节点和 3- 节点目的是为了让树平衡一颗完美平衡的 2-3 查找树的所有空链接到根节点的距离应该是相同的
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1097658b-c0e6-4821-be9b-25304726a11c.jpg" width="160px"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1097658b-c0e6-4821-be9b-25304726a11c.jpg" width="160px"/> </div><br>
## 1. 插入操作
@ -496,11 +530,11 @@ private List<Key> keys(Node x, Key l, Key h) {
- 如果插入到 2- 节点上那么直接将新节点和原来的节点组成 3- 节点即可
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0c6f9930-8704-4a54-af23-19f9ca3e48b0.jpg" width="350"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0c6f9930-8704-4a54-af23-19f9ca3e48b0.jpg" width="350"/> </div><br>
- 如果是插入到 3- 节点上就会产生一个临时 4- 节点时需要将 4- 节点分裂成 3 2- 节点并将中间的 2- 节点移到上层节点中如果上移操作继续产生临时 4- 节点则一直进行分裂上移直到不存在临时 4- 节点
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7002c01b-1ed5-475a-9e5f-5fc8a4cdbcc0.jpg" width="460"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7002c01b-1ed5-475a-9e5f-5fc8a4cdbcc0.jpg" width="460"/> </div><br>
## 2. 性质
@ -512,7 +546,7 @@ private List<Key> keys(Node x, Key l, Key h) {
红黑树是 2-3 查找树但它不需要分别定义 2- 节点和 3- 节点而是在普通的二叉查找树之上为节点添加颜色指向一个节点的链接颜色如果为红色那么这个节点和上层节点表示的是一个 3- 节点而黑色则是普通链接
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f1912ba6-6402-4321-9aa8-13d32fd121d1.jpg" width="240"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f1912ba6-6402-4321-9aa8-13d32fd121d1.jpg" width="240"/> </div><br>
红黑树具有以下性质
@ -521,7 +555,7 @@ private List<Key> keys(Node x, Key l, Key h) {
画红黑树时可以将红链接画平
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f5cb6028-425d-4939-91eb-cca9dd6b6c6c.jpg" width="220"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f5cb6028-425d-4939-91eb-cca9dd6b6c6c.jpg" width="220"/> </div><br>
```java
public class RedBlackBST<Key extends Comparable<Key>, Value> extends BST<Key, Value> {
@ -541,7 +575,7 @@ public class RedBlackBST<Key extends Comparable<Key>, Value> extends BST<Key, Va
因为合法的红链接都为左链接如果出现右链接为红链接那么就需要进行左旋转操作
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f4d534ab-0092-4a81-9e5b-ae889b9a72be.jpg" width="480"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f4d534ab-0092-4a81-9e5b-ae889b9a72be.jpg" width="480"/> </div><br>
```java
public Node rotateLeft(Node h) {
@ -560,7 +594,7 @@ public Node rotateLeft(Node h) {
进行右旋转是为了转换两个连续的左红链接这会在之后的插入过程中探讨
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/63c8ffea-a9f2-4ebe-97d1-d71be71246f9.jpg" width="480"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/63c8ffea-a9f2-4ebe-97d1-d71be71246f9.jpg" width="480"/> </div><br>
```java
public Node rotateRight(Node h) {
@ -579,7 +613,7 @@ public Node rotateRight(Node h) {
一个 4- 节点在红黑树中表现为一个节点的左右子节点都是红色的分裂 4- 节点除了需要将子节点的颜色由红变黑之外同时需要将父节点的颜色由黑变红 2-3 树的角度看就是将中间节点移到上层节点
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/094b279a-b2db-4be7-87a3-b2a039c7448e.jpg" width="270"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/094b279a-b2db-4be7-87a3-b2a039c7448e.jpg" width="270"/> </div><br>
```java
void flipColors(Node h) {
@ -597,7 +631,7 @@ void flipColors(Node h) {
- 如果左子节点是红色的而且左子节点的左子节点也是红色的进行右旋转
- 如果左右子节点均为红色的进行颜色转换
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4c457532-550b-4eca-b881-037b84b4934b.jpg" width="430"/>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4c457532-550b-4eca-b881-037b84b4934b.jpg" width="430"/> </div><br>
```java
@Override
@ -722,7 +756,7 @@ public class Transaction {
对于 N 个键M 条链表 (N>M)如果哈希函数能够满足均匀性的条件每条链表的大小趋向于 N/M因此未命中的查找和插入操作所需要的比较次数为 \~N/M
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/cbbfe06c-f0cb-47c4-bf7b-2780aebd98b2.png" width="330px">
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/cbbfe06c-f0cb-47c4-bf7b-2780aebd98b2.png" width="330px"> </div><br>
## 3. 线性探测法
@ -731,7 +765,7 @@ public class Transaction {
使用线性探测法数组的大小 M 应当大于键的个数 NM>N)
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0dbc4f7d-05c9-4aae-8065-7b7ea7e9709e.gif" width="350px">
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0dbc4f7d-05c9-4aae-8065-7b7ea7e9709e.gif" width="350px"> </div><br>
```java
public class LinearProbingHashST<Key, Value> implements UnorderedST<Key, Value> {
@ -833,7 +867,7 @@ public void delete(Key key) {
线性探测法的成本取决于连续条目的长度连续条目也叫聚簇当聚簇很长时在查找和插入时也需要进行很多次探测例如下图中 2\~4 位置就是一个聚簇
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ace20410-f053-4c4a-aca4-2c603ff11bbe.png" width="340px">
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ace20410-f053-4c4a-aca4-2c603ff11bbe.png" width="340px"> </div><br>
α = N/M α 称为使用率理论证明 α 小于 1/2 时探测的预计次数只在 1.5 2.5 之间为了保证散列表的性能应当调整数组的大小使得 α [1/4, 1/2] 之间
@ -904,3 +938,10 @@ public class SparseVector {
}
}
```
<div align="center"><img width="320px" src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/githubio/公众号二维码-1.png"></img></div>