Skip to content

Commit 1583edb

Browse files
authored
Merge pull request #2 from CyC2018/master
updating
2 parents 6998eb7 + 4f5c749 commit 1583edb

File tree

6 files changed

+76
-64
lines changed

6 files changed

+76
-64
lines changed

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ Google 开源项目的代码风格规范。
147147

148148
**授权相关**
149149

150-
虽然没有加开源协议,但是默认允许非商业使用
150+
虽然没有加开源协议,但是允许非商业性使用
151151

152152
转载使用请注明出处,谢谢!
153153

@@ -157,15 +157,15 @@ Google 开源项目的代码风格规范。
157157

158158
进行 Markdown 文档转换是因为 Github 使用的 GFM 不支持 MathJax 公式和 TOC 标记,所以需要替换 MathJax 公式为 CodeCogs 的云服务和重新生成 TOC 目录。
159159

160-
这里提供了笔者实现的 GFM 文档转换工具的下载[GFM-Converter](https://github.com/CyC2018/GFM-Converter)
160+
这里提供了笔者实现的 GFM 文档转换工具的链接[GFM-Converter](https://github.com/CyC2018/GFM-Converter)
161161

162162
**排版指南**
163163

164164
笔记内容按照 [中文文案排版指北](http://mazhuang.org/wiki/chinese-copywriting-guidelines/) 进行排版,以保证内容的可读性。
165165

166166
笔记不使用 `![]()` 这种方式来引用图片,而是用 `<img>` 标签。一方面是为了能够控制图片以合适的大小显示,另一方面是因为 GFM 不支持 `<center> ![]() </center>` 让图片居中显示,只能使用 `<div align="center"> <img src=""/> </div>` 达到居中的效果。
167167

168-
这里提供了笔者实现的中英混排文档在线排版工具[Text-Typesetting](https://github.com/CyC2018/Markdown-Typesetting)
168+
这里提供了笔者实现的中英混排文档在线排版工具的链接[Text-Typesetting](https://github.com/CyC2018/Markdown-Typesetting)
169169

170170
**声明**
171171

notes/Socket.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* [poll](#poll)
1313
* [epoll](#epoll)
1414
* [select 和 poll 比较](#select-和-poll-比较)
15-
* [eopll 工作模式](#eopll-工作模式)
15+
* [epoll 工作模式](#epoll-工作模式)
1616
* [应用场景](#应用场景)
1717
* [参考资料](#参考资料)
1818
<!-- GFM-TOC -->
@@ -303,7 +303,7 @@ poll 和 select 在速度上都很慢。
303303

304304
几乎所有的系统都支持 select,但是只有比较新的系统支持 poll。
305305

306-
## eopll 工作模式
306+
## epoll 工作模式
307307

308308
epoll_event 有两种触发模式:LT(level trigger)和 ET(edge trigger)。
309309

notes/数据库系统原理.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
* [快照读与当前读](#快照读与当前读)
2626
* [六、Next-Key Locks](#六next-key-locks)
2727
* [Record Locks](#record-locks)
28-
* [Grap Locks](#grap-locks)
28+
* [Gap Locks](#gap-locks)
2929
* [Next-Key Locks](#next-key-locks)
3030
* [七、关系数据库设计理论](#七关系数据库设计理论)
3131
* [函数依赖](#函数依赖)

notes/算法.md

+32-26
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
* [堆排序](#堆排序)
2525
* [小结](#小结)
2626
* [六、查找](#六查找)
27-
* [链表实现无序符号表](#链表实现无序符号表)
28-
* [二分查找实现有序符号表](#二分查找实现有序符号表)
27+
* [初级实现](#初级实现)
2928
* [二叉查找树](#二叉查找树)
3029
* [2-3 查找树](#2-3-查找树)
3130
* [红黑树](#红黑树)
@@ -1178,7 +1177,9 @@ public interface OrderedST<Key extends Comparable<Key>, Value> {
11781177
}
11791178
```
11801179

1181-
## 链表实现无序符号表
1180+
## 初级实现
1181+
1182+
### 1. 链表实现无序符号表
11821183

11831184
```java
11841185
public class ListUnorderedST<Key, Value> implements UnorderedST<Key, Value> {
@@ -1253,7 +1254,7 @@ public class ListUnorderedST<Key, Value> implements UnorderedST<Key, Value> {
12531254
}
12541255
```
12551256

1256-
## 二分查找实现有序符号表
1257+
### 2. 二分查找实现有序符号表
12571258

12581259
使用一对平行数组,一个存储键一个存储值。
12591260

@@ -1308,7 +1309,7 @@ public class BinarySearchOrderedST<Key extends Comparable<Key>, Value> implement
13081309
@Override
13091310
public void put(Key key, Value value) {
13101311
int index = rank(key);
1311-
// 如果找到已经存在的节点键位 key,就更新这个节点的值为 value
1312+
// 如果找到已经存在的节点键为 key,就更新这个节点的值为 value
13121313
if (index < N && keys[index].compareTo(key) == 0) {
13131314
values[index] = value;
13141315
return;
@@ -1391,14 +1392,14 @@ public class BST<Key extends Comparable<Key>, Value> implements OrderedST<Key, V
13911392
return 0;
13921393
return x.N;
13931394
}
1394-
1395+
13951396
protected void recalculateSize(Node x) {
13961397
x.N = size(x.left) + size(x.right) + 1;
13971398
}
13981399
}
13991400
```
14001401

1401-
(为了方便绘图,二叉树的空链接不画出来。)
1402+
(为了方便绘图,下文中二叉树的空链接不画出来。)
14021403

14031404
### 1. get()
14041405

@@ -1427,7 +1428,7 @@ private Value get(Node x, Key key) {
14271428

14281429
### 2. put()
14291430

1430-
当插入的键不存在于树中,需要创建一个新节点,并且更新上层节点的链接使得该节点正确链接到树中
1431+
当插入的键不存在于树中,需要创建一个新节点,并且更新上层节点的链接指向该节点,使得该节点正确地链接到树中
14311432

14321433
<div align="center"> <img src="../pics//107a6a2b-f15b-4cad-bced-b7fb95258c9c.png" width="200"/> </div><br>
14331434

@@ -1454,7 +1455,9 @@ private Node put(Node x, Key key, Value value) {
14541455

14551456
### 3. 分析
14561457

1457-
二叉查找树的算法运行时间取决于树的形状,而树的形状又取决于键被插入的先后顺序。最好的情况下树是完全平衡的,每条空链接和根节点的距离都为 logN。
1458+
二叉查找树的算法运行时间取决于树的形状,而树的形状又取决于键被插入的先后顺序。
1459+
1460+
最好的情况下树是完全平衡的,每条空链接和根节点的距离都为 logN。
14581461

14591462
<div align="center"> <img src="../pics//4d741402-344d-4b7c-be01-e57184bcad0e.png" width="200"/> </div><br>
14601463

@@ -1467,8 +1470,7 @@ private Node put(Node x, Key key, Value value) {
14671470
floor(key):小于等于键的最大键
14681471

14691472
- 如果键小于根节点的键,那么 floor(key) 一定在左子树中;
1470-
- 如果键大于根节点的键,需要先判断右子树中是否存在 floor(key),如果存在就找到,否则根节点就是 floor(key)。
1471-
1473+
- 如果键大于根节点的键,需要先判断右子树中是否存在 floor(key),如果存在就返回,否则根节点就是 floor(key)。
14721474

14731475
```java
14741476
public Key floor(Key key) {
@@ -1497,7 +1499,7 @@ rank(key) 返回 key 的排名。
14971499

14981500
- 如果键和根节点的键相等,返回左子树的节点数;
14991501
- 如果小于,递归计算在左子树中的排名;
1500-
- 如果大于,递归计算在右子树中的排名,并加上左子树的节点数,再加上 1(根节点)。
1502+
- 如果大于,递归计算在右子树中的排名,加上左子树的节点数,再加上 1(根节点)。
15011503

15021504
```java
15031505
@Override
@@ -1793,15 +1795,15 @@ private Node put(Node x, Key key, Value value) {
17931795

17941796
- 一致性:相等的键应当有相等的 hash 值,两个键相等表示调用 equals() 返回的值相等。
17951797
- 高效性:计算应当简便,有必要的话可以把 hash 值缓存起来,在调用 hash 函数时直接返回。
1796-
- 均匀性:所有键的 hash 值应当均匀地分布到 [0, M-1] 之间,这个条件至关重要,直接影响到散列表的性能
1798+
- 均匀性:所有键的 hash 值应当均匀地分布到 [0, M-1] 之间,如果不能满足这个条件,有可能产生很多冲突,从而导致散列表的性能下降
17971799

17981800
除留余数法可以将整数散列到 [0, M-1] 之间,例如一个正整数 k,计算 k%M 既可得到一个 [0, M-1] 之间的 hash 值。注意 M 必须是一个素数,否则无法利用键包含的所有信息。例如 M 为 10<sup>k</sup>,那么只能利用键的后 k 位。
17991801

1800-
对于其它数,可以将其转换成整数的形式,然后利用除留余数法。例如对于浮点数,可以将其表示成二进制形式,然后使用二进制形式的整数值进行除留余数法
1802+
对于其它数,可以将其转换成整数的形式,然后利用除留余数法。例如对于浮点数,可以将其的二进制形式转换成整数
18011803

1802-
对于有多部分组合的键,每部分都需要计算 hash 值,并且最后合并时需要让每部分 hash 值都具有同等重要的地位。可以将该键看成 R 进制的整数,键中每部分都具有不同的权值
1804+
对于多部分组合的类型,每个部分都需要计算 hash 值,这些 hash 值都具有同等重要的地位。为了达到这个目的,可以将该类型看成 R 进制的整数,每个部分都具有不同的权值
18031805

1804-
例如,字符串的散列函数实现如下
1806+
例如,字符串的散列函数实现如下
18051807

18061808
```java
18071809
int hash = 0;
@@ -1823,7 +1825,7 @@ Java 中的 hashCode() 实现了 hash 函数,但是默认使用对象的内存
18231825
int hash = (x.hashCode() & 0x7fffffff) % M;
18241826
```
18251827

1826-
使用 Java 自带的 HashMap 等自带的哈希表实现时,只需要去实现 Key 类型的 hashCode() 函数即可。Java 规定 hashCode() 能够将键均匀分布于所有的 32 位整数,Java 中的 String、Integer 等对象的 hashCode() 都能实现这一点。以下展示了自定义类型如何实现 hashCode()
1828+
使用 Java 自带的 HashMap 等自带的哈希表实现时,只需要去实现 Key 类型的 hashCode() 函数即可。Java 规定 hashCode() 能够将键均匀分布于所有的 32 位整数,Java 中的 String、Integer 等对象的 hashCode() 都能实现这一点。以下展示了自定义类型如何实现 hashCode()
18271829

18281830
```java
18291831
public class Transaction {
@@ -1850,15 +1852,19 @@ public class Transaction {
18501852

18511853
### 2. 基于拉链法的散列表
18521854

1853-
拉链法使用链表来存储 hash 值相同的键,从而解决冲突。此时查找需要分两步,首先查找 Key 所在的链表,然后在链表中顺序查找。
1855+
拉链法使用链表来存储 hash 值相同的键,从而解决冲突。
18541856

1855-
<div align="center"> <img src="../pics//b4252c85-6fb0-4995-9a68-a1a5925fbdb1.png" width="300"/> </div><br>
1857+
查找需要分两步,首先查找 Key 所在的链表,然后在链表中顺序查找。
18561858

1857-
对于 N 个键,M 条链表 (N>M),如果哈希函数能够满足均匀性的条件,每条链表的大小趋向于 N/M,因此未命中的查找和插入操作所需要的比较次数为 \~N/M。
1859+
对于 N 个键,M 条链表 (N>M),如果 hash 函数能够满足均匀性的条件,每条链表的大小趋向于 N/M,因此未命中的查找和插入操作所需要的比较次数为 \~N/M。
1860+
1861+
<div align="center"> <img src="../pics//b4252c85-6fb0-4995-9a68-a1a5925fbdb1.png" width="300"/> </div><br>
18581862

18591863
### 3. 基于线性探测法的散列表
18601864

1861-
线性探测法使用空位来解决冲突,当冲突发生时,向前探测一个空位来存储冲突的键。使用线性探测法,数组的大小 M 应当大于键的个数 N(M>N)。
1865+
线性探测法使用空位来解决冲突,当冲突发生时,向前探测一个空位来存储冲突的键。
1866+
1867+
使用线性探测法,数组的大小 M 应当大于键的个数 N(M>N)。
18621868

18631869
<div align="center"> <img src="../pics//dbb8516d-37ba-4e2c-b26b-eefd7de21b45.png" width="400"/> </div><br>
18641870

@@ -1962,9 +1968,7 @@ public void delete(Key key) {
19621968

19631969
<div align="center"> <img src="../pics//386cd64f-7a9d-40e6-8c55-22b90ee2d258.png" width="400"/> </div><br>
19641970

1965-
α = N/M,把 α 称为利用率。理论证明,当 α 小于 1/2 时探测的预计次数只在 1.5 到 2.5 之间。
1966-
1967-
为了保证散列表的性能,应当调整数组的大小,使得 α 在 [1/4, 1/2] 之间。
1971+
α = N/M,把 α 称为使用率。理论证明,当 α 小于 1/2 时探测的预计次数只在 1.5 到 2.5 之间。为了保证散列表的性能,应当调整数组的大小,使得 α 在 [1/4, 1/2] 之间。
19681972

19691973
```java
19701974
private void resize() {
@@ -2044,7 +2048,9 @@ public class SparseVector {
20442048
2. 将 1 个圆盘从 from -> to
20452049
3. 将 n-1 个圆盘从 buffer -> to
20462050

2047-
如果只有一个圆盘,那么只需要进行一次移动操作,从上面的移动步骤可以知道,n 圆盘需要移动 (n-1)+1+(n-1) = 2n-1 次。
2051+
如果只有一个圆盘,那么只需要进行一次移动操作。
2052+
2053+
从上面的讨论可以知道,n 圆盘需要移动 (n-1)+1+(n-1) = 2n-1 次。
20482054

20492055
<div align="center"> <img src="../pics//54f1e052-0596-4b5e-833c-e80d75bf3f9b.png" width="300"/> </div><br>
20502056

@@ -2093,7 +2099,7 @@ from H1 to H3
20932099
- c : 40
20942100
- d : 80
20952101

2096-
可以将每种字符转换成二进制编码,例如将 a 转换为 00,b 转换为 01,c 转换为 10,d 转换为 11。这是最简单的一种编码方式,没有考虑各个字符的权值(出现频率)。而哈夫曼编码能让出现频率最大的字符编码最短,从而保证最终的编码长度最短
2102+
可以将每种字符转换成二进制编码,例如将 a 转换为 00,b 转换为 01,c 转换为 10,d 转换为 11。这是最简单的一种编码方式,没有考虑各个字符的权值(出现频率)。而哈夫曼编码能让出现频率最高的字符的编码最短,从而保证整体的编码长度最短
20972103

20982104
首先生成一颗哈夫曼树,每次生成过程中选取频率最少的两个节点,生成一个新节点作为它们的父节点,并且新节点的频率为两个节点的和。选取频率最少的原因是,生成过程使得先选取的节点在树的最底层,那么需要的编码长度更长,频率更少可以使得总编码长度更少。
20992105

0 commit comments

Comments
 (0)