Skip to content

Commit b40a9d7

Browse files
committed
更新文档
1 parent 0f084df commit b40a9d7

20 files changed

Lines changed: 131 additions & 162 deletions

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222

2323
![img](https://raw.githubusercontent.com/dunwu/images/dev/snap/20200702071922.png)
2424

25-
- [算法概述](docs/overview.md)
26-
- [复杂度分析](docs/复杂度分析.md)
27-
- [数组和链表](docs/数组和链表.md)
28-
- [栈和队列](docs/栈和队列.md)
25+
- [数据结构和算法指南](docs/数据结构和算法指南.md)
26+
- [复杂度分析](docs/复杂度分析.md) - 关键词:**`时间复杂度`****`空间复杂度`****`大 O 表示法`****`复杂度量级`**
27+
- [数组和链表](docs/数组和链表.md) - 关键词:**`线性表`****`一维数组`****`多维数组`****`随机访问`****`单链表`****`双链表`****`循环链表`**
28+
- [栈和队列](docs/栈和队列.md) - 关键词:**`先进后出`****`后进先出`****`循环队列`**
2929
- [线性表的查找](docs/线性表的查找.md)
3030
- [线性表的排序](docs/线性表的排序.md)
3131
- [跳表](docs/跳表.md)

assets/数据结构和算法.xmind

3.15 KB
Binary file not shown.
File renamed without changes.
41.6 KB
Binary file not shown.
46.7 KB
Binary file not shown.

docs/B+树.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ B+树是在二叉查找树的基础上进行了改造:树中的节点并不存
66

77

88

9-
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220311092926.jpg)
9+
![img](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220311092926.jpg)
1010

1111
改造之后,如果我们要求某个区间的数据。我们只需要拿区间的起始值,在树中进行查找,当查找到某个叶子节点之后,我们再顺着链表往后遍历,直到链表中的结点数据值大于区间的终止值为止。所有遍历到的数据,就是符合区间值的所有数据。
1212

13-
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220311092929.jpg)
13+
![img](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220311092929.jpg)
1414

1515
但是,我们要为几千万、上亿的数据构建索引,如果将索引存储在内存中,尽管内存访问的速度非常快,查询的效率非常高,但是,占用的内存会非常多。
1616

docs/LSM树.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ LSM 树就是根据这个思路设计了这样一个机制:当数据写入时
1717

1818
可以参考两个有序链表归并排序的过程,将 C0 树和 C1 树的所有叶子节点中存储的数据,看作是两个有序链表,那滚动合并问题就变成了我们熟悉的两个有序链表的归并问题。不过由于涉及磁盘操作,那为了提高写入效率和检索效率,我们还需要针对磁盘的特性,在一些归并细节上进行优化。
1919

20-
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220316105440.png)
20+
![img](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220316105440.png)
2121

2222
由于磁盘具有顺序读写效率高的特性,因此,为了提高 C1 树中节点的读写性能,除了根节点以外的节点都要尽可能地存放到连续的块中,让它们能作为一个整体单位来读写。这种包含多个节点的块就叫作多页块(Multi-Pages Block)。
2323

@@ -29,7 +29,7 @@ LSM 树就是根据这个思路设计了这样一个机制:当数据写入时
2929

3030
第四步,重复第三步,直到遍历完 C0 树和 C1 树的所有叶子节点,并将所有的归并结果写入到磁盘。这个时候,我们就可以同时删除 C0 树和 C1 树中被处理过的叶子节点。这样就完成了滚动归并的过程。
3131

32-
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220316110736.png)
32+
![img](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220316110736.png)
3333

3434
### LSM 树是如何检索
3535

@@ -58,7 +58,7 @@ WAL 技术保存和恢复数据的具体步骤如下:
5858
3. 系统会周期性地检查内存中的数据是否都被处理完了(比如,被删除或者写入磁盘),并且生成对应的检查点(Check Point)记录在磁盘中。然后,我们就可以随时删除被处理完的数据了。这样一来,log 文件就不会无限增长了。
5959
4. 系统崩溃重启,我们只需要从磁盘中读取检查点,就能知道最后一次成功处理的数据在 log 文件中的位置。接下来,我们就可以把这个位置之后未被处理的数据,从 log 文件中读出,然后重新加载到内存中。
6060

61-
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220316104837.png)
61+
![img](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220316104837.png)
6262

6363
## 参考资料
6464

docs/overview.md

Lines changed: 0 additions & 33 deletions
This file was deleted.

docs/哈希表.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
**哈希表用的是数组支持按照下标随机访问数据的特性,所以哈希表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有哈希表**
2222

23-
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220320201844.png)
23+
![img](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220320201844.png)
2424

2525
哈希表通过散列函数把元素的键值映射为下标,然后将数据存储在数组中对应下标的位置。按照键值查询元素时,用同样的散列函数,将键值转化数组下标,从对应的数组下标的位置取数据。
2626

@@ -80,13 +80,13 @@
8080

8181
**线性探测**(Linear Probing):当我们往哈希表中插入数据时,如果某个数据经过散列函数散列之后,存储位置已经被占用了,我们就从当前位置开始,依次往后查找,看是否有空闲位置,直到找到为止。
8282

83-
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220310110920.jpg)
83+
![img](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220310110920.jpg)
8484

8585
对于使用线性探测法解决冲突的哈希表,删除操作稍微有些特别。我们不能单纯地把要删除的元素设置为空。这是为什么呢?在查找的时候,一旦我们通过线性探测方法,找到一个空闲位置,我们就可以认定哈希表中不存在这个数据。但是,如果这个空闲位置是我们后来删除的,就会导致原来的查找算法失效。本来存在的数据,会被认定为不存在。这个问题如何解决呢?
8686

8787
我们可以将删除的元素,特殊标记为 deleted。当线性探测查找的时候,遇到标记为 deleted 的空间,并不是停下来,而是继续往下探测。
8888

89-
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220310111103.jpg)
89+
![img](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220310111103.jpg)
9090

9191
线性探测法其实存在很大问题。当哈希表中插入的数据越来越多时,散列冲突发生的可能性就会越来越大,空闲位置会越来越少,线性探测的时间就会越来越久。极端情况下,我们可能需要探测整个哈希表,所以最坏情况下的时间复杂度为 O(n)。同理,在删除和查找时,也有可能会线性探测整张哈希表,才能找到要查找或者删除的数据。
9292

@@ -98,7 +98,7 @@
9898

9999
**基于链表的散列冲突处理方法比较适合存储大对象、大数据量的哈希表,而且,比起开放寻址法,它更加灵活,支持更多的优化策略,比如用红黑树代替链表**
100100

101-
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220310111320.jpg)
101+
![img](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220310111320.jpg)
102102

103103
当插入的时候,我们只需要通过散列函数计算出对应的散列槽位,将其插入到对应链表中即可,所以插入的时间复杂度是 O(1)。当查找、删除一个元素时,我们同样通过散列函数计算出对应的槽,然后遍历链表查找或者删除。那查找或删除操作的时间复杂度是多少呢?
104104

docs/图.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
如果图的边没有方向性,则被成为无向图。
2424

25-
![](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220314093554.jpg)
25+
![img](https://raw.githubusercontent.com/dunwu/images/dev/snap/20220314093554.jpg)
2626

2727
## 图的基本操作
2828

0 commit comments

Comments
 (0)