auto commit

This commit is contained in:
CyC2018 2019-12-06 00:29:51 +08:00
parent 06199c5364
commit 8ca2b6426f
115 changed files with 522 additions and 522 deletions

View File

@ -13,7 +13,7 @@
<br>
<div align="center">
<img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/githubio/LogoMakr_0zpEzN.png" width="200px">
<img src="assets/LogoMakr_0zpEzN.png" width="200px">
</div>
@ -85,7 +85,7 @@
<div align="center">
<a href="https://www.nowcoder.com/discuss/137593?from=cyc_github"> 我的面经 </a> / <a href="https://cyc2018.github.io"> 我的简历 </a> / <a href="https://github.com/CyC2018/Markdown-Resume"> 简历模版 </a> / <a href="https://github.com/CyC2018/Job-Recommend"> 内推 </a> / <a href="https://xiaozhuanlan.com/CyC2018"> 专栏 </a> / <a href="assets/QQ2群.png"> QQ </a>
<br><br>
<img width="320px" src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/githubio/公众号二维码-2.png"></img>
<img width="320px" src="assets/公众号二维码-2.png"></img>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -10,13 +10,13 @@
<!--<div align="center"><img src="https://latex.codecogs.com/gif.latex?f(n)=\left\{\begin{array}{rcl}0&&{n=0}\\1&&{n=1}\\f(n-1)+f(n-2)&&{n>1}\end{array}\right." class="mathjax-pic"/></div> <br> -->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/45be9587-6069-4ab7-b9ac-840db1a53744.jpg" width="330px"> </div><br>
<div align="center"> <img src="pics/45be9587-6069-4ab7-b9ac-840db1a53744.jpg" width="330px"> </div><br>
## 解题思路
如果使用递归求解会重复计算一些子问题例如计算 f(4) 需要计算 f(3) f(2)计算 f(3) 需要计算 f(2) f(1)可以看到 f(2) 被重复计算了
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c13e2a3d-b01c-4a08-a69b-db2c4e821e09.png" width="350px"/> </div><br>
<div align="center"> <img src="pics/c13e2a3d-b01c-4a08-a69b-db2c4e821e09.png" width="350px"/> </div><br>
递归是将一个问题划分成多个子问题求解动态规划也是如此但是动态规划会把子问题的解缓存起来从而避免重复求解子问题

View File

@ -8,23 +8,23 @@
我们可以用 2\*1 的小矩形横着或者竖着去覆盖更大的矩形请问用 n 2\*1 的小矩形无重叠地覆盖一个 2\*n 的大矩形总共有多少种方法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b903fda8-07d0-46a7-91a7-e803892895cf.gif" width="100px"> </div><br>
<div align="center"> <img src="pics/b903fda8-07d0-46a7-91a7-e803892895cf.gif" width="100px"> </div><br>
## 解题思路
n 1 只有一种覆盖方法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f6e146f1-57ad-411b-beb3-770a142164ef.png" width="100px"> </div><br>
<div align="center"> <img src="pics/f6e146f1-57ad-411b-beb3-770a142164ef.png" width="100px"> </div><br>
n 2 有两种覆盖方法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/fb3b8f7a-4293-4a38-aae1-62284db979a3.png" width="200px"> </div><br>
<div align="center"> <img src="pics/fb3b8f7a-4293-4a38-aae1-62284db979a3.png" width="200px"> </div><br>
要覆盖 2\*n 的大矩形可以先覆盖 2\*1 的矩形再覆盖 2\*(n-1) 的矩形或者先覆盖 2\*2 的矩形再覆盖 2\*(n-2) 的矩形而覆盖 2\*(n-1) 2\*(n-2) 的矩形可以看成子问题该问题的递推公式如下
<!-- <div align="center"><img src="https://latex.codecogs.com/gif.latex?f(n)=\left\{\begin{array}{rcl}1&&{n=1}\\2&&{n=2}\\f(n-1)+f(n-2)&&{n>1}\end{array}\right." class="mathjax-pic"/></div> <br> -->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/508c6e52-9f93-44ed-b6b9-e69050e14807.jpg" width="370px"> </div><br>
<div align="center"> <img src="pics/508c6e52-9f93-44ed-b6b9-e69050e14807.jpg" width="370px"> </div><br>
```java
public int RectCover(int n) {

View File

@ -8,21 +8,21 @@
一只青蛙一次可以跳上 1 级台阶也可以跳上 2 求该青蛙跳上一个 n 级的台阶总共有多少种跳法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9dae7475-934f-42e5-b3b3-12724337170a.png" width="380px"> </div><br>
<div align="center"> <img src="pics/9dae7475-934f-42e5-b3b3-12724337170a.png" width="380px"> </div><br>
## 解题思路
n = 1 只有一种跳法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/72aac98a-d5df-4bfa-a71a-4bb16a87474c.png" width="250px"> </div><br>
<div align="center"> <img src="pics/72aac98a-d5df-4bfa-a71a-4bb16a87474c.png" width="250px"> </div><br>
n = 2 有两种跳法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1b80288d-1b35-4cd3-aa17-7e27ab9a2389.png" width="300px"> </div><br>
<div align="center"> <img src="pics/1b80288d-1b35-4cd3-aa17-7e27ab9a2389.png" width="300px"> </div><br>
n 阶台阶可以先跳 1 阶台阶再跳 n-1 阶台阶或者先跳 2 阶台阶再跳 n-2 阶台阶 n-1 n-2 阶台阶的跳法可以看成子问题该问题的递推公式为
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/508c6e52-9f93-44ed-b6b9-e69050e14807.jpg" width="350px"> </div><br>
<div align="center"> <img src="pics/508c6e52-9f93-44ed-b6b9-e69050e14807.jpg" width="350px"> </div><br>
```java
public int JumpFloor(int n) {

View File

@ -8,7 +8,7 @@
一只青蛙一次可以跳上 1 级台阶也可以跳上 2 ... 它也可以跳上 n 求该青蛙跳上一个 n 级的台阶总共有多少种跳法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/cd411a94-3786-4c94-9e08-f28320e010d5.png" width="380px"> </div><br>
<div align="center"> <img src="pics/cd411a94-3786-4c94-9e08-f28320e010d5.png" width="380px"> </div><br>
## 解题思路

View File

@ -6,13 +6,13 @@
把一个数组最开始的若干个元素搬到数组的末尾我们称之为数组的旋转输入一个非递减排序的数组的一个旋转输出旋转数组的最小元素
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0038204c-4b8a-42a5-921d-080f6674f989.png" width="210px"> </div><br>
<div align="center"> <img src="pics/0038204c-4b8a-42a5-921d-080f6674f989.png" width="210px"> </div><br>
## 解题思路
将旋转数组对半分可以得到一个包含最小元素的新旋转数组以及一个非递减排序的数组新的旋转数组的数组元素是原数组的一半从而将问题规模减少了一半这种折半性质的算法的时间复杂度为 O(logN)为了方便这里将 log<sub>2</sub>N 写为 logN
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/424f34ab-a9fd-49a6-9969-d76b42251365.png" width="300px"> </div><br>
<div align="center"> <img src="pics/424f34ab-a9fd-49a6-9969-d76b42251365.png" width="300px"> </div><br>
此时问题的关键在于确定对半分得到的两个数组哪一个是旋转数组哪一个是非递减数组我们很容易知道非递减数组的第一个元素一定小于等于最后一个元素

View File

@ -8,13 +8,13 @@
例如下面的矩阵包含了一条 bfce 路径
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1db1c7ea-0443-478b-8df9-7e33b1336cc4.png" width="200px"> </div><br>
<div align="center"> <img src="pics/1db1c7ea-0443-478b-8df9-7e33b1336cc4.png" width="200px"> </div><br>
## 解题思路
使用回溯法backtracking进行求解它是一种暴力搜索方法通过搜索所有可能的结果来求解问题回溯法在一次搜索结束时需要进行回溯回退将这一次搜索过程中设置的状态进行清除从而开始一次新的搜索过程例如下图示例中 f 开始下一步有 4 种搜索可能如果先搜索 b需要将 b 标记为已经使用防止重复使用在这一次搜索结束之后需要将 b 的已经使用状态清除并搜索 c
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/dc964b86-7a08-4bde-a3d9-e6ddceb29f98.png" width="200px"> </div><br>
<div align="center"> <img src="pics/dc964b86-7a08-4bde-a3d9-e6ddceb29f98.png" width="200px"> </div><br>
本题的输入是数组而不是矩阵二维数组因此需要先将数组转换成矩阵

View File

@ -12,7 +12,7 @@
<!--<div align="center"><img src="https://latex.codecogs.com/gif.latex?x^n=\left\{\begin{array}{rcl}(x*x)^{n/2}&&{n\%2=0}\\x*(x*x)^{n/2}&&{n\%2=1}\end{array}\right." class="mathjax-pic"/></div> <br>-->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/48b1d459-8832-4e92-938a-728aae730739.jpg" width="330px"> </div><br>
<div align="center"> <img src="pics/48b1d459-8832-4e92-938a-728aae730739.jpg" width="330px"> </div><br>
因为 (x\*x)<sup>n/2</sup> 可以通过递归求解并且每次递归 n 都减小一半因此整个算法的时间复杂度为 O(logN)

View File

@ -4,11 +4,11 @@
如果该节点不是尾节点那么可以直接将下一个节点的值赋给该节点然后令该节点指向下下个节点再删除下一个节点时间复杂度为 O(1)
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1176f9e1-3442-4808-a47a-76fbaea1b806.png" width="600"/> </div><br>
<div align="center"> <img src="pics/1176f9e1-3442-4808-a47a-76fbaea1b806.png" width="600"/> </div><br>
否则就需要先遍历链表找到节点的前一个节点然后让前一个节点指向 null时间复杂度为 O(N)
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4bf8d0ba-36f0-459e-83a0-f15278a5a157.png" width="600"/> </div><br>
<div align="center"> <img src="pics/4bf8d0ba-36f0-459e-83a0-f15278a5a157.png" width="600"/> </div><br>
综上如果进行 N 次操作那么大约需要操作节点的次数为 N-1+N=2N-1其中 N-1 表示 N-1 个不是尾节点的每个节点以 O(1) 的时间复杂度操作节点的总次数N 表示 1 个尾节点以 O(N) 的时间复杂度操作节点的总次数(2N-1)/N \~ 2因此该算法的平均时间复杂度为 O(1)

View File

@ -4,7 +4,7 @@
## 题目描述
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/17e301df-52e8-4886-b593-841a16d13e44.png" width="450"/> </div><br>
<div align="center"> <img src="pics/17e301df-52e8-4886-b593-841a16d13e44.png" width="450"/> </div><br>
## 解题描述

View File

@ -6,7 +6,7 @@
需要保证奇数和奇数偶数和偶数之间的相对位置不变这和书本不太一样
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d03a2efa-ef19-4c96-97e8-ff61df8061d3.png" width="200px"> </div><br>
<div align="center"> <img src="pics/d03a2efa-ef19-4c96-97e8-ff61df8061d3.png" width="200px"> </div><br>
## 解题思路

View File

@ -6,7 +6,7 @@
设链表的长度为 N设置两个指针 P1 P2先让 P1 移动 K 个节点则还有 N - K 个节点可以移动此时让 P1 P2 同时移动可以知道当 P1 移动到链表结尾时P2 移动到第 N - K 个节点处该位置就是倒数第 K 个节点
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6b504f1f-bf76-4aab-a146-a9c7a58c2029.png" width="500"/> </div><br>
<div align="center"> <img src="pics/6b504f1f-bf76-4aab-a146-a9c7a58c2029.png" width="500"/> </div><br>
```java
public ListNode FindKthToTail(ListNode head, int k) {

View File

@ -22,7 +22,7 @@
上面的等值没有很强的规律但是我们可以发现 y+z 就是圆环的总长度因此我们将上面的等式再分解x=(N-2)(y+z)+z这个等式左边是从起点x1 到环入口节点 y1 的长度而右边是在圆环中走过 (N-2) 再从相遇点 z1 再走过长度为 z 的长度此时我们可以发现如果让两个指针同时从起点 x1 和相遇点 z1 开始每次只走过一个距离那么最后他们会在环入口节点相遇
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/bb7fc182-98c2-4860-8ea3-630e27a5f29f.png" width="500"/> </div><br>
<div align="center"> <img src="pics/bb7fc182-98c2-4860-8ea3-630e27a5f29f.png" width="500"/> </div><br>
```java
public ListNode EntryNodeOfLoop(ListNode pHead) {

View File

@ -4,7 +4,7 @@
## 题目描述
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c094d2bc-ec75-444b-af77-d369dfb6b3b4.png" width="400"/> </div><br>
<div align="center"> <img src="pics/c094d2bc-ec75-444b-af77-d369dfb6b3b4.png" width="400"/> </div><br>
## 解题思路

View File

@ -4,7 +4,7 @@
## 题目描述
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/84a5b15a-86c5-4d8e-9439-d9fd5a4699a1.jpg" width="450"/> </div><br>
<div align="center"> <img src="pics/84a5b15a-86c5-4d8e-9439-d9fd5a4699a1.jpg" width="450"/> </div><br>
## 解题思路

View File

@ -4,7 +4,7 @@
## 题目描述
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0c12221f-729e-4c22-b0ba-0dfc909f8adf.jpg" width="300"/> </div><br>
<div align="center"> <img src="pics/0c12221f-729e-4c22-b0ba-0dfc909f8adf.jpg" width="300"/> </div><br>
## 解题思路

View File

@ -4,7 +4,7 @@
## 题目描述
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0c12221f-729e-4c22-b0ba-0dfc909f8adf.jpg" width="300"/> </div><br>
<div align="center"> <img src="pics/0c12221f-729e-4c22-b0ba-0dfc909f8adf.jpg" width="300"/> </div><br>
## 解题思路

View File

@ -6,7 +6,7 @@
下图的矩阵顺时针打印结果为1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/48517227-324c-4664-bd26-a2d2cffe2bfe.png" width="200px"> </div><br>
<div align="center"> <img src="pics/48517227-324c-4664-bd26-a2d2cffe2bfe.png" width="200px"> </div><br>
## 解题思路

View File

@ -24,7 +24,7 @@ Output:
(2, 3, 1, 0, 2, 5) 为例遍历到位置 4 该位置上的数为 2但是第 2 个位置上已经有一个 2 的值了因此可以知道 2 重复
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/643b6f18-f933-4ac5-aa7a-e304dbd7fe49.gif" width="350px"> </div><br>
<div align="center"> <img src="pics/643b6f18-f933-4ac5-aa7a-e304dbd7fe49.gif" width="350px"> </div><br>
```java

View File

@ -8,7 +8,7 @@
例如以下二叉树层次遍历的结果为1,2,3,4,5,6,7
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d5e838cf-d8a2-49af-90df-1b2a714ee676.jpg" width="250"/> </div><br>
<div align="center"> <img src="pics/d5e838cf-d8a2-49af-90df-1b2a714ee676.jpg" width="250"/> </div><br>
## 解题思路

View File

@ -8,7 +8,7 @@
例如下图是后序遍历序列 1,3,2 所对应的二叉搜索树
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/13454fa1-23a8-4578-9663-2b13a6af564a.jpg" width="150"/> </div><br>
<div align="center"> <img src="pics/13454fa1-23a8-4578-9663-2b13a6af564a.jpg" width="150"/> </div><br>
## 解题思路

View File

@ -8,7 +8,7 @@
下图的二叉树有两条和为 22 的路径10, 5, 7 10, 12
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ed77b0e6-38d9-4a34-844f-724f3ffa2c12.jpg" width="200"/> </div><br>
<div align="center"> <img src="pics/ed77b0e6-38d9-4a34-844f-724f3ffa2c12.jpg" width="200"/> </div><br>
## 解题思路

View File

@ -18,21 +18,21 @@ public class RandomListNode {
}
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/66a01953-5303-43b1-8646-0c77b825e980.png" width="300"/> </div><br>
<div align="center"> <img src="pics/66a01953-5303-43b1-8646-0c77b825e980.png" width="300"/> </div><br>
## 解题思路
第一步在每个节点的后面插入复制的节点
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/dfd5d3f8-673c-486b-8ecf-d2082107b67b.png" width="600"/> </div><br>
<div align="center"> <img src="pics/dfd5d3f8-673c-486b-8ecf-d2082107b67b.png" width="600"/> </div><br>
第二步对复制节点的 random 链接进行赋值
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/cafbfeb8-7dfe-4c0a-a3c9-750eeb824068.png" width="600"/> </div><br>
<div align="center"> <img src="pics/cafbfeb8-7dfe-4c0a-a3c9-750eeb824068.png" width="600"/> </div><br>
第三步拆分
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e151b5df-5390-4365-b66e-b130cd253c12.png" width="600"/> </div><br>
<div align="center"> <img src="pics/e151b5df-5390-4365-b66e-b130cd253c12.png" width="600"/> </div><br>
```java
public RandomListNode Clone(RandomListNode pHead) {

View File

@ -6,7 +6,7 @@
输入一棵二叉搜索树将该二叉搜索树转换成一个排序的双向链表要求不能创建任何新的结点只能调整树中结点指针的指向
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/05a08f2e-9914-4a77-92ef-aebeaecf4f66.jpg" width="400"/> </div><br>
<div align="center"> <img src="pics/05a08f2e-9914-4a77-92ef-aebeaecf4f66.jpg" width="400"/> </div><br>
## 解题思路

View File

@ -28,7 +28,7 @@ Given target = 20, return false.
该二维数组中的一个数小于它的数一定在其左边大于它的数一定在其下边因此从右上角开始查找就可以根据 target 和当前元素的大小关系来缩小查找区间当前元素的查找区间为左下角的所有元素
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/35a8c711-0dc0-4613-95f3-be96c6c6e104.gif" width="400px"> </div><br>
<div align="center"> <img src="pics/35a8c711-0dc0-4613-95f3-be96c6c6e104.gif" width="400px"> </div><br>
```java
public boolean Find(int target, int[][] matrix) {

View File

@ -27,7 +27,7 @@ Output:
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f7c1fea2-c1e7-4d31-94b5-0d9df85e093c.gif" width="350px"> </div><br>
<div align="center"> <img src="pics/f7c1fea2-c1e7-4d31-94b5-0d9df85e093c.gif" width="350px"> </div><br>
```java
public String replaceSpace(StringBuffer str) {

View File

@ -4,7 +4,7 @@
## 题目描述
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/5f1cb999-cb9a-4f6c-a0af-d90377295ab8.png" width="500"/> </div><br>
<div align="center"> <img src="pics/5f1cb999-cb9a-4f6c-a0af-d90377295ab8.png" width="500"/> </div><br>
## 解题思路

View File

@ -6,7 +6,7 @@
从根结点到叶结点依次经过的结点含根叶结点形成树的一条路径最长路径的长度为树的深度
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ba355101-4a93-4c71-94fb-1da83639727b.jpg" width="350px"/> </div><br>
<div align="center"> <img src="pics/ba355101-4a93-4c71-94fb-1da83639727b.jpg" width="350px"/> </div><br>
## 解题思路

View File

@ -6,7 +6,7 @@
平衡二叉树左右子树高度差不超过 1
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/af1d1166-63af-47b6-9aa3-2bf2bd37bd03.jpg" width="250px"/> </div><br>
<div align="center"> <img src="pics/af1d1166-63af-47b6-9aa3-2bf2bd37bd03.jpg" width="250px"/> </div><br>
## 解题思路

View File

@ -8,7 +8,7 @@
从尾到头反过来打印出每个结点的值
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f5792051-d9b2-4ca4-a234-a4a2de3d5a57.png" width="300px"> </div><br>
<div align="center"> <img src="pics/f5792051-d9b2-4ca4-a234-a4a2de3d5a57.png" width="300px"> </div><br>
## 解题思路
@ -39,13 +39,13 @@ node2.next = node3;
node1.next = node2;
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/58c8e370-3bec-4c2b-bf17-c8d34345dd17.gif" width="220px"> </div><br>
<div align="center"> <img src="pics/58c8e370-3bec-4c2b-bf17-c8d34345dd17.gif" width="220px"> </div><br>
为了能将一个节点插入头部我们引入了一个叫头结点的辅助节点该节点不存储值只是为了方便进行插入操作不要将头结点与第一个节点混起来第一个节点是链表中第一个真正存储值的节点
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0dae7e93-cfd1-4bd3-97e8-325b032b716f-1572687622947.gif" width="420px"> </div><br>
<div align="center"> <img src="pics/0dae7e93-cfd1-4bd3-97e8-325b032b716f-1572687622947.gif" width="420px"> </div><br>
```java
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
@ -72,7 +72,7 @@ public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
栈具有后进先出的特点在遍历链表时将值按顺序放入栈中最后出栈的顺序即为逆序
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9d1deeba-4ae1-41dc-98f4-47d85b9831bc.gif" width="340px"> </div><br>
<div align="center"> <img src="pics/9d1deeba-4ae1-41dc-98f4-47d85b9831bc.gif" width="340px"> </div><br>
```java
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {

View File

@ -8,7 +8,7 @@
n 个骰子扔在地上求点数和为 s 的概率
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/195f8693-5ec4-4987-8560-f25e365879dd.png" width="300px"> </div><br>
<div align="center"> <img src="pics/195f8693-5ec4-4987-8560-f25e365879dd.png" width="300px"> </div><br>
## 解题思路

View File

@ -8,7 +8,7 @@
五张牌其中大小鬼为癞子牌面为 0判断这五张牌是否能组成顺子
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/eaa506b6-0747-4bee-81f8-3cda795d8154.png" width="350px"> </div><br>
<div align="center"> <img src="pics/eaa506b6-0747-4bee-81f8-3cda795d8154.png" width="350px"> </div><br>
## 解题思路

View File

@ -8,7 +8,7 @@
可以有一次买入和一次卖出买入必须在前求最大收益
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/42661013-750f-420b-b3c1-437e9a11fb65.png" width="220px"> </div><br>
<div align="center"> <img src="pics/42661013-750f-420b-b3c1-437e9a11fb65.png" width="220px"> </div><br>
## 解题思路

View File

@ -8,7 +8,7 @@
给定一个数组 A[0, 1,..., n-1]请构建一个数组 B[0, 1,..., n-1]其中 B 中的元素 B[i]=A[0]\*A[1]\*...\*A[i-1]\*A[i+1]\*...\*A[n-1]要求不能使用除法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4240a69f-4d51-4d16-b797-2dfe110f30bd.png" width="250px"> </div><br>
<div align="center"> <img src="pics/4240a69f-4d51-4d16-b797-2dfe110f30bd.png" width="250px"> </div><br>
## 解题思路

View File

@ -11,7 +11,7 @@
在二叉查找树中两个节点 p, q 的公共祖先 root 满足 root.val >= p.val && root.val <= q.val
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/047faac4-a368-4565-8331-2b66253080d3.jpg" width="250"/> </div><br>
<div align="center"> <img src="pics/047faac4-a368-4565-8331-2b66253080d3.jpg" width="250"/> </div><br>
```java
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
@ -35,7 +35,7 @@ public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
在左右子树中查找是否存在 p 或者 q如果 p q 分别在两个子树中那么就说明根节点就是最低公共祖先
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d27c99f0-7881-4f2d-9675-c75cbdee3acd.jpg" width="250"/> </div><br>
<div align="center"> <img src="pics/d27c99f0-7881-4f2d-9675-c75cbdee3acd.jpg" width="250"/> </div><br>
```java
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {

View File

@ -10,13 +10,13 @@
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191102210342488.png" width="400"/> </div><br>
<div align="center"> <img src="pics/image-20191102210342488.png" width="400"/> </div><br>
## 解题思路
前序遍历的第一个值为根节点的值使用这个值将中序遍历结果分成两部分左部分为树的左子树中序遍历结果右部分为树的右子树中序遍历的结果然后分别对左右子树递归地求解
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/60c4a44c-7829-4242-b3a1-26c3b513aaf0.gif" width="430px"> </div><br>
<div align="center"> <img src="pics/60c4a44c-7829-4242-b3a1-26c3b513aaf0.gif" width="430px"> </div><br>
```java
// 缓存中序遍历数组每个值对应的索引

View File

@ -35,17 +35,17 @@ void traverse(TreeNode root) {
}
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ad5cc8fc-d59b-45ce-8899-63a18320d97e.gif" width="300px"/> </div><br>
<div align="center"> <img src="pics/ad5cc8fc-d59b-45ce-8899-63a18320d97e.gif" width="300px"/> </div><br>
如果一个节点的右子树不为空那么该节点的下一个节点是右子树的最左节点
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7008dc2b-6f13-4174-a516-28b2d75b0152.gif" width="300px"/> </div><br>
<div align="center"> <img src="pics/7008dc2b-6f13-4174-a516-28b2d75b0152.gif" width="300px"/> </div><br>
否则向上找第一个左链接指向的树包含该节点的祖先节点
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/094e3ac8-e080-4e94-9f0a-64c25abc695e.gif" width="300px"/> </div><br>
<div align="center"> <img src="pics/094e3ac8-e080-4e94-9f0a-64c25abc695e.gif" width="300px"/> </div><br>
```java
public TreeLinkNode GetNext(TreeLinkNode pNode) {

View File

@ -12,7 +12,7 @@
in 栈用来处理入栈push操作out 栈用来处理出栈pop操作一个元素进入 in 栈之后出栈的顺序被反转当元素要出栈时需要先进入 out 此时元素出栈顺序再一次被反转因此出栈顺序就和最开始入栈顺序是相同的先进入的元素先退出这就是队列的顺序
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/3ea280b5-be7d-471b-ac76-ff020384357c.gif" width="450"/> </div><br>
<div align="center"> <img src="pics/3ea280b5-be7d-471b-ac76-ff020384357c.gif" width="450"/> </div><br>
```java
Stack<Integer> in = new Stack<Integer>();

View File

@ -14,13 +14,13 @@
Docker 主要解决环境配置问题它是一种虚拟化技术对进程进行隔离被隔离的进程独立于宿主操作系统和其它隔离的进程使用 Docker 可以不修改应用程序代码不需要开发人员学习特定环境下的技术就能够将现有的应用程序部署在其它机器上
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/011f3ef6-d824-4d43-8b2c-36dab8eaaa72-1.png" width="400px"/> </div><br>
<div align="center"> <img src="pics/011f3ef6-d824-4d43-8b2c-36dab8eaaa72-1.png" width="400px"/> </div><br>
# 与虚拟机的比较
虚拟机也是一种虚拟化技术它与 Docker 最大的区别在于它是通过模拟硬件并在硬件上安装操作系统来实现
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/be608a77-7b7f-4f8e-87cc-f2237270bf69.png" width="500"/> </div><br>
<div align="center"> <img src="pics/be608a77-7b7f-4f8e-87cc-f2237270bf69.png" width="500"/> </div><br>
## 启动速度
@ -74,7 +74,7 @@ Docker 轻量级的特点使得它很适合用于部署、维护、组合微服
构建容器时通过在镜像的基础上添加一个可写层writable layer用来保存着容器运行过程中的修改
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/docker-filesystems-busyboxrw.png"/> </div><br>
<div align="center"> <img src="pics/docker-filesystems-busyboxrw.png"/> </div><br>
# 参考资料

View File

@ -18,7 +18,7 @@
Git 属于分布式版本控制系统 SVN 属于集中式
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1fe2dc77-9a2d-4643-90b3-bbf50f649bac.png" width="600px"> </div><br>
<div align="center"> <img src="pics/1fe2dc77-9a2d-4643-90b3-bbf50f649bac.png" width="600px"> </div><br>
集中式版本控制只有中心服务器拥有一份代码而分布式版本控制每个人的电脑上就有一份完整的代码
@ -40,45 +40,45 @@ Github 就是一个中心服务器。
Git 的版本库有一个称为 Stage 的暂存区以及最后的 History 版本库History 存储所有分支信息使用一个 HEAD 指针指向当前分支
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/71b97a50-a49f-4f1a-81d1-48c3364d61b3.png" width="700px"> </div><br>
<div align="center"> <img src="pics/71b97a50-a49f-4f1a-81d1-48c3364d61b3.png" width="700px"> </div><br>
- git add files 把文件的修改添加到暂存区
- git commit 把暂存区的修改提交到当前分支提交之后暂存区就被清空了
- git reset -- files 使用当前分支上的修改覆盖暂存区用来撤销最后一次 git add files
- git checkout -- files 使用暂存区的修改覆盖工作目录用来撤销本地修改
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/72ee7e9a-194d-42e9-b4d7-29c23417ca18.png" width="320px"> </div><br>
<div align="center"> <img src="pics/72ee7e9a-194d-42e9-b4d7-29c23417ca18.png" width="320px"> </div><br>
可以跳过暂存区域直接从分支中取出修改或者直接提交修改到分支中
- git commit -a 直接把所有文件的修改添加到暂存区然后执行提交
- git checkout HEAD -- files 取出最后一次修改可以用来进行回滚操作
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a4a0a6e6-386b-4bfa-b899-ec33d3310f3e.png" width="500px"> </div><br>
<div align="center"> <img src="pics/a4a0a6e6-386b-4bfa-b899-ec33d3310f3e.png" width="500px"> </div><br>
# 分支实现
使用指针将每个提交连接成一条时间线HEAD 指针指向当前分支指针
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ec4d7464-7140-46d8-827e-d63634202e1e.png" width="220px"> </div><br>
<div align="center"> <img src="pics/ec4d7464-7140-46d8-827e-d63634202e1e.png" width="220px"> </div><br>
新建分支是新建一个指针指向时间线的最后一个节点并让 HEAD 指针指向新分支表示新分支成为当前分支
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/66d00642-ce37-466c-8f7a-143d0bf84cd6.png" width="220px"> </div><br>
<div align="center"> <img src="pics/66d00642-ce37-466c-8f7a-143d0bf84cd6.png" width="220px"> </div><br>
每次提交只会让当前分支指针向前移动而其它分支指针不会移动
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/72a01242-e6b4-46c5-a285-24e754d63093.png" width="300px"> </div><br>
<div align="center"> <img src="pics/72a01242-e6b4-46c5-a285-24e754d63093.png" width="300px"> </div><br>
合并分支也只需要改变指针即可
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/94617147-0cbd-4a28-847d-81e52efb1b1e.png" width="300px"> </div><br>
<div align="center"> <img src="pics/94617147-0cbd-4a28-847d-81e52efb1b1e.png" width="300px"> </div><br>
# 冲突
当两个分支都对同一个文件的同一行进行了修改在分支合并时就会产生冲突
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/32b05e81-41b3-414a-8656-736c9604e3d6.png" width="300px"> </div><br>
<div align="center"> <img src="pics/32b05e81-41b3-414a-8656-736c9604e3d6.png" width="300px"> </div><br>
Git 会使用 <<<<<<< ======= >>>>>>> 标记出不同分支的内容只需要把不同分支中冲突部分修改成一样就能解决冲突
@ -100,7 +100,7 @@ Creating a new branch is quick AND simple.
$ git merge --no-ff -m "merge with no-ff" dev
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9a519773-84b2-4c81-81cf-4e7dd739a97a.png" width="350px"> </div><br>
<div align="center"> <img src="pics/9a519773-84b2-4c81-81cf-4e7dd739a97a.png" width="350px"> </div><br>
# 分支管理策略
@ -108,7 +108,7 @@ master 分支应该是非常稳定的,只用来发布新版本;
日常开发在开发分支 dev 上进行
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/245fd2fb-209c-4ad5-bc5e-eb5664966a0e.jpg" width=""> </div><br>
<div align="center"> <img src="pics/245fd2fb-209c-4ad5-bc5e-eb5664966a0e.jpg" width=""> </div><br>
# 储藏Stashing
@ -148,7 +148,7 @@ $ ssh-keygen -t rsa -C "youremail@example.com"
# Git 命令一览
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7a29acce-f243-4914-9f00-f2988c528412.jpg" width=""> </div><br>
<div align="center"> <img src="pics/7a29acce-f243-4914-9f00-f2988c528412.jpg" width=""> </div><br>
比较详细的地址http://www.cheat-sheets.org/saved-copy/git-cheat-sheet.pdf

View File

@ -62,17 +62,17 @@
URI 包含 URL URN
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/8441b2c4-dca7-4d6b-8efb-f22efccaf331.png" width="500px"> </div><br>
<div align="center"> <img src="pics/8441b2c4-dca7-4d6b-8efb-f22efccaf331.png" width="500px"> </div><br>
## 请求和响应报文
### 1. 请求报文
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/HTTP_RequestMessageExample.png" width=""/> </div><br>
<div align="center"> <img src="pics/HTTP_RequestMessageExample.png" width=""/> </div><br>
### 2. 响应报文
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/HTTP_ResponseMessageExample.png" width=""/> </div><br>
<div align="center"> <img src="pics/HTTP_ResponseMessageExample.png" width=""/> </div><br>
# HTTP 方法
@ -159,7 +159,7 @@ DELETE /file.html HTTP/1.1
CONNECT www.example.com:443 HTTP/1.1
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/dc00f70e-c5c8-4d20-baf1-2d70014a97e3.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/dc00f70e-c5c8-4d20-baf1-2d70014a97e3.jpg" width=""/> </div><br>
## TRACE
@ -302,7 +302,7 @@ CONNECT www.example.com:443 HTTP/1.1
## 连接管理
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/HTTP1_x_Connections.png" width="800"/> </div><br>
<div align="center"> <img src="pics/HTTP1_x_Connections.png" width="800"/> </div><br>
### 1. 短连接与长连接
@ -631,11 +631,11 @@ HTTP/1.1 使用虚拟主机技术,使得一台服务器拥有多个域名,
- 用户察觉得到正向代理的存在
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a314bb79-5b18-4e63-a976-3448bffa6f1b.png" width=""/> </div><br>
<div align="center"> <img src="pics/a314bb79-5b18-4e63-a976-3448bffa6f1b.png" width=""/> </div><br>
- 而反向代理一般位于内部网络中用户察觉不到
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2d09a847-b854-439c-9198-b29c65810944.png" width=""/> </div><br>
<div align="center"> <img src="pics/2d09a847-b854-439c-9198-b29c65810944.png" width=""/> </div><br>
### 2. 网关
@ -657,7 +657,7 @@ HTTPS 并不是新协议,而是让 HTTP 先和 SSLSecure Sockets Layer
通过使用 SSLHTTPS 具有了加密防窃听认证防伪装和完整性保护防篡改
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ssl-offloading.jpg" width="700"/> </div><br>
<div align="center"> <img src="pics/ssl-offloading.jpg" width="700"/> </div><br>
## 加密
@ -668,7 +668,7 @@ HTTPS 并不是新协议,而是让 HTTP 先和 SSLSecure Sockets Layer
- 优点运算速度快
- 缺点无法安全地将密钥传输给通信方
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7fffa4b8-b36d-471f-ad0c-a88ee763bb76.png" width="600"/> </div><br>
<div align="center"> <img src="pics/7fffa4b8-b36d-471f-ad0c-a88ee763bb76.png" width="600"/> </div><br>
### 2.非对称密钥加密
@ -681,7 +681,7 @@ HTTPS 并不是新协议,而是让 HTTP 先和 SSLSecure Sockets Layer
- 优点可以更安全地将公开密钥传输给通信发送方
- 缺点运算速度慢
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/39ccb299-ee99-4dd1-b8b4-2f9ec9495cb4.png" width="600"/> </div><br>
<div align="center"> <img src="pics/39ccb299-ee99-4dd1-b8b4-2f9ec9495cb4.png" width="600"/> </div><br>
### 3. HTTPS 采用的加密方式
@ -690,7 +690,7 @@ HTTPS 并不是新协议,而是让 HTTP 先和 SSLSecure Sockets Layer
- 使用非对称密钥加密方式传输对称密钥加密方式所需要的 Secret Key从而保证安全性;
- 获取到 Secret Key 再使用对称密钥加密方式进行通信从而保证效率下图中的 Session Key 就是 Secret Key
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/How-HTTPS-Works.png" width="600"/> </div><br>
<div align="center"> <img src="pics/How-HTTPS-Works.png" width="600"/> </div><br>
## 认证
@ -702,7 +702,7 @@ HTTPS 并不是新协议,而是让 HTTP 先和 SSLSecure Sockets Layer
进行 HTTPS 通信时服务器会把证书发送给客户端客户端取得其中的公开密钥之后先使用数字签名进行验证如果验证通过就可以开始通信了
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2017-06-11-ca.png" width=""/> </div><br>
<div align="center"> <img src="pics/2017-06-11-ca.png" width=""/> </div><br>
## 完整性保护
@ -731,7 +731,7 @@ HTTP/1.x 实现简单是以牺牲性能为代价的:
HTTP/2.0 将报文分成 HEADERS 帧和 DATA 它们都是二进制格式的
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/86e6a91d-a285-447a-9345-c5484b8d0c47.png" width="400"/> </div><br>
<div align="center"> <img src="pics/86e6a91d-a285-447a-9345-c5484b8d0c47.png" width="400"/> </div><br>
在通信过程中只会有一个 TCP 连接存在它承载了任意数量的双向数据流Stream
@ -739,13 +739,13 @@ HTTP/2.0 将报文分成 HEADERS 帧和 DATA 帧,它们都是二进制格式
- 消息Message是与逻辑请求或响应对应的完整的一系列帧
- Frame是最小的通信单位来自不同数据流的帧可以交错发送然后再根据每个帧头的数据流标识符重新组装
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/af198da1-2480-4043-b07f-a3b91a88b815.png" width="600"/> </div><br>
<div align="center"> <img src="pics/af198da1-2480-4043-b07f-a3b91a88b815.png" width="600"/> </div><br>
## 服务端推送
HTTP/2.0 在客户端请求一个资源时会把相关的资源一起发送给客户端客户端就不需要再次发起请求了例如客户端请求 page.html 页面服务端就把 script.js style.css 等与之相关的资源一起发给客户端
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e3f1657c-80fc-4dfa-9643-bf51abd201c6.png" width="800"/> </div><br>
<div align="center"> <img src="pics/e3f1657c-80fc-4dfa-9643-bf51abd201c6.png" width="800"/> </div><br>
## 首部压缩
@ -755,7 +755,7 @@ HTTP/2.0 要求客户端和服务器同时维护和更新一个包含之前见
不仅如此HTTP/2.0 也使用 Huffman 编码对首部字段进行压缩
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/_u4E0B_u8F7D.png" width="600"/> </div><br>
<div align="center"> <img src="pics/_u4E0B_u8F7D.png" width="600"/> </div><br>
# HTTP/1.1 新特性

View File

@ -97,7 +97,7 @@ Java I/O 使用了装饰者模式来实现。以 InputStream 为例,
- FileInputStream InputStream 的子类属于具体组件提供了字节流的输入操作
- FilterInputStream 属于抽象装饰者装饰者用于装饰组件为组件提供额外的功能例如 BufferedInputStream FileInputStream 提供缓存的功能
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9709694b-db05-4cce-8d2f-1c8b09f4d921.png" width="650px"> </div><br>
<div align="center"> <img src="pics/9709694b-db05-4cce-8d2f-1c8b09f4d921.png" width="650px"> </div><br>
实例化一个具有缓存功能的字节流对象时只需要在 FileInputStream 对象上再套一层 BufferedInputStream 对象即可
@ -277,7 +277,7 @@ public static void main(String[] args) throws IOException {
- Socket客户端类
- 服务器和客户端通过 InputStream OutputStream 进行输入输出
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1e6affc4-18e5-4596-96ef-fb84c63bf88a.png" width="550px"> </div><br>
<div align="center"> <img src="pics/1e6affc4-18e5-4596-96ef-fb84c63bf88a.png" width="550px"> </div><br>
## Datagram
@ -339,23 +339,23 @@ I/O 包和 NIO 已经很好地集成了java.io.\* 已经以 NIO 为基础重
新建一个大小为 8 个字节的缓冲区此时 position 0 limit = capacity = 8capacity 变量不会改变下面的讨论会忽略它
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1bea398f-17a7-4f67-a90b-9e2d243eaa9a.png"/> </div><br>
<div align="center"> <img src="pics/1bea398f-17a7-4f67-a90b-9e2d243eaa9a.png"/> </div><br>
从输入通道中读取 5 个字节数据写入缓冲区中此时 position 5limit 保持不变
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/80804f52-8815-4096-b506-48eef3eed5c6.png"/> </div><br>
<div align="center"> <img src="pics/80804f52-8815-4096-b506-48eef3eed5c6.png"/> </div><br>
在将缓冲区的数据写到输出通道之前需要先调用 flip() 方法这个方法将 limit 设置为当前 position并将 position 设置为 0
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/952e06bd-5a65-4cab-82e4-dd1536462f38.png"/> </div><br>
<div align="center"> <img src="pics/952e06bd-5a65-4cab-82e4-dd1536462f38.png"/> </div><br>
从缓冲区中取 4 个字节到输出缓冲中此时 position 设为 4
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b5bdcbe2-b958-4aef-9151-6ad963cb28b4.png"/> </div><br>
<div align="center"> <img src="pics/b5bdcbe2-b958-4aef-9151-6ad963cb28b4.png"/> </div><br>
最后需要调用 clear() 方法来清空缓冲区此时 position limit 都被设置为最初位置
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/67bf5487-c45d-49b6-b9c0-a058d8c68902.png"/> </div><br>
<div align="center"> <img src="pics/67bf5487-c45d-49b6-b9c0-a058d8c68902.png"/> </div><br>
## 文件 NIO 实例
@ -413,7 +413,7 @@ NIO 实现了 IO 多路复用中的 Reactor 模型,一个线程 Thread 使用
应该注意的是只有套接字 Channel 才能配置为非阻塞 FileChannel 不能 FileChannel 配置非阻塞也没有意义
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/093f9e57-429c-413a-83ee-c689ba596cef.png" width="350px"> </div><br>
<div align="center"> <img src="pics/093f9e57-429c-413a-83ee-c689ba596cef.png" width="350px"> </div><br>
### 1. 创建选择器

View File

@ -193,7 +193,7 @@ value 数组被声明为 final这意味着 value 数组初始化之后就不
如果一个 String 对象已经被创建过了那么就会从 String Pool 中取得引用只有 String 是不可变的才可能使用 String Pool
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9112288f-23f5-4e53-b222-a46fdbca1603.png" width="300px"> </div><br>
<div align="center"> <img src="pics/9112288f-23f5-4e53-b222-a46fdbca1603.png" width="300px"> </div><br>
**3. 安全性**
@ -1356,7 +1356,7 @@ Throwable 可以用来表示任何可以作为异常抛出的类,分为两种
- **受检异常** 需要用 try...catch... 语句捕获并进行处理并且可以从异常中恢复
- **非受检异常** 是程序运行时错误例如除 0 会引发 Arithmetic Exception此时程序崩溃并且无法恢复
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/PPjwP.png" width="600"/> </div><br>
<div align="center"> <img src="pics/PPjwP.png" width="600"/> </div><br>
- [Java 入门之异常处理](https://www.tianmaying.com/tutorial/Java-Exception)
- [Java 异常的面试问题及答案 -Part 1](http://www.importnew.com/7383.html)

View File

@ -24,7 +24,7 @@
## Collection
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/73403d84-d921-49f1-93a9-d8fe050f3497.png" width="800px"> </div><br>
<div align="center"> <img src="pics/73403d84-d921-49f1-93a9-d8fe050f3497.png" width="800px"> </div><br>
### 1. Set
@ -50,7 +50,7 @@
## Map
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/774d756b-902a-41a3-a3fd-81ca3ef688dc.png" width="500px"> </div><br>
<div align="center"> <img src="pics/774d756b-902a-41a3-a3fd-81ca3ef688dc.png" width="500px"> </div><br>
- TreeMap基于红黑树实现
@ -65,7 +65,7 @@
## 迭代器模式
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/93fb1d38-83f9-464a-a733-67b2e6bfddda.png" width="600px"> </div><br>
<div align="center"> <img src="pics/93fb1d38-83f9-464a-a733-67b2e6bfddda.png" width="600px"> </div><br>
Collection 继承了 Iterable 接口其中的 iterator() 方法能够产生一个 Iterator 对象通过这个对象就可以迭代遍历 Collection 中的元素
@ -126,7 +126,7 @@ public class ArrayList<E> extends AbstractList<E>
private static final int DEFAULT_CAPACITY = 10;
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/52a7744f-5bce-4ff3-a6f0-8449334d9f3d.png" width="400px"> </div><br>
<div align="center"> <img src="pics/52a7744f-5bce-4ff3-a6f0-8449334d9f3d.png" width="400px"> </div><br>
### 2. 扩容
@ -430,7 +430,7 @@ transient Node<E> first;
transient Node<E> last;
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c8563120-cb00-4dd6-9213-9d9b337a7f7c.png" width="500px"> </div><br>
<div align="center"> <img src="pics/c8563120-cb00-4dd6-9213-9d9b337a7f7c.png" width="500px"> </div><br>
### 2. ArrayList 的比较
@ -452,7 +452,7 @@ transient Entry[] table;
Entry 存储着键值对它包含了四个字段 next 字段我们可以看出 Entry 是一个链表即数组中的每个位置被当成一个桶一个桶存放一个链表HashMap 使用拉链法来解决冲突同一个链表中存放哈希值和散列桶取模运算结果相同的 Entry
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9420a703-1f9d-42ce-808e-bcb82b56483d.png" width="550px"> </div><br>
<div align="center"> <img src="pics/9420a703-1f9d-42ce-808e-bcb82b56483d.png" width="550px"> </div><br>
```java
static class Entry<K,V> implements Map.Entry<K,V> {
@ -528,7 +528,7 @@ map.put("K3", "V3");
- 计算键值对所在的桶
- 在链表上顺序查找时间复杂度显然和链表的长度成正比
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e0870f80-b79e-4542-ae39-7420d4b0d8fe.png" width="550px"> </div><br>
<div align="center"> <img src="pics/e0870f80-b79e-4542-ae39-7420d4b0d8fe.png" width="550px"> </div><br>
### 3. put 操作
@ -864,7 +864,7 @@ final Segment<K,V>[] segments;
static final int DEFAULT_CONCURRENCY_LEVEL = 16;
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/db808eff-31d7-4229-a4ad-b8ae71870a3a.png" width="550px"> </div><br>
<div align="center"> <img src="pics/db808eff-31d7-4229-a4ad-b8ae71870a3a.png" width="550px"> </div><br>
### 2. size 操作

View File

@ -61,7 +61,7 @@
# 线程状态转换
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/adfb427d-3b21-40d7-a142-757f4ed73079.png" width="600px"> </div><br>
<div align="center"> <img src="pics/adfb427d-3b21-40d7-a142-757f4ed73079.png" width="600px"> </div><br>
## 新建New
@ -736,7 +736,7 @@ java.util.concurrentJ.U.C大大提高了并发性能AQS 被认为是 J.
维护了一个计数器 cnt每次调用 countDown() 方法会让计数器的值减 1减到 0 的时候那些因为调用 await() 方法而在等待的线程就会被唤醒
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ba078291-791e-4378-b6d1-ece76c2f0b14.png" width="300px"> </div><br>
<div align="center"> <img src="pics/ba078291-791e-4378-b6d1-ece76c2f0b14.png" width="300px"> </div><br>
```java
public class CountdownLatchExample {
@ -785,7 +785,7 @@ public CyclicBarrier(int parties) {
}
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f71af66b-0d54-4399-a44b-f47b58321984.png" width="300px"> </div><br>
<div align="center"> <img src="pics/f71af66b-0d54-4399-a44b-f47b58321984.png" width="300px"> </div><br>
```java
public class CyclicBarrierExample {
@ -1022,7 +1022,7 @@ public class ForkJoinPool extends AbstractExecutorService
ForkJoinPool 实现了工作窃取算法来提高 CPU 的利用率每个线程都维护了一个双端队列用来存储需要执行的任务工作窃取算法允许空闲的线程从其它线程的双端队列中窃取一个任务来执行窃取的任务必须是最晚的任务避免和队列所属线程发生竞争例如下图中Thread2 Thread1 的队列中拿出最晚的 Task1 任务Thread1 会拿出 Task2 来执行这样就避免发生竞争但是如果队列中只有一个任务时还是会发生竞争
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e42f188f-f4a9-4e6f-88fc-45f4682072fb.png" width="300px"> </div><br>
<div align="center"> <img src="pics/e42f188f-f4a9-4e6f-88fc-45f4682072fb.png" width="300px"> </div><br>
# 线程不安全示例
@ -1077,19 +1077,19 @@ Java 内存模型试图屏蔽各种硬件和操作系统的内存访问差异,
加入高速缓存带来了一个新的问题缓存一致性如果多个缓存共享同一块主内存区域那么多个缓存的数据可能会不一致需要一些协议来解决这个问题
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/942ca0d2-9d5c-45a4-89cb-5fd89b61913f.png" width="600px"> </div><br>
<div align="center"> <img src="pics/942ca0d2-9d5c-45a4-89cb-5fd89b61913f.png" width="600px"> </div><br>
所有的变量都存储在主内存中每个线程还有自己的工作内存工作内存存储在高速缓存或者寄存器中保存了该线程使用的变量的主内存副本拷贝
线程只能直接操作工作内存中的变量不同线程之间的变量值传递需要通过主内存来完成
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/15851555-5abc-497d-ad34-efed10f43a6b.png" width="600px"> </div><br>
<div align="center"> <img src="pics/15851555-5abc-497d-ad34-efed10f43a6b.png" width="600px"> </div><br>
## 内存间交互操作
Java 内存模型定义了 8 个操作来完成主内存和工作内存的交互操作
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/8b7ebbad-9604-4375-84e3-f412099d170c.png" width="450px"> </div><br>
<div align="center"> <img src="pics/8b7ebbad-9604-4375-84e3-f412099d170c.png" width="450px"> </div><br>
- read把一个变量的值从主内存传输到工作内存中
- load read 之后执行 read 得到的值放入工作内存的变量副本中
@ -1112,11 +1112,11 @@ Java 内存模型保证了 read、load、use、assign、store、write、lock 和
下图演示了两个线程同时对 cnt 进行操作loadassignstore 这一系列操作整体上看不具备原子性那么在 T1 修改 cnt 并且还没有将修改后的值写入主内存T2 依然可以读入旧值可以看出这两个线程虽然执行了两次自增运算但是主内存中 cnt 的值最后为 1 而不是 2因此对 int 类型读写操作满足原子性只是说明 loadassignstore 这些单个操作具备原子性
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2797a609-68db-4d7b-8701-41ac9a34b14f.jpg" width="300px"> </div><br>
<div align="center"> <img src="pics/2797a609-68db-4d7b-8701-41ac9a34b14f.jpg" width="300px"> </div><br>
AtomicInteger 能保证多个线程修改的原子性
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/dd563037-fcaa-4bd8-83b6-b39d93a12c77.jpg" width="300px"> </div><br>
<div align="center"> <img src="pics/dd563037-fcaa-4bd8-83b6-b39d93a12c77.jpg" width="300px"> </div><br>
使用 AtomicInteger 重写之前线程不安全的代码之后得到以下线程安全实现
@ -1224,7 +1224,7 @@ volatile 关键字通过添加内存屏障的方式来禁止指令重排,即
在一个线程内在程序前面的操作先行发生于后面的操作
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/874b3ff7-7c5c-4e7a-b8ab-a82a3e038d20.png" width="180px"> </div><br>
<div align="center"> <img src="pics/874b3ff7-7c5c-4e7a-b8ab-a82a3e038d20.png" width="180px"> </div><br>
### 2. 管程锁定规则
@ -1232,7 +1232,7 @@ volatile 关键字通过添加内存屏障的方式来禁止指令重排,即
一个 unlock 操作先行发生于后面对同一个锁的 lock 操作
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/8996a537-7c4a-4ec8-a3b7-7ef1798eae26.png" width="350px"> </div><br>
<div align="center"> <img src="pics/8996a537-7c4a-4ec8-a3b7-7ef1798eae26.png" width="350px"> </div><br>
### 3. volatile 变量规则
@ -1240,7 +1240,7 @@ volatile 关键字通过添加内存屏障的方式来禁止指令重排,即
对一个 volatile 变量的写操作先行发生于后面对这个变量的读操作
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/942f33c9-8ad9-4987-836f-007de4c21de0.png" width="400px"> </div><br>
<div align="center"> <img src="pics/942f33c9-8ad9-4987-836f-007de4c21de0.png" width="400px"> </div><br>
### 4. 线程启动规则
@ -1248,7 +1248,7 @@ volatile 关键字通过添加内存屏障的方式来禁止指令重排,即
Thread 对象的 start() 方法调用先行发生于此线程的每一个动作
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6270c216-7ec0-4db7-94de-0003bce37cd2.png" width="380px"> </div><br>
<div align="center"> <img src="pics/6270c216-7ec0-4db7-94de-0003bce37cd2.png" width="380px"> </div><br>
### 5. 线程加入规则
@ -1256,7 +1256,7 @@ Thread 对象的 start() 方法调用先行发生于此线程的每一个动作
Thread 对象的结束先行发生于 join() 方法返回
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/233f8d89-31d7-413f-9c02-042f19c46ba1.png" width="400px"> </div><br>
<div align="center"> <img src="pics/233f8d89-31d7-413f-9c02-042f19c46ba1.png" width="400px"> </div><br>
### 6. 线程中断规则
@ -1474,7 +1474,7 @@ public class ThreadLocalExample1 {
它所对应的底层结构图为
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6782674c-1bfe-4879-af39-e9d722a95d39.png" width="500px"> </div><br>
<div align="center"> <img src="pics/6782674c-1bfe-4879-af39-e9d722a95d39.png" width="500px"> </div><br>
每个 Thread 都有一个 ThreadLocal.ThreadLocalMap 对象
@ -1577,17 +1577,17 @@ JDK 1.6 引入了偏向锁和轻量级锁,从而让锁拥有了四个状态:
以下是 HotSpot 虚拟机对象头的内存布局这些数据被称为 Mark Word其中 tag bits 对应了五个状态这些状态在右侧的 state 表格中给出除了 marked for gc 状态其它四个状态已经在前面介绍过了
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/bb6a49be-00f2-4f27-a0ce-4ed764bc605c.png" width="500"/> </div><br>
<div align="center"> <img src="pics/bb6a49be-00f2-4f27-a0ce-4ed764bc605c.png" width="500"/> </div><br>
下图左侧是一个线程的虚拟机栈其中有一部分称为 Lock Record 的区域这是在轻量级锁运行过程创建的用于存放锁对象的 Mark Word而右侧就是一个锁对象包含了 Mark Word 和其它信息
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/051e436c-0e46-4c59-8f67-52d89d656182.png" width="500"/> </div><br>
<div align="center"> <img src="pics/051e436c-0e46-4c59-8f67-52d89d656182.png" width="500"/> </div><br>
轻量级锁是相对于传统的重量级锁而言它使用 CAS 操作来避免重量级锁使用互斥量的开销对于绝大部分的锁在整个同步周期内都是不存在竞争的因此也就不需要都使用互斥量进行同步可以先采用 CAS 操作进行同步如果 CAS 失败了再改用互斥量进行同步
当尝试获取一个锁对象时如果锁对象标记为 0 01说明锁对象的锁未锁定unlocked状态此时虚拟机在当前线程的虚拟机栈中创建 Lock Record然后使用 CAS 操作将对象的 Mark Word 更新为 Lock Record 指针如果 CAS 操作成功了那么线程就获取了该对象上的锁并且对象的 Mark Word 的锁标记变为 00表示该对象处于轻量级锁状态
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/baaa681f-7c52-4198-a5ae-303b9386cf47.png" width="400"/> </div><br>
<div align="center"> <img src="pics/baaa681f-7c52-4198-a5ae-303b9386cf47.png" width="400"/> </div><br>
如果 CAS 操作失败了虚拟机首先会检查对象的 Mark Word 是否指向当前线程的虚拟机栈如果是的话说明当前线程已经拥有了这个锁对象那就可以直接进入同步块继续执行否则说明这个锁对象已经被其他线程线程抢占了如果有两条以上的线程争用同一个锁那轻量级锁就不再有效要膨胀为重量级锁
@ -1599,7 +1599,7 @@ JDK 1.6 引入了偏向锁和轻量级锁,从而让锁拥有了四个状态:
当有另外一个线程去尝试获取这个锁对象时偏向状态就宣告结束此时撤销偏向Revoke Bias后恢复到未锁定状态或者轻量级锁状态
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/390c913b-5f31-444f-bbdb-2b88b688e7ce.jpg" width="600"/> </div><br>
<div align="center"> <img src="pics/390c913b-5f31-444f-bbdb-2b88b688e7ce.jpg" width="600"/> </div><br>
# 十三多线程开发良好的实践

View File

@ -32,7 +32,7 @@
# 运行时数据区域
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/5778d113-8e13-4c53-b5bf-801e58080b97.png" width="400px"> </div><br>
<div align="center"> <img src="pics/5778d113-8e13-4c53-b5bf-801e58080b97.png" width="400px"> </div><br>
## 程序计数器
@ -42,7 +42,7 @@
每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表操作数栈常量池引用等信息从方法调用直至执行完成的过程对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/8442519f-0b4d-48f4-8229-56f984363c69.png" width="400px"> </div><br>
<div align="center"> <img src="pics/8442519f-0b4d-48f4-8229-56f984363c69.png" width="400px"> </div><br>
可以通过 -Xss 这个虚拟机参数来指定每个线程的 Java 虚拟机栈内存大小 JDK 1.4 中默认为 256K而在 JDK 1.5+ 默认为 1M
@ -61,7 +61,7 @@ java -Xss2M HackTheJava
本地方法一般是用其它语言CC++ 或汇编语言等编写的并且被编译为基于本机硬件和操作系统的程序对待这些方法需要特别处理
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/66a6899d-c6b0-4a47-8569-9d08f0baf86c.png" width="300px"> </div><br>
<div align="center"> <img src="pics/66a6899d-c6b0-4a47-8569-9d08f0baf86c.png" width="300px"> </div><br>
##
@ -146,7 +146,7 @@ Java 虚拟机使用该算法来判断对象是否可被回收GC Roots 一般
- 方法区中类静态属性引用的对象
- 方法区中的常量引用的对象
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/83d909d2-3858-4fe1-8ff4-16471db0b180.png" width="350px"> </div><br>
<div align="center"> <img src="pics/83d909d2-3858-4fe1-8ff4-16471db0b180.png" width="350px"> </div><br>
### 3. 方法区的回收
@ -227,7 +227,7 @@ obj = null;
### 1. 标记 - 清除
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/005b481b-502b-4e3f-985d-d043c2b330aa.png" width="400px"> </div><br>
<div align="center"> <img src="pics/005b481b-502b-4e3f-985d-d043c2b330aa.png" width="400px"> </div><br>
在标记阶段程序会检查每个对象是否为活动对象如果是活动对象则程序会在对象头部打上标记
@ -242,7 +242,7 @@ obj = null;
### 2. 标记 - 整理
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ccd773a5-ad38-4022-895c-7ac318f31437.png" width="400px"> </div><br>
<div align="center"> <img src="pics/ccd773a5-ad38-4022-895c-7ac318f31437.png" width="400px"> </div><br>
让所有存活的对象都向一端移动然后直接清理掉端边界以外的内存
@ -256,7 +256,7 @@ obj = null;
### 3. 复制
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b2b77b9e-958c-4016-8ae5-9c6edd83871e.png" width="400px"> </div><br>
<div align="center"> <img src="pics/b2b77b9e-958c-4016-8ae5-9c6edd83871e.png" width="400px"> </div><br>
将内存划分为大小相等的两块每次只使用其中一块当这一块内存用完了就将还存活的对象复制到另一块上面然后再把使用过的内存空间进行一次清理
@ -277,7 +277,7 @@ HotSpot 虚拟机的 Eden 和 Survivor 大小比例默认为 8:1保证了内
## 垃圾收集器
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c625baa0-dde6-449e-93df-c3a67f2f430f.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/c625baa0-dde6-449e-93df-c3a67f2f430f.jpg" width=""/> </div><br>
以上是 HotSpot 虚拟机中的 7 个垃圾收集器连线表示垃圾收集器可以配合使用
@ -286,7 +286,7 @@ HotSpot 虚拟机的 Eden 和 Survivor 大小比例默认为 8:1保证了内
### 1. Serial 收集器
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/22fda4ae-4dd5-489d-ab10-9ebfdad22ae0.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/22fda4ae-4dd5-489d-ab10-9ebfdad22ae0.jpg" width=""/> </div><br>
Serial 翻译为串行也就是说它以串行的方式执行
@ -298,7 +298,7 @@ Serial 翻译为串行,也就是说它以串行的方式执行。
### 2. ParNew 收集器
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/81538cd5-1bcf-4e31-86e5-e198df1e013b.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/81538cd5-1bcf-4e31-86e5-e198df1e013b.jpg" width=""/> </div><br>
它是 Serial 收集器的多线程版本
@ -318,7 +318,7 @@ Serial 翻译为串行,也就是说它以串行的方式执行。
### 4. Serial Old 收集器
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/08f32fd3-f736-4a67-81ca-295b2a7972f2.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/08f32fd3-f736-4a67-81ca-295b2a7972f2.jpg" width=""/> </div><br>
Serial 收集器的老年代版本也是给 Client 场景下的虚拟机使用如果用在 Server 场景下它有两大用途
@ -327,7 +327,7 @@ Serial 翻译为串行,也就是说它以串行的方式执行。
### 5. Parallel Old 收集器
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/278fe431-af88-4a95-a895-9c3b80117de3.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/278fe431-af88-4a95-a895-9c3b80117de3.jpg" width=""/> </div><br>
Parallel Scavenge 收集器的老年代版本
@ -335,7 +335,7 @@ Serial 翻译为串行,也就是说它以串行的方式执行。
### 6. CMS 收集器
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/62e77997-6957-4b68-8d12-bfd609bb2c68.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/62e77997-6957-4b68-8d12-bfd609bb2c68.jpg" width=""/> </div><br>
CMSConcurrent Mark SweepMark Sweep 指的是标记 - 清除算法
@ -360,17 +360,17 @@ G1Garbage-First它是一款面向服务端应用的垃圾收集器
堆被分为新生代和老年代其它收集器进行收集的范围都是整个新生代或者老年代 G1 可以直接对新生代和老年代一起回收
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4cf711a8-7ab2-4152-b85c-d5c226733807.png" width="600"/> </div><br>
<div align="center"> <img src="pics/4cf711a8-7ab2-4152-b85c-d5c226733807.png" width="600"/> </div><br>
G1 把堆划分成多个大小相等的独立区域Region新生代和老年代不再物理隔离
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9bbddeeb-e939-41f0-8e8e-2b1a0aa7e0a7.png" width="600"/> </div><br>
<div align="center"> <img src="pics/9bbddeeb-e939-41f0-8e8e-2b1a0aa7e0a7.png" width="600"/> </div><br>
通过引入 Region 的概念从而将原来的一整块内存空间划分成多个的小空间使得每个小空间可以单独进行垃圾回收这种划分方法带来了很大的灵活性使得可预测的停顿时间模型成为可能通过记录每个 Region 垃圾回收时间以及回收所获得的空间这两个值是通过过去回收的经验获得并维护一个优先列表每次根据允许的收集时间优先回收价值最大的 Region
每个 Region 都有一个 Remembered Set用来记录该 Region 对象的引用对象所在的 Region通过使用 Remembered Set在做可达性分析的时候就可以避免全堆扫描
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f99ee771-c56f-47fb-9148-c0036695b5fe.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/f99ee771-c56f-47fb-9148-c0036695b5fe.jpg" width=""/> </div><br>
如果不计算维护 Remembered Set 的操作G1 收集器的运作大致可划分为以下几个步骤
@ -458,7 +458,7 @@ G1 把堆划分成多个大小相等的独立区域Region新生代和
## 类的生命周期
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/335fe19c-4a76-45ab-9320-88c90d6a0d7e.png" width="600px"> </div><br>
<div align="center"> <img src="pics/335fe19c-4a76-45ab-9320-88c90d6a0d7e.png" width="600px"> </div><br>
包括以下 7 个阶段
@ -628,7 +628,7 @@ System.out.println(ConstClass.HELLOWORLD);
下图展示了类加载器之间的层次关系称为双亲委派模型Parents Delegation Model该模型要求除了顶层的启动类加载器外其它的类加载器都要有自己的父类加载器这里的父子关系一般通过组合关系Composition来实现而不是继承关系Inheritance
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0dd2d40a-5b2b-4d45-b176-e75a4cd4bdbf.png" width="500px"> </div><br>
<div align="center"> <img src="pics/0dd2d40a-5b2b-4d45-b176-e75a4cd4bdbf.png" width="500px"> </div><br>
### 1. 工作过程

View File

@ -61,7 +61,7 @@
<!--<div align="center"><img src="https://latex.codecogs.com/gif.latex?dp[i]=dp[i-1]+dp[i-2]" class="mathjax-pic"/></div> <br>-->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/14fe1e71-8518-458f-a220-116003061a83.png" width="200px"> </div><br>
<div align="center"> <img src="pics/14fe1e71-8518-458f-a220-116003061a83.png" width="200px"> </div><br>
考虑到 dp[i] 只与 dp[i - 1] dp[i - 2] 有关因此可以只用两个变量来存储 dp[i - 1] dp[i - 2]使得原来的 O(N) 空间复杂度优化为 O(1) 复杂度
@ -94,7 +94,7 @@ public int climbStairs(int n) {
<!--<div align="center"><img src="https://latex.codecogs.com/gif.latex?dp[i]=max(dp[i-2]+nums[i],dp[i-1])" class="mathjax-pic"/></div> <br>-->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2de794ca-aa7b-48f3-a556-a0e2708cb976.jpg" width="350px"> </div><br>
<div align="center"> <img src="pics/2de794ca-aa7b-48f3-a556-a0e2708cb976.jpg" width="350px"> </div><br>
```java
public int rob(int[] nums) {
@ -150,7 +150,7 @@ private int rob(int[] nums, int first, int last) {
<!--<div align="center"><img src="https://latex.codecogs.com/gif.latex?dp[i]=(i-1)*dp[i-2]+(i-1)*dp[i-1]" class="mathjax-pic"/></div> <br>-->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/da1f96b9-fd4d-44ca-8925-fb14c5733388.png" width="350px"> </div><br>
<div align="center"> <img src="pics/da1f96b9-fd4d-44ca-8925-fb14c5733388.png" width="350px"> </div><br>
## 5. 母牛生产
@ -162,7 +162,7 @@ private int rob(int[] nums, int first, int last) {
<!--<div align="center"><img src="https://latex.codecogs.com/gif.latex?dp[i]=dp[i-1]+dp[i-3]" class="mathjax-pic"/></div> <br>-->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/879814ee-48b5-4bcb-86f5-dcc400cb81ad.png" width="250px"> </div><br>
<div align="center"> <img src="pics/879814ee-48b5-4bcb-86f5-dcc400cb81ad.png" width="250px"> </div><br>
# 矩阵路径
@ -212,7 +212,7 @@ public int minPathSum(int[][] grid) {
题目描述统计从矩阵左上角到右下角的路径总数每次只能向右或者向下移动
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/dc82f0f3-c1d4-4ac8-90ac-d5b32a9bd75a.jpg" width=""> </div><br>
<div align="center"> <img src="pics/dc82f0f3-c1d4-4ac8-90ac-d5b32a9bd75a.jpg" width=""> </div><br>
```java
public int uniquePaths(int m, int n) {
@ -443,7 +443,7 @@ public int numDecodings(String s) {
<!--<div align="center"><img src="https://latex.codecogs.com/gif.latex?dp[n]=max\{1,dp[i]+1|S_i<S_n\&\&i<n\}" class="mathjax-pic"/></div> <br>-->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ee994da4-0fc7-443d-ac56-c08caf00a204.jpg" width="350px"> </div><br>
<div align="center"> <img src="pics/ee994da4-0fc7-443d-ac56-c08caf00a204.jpg" width="350px"> </div><br>
对于一个长度为 N 的序列最长递增子序列并不一定会以 S<sub>N</sub> 为结尾因此 dp[N] 不是序列的最长递增子序列的长度需要遍历 dp 数组找出最大值才是所要的结果max{ dp[i] | 1 <= i <= N} 即为所求
@ -616,7 +616,7 @@ public int wiggleMaxLength(int[] nums) {
<!--<div align="center"><img src="https://latex.codecogs.com/gif.latex?dp[i][j]=\left\{\begin{array}{rcl}dp[i-1][j-1]&&{S1_i==S2_j}\\max(dp[i-1][j],dp[i][j-1])&&{S1_i<>S2_j}\end{array}\right." class="mathjax-pic"/></div> <br>-->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ecd89a22-c075-4716-8423-e0ba89230e9a.jpg" width="450px"> </div><br>
<div align="center"> <img src="pics/ecd89a22-c075-4716-8423-e0ba89230e9a.jpg" width="450px"> </div><br>
对于长度为 N 的序列 S<sub>1</sub> 和长度为 M 的序列 S<sub>2</sub>dp[N][M] 就是序列 S<sub>1</sub> 和序列 S<sub>2</sub> 的最长公共子序列长度
@ -662,7 +662,7 @@ public int wiggleMaxLength(int[] nums) {
<!--<div align="center"><img src="https://latex.codecogs.com/gif.latex?dp[i][j]=max(dp[i-1][j],dp[i-1][j-w]+v)" class="mathjax-pic"/></div> <br>-->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/8cb2be66-3d47-41ba-b55b-319fc68940d4.png" width="400px"> </div><br>
<div align="center"> <img src="pics/8cb2be66-3d47-41ba-b55b-319fc68940d4.png" width="400px"> </div><br>
```java
// W 为背包总体积
@ -691,7 +691,7 @@ public int knapsack(int W, int N, int[] weights, int[] values) {
<!--<div align="center"><img src="https://latex.codecogs.com/gif.latex?dp[j]=max(dp[j],dp[j-w]+v)" class="mathjax-pic"/></div> <br>-->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9ae89f16-7905-4a6f-88a2-874b4cac91f4.jpg" width="300px"> </div><br>
<div align="center"> <img src="pics/9ae89f16-7905-4a6f-88a2-874b4cac91f4.jpg" width="300px"> </div><br>
因为 dp[j-w] 表示 dp[i-1][j-w]因此不能先求 dp[i][j-w]防止将 dp[i-1][j-w] 覆盖也就是说要先计算 dp[i][j] 再计算 dp[i][j-w]在程序实现时需要按倒序来循环求解
@ -1055,7 +1055,7 @@ public int combinationSum4(int[] nums, int target) {
题目描述交易之后需要有一天的冷却时间
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ffd96b99-8009-487c-8e98-11c9d44ef14f.png" width="300px"> </div><br>
<div align="center"> <img src="pics/ffd96b99-8009-487c-8e98-11c9d44ef14f.png" width="300px"> </div><br>
```java
public int maxProfit(int[] prices) {
@ -1098,7 +1098,7 @@ The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
题目描述每交易一次都要支付一定的费用
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1e2c588c-72b7-445e-aacb-d55dc8a88c29.png" width="300px"> </div><br>
<div align="center"> <img src="pics/1e2c588c-72b7-445e-aacb-d55dc8a88c29.png" width="300px"> </div><br>
```java
public int maxProfit(int[] prices, int fee) {

View File

@ -32,7 +32,7 @@ Output: index1=1, index2=2
数组中的元素最多遍历一次时间复杂度为 O(N)只使用了两个额外变量空间复杂度为 O(1)
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/437cb54c-5970-4ba9-b2ef-2541f7d6c81e.gif" width="200px"> </div><br>
<div align="center"> <img src="pics/437cb54c-5970-4ba9-b2ef-2541f7d6c81e.gif" width="200px"> </div><br>
```java
public int[] twoSum(int[] numbers, int target) {
@ -102,7 +102,7 @@ Explanation: 1 * 1 + 2 * 2 = 5
Given s = "leetcode", return "leotcede".
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a7cb8423-895d-4975-8ef8-662a0029c772.png" width="400px"> </div><br>
<div align="center"> <img src="pics/a7cb8423-895d-4975-8ef8-662a0029c772.png" width="400px"> </div><br>
使用双指针一个指针从头向尾遍历一个指针从尾到头遍历当两个指针都遍历到元音字符时交换这两个元音字符
@ -111,7 +111,7 @@ Given s = "leetcode", return "leotcede".
- 时间复杂度为 O(N)只需要遍历所有元素一次
- 空间复杂度 O(1)只需要使用两个额外变量
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ef25ff7c-0f63-420d-8b30-eafbeea35d11.gif" width="400px"> </div><br>
<div align="center"> <img src="pics/ef25ff7c-0f63-420d-8b30-eafbeea35d11.gif" width="400px"> </div><br>
```java
private final static HashSet<Character> vowels = new HashSet<>(
@ -155,7 +155,7 @@ Explanation: You could delete the character 'c'.
使用双指针可以很容易判断一个字符串是否是回文字符串令一个指针从左到右遍历一个指针从右到左遍历这两个指针同时移动一个位置每次都判断两个指针指向的字符是否相同如果都相同字符串才是具有左右对称性质的回文字符串
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/fcc941ec-134b-4dcd-bc86-1702fd305300.gif" width="250px"> </div><br>
<div align="center"> <img src="pics/fcc941ec-134b-4dcd-bc86-1702fd305300.gif" width="250px"> </div><br>
本题的关键是处理删除一个字符在使用双指针遍历字符串时如果出现两个指针指向的字符不相等的情况我们就试着删除一个字符再判断删除完之后的字符串是否是回文字符串
@ -163,7 +163,7 @@ Explanation: You could delete the character 'c'.
在试着删除字符时我们既可以删除左指针指向的字符也可以删除右指针指向的字符
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/db5f30a7-8bfa-4ecc-ab5d-747c77818964.gif" width="300px"> </div><br>
<div align="center"> <img src="pics/db5f30a7-8bfa-4ecc-ab5d-747c77818964.gif" width="300px"> </div><br>
```java
public boolean validPalindrome(String s) {

View File

@ -200,7 +200,7 @@ public String frequencySort(String s) {
有三种颜色的球算法的目标是将这三种球按颜色顺序正确地排列它其实是三向切分快速排序的一种变种在三向切分快速排序中每次切分都将数组分成三个区间小于切分元素等于切分元素大于切分元素而该算法是将数组分成三个区间等于红色等于白色等于蓝色
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7a3215ec-6fb7-4935-8b0d-cb408208f7cb.png"/> </div><br>
<div align="center"> <img src="pics/7a3215ec-6fb7-4935-8b0d-cb408208f7cb.png"/> </div><br>
## 1. 按颜色进行排序

View File

@ -32,7 +32,7 @@
# BFS
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/95903878-725b-4ed9-bded-bc4aae0792a9.jpg"/> </div><br>
<div align="center"> <img src="pics/95903878-725b-4ed9-bded-bc4aae0792a9.jpg"/> </div><br>
广度优先搜索一层一层地进行遍历每层遍历都以上一层遍历的结果作为起点遍历一个距离能访问到的所有节点需要注意的是遍历过的节点不能再次被遍历
@ -269,7 +269,7 @@ private int getShortestPath(List<Integer>[] graphic, int start, int end) {
# DFS
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/74dc31eb-6baa-47ea-ab1c-d27a0ca35093.png"/> </div><br>
<div align="center"> <img src="pics/74dc31eb-6baa-47ea-ab1c-d27a0ca35093.png"/> </div><br>
广度优先搜索一层一层遍历每一层得到的所有新节点要用队列存储起来以备下一层遍历的时候再遍历
@ -591,7 +591,7 @@ Backtracking回溯属于 DFS。
[Leetcode](https://leetcode.com/problems/letter-combinations-of-a-phone-number/description/) / [力扣](https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/description/)
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9823768c-212b-4b1a-b69a-b3f59e07b977.jpg"/> </div><br>
<div align="center"> <img src="pics/9823768c-212b-4b1a-b69a-b3f59e07b977.jpg"/> </div><br>
```html
Input:Digit string "23"
@ -1194,7 +1194,7 @@ private boolean isPalindrome(String s, int begin, int end) {
[Leetcode](https://leetcode.com/problems/sudoku-solver/description/) / [力扣](https://leetcode-cn.com/problems/sudoku-solver/description/)
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0e8fdc96-83c1-4798-9abe-45fc91d70b9d.png"/> </div><br>
<div align="center"> <img src="pics/0e8fdc96-83c1-4798-9abe-45fc91d70b9d.png"/> </div><br>
```java
private boolean[][] rowsUsed = new boolean[9][10];
@ -1253,7 +1253,7 @@ private int cubeNum(int i, int j) {
[Leetcode](https://leetcode.com/problems/n-queens/description/) / [力扣](https://leetcode-cn.com/problems/n-queens/description/)
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/067b310c-6877-40fe-9dcf-10654e737485.jpg"/> </div><br>
<div align="center"> <img src="pics/067b310c-6877-40fe-9dcf-10654e737485.jpg"/> </div><br>
n\*n 的矩阵中摆放 n 个皇后并且每个皇后不能在同一行同一列同一对角线上求所有的 n 皇后的解
@ -1261,12 +1261,12 @@ private int cubeNum(int i, int j) {
45 度对角线标记数组的长度为 2 \* n - 1通过下图可以明确 (r, c) 的位置所在的数组下标为 r + c
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9c422923-1447-4a3b-a4e1-97e663738187.jpg" width="300px"> </div><br>
<div align="center"> <img src="pics/9c422923-1447-4a3b-a4e1-97e663738187.jpg" width="300px"> </div><br>
135 度对角线标记数组的长度也是 2 \* n - 1(r, c) 的位置所在的数组下标为 n - 1 - (r - c)
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7a85e285-e152-4116-b6dc-3fab27ba9437.jpg" width="300px"> </div><br>
<div align="center"> <img src="pics/7a85e285-e152-4116-b6dc-3fab27ba9437.jpg" width="300px"> </div><br>
```java
private List<List<String>> solutions;

View File

@ -1045,7 +1045,7 @@ private void inOrder(TreeNode node, List<Integer> nums) {
# Trie
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/5c638d59-d4ae-4ba4-ad44-80bdc30f38dd.jpg"/> </div><br>
<div align="center"> <img src="pics/5c638d59-d4ae-4ba4-ad44-80bdc30f38dd.jpg"/> </div><br>
Trie又称前缀树或字典树用于判断字符串是否存在或者是否具有某种字符串前缀

View File

@ -35,7 +35,7 @@ Output: 2
证明假设在某次选择中贪心策略选择给当前满足度最小的孩子分配第 m 个饼干 m 个饼干为可以满足该孩子的最小饼干假设存在一种最优策略可以给该孩子分配第 n 个饼干并且 m < n我们可以发现经过这一轮分配贪心策略分配后剩下的饼干一定有一个比最优策略来得大因此在后续的分配中贪心策略一定能满足更多的孩子也就是说不存在比贪心策略更优的策略即贪心策略就是最优策略
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e69537d2-a016-4676-b169-9ea17eeb9037.gif" width="430px"> </div><br>
<div align="center"> <img src="pics/e69537d2-a016-4676-b169-9ea17eeb9037.gif" width="430px"> </div><br>
```java
public int findContentChildren(int[] grid, int[] size) {

View File

@ -165,7 +165,7 @@ Linux 发行版是 Linux 内核及各种应用软件的集成版本。
- 编辑模式Insert mode按下 "i" 等按键之后进入可以对文本进行编辑
- 指令列模式Bottom-line mode按下 ":" 按键之后进入用于保存退出等操作
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b5e9fa4d-78d3-4176-8273-756d970742c7.png" width="500"/> </div><br>
<div align="center"> <img src="pics/b5e9fa4d-78d3-4176-8273-756d970742c7.png" width="500"/> </div><br>
在指令列模式下有以下命令用于离开或者保存文件
@ -199,25 +199,25 @@ GNU 计划,译为革奴计划,它的目标是创建一套完全自由的操
IDEATA全称 Advanced Technology Attachment接口速度最大为 133MB/s因为并口线的抗干扰性太差且排线占用空间较大不利电脑内部散热已逐渐被 SATA 所取代
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/924914c0-660c-4e4a-bbc0-1df1146e7516.jpg" width="400"/> </div><br>
<div align="center"> <img src="pics/924914c0-660c-4e4a-bbc0-1df1146e7516.jpg" width="400"/> </div><br>
### 2. SATA
SATA 全称 Serial ATA也就是使用串口的 ATA 接口抗干扰性强且对数据线的长度要求比 ATA 低很多支持热插拔等功能SATA-II 的接口速度为 300MiB/s SATA-III 标准可达到 600MiB/s 的传输速度SATA 的数据线也比 ATA 的细得多有利于机箱内的空气流通整理线材也比较方便
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f9f2a16b-4843-44d1-9759-c745772e9bcf.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/f9f2a16b-4843-44d1-9759-c745772e9bcf.jpg" width=""/> </div><br>
### 3. SCSI
SCSI 全称是 Small Computer System Interface小型机系统接口SCSI 硬盘广为工作站以及个人电脑以及服务器所使用因此会使用较为先进的技术如碟片转速 15000rpm 的高转速且传输时 CPU 占用率较低但是单价也比相同容量的 ATA SATA 硬盘更加昂贵
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f0574025-c514-49f5-a591-6d6a71f271f7.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/f0574025-c514-49f5-a591-6d6a71f271f7.jpg" width=""/> </div><br>
### 4. SAS
SASSerial Attached SCSI是新一代的 SCSI 技术 SATA 硬盘相同都是采取序列式技术以获得更高的传输速度可达到 6Gb/s此外也通过缩小连接线改善系统内部空间等
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6729baa0-57d7-4817-b3aa-518cbccf824c.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/6729baa0-57d7-4817-b3aa-518cbccf824c.jpg" width=""/> </div><br>
## 磁盘的文件名
@ -252,7 +252,7 @@ GPT 没有扩展分区概念,都是主分区,每个 LBA 可以分 4 个分
MBR 不支持 2.2 TB 以上的硬盘GPT 则最多支持到 2<sup>33</sup> TB = 8 ZB
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/GUID_Partition_Table_Scheme.svg.png" width="400"/> </div><br>
<div align="center"> <img src="pics/GUID_Partition_Table_Scheme.svg.png" width="400"/> </div><br>
## 开机检测程序
@ -260,7 +260,7 @@ MBR 不支持 2.2 TB 以上的硬盘GPT 则最多支持到 2<sup>33</sup> TB
BIOSBasic Input/Output System基本输入输出系统它是一个固件嵌入在硬件中的软件BIOS 程序存放在断电后内容不会丢失的只读内存中
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/50831a6f-2777-46ea-a571-29f23c85cc21.jpg"/> </div><br>
<div align="center"> <img src="pics/50831a6f-2777-46ea-a571-29f23c85cc21.jpg"/> </div><br>
BIOS 是开机的时候计算机执行的第一个程序这个程序知道可以开机的磁盘并读取磁盘第一个扇区的主要开机记录MBR由主要开机记录MBR执行其中的开机管理程序这个开机管理程序会加载操作系统的核心文件
@ -268,7 +268,7 @@ BIOS 是开机的时候计算机执行的第一个程序,这个程序知道可
下图中第一扇区的主要开机记录MBR中的开机管理程序提供了两个选单M1M2M1 指向了 Windows 操作系统 M2 指向其它分区的启动扇区里面包含了另外一个开机管理程序提供了一个指向 Linux 的选单
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f900f266-a323-42b2-bc43-218fdb8811a8.jpg" width="600"/> </div><br>
<div align="center"> <img src="pics/f900f266-a323-42b2-bc43-218fdb8811a8.jpg" width="600"/> </div><br>
安装多重引导最好先安装 Windows 再安装 Linux因为安装 Windows 时会覆盖掉主要开机记录MBR Linux 可以选择将开机管理程序安装在主要开机记录MBR或者其它分区的启动扇区并且可以设置开机管理程序的选单
@ -294,17 +294,17 @@ BIOS 不可以读取 GPT 分区表,而 UEFI 可以。
- superblock记录文件系统的整体信息包括 inode block 的总量使用量剩余量以及文件系统的格式与相关信息等
- block bitmap记录 block 是否被使用的位图
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/BSD_disk.png" width="800"/> </div><br>
<div align="center"> <img src="pics/BSD_disk.png" width="800"/> </div><br>
## 文件读取
对于 Ext2 文件系统当要读取一个文件的内容时先在 inode 中查找文件内容所在的所有 block然后把所有 block 的内容读出来
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/12a65cc6-20e0-4706-9fe6-3ba49413d7f6.png" width="500px"> </div><br>
<div align="center"> <img src="pics/12a65cc6-20e0-4706-9fe6-3ba49413d7f6.png" width="500px"> </div><br>
而对于 FAT 文件系统它没有 inode每个 block 中存储着下一个 block 的编号
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/5b718e86-7102-4bb6-8ca5-d1dd791530c5.png" width="500px"> </div><br>
<div align="center"> <img src="pics/5b718e86-7102-4bb6-8ca5-d1dd791530c5.png" width="500px"> </div><br>
## 磁盘碎片
@ -341,7 +341,7 @@ inode 具有以下特点:
inode 中记录了文件内容所在的 block 编号但是每个 block 非常小一个大文件随便都需要几十万的 block而一个 inode 大小有限无法直接引用这么多 block 编号因此引入了间接双间接三间接引用间接引用让 inode 记录的引用 block 块记录引用信息
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/inode_with_signatures.jpg" width="600"/> </div><br>
<div align="center"> <img src="pics/inode_with_signatures.jpg" width="600"/> </div><br>
## 目录
@ -367,7 +367,7 @@ ext3/ext4 文件系统引入了日志功能,可以利用日志来修复文件
- /usr (unix software resource)所有系统默认软件都会安装到这个目录
- /var (variable)存放系统或程序运行过程中的数据文件
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/linux-filesystem.png" width=""/> </div><br>
<div align="center"> <img src="pics/linux-filesystem.png" width=""/> </div><br>
# 文件
@ -534,7 +534,7 @@ cp [-adfilprsu] source destination
## 链接
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1e46fd03-0cda-4d60-9b1c-0c256edaf6b2.png" width="450px"> </div><br>
<div align="center"> <img src="pics/1e46fd03-0cda-4d60-9b1c-0c256edaf6b2.png" width="450px"> </div><br>
```html
@ -662,7 +662,7 @@ example: find . -name "shadow*"
+44 -4 的指示的时间范围如下
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/658fc5e7-79c0-4247-9445-d69bf194c539.png" width=""/> </div><br>
<div align="center"> <img src="pics/658fc5e7-79c0-4247-9445-d69bf194c539.png" width=""/> </div><br>
** 与文件拥有者和所属群组有关的选项**
@ -1176,7 +1176,7 @@ dmtsai lines: 5 columns: 9
| T | stopped (either by a job control signal or because it is being traced) <br> 结束进程既可以被作业控制信号结束也可能是正在被追踪|
<br>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2bab4127-3e7d-48cc-914e-436be859fb05.png" width="490px"/> </div><br>
<div align="center"> <img src="pics/2bab4127-3e7d-48cc-914e-436be859fb05.png" width="490px"/> </div><br>
## SIGCHLD
@ -1189,7 +1189,7 @@ dmtsai lines: 5 columns: 9
在子进程退出时它的进程描述符不会立即释放这是为了让父进程得到子进程信息父进程通过 wait() waitpid() 来获得一个已经退出的子进程的信息
<div align="center"> <!-- <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/flow.png" width=""/> --> </div><br>
<div align="center"> <!-- <img src="pics/flow.png" width=""/> --> </div><br>
## wait()

View File

@ -42,7 +42,7 @@ B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具
B+ Tree 一个节点中的 key 从左到右非递减排列如果某个指针的左右相邻 key 分别是 key<sub>i</sub> key<sub>i+1</sub>且不为 null则该指针指向节点的所有 key 大于等于 key<sub>i</sub> 且小于等于 key<sub>i+1</sub>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/33576849-9275-47bb-ada7-8ded5f5e7c73.png" width="350px"> </div><br>
<div align="center"> <img src="pics/33576849-9275-47bb-ada7-8ded5f5e7c73.png" width="350px"> </div><br>
### 2. 操作
@ -84,11 +84,11 @@ B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具
InnoDB B+Tree 索引分为主索引和辅助索引主索引的叶子节点 data 域记录着完整的数据记录这种索引方式被称为聚簇索引因为无法把数据行存放在两个不同的地方所以一个表只能有一个聚簇索引
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/45016e98-6879-4709-8569-262b2d6d60b9.png" width="350px"> </div><br>
<div align="center"> <img src="pics/45016e98-6879-4709-8569-262b2d6d60b9.png" width="350px"> </div><br>
辅助索引的叶子节点的 data 域记录着主键的值因此在使用辅助索引进行查找时需要先查找到主键值然后再到主索引中进行查找
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7c349b91-050b-4d72-a7f8-ec86320307ea.png" width="350px"> </div><br>
<div align="center"> <img src="pics/7c349b91-050b-4d72-a7f8-ec86320307ea.png" width="350px"> </div><br>
### 2. 哈希索引
@ -350,7 +350,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
当一个表的数据不断增多时Sharding 是必然的选择它可以将数据分布到集群的不同节点上从而缓存单个数据库的压力
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/63c2909f-0c5f-496f-9fe5-ee9176b31aba.jpg" width=""> </div><br>
<div align="center"> <img src="pics/63c2909f-0c5f-496f-9fe5-ee9176b31aba.jpg" width=""> </div><br>
## 垂直切分
@ -358,7 +358,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
在数据库的层面使用垂直切分将按数据库中表的密集程度部署到不同的库中例如将原来的电商数据库垂直切分成商品数据库用户数据库等
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e130e5b8-b19a-4f1e-b860-223040525cf6.jpg" width=""> </div><br>
<div align="center"> <img src="pics/e130e5b8-b19a-4f1e-b860-223040525cf6.jpg" width=""> </div><br>
## Sharding 策略
@ -392,7 +392,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
- **I/O 线程** 负责从主服务器上读取二进制日志并写入从服务器的中继日志Relay log
- **SQL 线程** 负责读取中继日志解析出主服务器已经执行的数据更改并在从服务器中重放Replay
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/master-slave.png" width=""> </div><br>
<div align="center"> <img src="pics/master-slave.png" width=""> </div><br>
## 读写分离
@ -406,7 +406,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
读写分离常用代理方式来实现代理服务器接收应用层传来的读写请求然后决定转发到哪个服务器
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/master-slave-proxy.png" width=""> </div><br>
<div align="center"> <img src="pics/master-slave-proxy.png" width=""> </div><br>
# 参考资料

View File

@ -67,7 +67,7 @@ Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,
## STRING
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6019b2db-bc3e-4408-b6d8-96025f4481d6.png" width="400"/> </div><br>
<div align="center"> <img src="pics/6019b2db-bc3e-4408-b6d8-96025f4481d6.png" width="400"/> </div><br>
```html
> set hello world
@ -82,7 +82,7 @@ OK
## LIST
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/fb327611-7e2b-4f2f-9f5b-38592d408f07.png" width="400"/> </div><br>
<div align="center"> <img src="pics/fb327611-7e2b-4f2f-9f5b-38592d408f07.png" width="400"/> </div><br>
```html
> rpush list-key item
@ -110,7 +110,7 @@ OK
## SET
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/cd5fbcff-3f35-43a6-8ffa-082a93ce0f0e.png" width="400"/> </div><br>
<div align="center"> <img src="pics/cd5fbcff-3f35-43a6-8ffa-082a93ce0f0e.png" width="400"/> </div><br>
```html
> sadd set-key item
@ -144,7 +144,7 @@ OK
## HASH
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7bd202a7-93d4-4f3a-a878-af68ae25539a.png" width="400"/> </div><br>
<div align="center"> <img src="pics/7bd202a7-93d4-4f3a-a878-af68ae25539a.png" width="400"/> </div><br>
```html
> hset hash-key sub-key1 value1
@ -175,7 +175,7 @@ OK
## ZSET
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1202b2d6-9469-4251-bd47-ca6034fb6116.png" width="400"/> </div><br>
<div align="center"> <img src="pics/1202b2d6-9469-4251-bd47-ca6034fb6116.png" width="400"/> </div><br>
```html
> zadd zset-key 728 member1
@ -317,11 +317,11 @@ int dictRehash(dict *d, int n) {
跳跃表是基于多指针有序链表实现的可以看成多个有序链表
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/beba612e-dc5b-4fc2-869d-0b23408ac90a.png" width="600px"/> </div><br>
<div align="center"> <img src="pics/beba612e-dc5b-4fc2-869d-0b23408ac90a.png" width="600px"/> </div><br>
在查找时从上层指针开始查找找到对应的区间之后再到下一层去查找下图演示了查找 22 的过程
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0ea37ee2-c224-4c79-b895-e131c6805c40.png" width="600px"/> </div><br>
<div align="center"> <img src="pics/0ea37ee2-c224-4c79-b895-e131c6805c40.png" width="600px"/> </div><br>
与红黑树等平衡树相比跳跃表具有以下优点
@ -472,7 +472,7 @@ Redis 服务器是一个事件驱动程序。
Redis 基于 Reactor 模式开发了自己的网络事件处理器使用 I/O 多路复用程序来同时监听多个套接字并将到达的事件传送给文件事件分派器分派器会根据套接字产生的事件类型调用相应的事件处理器
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9ea86eb5-000a-4281-b948-7b567bd6f1d8.png" width=""/> </div><br>
<div align="center"> <img src="pics/9ea86eb5-000a-4281-b948-7b567bd6f1d8.png" width=""/> </div><br>
## 时间事件
@ -525,7 +525,7 @@ def main():
从事件处理的角度来看服务器运行流程如下
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c0a9fa91-da2e-4892-8c9f-80206a6f7047.png" width="350"/> </div><br>
<div align="center"> <img src="pics/c0a9fa91-da2e-4892-8c9f-80206a6f7047.png" width="350"/> </div><br>
# 十一复制
@ -545,7 +545,7 @@ def main():
随着负载不断上升主服务器可能无法很快地更新所有从服务器或者重新连接和重新同步从服务器将导致系统超载为了解决这个问题可以创建一个中间层来分担主服务器的复制工作中间层的服务器是最上层服务器的从服务器又是最下层服务器的主服务器
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/395a9e83-b1a1-4a1d-b170-d081e7bb5bab.png" width="600"/> </div><br>
<div align="center"> <img src="pics/395a9e83-b1a1-4a1d-b170-d081e7bb5bab.png" width="600"/> </div><br>
# 十二Sentinel
@ -580,7 +580,7 @@ Sentinel哨兵可以监听集群中的服务器并在主服务器进入
Redis 没有关系型数据库中的表这一概念来将同种类型的数据存放在一起而是使用命名空间的方式来实现这一功能键名的前面部分存储命名空间后面部分的内容存储 ID通常使用 : 来进行分隔例如下面的 HASH 的键名为 article:92617其中 article 为命名空间ID 92617
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7c54de21-e2ff-402e-bc42-4037de1c1592.png" width="400"/> </div><br>
<div align="center"> <img src="pics/7c54de21-e2ff-402e-bc42-4037de1c1592.png" width="400"/> </div><br>
## 点赞功能
@ -588,13 +588,13 @@ Redis 没有关系型数据库中的表这一概念来将同种类型的数据
为了节约内存规定一篇文章发布满一周之后就不能再对它进行投票而文章的已投票集合也会被删除可以为文章的已投票集合设置一个一周的过期时间就能实现这个规定
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/485fdf34-ccf8-4185-97c6-17374ee719a0.png" width="400"/> </div><br>
<div align="center"> <img src="pics/485fdf34-ccf8-4185-97c6-17374ee719a0.png" width="400"/> </div><br>
## 对文章进行排序
为了按发布时间和点赞数进行排序可以建立一个文章发布时间的有序集合和一个文章点赞数的有序集合下图中的 score 就是这里所说的点赞数下面所示的有序集合分值并不直接是时间和点赞数而是根据时间和点赞数间接计算出来的
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f7d170a3-e446-4a64-ac2d-cb95028f81a8.png" width="800"/> </div><br>
<div align="center"> <img src="pics/f7d170a3-e446-4a64-ac2d-cb95028f81a8.png" width="800"/> </div><br>
# 参考资料

View File

@ -46,7 +46,7 @@ Unix 有五种 I/O 模型:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1492928416812_4.png"/> </div><br>
<div align="center"> <img src="pics/1492928416812_4.png"/> </div><br>
## 非阻塞式 I/O
@ -54,7 +54,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
由于 CPU 要处理更多的系统调用因此这种模型的 CPU 利用率比较低
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1492929000361_5.png"/> </div><br>
<div align="center"> <img src="pics/1492929000361_5.png"/> </div><br>
## I/O 复用
@ -64,7 +64,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
如果一个 Web 服务器没有 I/O 复用那么每一个 Socket 连接都需要创建一个线程去处理如果同时有几万个连接那么就需要创建相同数量的线程相比于多进程和多线程技术I/O 复用不需要进程线程创建和切换的开销系统开销更小
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1492929444818_6.png"/> </div><br>
<div align="center"> <img src="pics/1492929444818_6.png"/> </div><br>
## 信号驱动 I/O
@ -72,7 +72,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
相比于非阻塞式 I/O 的轮询方式信号驱动 I/O CPU 利用率更高
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1492929553651_7.png"/> </div><br>
<div align="center"> <img src="pics/1492929553651_7.png"/> </div><br>
## 异步 I/O
@ -80,7 +80,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
异步 I/O 与信号驱动 I/O 的区别在于异步 I/O 的信号是通知应用进程 I/O 完成而信号驱动 I/O 的信号是通知应用进程可以开始 I/O
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1492930243286_8.png"/> </div><br>
<div align="center"> <img src="pics/1492930243286_8.png"/> </div><br>
## 五大 I/O 模型比较
@ -91,7 +91,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
非阻塞式 I/O 信号驱动 I/O 和异步 I/O 在第一阶段不会阻塞
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1492928105791_3.png"/> </div><br>
<div align="center"> <img src="pics/1492928105791_3.png"/> </div><br>
# I/O 复用

View File

@ -48,11 +48,11 @@
- minmax 表示数量范围
- firstlast 表示访问空间的包含范围
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7d97dde0-0695-4707-bb68-e6c13a2e1b45.png" width="200px"> </div><br>
<div align="center"> <img src="pics/7d97dde0-0695-4707-bb68-e6c13a2e1b45.png" width="200px"> </div><br>
- beginend 表示访问空间的排除范围 end 不包含尾部
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d85870db-f28c-48c3-9d24-85a36fda5e51.png" width="200px"> </div><br>
<div align="center"> <img src="pics/d85870db-f28c-48c3-9d24-85a36fda5e51.png" width="200px"> </div><br>
# 良好的代码风格

View File

@ -70,7 +70,7 @@ EXPIRE 指令可以为一个键值对设置一个过期时间,从而避免了
Zookeeper 提供了一种树形结构的命名空间/app1/p_1 节点的父节点为 /app1
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/aefa8042-15fa-4e8b-9f50-20b282a2c624.png" width="320px"> </div><br>
<div align="center"> <img src="pics/aefa8042-15fa-4e8b-9f50-20b282a2c624.png" width="320px"> </div><br>
### 2. 节点类型
@ -118,7 +118,7 @@ Zookeeper 提供了一种树形结构的命名空间,/app1/p_1 节点的父节
协调者询问参与者事务是否执行成功参与者发回事务执行结果询问可以看成一种投票需要参与者都同意才能执行
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/44d33643-1004-43a3-b99a-4d688a08d0a1.png" width="550px"> </div><br>
<div align="center"> <img src="pics/44d33643-1004-43a3-b99a-4d688a08d0a1.png" width="550px"> </div><br>
#### 1.2 提交阶段
@ -126,7 +126,7 @@ Zookeeper 提供了一种树形结构的命名空间,/app1/p_1 节点的父节
需要注意的是在准备阶段参与者执行了事务但是还未提交只有在提交阶段接收到协调者发来的通知后才进行提交或者回滚
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d2ae9932-e2b1-4191-8ee9-e573f36d3895.png" width="550px"> </div><br>
<div align="center"> <img src="pics/d2ae9932-e2b1-4191-8ee9-e573f36d3895.png" width="550px"> </div><br>
### 2. 存在的问题
@ -154,14 +154,14 @@ Zookeeper 提供了一种树形结构的命名空间,/app1/p_1 节点的父节
2. 之后将本地消息表中的消息转发到消息队列中如果转发成功则将消息从本地消息表中删除否则继续重新转发
3. 在分布式事务操作的另一方从消息队列中读取一个消息并执行消息中的操作
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/476329d4-e2ef-4f7b-8ac9-a52a6f784600.png" width="740px"> </div><br>
<div align="center"> <img src="pics/476329d4-e2ef-4f7b-8ac9-a52a6f784600.png" width="740px"> </div><br>
# CAP
分布式系统不可能同时满足一致性CConsistency可用性AAvailability和分区容忍性PPartition Tolerance最多只能同时满足其中两项
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a14268b3-b937-4ffa-a34a-4cc53071686b.jpg" width="450px"> </div><br>
<div align="center"> <img src="pics/a14268b3-b937-4ffa-a34a-4cc53071686b.jpg" width="450px"> </div><br>
## 一致性
@ -225,7 +225,7 @@ ACID 要求强一致性,通常运用在传统的数据库系统上。而 BASE
- 接受者Acceptor对每个提议进行投票
- 告知者Learner被告知投票的结果不参与投票过程
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b988877c-0f0a-4593-916d-de2081320628.jpg"/> </div><br>
<div align="center"> <img src="pics/b988877c-0f0a-4593-916d-de2081320628.jpg"/> </div><br>
## 执行过程
@ -235,19 +235,19 @@ ACID 要求强一致性,通常运用在传统的数据库系统上。而 BASE
下图演示了两个 Proposer 和三个 Acceptor 的系统中运行该算法的初始过程每个 Proposer 都会向所有 Acceptor 发送 Prepare 请求
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1a9977e4-2f5c-49a6-aec9-f3027c9f46a7.png"/> </div><br>
<div align="center"> <img src="pics/1a9977e4-2f5c-49a6-aec9-f3027c9f46a7.png"/> </div><br>
Acceptor 接收到一个 Prepare 请求包含的提议为 [n1, v1]并且之前还未接收过 Prepare 请求那么发送一个 Prepare 响应设置当前接收到的提议为 [n1, v1]并且保证以后不会再接受序号小于 n1 的提议
如下图Acceptor X 在收到 [n=2, v=8] Prepare 请求时由于之前没有接收过提议因此就发送一个 [no previous] Prepare 响应设置当前接收到的提议为 [n=2, v=8]并且保证以后不会再接受序号小于 2 的提议其它的 Acceptor 类似
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/fb44307f-8e98-4ff7-a918-31dacfa564b4.jpg"/> </div><br>
<div align="center"> <img src="pics/fb44307f-8e98-4ff7-a918-31dacfa564b4.jpg"/> </div><br>
如果 Acceptor 接收到一个 Prepare 请求包含的提议为 [n2, v2]并且之前已经接收过提议 [n1, v1]如果 n1 > n2那么就丢弃该提议请求否则发送 Prepare 响应 Prepare 响应包含之前已经接收过的提议 [n1, v1]设置当前接收到的提议为 [n2, v2]并且保证以后不会再接受序号小于 n2 的提议
如下图Acceptor Z 收到 Proposer A 发来的 [n=2, v=8] Prepare 请求由于之前已经接收过 [n=4, v=5] 的提议并且 n > 2因此就抛弃该提议请求Acceptor X 收到 Proposer B 发来的 [n=4, v=5] Prepare 请求因为之前接收到的提议为 [n=2, v=8]并且 2 <= 4因此就发送 [n=2, v=8] Prepare 响应设置当前接收到的提议为 [n=4, v=5]并且保证以后不会再接受序号小于 4 的提议Acceptor Y 类似
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2bcc58ad-bf7f-485c-89b5-e7cafc211ce2.jpg"/> </div><br>
<div align="center"> <img src="pics/2bcc58ad-bf7f-485c-89b5-e7cafc211ce2.jpg"/> </div><br>
### 2. Accept 阶段
@ -257,13 +257,13 @@ Proposer A 接收到两个 Prepare 响应之后,就发送 [n=2, v=8] Accept
Proposer B 过后也收到了两个 Prepare 响应因此也开始发送 Accept 请求需要注意的是Accept 请求的 v 需要取它收到的最大提议编号对应的 v 也就是 8因此它发送 [n=4, v=8] Accept 请求
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9b838aee-0996-44a5-9b0f-3d1e3e2f5100.png"/> </div><br>
<div align="center"> <img src="pics/9b838aee-0996-44a5-9b0f-3d1e3e2f5100.png"/> </div><br>
### 3. Learn 阶段
Acceptor 接收到 Accept 请求时如果序号大于等于该 Acceptor 承诺的最小序号那么就发送 Learn 提议给所有的 Learner Learner 发现有大多数的 Acceptor 接收了某个提议那么该提议的提议值就被 Paxos 选择出来
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/bf667594-bb4b-4634-bf9b-0596a45415ba.jpg"/> </div><br>
<div align="center"> <img src="pics/bf667594-bb4b-4634-bf9b-0596a45415ba.jpg"/> </div><br>
## 约束条件
@ -291,47 +291,47 @@ Raft 也是分布式一致性协议,主要是用来竞选主节点。
- 下图展示一个分布式系统的最初阶段此时只有 Follower 没有 LeaderNode A 等待一个随机的竞选超时时间之后没收到 Leader 发来的心跳包因此进入竞选阶段
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/111521118015898.gif"/> </div><br>
<div align="center"> <img src="pics/111521118015898.gif"/> </div><br>
- 此时 Node A 发送投票请求给其它所有节点
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/111521118445538.gif"/> </div><br>
<div align="center"> <img src="pics/111521118445538.gif"/> </div><br>
- 其它节点会对请求进行回复如果超过一半的节点回复了那么该 Candidate 就会变成 Leader
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/111521118483039.gif"/> </div><br>
<div align="center"> <img src="pics/111521118483039.gif"/> </div><br>
- 之后 Leader 会周期性地发送心跳包给 FollowerFollower 接收到心跳包会重新开始计时
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/111521118640738.gif"/> </div><br>
<div align="center"> <img src="pics/111521118640738.gif"/> </div><br>
## 多个 Candidate 竞选
- 如果有多个 Follower 成为 Candidate并且所获得票数相同那么就需要重新开始投票例如下图中 Node B Node D 都获得两票需要重新开始投票
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/111521119203347.gif"/> </div><br>
<div align="center"> <img src="pics/111521119203347.gif"/> </div><br>
- 由于每个节点设置的随机竞选超时时间不同因此下一次再次出现多个 Candidate 并获得同样票数的概率很低
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/111521119368714.gif"/> </div><br>
<div align="center"> <img src="pics/111521119368714.gif"/> </div><br>
## 数据同步
- 来自客户端的修改都会被传入 Leader注意该修改还未被提交只是写入日志中
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/71550414107576.gif"/> </div><br>
<div align="center"> <img src="pics/71550414107576.gif"/> </div><br>
- Leader 会把修改复制到所有 Follower
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/91550414131331.gif"/> </div><br>
<div align="center"> <img src="pics/91550414131331.gif"/> </div><br>
- Leader 会等待大多数的 Follower 也进行了修改然后才将修改提交
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/101550414151983.gif"/> </div><br>
<div align="center"> <img src="pics/101550414151983.gif"/> </div><br>
- 此时 Leader 会通知的所有 Follower 让它们也提交修改此时所有节点的值达成一致
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/111550414182638.gif"/> </div><br>
<div align="center"> <img src="pics/111550414182638.gif"/> </div><br>
# 参考

View File

@ -26,13 +26,13 @@
<!--<div align="center"><img src="https://latex.codecogs.com/gif.latex?f(n)=\left\{\begin{array}{rcl}0&&{n=0}\\1&&{n=1}\\f(n-1)+f(n-2)&&{n>1}\end{array}\right." class="mathjax-pic"/></div> <br> -->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/45be9587-6069-4ab7-b9ac-840db1a53744.jpg" width="300px"> </div><br>
<div align="center"> <img src="pics/45be9587-6069-4ab7-b9ac-840db1a53744.jpg" width="300px"> </div><br>
## 解题思路
如果使用递归求解会重复计算一些子问题例如计算 f(4) 需要计算 f(3) f(2)计算 f(3) 需要计算 f(2) f(1)可以看到 f(2) 被重复计算了
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c13e2a3d-b01c-4a08-a69b-db2c4e821e09.png" width="350px"/> </div><br>
<div align="center"> <img src="pics/c13e2a3d-b01c-4a08-a69b-db2c4e821e09.png" width="350px"/> </div><br>
递归是将一个问题划分成多个子问题求解动态规划也是如此但是动态规划会把子问题的解缓存起来从而避免重复求解子问题
@ -92,23 +92,23 @@ public class Solution {
我们可以用 2\*1 的小矩形横着或者竖着去覆盖更大的矩形请问用 n 2\*1 的小矩形无重叠地覆盖一个 2\*n 的大矩形总共有多少种方法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b903fda8-07d0-46a7-91a7-e803892895cf.gif" width="100px"> </div><br>
<div align="center"> <img src="pics/b903fda8-07d0-46a7-91a7-e803892895cf.gif" width="100px"> </div><br>
## 解题思路
n 1 只有一种覆盖方法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f6e146f1-57ad-411b-beb3-770a142164ef.png" width="100px"> </div><br>
<div align="center"> <img src="pics/f6e146f1-57ad-411b-beb3-770a142164ef.png" width="100px"> </div><br>
n 2 有两种覆盖方法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/fb3b8f7a-4293-4a38-aae1-62284db979a3.png" width="200px"> </div><br>
<div align="center"> <img src="pics/fb3b8f7a-4293-4a38-aae1-62284db979a3.png" width="200px"> </div><br>
要覆盖 2\*n 的大矩形可以先覆盖 2\*1 的矩形再覆盖 2\*(n-1) 的矩形或者先覆盖 2\*2 的矩形再覆盖 2\*(n-2) 的矩形而覆盖 2\*(n-1) 2\*(n-2) 的矩形可以看成子问题该问题的递推公式如下
<!-- <div align="center"><img src="https://latex.codecogs.com/gif.latex?f(n)=\left\{\begin{array}{rcl}1&&{n=1}\\2&&{n=2}\\f(n-1)+f(n-2)&&{n>1}\end{array}\right." class="mathjax-pic"/></div> <br> -->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/508c6e52-9f93-44ed-b6b9-e69050e14807.jpg" width="350px"> </div><br>
<div align="center"> <img src="pics/508c6e52-9f93-44ed-b6b9-e69050e14807.jpg" width="350px"> </div><br>
```java
public int RectCover(int n) {
@ -133,21 +133,21 @@ public int RectCover(int n) {
一只青蛙一次可以跳上 1 级台阶也可以跳上 2 求该青蛙跳上一个 n 级的台阶总共有多少种跳法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9dae7475-934f-42e5-b3b3-12724337170a.png" width="380px"> </div><br>
<div align="center"> <img src="pics/9dae7475-934f-42e5-b3b3-12724337170a.png" width="380px"> </div><br>
## 解题思路
n = 1 只有一种跳法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/72aac98a-d5df-4bfa-a71a-4bb16a87474c.png" width="250px"> </div><br>
<div align="center"> <img src="pics/72aac98a-d5df-4bfa-a71a-4bb16a87474c.png" width="250px"> </div><br>
n = 2 有两种跳法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1b80288d-1b35-4cd3-aa17-7e27ab9a2389.png" width="300px"> </div><br>
<div align="center"> <img src="pics/1b80288d-1b35-4cd3-aa17-7e27ab9a2389.png" width="300px"> </div><br>
n 阶台阶可以先跳 1 阶台阶再跳 n-1 阶台阶或者先跳 2 阶台阶再跳 n-2 阶台阶 n-1 n-2 阶台阶的跳法可以看成子问题该问题的递推公式为
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/508c6e52-9f93-44ed-b6b9-e69050e14807.jpg" width="350px"> </div><br>
<div align="center"> <img src="pics/508c6e52-9f93-44ed-b6b9-e69050e14807.jpg" width="350px"> </div><br>
```java
public int JumpFloor(int n) {
@ -172,7 +172,7 @@ public int JumpFloor(int n) {
一只青蛙一次可以跳上 1 级台阶也可以跳上 2 ... 它也可以跳上 n 求该青蛙跳上一个 n 级的台阶总共有多少种跳法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/cd411a94-3786-4c94-9e08-f28320e010d5.png" width="380px"> </div><br>
<div align="center"> <img src="pics/cd411a94-3786-4c94-9e08-f28320e010d5.png" width="380px"> </div><br>
## 解题思路
@ -232,13 +232,13 @@ public int JumpFloorII(int target) {
把一个数组最开始的若干个元素搬到数组的末尾我们称之为数组的旋转输入一个非递减排序的数组的一个旋转输出旋转数组的最小元素
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0038204c-4b8a-42a5-921d-080f6674f989.png" width="210px"> </div><br>
<div align="center"> <img src="pics/0038204c-4b8a-42a5-921d-080f6674f989.png" width="210px"> </div><br>
## 解题思路
将旋转数组对半分可以得到一个包含最小元素的新旋转数组以及一个非递减排序的数组新的旋转数组的数组元素是原数组的一半从而将问题规模减少了一半这种折半性质的算法的时间复杂度为 O(logN)为了方便这里将 log<sub>2</sub>N 写为 logN
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/424f34ab-a9fd-49a6-9969-d76b42251365.png" width="300px"> </div><br>
<div align="center"> <img src="pics/424f34ab-a9fd-49a6-9969-d76b42251365.png" width="300px"> </div><br>
此时问题的关键在于确定对半分得到的两个数组哪一个是旋转数组哪一个是非递减数组我们很容易知道非递减数组的第一个元素一定小于等于最后一个元素
@ -300,13 +300,13 @@ private int minNumber(int[] nums, int l, int h) {
例如下面的矩阵包含了一条 bfce 路径
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1db1c7ea-0443-478b-8df9-7e33b1336cc4.png" width="200px"> </div><br>
<div align="center"> <img src="pics/1db1c7ea-0443-478b-8df9-7e33b1336cc4.png" width="200px"> </div><br>
## 解题思路
使用回溯法backtracking进行求解它是一种暴力搜索方法通过搜索所有可能的结果来求解问题回溯法在一次搜索结束时需要进行回溯回退将这一次搜索过程中设置的状态进行清除从而开始一次新的搜索过程例如下图示例中 f 开始下一步有 4 种搜索可能如果先搜索 b需要将 b 标记为已经使用防止重复使用在这一次搜索结束之后需要将 b 的已经使用状态清除并搜索 c
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/dc964b86-7a08-4bde-a3d9-e6ddceb29f98.png" width="200px"> </div><br>
<div align="center"> <img src="pics/dc964b86-7a08-4bde-a3d9-e6ddceb29f98.png" width="200px"> </div><br>
本题的输入是数组而不是矩阵二维数组因此需要先将数组转换成矩阵
@ -522,7 +522,7 @@ public int NumberOf1(int n) {
<!--<div align="center"><img src="https://latex.codecogs.com/gif.latex?x^n=\left\{\begin{array}{rcl}(x*x)^{n/2}&&{n\%2=0}\\x*(x*x)^{n/2}&&{n\%2=1}\end{array}\right." class="mathjax-pic"/></div> <br>-->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/48b1d459-8832-4e92-938a-728aae730739.jpg" width="330px"> </div><br>
<div align="center"> <img src="pics/48b1d459-8832-4e92-938a-728aae730739.jpg" width="330px"> </div><br>
因为 (x\*x)<sup>n/2</sup> 可以通过递归求解并且每次递归 n 都减小一半因此整个算法的时间复杂度为 O(logN)
@ -592,11 +592,11 @@ private void printNumber(char[] number) {
如果该节点不是尾节点那么可以直接将下一个节点的值赋给该节点然后令该节点指向下下个节点再删除下一个节点时间复杂度为 O(1)
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1176f9e1-3442-4808-a47a-76fbaea1b806.png" width="600"/> </div><br>
<div align="center"> <img src="pics/1176f9e1-3442-4808-a47a-76fbaea1b806.png" width="600"/> </div><br>
否则就需要先遍历链表找到节点的前一个节点然后让前一个节点指向 null时间复杂度为 O(N)
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4bf8d0ba-36f0-459e-83a0-f15278a5a157.png" width="600"/> </div><br>
<div align="center"> <img src="pics/4bf8d0ba-36f0-459e-83a0-f15278a5a157.png" width="600"/> </div><br>
综上如果进行 N 次操作那么大约需要操作节点的次数为 N-1+N=2N-1其中 N-1 表示 N-1 个不是尾节点的每个节点以 O(1) 的时间复杂度操作节点的总次数N 表示 1 个尾节点以 O(N) 的时间复杂度操作节点的总次数(2N-1)/N \~ 2因此该算法的平均时间复杂度为 O(1)
@ -630,7 +630,7 @@ public ListNode deleteNode(ListNode head, ListNode tobeDelete) {
## 题目描述
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/17e301df-52e8-4886-b593-841a16d13e44.png" width="450"/> </div><br>
<div align="center"> <img src="pics/17e301df-52e8-4886-b593-841a16d13e44.png" width="450"/> </div><br>
## 解题描述

View File

@ -70,7 +70,7 @@ public boolean isNumeric(char[] str) {
需要保证奇数和奇数偶数和偶数之间的相对位置不变这和书本不太一样
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d03a2efa-ef19-4c96-97e8-ff61df8061d3.png" width="200px"> </div><br>
<div align="center"> <img src="pics/d03a2efa-ef19-4c96-97e8-ff61df8061d3.png" width="200px"> </div><br>
## 解题思路
@ -131,7 +131,7 @@ private void swap(int[] nums, int i, int j) {
设链表的长度为 N设置两个指针 P1 P2先让 P1 移动 K 个节点则还有 N - K 个节点可以移动此时让 P1 P2 同时移动可以知道当 P1 移动到链表结尾时P2 移动到第 N - K 个节点处该位置就是倒数第 K 个节点
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6b504f1f-bf76-4aab-a146-a9c7a58c2029.png" width="500"/> </div><br>
<div align="center"> <img src="pics/6b504f1f-bf76-4aab-a146-a9c7a58c2029.png" width="500"/> </div><br>
```java
public ListNode FindKthToTail(ListNode head, int k) {
@ -165,7 +165,7 @@ public ListNode FindKthToTail(ListNode head, int k) {
在相遇点slow 要到环的入口点还需要移动 z 个节点如果让 fast 重新从头开始移动并且速度变为每次移动一个节点那么它到环入口点还需要移动 x 个节点在上面已经推导出 x=z因此 fast slow 将在环入口点相遇
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/bb7fc182-98c2-4860-8ea3-630e27a5f29f.png" width="500"/> </div><br>
<div align="center"> <img src="pics/bb7fc182-98c2-4860-8ea3-630e27a5f29f.png" width="500"/> </div><br>
```java
public ListNode EntryNodeOfLoop(ListNode pHead) {
@ -228,7 +228,7 @@ public ListNode ReverseList(ListNode head) {
## 题目描述
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c094d2bc-ec75-444b-af77-d369dfb6b3b4.png" width="400"/> </div><br>
<div align="center"> <img src="pics/c094d2bc-ec75-444b-af77-d369dfb6b3b4.png" width="400"/> </div><br>
## 解题思路
@ -280,7 +280,7 @@ public ListNode Merge(ListNode list1, ListNode list2) {
## 题目描述
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/84a5b15a-86c5-4d8e-9439-d9fd5a4699a1.jpg" width="450"/> </div><br>
<div align="center"> <img src="pics/84a5b15a-86c5-4d8e-9439-d9fd5a4699a1.jpg" width="450"/> </div><br>
## 解题思路
@ -308,7 +308,7 @@ private boolean isSubtreeWithRoot(TreeNode root1, TreeNode root2) {
## 题目描述
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0c12221f-729e-4c22-b0ba-0dfc909f8adf.jpg" width="300"/> </div><br>
<div align="center"> <img src="pics/0c12221f-729e-4c22-b0ba-0dfc909f8adf.jpg" width="300"/> </div><br>
## 解题思路
@ -334,7 +334,7 @@ private void swap(TreeNode root) {
## 题目描述
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0c12221f-729e-4c22-b0ba-0dfc909f8adf.jpg" width="300"/> </div><br>
<div align="center"> <img src="pics/0c12221f-729e-4c22-b0ba-0dfc909f8adf.jpg" width="300"/> </div><br>
## 解题思路
@ -364,7 +364,7 @@ boolean isSymmetrical(TreeNode t1, TreeNode t2) {
下图的矩阵顺时针打印结果为1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/48517227-324c-4664-bd26-a2d2cffe2bfe.png" width="200px"> </div><br>
<div align="center"> <img src="pics/48517227-324c-4664-bd26-a2d2cffe2bfe.png" width="200px"> </div><br>
## 解题思路

View File

@ -87,7 +87,7 @@ public boolean IsPopOrder(int[] pushSequence, int[] popSequence) {
例如以下二叉树层次遍历的结果为1,2,3,4,5,6,7
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d5e838cf-d8a2-49af-90df-1b2a714ee676.jpg" width="250"/> </div><br>
<div align="center"> <img src="pics/d5e838cf-d8a2-49af-90df-1b2a714ee676.jpg" width="250"/> </div><br>
## 解题思路
@ -195,7 +195,7 @@ public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
例如下图是后序遍历序列 1,3,2 所对应的二叉搜索树
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/13454fa1-23a8-4578-9663-2b13a6af564a.jpg" width="150"/> </div><br>
<div align="center"> <img src="pics/13454fa1-23a8-4578-9663-2b13a6af564a.jpg" width="150"/> </div><br>
## 解题思路
@ -230,7 +230,7 @@ private boolean verify(int[] sequence, int first, int last) {
下图的二叉树有两条和为 22 的路径10, 5, 7 10, 12
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ed77b0e6-38d9-4a34-844f-724f3ffa2c12.jpg" width="200"/> </div><br>
<div align="center"> <img src="pics/ed77b0e6-38d9-4a34-844f-724f3ffa2c12.jpg" width="200"/> </div><br>
## 解题思路
@ -277,21 +277,21 @@ public class RandomListNode {
}
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/66a01953-5303-43b1-8646-0c77b825e980.png" width="300"/> </div><br>
<div align="center"> <img src="pics/66a01953-5303-43b1-8646-0c77b825e980.png" width="300"/> </div><br>
## 解题思路
第一步在每个节点的后面插入复制的节点
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/dfd5d3f8-673c-486b-8ecf-d2082107b67b.png" width="600"/> </div><br>
<div align="center"> <img src="pics/dfd5d3f8-673c-486b-8ecf-d2082107b67b.png" width="600"/> </div><br>
第二步对复制节点的 random 链接进行赋值
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/cafbfeb8-7dfe-4c0a-a3c9-750eeb824068.png" width="600"/> </div><br>
<div align="center"> <img src="pics/cafbfeb8-7dfe-4c0a-a3c9-750eeb824068.png" width="600"/> </div><br>
第三步拆分
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e151b5df-5390-4365-b66e-b130cd253c12.png" width="600"/> </div><br>
<div align="center"> <img src="pics/e151b5df-5390-4365-b66e-b130cd253c12.png" width="600"/> </div><br>
```java
public RandomListNode Clone(RandomListNode pHead) {
@ -333,7 +333,7 @@ public RandomListNode Clone(RandomListNode pHead) {
输入一棵二叉搜索树将该二叉搜索树转换成一个排序的双向链表要求不能创建任何新的结点只能调整树中结点指针的指向
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/05a08f2e-9914-4a77-92ef-aebeaecf4f66.jpg" width="400"/> </div><br>
<div align="center"> <img src="pics/05a08f2e-9914-4a77-92ef-aebeaecf4f66.jpg" width="400"/> </div><br>
## 解题思路

View File

@ -33,7 +33,7 @@ Output:
(2, 3, 1, 0, 2, 5) 为例遍历到位置 4 该位置上的数为 2但是第 2 个位置上已经有一个 2 的值了因此可以知道 2 重复
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/49d2adc1-b28a-44bf-babb-d44993f4a2e3.gif" width="250px"> </div><br>
<div align="center"> <img src="pics/49d2adc1-b28a-44bf-babb-d44993f4a2e3.gif" width="250px"> </div><br>
```java
@ -87,7 +87,7 @@ Given target = 20, return false.
该二维数组中的一个数小于它的数一定在其左边大于它的数一定在其下边因此从右上角开始查找就可以根据 target 和当前元素的大小关系来缩小查找区间当前元素的查找区间为左下角的所有元素
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0ad9f7ba-f408-4999-a77a-9b73562c9088.gif" width="200px"> </div><br>
<div align="center"> <img src="pics/0ad9f7ba-f408-4999-a77a-9b73562c9088.gif" width="200px"> </div><br>
```java
public boolean Find(int target, int[][] matrix) {
@ -132,7 +132,7 @@ Output:
从后向前遍是为了在改变 P2 所指向的内容时不会影响到 P1 遍历原来字符串的内容
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6980aef0-debe-4b4b-8da5-8b1befbc1408.gif" width="230px"> </div><br>
<div align="center"> <img src="pics/6980aef0-debe-4b4b-8da5-8b1befbc1408.gif" width="230px"> </div><br>
```java
public String replaceSpace(StringBuffer str) {
@ -164,7 +164,7 @@ public String replaceSpace(StringBuffer str) {
从尾到头反过来打印出每个结点的值
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f5792051-d9b2-4ca4-a234-a4a2de3d5a57.png" width="280px"> </div><br>
<div align="center"> <img src="pics/f5792051-d9b2-4ca4-a234-a4a2de3d5a57.png" width="280px"> </div><br>
## 解题思路
@ -192,7 +192,7 @@ public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
- 头结点是在头插法中使用的一个额外节点这个节点不存储值
- 第一个节点就是链表的第一个真正存储值的节点
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0dae7e93-cfd1-4bd3-97e8-325b032b716f.gif" width="370px"> </div><br>
<div align="center"> <img src="pics/0dae7e93-cfd1-4bd3-97e8-325b032b716f.gif" width="370px"> </div><br>
```java
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
@ -219,7 +219,7 @@ public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
栈具有后进先出的特点在遍历链表时将值按顺序放入栈中最后出栈的顺序即为逆序
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9d1deeba-4ae1-41dc-98f4-47d85b9831bc.gif" width="300px"> </div><br>
<div align="center"> <img src="pics/9d1deeba-4ae1-41dc-98f4-47d85b9831bc.gif" width="300px"> </div><br>
```java
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
@ -244,13 +244,13 @@ public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
根据二叉树的前序遍历和中序遍历的结果重建出该二叉树假设输入的前序遍历和中序遍历的结果中都不含重复的数字
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/31d9adce-2af8-4754-8386-0aabb4e500b0.png" width="300"/> </div><br>
<div align="center"> <img src="pics/31d9adce-2af8-4754-8386-0aabb4e500b0.png" width="300"/> </div><br>
## 解题思路
前序遍历的第一个值为根节点的值使用这个值将中序遍历结果分成两部分左部分为树的左子树中序遍历结果右部分为树的右子树中序遍历的结果
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c269e362-1128-4212-9cf3-d4c12b363b2f.gif" width="330px"> </div><br>
<div align="center"> <img src="pics/c269e362-1128-4212-9cf3-d4c12b363b2f.gif" width="330px"> </div><br>
```java
// 缓存中序遍历数组每个值对应的索引
@ -300,11 +300,11 @@ public class TreeLinkNode {
如果一个节点的右子树不为空那么该节点的下一个节点是右子树的最左节点
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b0611f89-1e5f-4494-a795-3544bf65042a.gif" width="220px"/> </div><br>
<div align="center"> <img src="pics/b0611f89-1e5f-4494-a795-3544bf65042a.gif" width="220px"/> </div><br>
否则向上找第一个左链接指向的树包含该节点的祖先节点
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/95080fae-de40-463d-a76e-783a0c677fec.gif" width="200px"/> </div><br>
<div align="center"> <img src="pics/95080fae-de40-463d-a76e-783a0c677fec.gif" width="200px"/> </div><br>
```java
public TreeLinkNode GetNext(TreeLinkNode pNode) {
@ -337,7 +337,7 @@ public TreeLinkNode GetNext(TreeLinkNode pNode) {
in 栈用来处理入栈push操作out 栈用来处理出栈pop操作一个元素进入 in 栈之后出栈的顺序被反转当元素要出栈时需要先进入 out 此时元素出栈顺序再一次被反转因此出栈顺序就和最开始入栈顺序是相同的先进入的元素先退出这就是队列的顺序
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/3ea280b5-be7d-471b-ac76-ff020384357c.gif" width="350"/> </div><br>
<div align="center"> <img src="pics/3ea280b5-be7d-471b-ac76-ff020384357c.gif" width="350"/> </div><br>
```java
Stack<Integer> in = new Stack<Integer>();

View File

@ -120,7 +120,7 @@ private void merge(int[] nums, int l, int m, int h) {
## 题目描述
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/5f1cb999-cb9a-4f6c-a0af-d90377295ab8.png" width="500"/> </div><br>
<div align="center"> <img src="pics/5f1cb999-cb9a-4f6c-a0af-d90377295ab8.png" width="500"/> </div><br>
## 解题思路
@ -212,7 +212,7 @@ private void inOrder(TreeNode root, int k) {
从根结点到叶结点依次经过的结点含根叶结点形成树的一条路径最长路径的长度为树的深度
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ba355101-4a93-4c71-94fb-1da83639727b.jpg" width="350px"/> </div><br>
<div align="center"> <img src="pics/ba355101-4a93-4c71-94fb-1da83639727b.jpg" width="350px"/> </div><br>
## 解题思路
@ -230,7 +230,7 @@ public int TreeDepth(TreeNode root) {
平衡二叉树左右子树高度差不超过 1
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/af1d1166-63af-47b6-9aa3-2bf2bd37bd03.jpg" width="250px"/> </div><br>
<div align="center"> <img src="pics/af1d1166-63af-47b6-9aa3-2bf2bd37bd03.jpg" width="250px"/> </div><br>
## 解题思路

View File

@ -19,7 +19,7 @@
n 个骰子扔在地上求点数和为 s 的概率
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/195f8693-5ec4-4987-8560-f25e365879dd.png" width="300px"> </div><br>
<div align="center"> <img src="pics/195f8693-5ec4-4987-8560-f25e365879dd.png" width="300px"> </div><br>
## 解题思路
@ -92,7 +92,7 @@ public List<Map.Entry<Integer, Double>> dicesSum(int n) {
五张牌其中大小鬼为癞子牌面为 0判断这五张牌是否能组成顺子
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/eaa506b6-0747-4bee-81f8-3cda795d8154.png" width="350px"> </div><br>
<div align="center"> <img src="pics/eaa506b6-0747-4bee-81f8-3cda795d8154.png" width="350px"> </div><br>
## 解题思路
@ -152,7 +152,7 @@ public int LastRemaining_Solution(int n, int m) {
可以有一次买入和一次卖出买入必须在前求最大收益
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/42661013-750f-420b-b3c1-437e9a11fb65.png" width="220px"> </div><br>
<div align="center"> <img src="pics/42661013-750f-420b-b3c1-437e9a11fb65.png" width="220px"> </div><br>
## 解题思路
@ -224,7 +224,7 @@ public int Add(int a, int b) {
给定一个数组 A[0, 1,..., n-1]请构建一个数组 B[0, 1,..., n-1]其中 B 中的元素 B[i]=A[0]\*A[1]\*...\*A[i-1]\*A[i+1]\*...\*A[n-1]要求不能使用除法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4240a69f-4d51-4d16-b797-2dfe110f30bd.png" width="250px"> </div><br>
<div align="center"> <img src="pics/4240a69f-4d51-4d16-b797-2dfe110f30bd.png" width="250px"> </div><br>
## 解题思路
@ -289,7 +289,7 @@ public int StrToInt(String str) {
二叉查找树中两个节点 p, q 的公共祖先 root 满足 root.val >= p.val && root.val <= q.val
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/047faac4-a368-4565-8331-2b66253080d3.jpg" width="220"/> </div><br>
<div align="center"> <img src="pics/047faac4-a368-4565-8331-2b66253080d3.jpg" width="220"/> </div><br>
```java
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
@ -309,7 +309,7 @@ public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
在左右子树中查找是否存在 p 或者 q如果 p q 分别在两个子树中那么就说明根节点就是最低公共祖先
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d27c99f0-7881-4f2d-9675-c75cbdee3acd.jpg" width="250"/> </div><br>
<div align="center"> <img src="pics/d27c99f0-7881-4f2d-9675-c75cbdee3acd.jpg" width="250"/> </div><br>
```java
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {

View File

@ -47,7 +47,7 @@
事务指的是满足 ACID 特性的一组操作可以通过 Commit 提交一个事务也可以使用 Rollback 进行回滚
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f74144be-857a-40cd-8ec7-87626ef4e20b.png" width="400px"> </div><br>
<div align="center"> <img src="pics/f74144be-857a-40cd-8ec7-87626ef4e20b.png" width="400px"> </div><br>
## ACID
@ -80,7 +80,7 @@
- 在并发的情况下多个事务并行执行事务不仅要满足原子性还需要满足隔离性才能满足一致性
- 事务满足持久化是为了能应对数据库崩溃的情况
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/417bc315-4409-48c6-83e0-59e8d405429e.jpg" width="400px"> </div><br>
<div align="center"> <img src="pics/417bc315-4409-48c6-83e0-59e8d405429e.jpg" width="400px"> </div><br>
## AUTOCOMMIT
@ -94,25 +94,25 @@ MySQL 默认采用自动提交模式。也就是说,如果不显式使用`STAR
T<sub>1</sub> T<sub>2</sub> 两个事务都对一个数据进行修改T<sub>1</sub> 先修改T<sub>2</sub> 随后修改T<sub>2</sub> 的修改覆盖了 T<sub>1</sub> 的修改
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/75184b58-c627-4edc-8dcf-605762ebb733.png" width="320px"> </div><br>
<div align="center"> <img src="pics/75184b58-c627-4edc-8dcf-605762ebb733.png" width="320px"> </div><br>
## 读脏数据
T<sub>1</sub> 修改一个数据T<sub>2</sub> 随后读取这个数据如果 T<sub>1</sub> 撤销了这次修改那么 T<sub>2</sub> 读取的数据是脏数据
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/af0e94d9-502d-4531-938f-d46dd29de52d.png" width="360px"> </div><br>
<div align="center"> <img src="pics/af0e94d9-502d-4531-938f-d46dd29de52d.png" width="360px"> </div><br>
## 不可重复读
T<sub>2</sub> 读取一个数据T<sub>1</sub> 对该数据做了修改如果 T<sub>2</sub> 再次读取这个数据此时读取的结果和第一次读取的结果不同
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/66ae164c-ad47-4905-895e-51fe38ce797a.png" width="360px"> </div><br>
<div align="center"> <img src="pics/66ae164c-ad47-4905-895e-51fe38ce797a.png" width="360px"> </div><br>
## 幻影读
T<sub>1</sub> 读取某个范围的数据T<sub>2</sub> 在这个范围内插入新的数据T<sub>1</sub> 再次读取这个范围的数据此时读取的结果和和第一次读取的结果不同
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/8fdc577d-552d-4b43-b5e4-a8f98bc2cb51.png" width="340px"> </div><br>
<div align="center"> <img src="pics/8fdc577d-552d-4b43-b5e4-a8f98bc2cb51.png" width="340px"> </div><br>
----
@ -322,7 +322,7 @@ MVCC 在每行记录后面都保存着两个隐藏的列,用来存储两个版
MVCC 使用到的快照存储在 Undo 日志中该日志通过回滚指针把一个数据行Record的所有快照连接起来
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e41405a8-7c05-4f70-8092-e961e28d3112.jpg" width=""/> </div><br>
<div align="center"> <img src="pics/e41405a8-7c05-4f70-8092-e961e28d3112.jpg" width=""/> </div><br>
## 实现过程
@ -536,7 +536,7 @@ Entity-Relationship有三个组成部分实体、属性、联系。
下图的 Course Student 是一对多的关系
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1d28ad05-39e5-49a2-a6a1-a6f496adba6a.png" width="380px"/> </div><br>
<div align="center"> <img src="pics/1d28ad05-39e5-49a2-a6a1-a6f496adba6a.png" width="380px"/> </div><br>
## 表示出现多次的关系
@ -544,19 +544,19 @@ Entity-Relationship有三个组成部分实体、属性、联系。
下图表示一个课程的先修关系先修关系出现两个 Course 实体第一个是先修课程后一个是后修课程因此需要用两条线来表示这种关系
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ac929ea3-daca-40ec-9e95-4b2fa6678243.png" width="250px"/> </div><br>
<div align="center"> <img src="pics/ac929ea3-daca-40ec-9e95-4b2fa6678243.png" width="250px"/> </div><br>
## 联系的多向性
虽然老师可以开设多门课并且可以教授多名学生但是对于特定的学生和课程只有一个老师教授这就构成了一个三元联系
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/5bb1b38a-527e-4802-a385-267dadbd30ba.png" width="350px"/> </div><br>
<div align="center"> <img src="pics/5bb1b38a-527e-4802-a385-267dadbd30ba.png" width="350px"/> </div><br>
## 表示子类
用一个三角形和两条线来连接类和子类与子类有关的属性和联系都连到子类上而与父类和子类都有关的连到父类上
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/14389ea4-8d96-4e96-9f76-564ca3324c1e.png" width="450px"/> </div><br>
<div align="center"> <img src="pics/14389ea4-8d96-4e96-9f76-564ca3324c1e.png" width="450px"/> </div><br>
# 参考资料

View File

@ -35,7 +35,7 @@
Ant 具有编译测试和打包功能其后出现的 Maven Ant 的功能基础上又新增了依赖管理功能而最新的 Gradle 又在 Maven 的功能基础上新增了对 Groovy 语言的支持
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/34751bd9-e8e4-4c20-94bc-f7217049fada.png" width="450px"> </div><br>
<div align="center"> <img src="pics/34751bd9-e8e4-4c20-94bc-f7217049fada.png" width="450px"> </div><br>
Gradle Maven 的区别是它使用 Groovy 这种特定领域语言DSL来管理构建脚本而不再使用 XML 这种标记性语言因为项目如果庞大的话XML 很容易就变得臃肿

View File

@ -173,7 +173,7 @@ a.+c
^\s*\/\/.*$
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/600e9c75-5033-4dad-ae2b-930957db638e.png"/> </div><br>
<div align="center"> <img src="pics/600e9c75-5033-4dad-ae2b-930957db638e.png"/> </div><br>
**匹配结果**

View File

@ -19,20 +19,20 @@
消息生产者向消息队列中发送了一个消息之后只能被一个消费者消费一次
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/206f965e-53b2-4732-90cf-75910b80d7ac.png" width="450px"/> </div><br>
<div align="center"> <img src="pics/206f965e-53b2-4732-90cf-75910b80d7ac.png" width="450px"/> </div><br>
## 发布/订阅
消息生产者向频道发送一个消息之后多个消费者可以从该频道订阅到这条消息并消费
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4e93f7d4-2623-4129-a939-59051256561e.png" width="450px"/> </div><br>
<div align="center"> <img src="pics/4e93f7d4-2623-4129-a939-59051256561e.png" width="450px"/> </div><br>
发布与订阅模式和观察者模式有以下不同
- 观察者模式中观察者和主题都知道对方的存在而在发布与订阅模式中生产者与消费者不知道对方的存在它们之间通过频道进行通信
- 观察者模式是同步的当事件触发时主题会调用观察者的方法然后等待方法返回而发布与订阅模式是异步的生产者向频道发送一个消息之后就不需要关心消费者何时去订阅这个消息可以立即返回
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/530764d5-f67f-47a2-8df4-57e8646e1400.png" width="450px"/> </div><br>
<div align="center"> <img src="pics/530764d5-f67f-47a2-8df4-57e8646e1400.png" width="450px"/> </div><br>
# 使用场景

View File

@ -1,6 +1,6 @@
# 汉诺塔
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/69d6c38d-1dec-4f72-ae60-60dbc10e9d15.png" width="300"/> </div><br>
<div align="center"> <img src="pics/69d6c38d-1dec-4f72-ae60-60dbc10e9d15.png" width="300"/> </div><br>
有三个柱子分别为 frombufferto需要将 from 上的圆盘全部移动到 to 并且要保证小圆盘始终在大圆盘上
@ -8,15 +8,15 @@
n-1 个圆盘从 from -> buffer
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f9240aa1-8d48-4959-b28a-7ca45c3e4d91.png" width="300"/> </div><br>
<div align="center"> <img src="pics/f9240aa1-8d48-4959-b28a-7ca45c3e4d91.png" width="300"/> </div><br>
1 个圆盘从 from -> to
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f579cab0-3d49-4d00-8e14-e9e1669d0f9f.png" width="300"/> </div><br>
<div align="center"> <img src="pics/f579cab0-3d49-4d00-8e14-e9e1669d0f9f.png" width="300"/> </div><br>
n-1 个圆盘从 buffer -> to
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d02f74dd-8e33-4f3c-bf29-53203a06695a.png" width="300"/> </div><br>
<div align="center"> <img src="pics/d02f74dd-8e33-4f3c-bf29-53203a06695a.png" width="300"/> </div><br>
如果只有一个圆盘那么只需要进行一次移动操作
@ -67,7 +67,7 @@ from H1 to H3
生成编码时从根节点出发向左遍历则添加二进制位 0向右则添加二进制位 1直到遍历到叶子节点叶子节点代表的字符的编码就是这个路径编码
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/8edc5164-810b-4cc5-bda8-2a2c98556377.jpg" width="300"/> </div><br>
<div align="center"> <img src="pics/8edc5164-810b-4cc5-bda8-2a2c98556377.jpg" width="300"/> </div><br>
```java
public class Huffman {

View File

@ -12,7 +12,7 @@
用于解决动态连通性问题能动态连接两个点并且判断两个点是否连通
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/02943a90-7dd4-4e9a-9325-f8217d3cc54d.jpg" width="350"/> </div><br>
<div align="center"> <img src="pics/02943a90-7dd4-4e9a-9325-f8217d3cc54d.jpg" width="350"/> </div><br>
| 方法 | 描述 |
| :---: | :---: |
@ -51,7 +51,7 @@ public abstract class UF {
但是 union 操作代价却很高需要将其中一个连通分量中的所有节点 id 值都修改为另一个节点的 id
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0972501d-f854-4d26-8fce-babb27c267f6.jpg" width="320"/> </div><br>
<div align="center"> <img src="pics/0972501d-f854-4d26-8fce-babb27c267f6.jpg" width="320"/> </div><br>
```java
public class QuickFindUF extends UF {
@ -91,7 +91,7 @@ public class QuickFindUF extends UF {
但是 find 操作开销很大因为同一个连通分量的节点 id 值不同id 值只是用来指向另一个节点因此需要一直向上查找操作直到找到最上层的节点
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/11b27de5-5a9d-45e4-95cc-417fa3ad1d38.jpg" width="280"/> </div><br>
<div align="center"> <img src="pics/11b27de5-5a9d-45e4-95cc-417fa3ad1d38.jpg" width="280"/> </div><br>
```java
public class QuickUnionUF extends UF {
@ -124,7 +124,7 @@ public class QuickUnionUF extends UF {
这种方法可以快速进行 union 操作但是 find 操作和树高成正比最坏的情况下树的高度为节点的数目
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/23e4462b-263f-4d15-8805-529e0ca7a4d1.jpg" width="100"/> </div><br>
<div align="center"> <img src="pics/23e4462b-263f-4d15-8805-529e0ca7a4d1.jpg" width="100"/> </div><br>
# 加权 Quick Union
@ -132,7 +132,7 @@ public class QuickUnionUF extends UF {
理论研究证明加权 quick-union 算法构造的树深度最多不超过 logN
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a9f18f8a-c1ea-422e-aa56-d91716b0f755.jpg" width="150"/> </div><br>
<div align="center"> <img src="pics/a9f18f8a-c1ea-422e-aa56-d91716b0f755.jpg" width="150"/> </div><br>
```java
public class WeightedQuickUnionUF extends UF {

View File

@ -29,7 +29,7 @@ public abstract class Sort<T extends Comparable<T>> {
选择排序需要 \~N<sup>2</sup>/2 次比较和 \~N 次交换它的运行时间与输入无关这个特点使得它对一个已经排序的数组也需要这么多的比较和交换操作
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/bc6be2d0-ed5e-4def-89e5-3ada9afa811a.gif" width="230px"> </div><br>
<div align="center"> <img src="pics/bc6be2d0-ed5e-4def-89e5-3ada9afa811a.gif" width="230px"> </div><br>
```java
public class Selection<T extends Comparable<T>> extends Sort<T> {
@ -56,7 +56,7 @@ public class Selection<T extends Comparable<T>> extends Sort<T> {
在一轮循环中如果没有发生交换那么说明数组已经是有序的此时可以直接退出
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0f8d178b-52d8-491b-9dfd-41e05a952578.gif" width="200px"> </div><br>
<div align="center"> <img src="pics/0f8d178b-52d8-491b-9dfd-41e05a952578.gif" width="200px"> </div><br>
```java
public class Bubble<T extends Comparable<T>> extends Sort<T> {
@ -90,7 +90,7 @@ public class Bubble<T extends Comparable<T>> extends Sort<T> {
- 最坏的情况下需要 \~N<sup>2</sup>/2 比较以及 \~N<sup>2</sup>/2 次交换最坏的情况是数组是倒序的
- 最好的情况下需要 N-1 次比较和 0 次交换最好的情况就是数组已经有序了
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/35253fa4-f60a-4e3b-aaec-8fc835aabdac.gif" width="200px"> </div><br>
<div align="center"> <img src="pics/35253fa4-f60a-4e3b-aaec-8fc835aabdac.gif" width="200px"> </div><br>
```java
public class Insertion<T extends Comparable<T>> extends Sort<T> {
@ -113,7 +113,7 @@ public class Insertion<T extends Comparable<T>> extends Sort<T> {
希尔排序使用插入排序对间隔 h 的序列进行排序通过不断减小 h最后令 h=1就可以使得整个数组是有序的
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7818c574-97a8-48db-8e62-8bfb030b02ba.png" width="450px"> </div><br>
<div align="center"> <img src="pics/7818c574-97a8-48db-8e62-8bfb030b02ba.png" width="450px"> </div><br>
```java
public class Shell<T extends Comparable<T>> extends Sort<T> {
@ -147,7 +147,7 @@ public class Shell<T extends Comparable<T>> extends Sort<T> {
归并排序的思想是将数组分成两部分分别进行排序然后归并起来
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ec840967-d127-4da3-b6bb-186996c56746.png" width="300px"> </div><br>
<div align="center"> <img src="pics/ec840967-d127-4da3-b6bb-186996c56746.png" width="300px"> </div><br>
## 1. 归并方法
@ -243,7 +243,7 @@ public class Down2UpMergeSort<T extends Comparable<T>> extends MergeSort<T> {
- 归并排序将数组分为两个子数组分别排序并将有序的子数组归并使得整个数组排序
- 快速排序通过一个切分元素将数组分为两个子数组左子数组小于等于切分元素右子数组大于等于切分元素将这两个子数组排序也就将整个数组排序了
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6234eb3d-ccf2-4987-a724-235aef6957b1.png" width="280px"> </div><br>
<div align="center"> <img src="pics/6234eb3d-ccf2-4987-a724-235aef6957b1.png" width="280px"> </div><br>
```java
public class QuickSort<T extends Comparable<T>> extends Sort<T> {
@ -274,7 +274,7 @@ public class QuickSort<T extends Comparable<T>> extends Sort<T> {
a[l] 作为切分元素然后从数组的左端向右扫描直到找到第一个大于等于它的元素再从数组的右端向左扫描找到第一个小于它的元素交换这两个元素不断进行这个过程就可以保证左指针 i 的左侧元素都不大于切分元素右指针 j 的右侧元素都不小于切分元素当两个指针相遇时将切分元素 a[l] a[j] 交换位置
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c4859290-e27d-4f12-becf-e2a5c1f3a275.gif" width="320px"> </div><br>
<div align="center"> <img src="pics/c4859290-e27d-4f12-becf-e2a5c1f3a275.gif" width="320px"> </div><br>
```java
private int partition(T[] nums, int l, int h) {
@ -378,7 +378,7 @@ public T select(T[] nums, int k) {
堆可以用数组来表示这是因为堆是完全二叉树而完全二叉树很容易就存储在数组中位置 k 的节点的父节点位置为 k/2而它的两个子节点的位置分别为 2k 2k+1这里不使用数组索引为 0 的位置是为了更清晰地描述节点的位置关系
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f48883c8-9d8a-494e-99a4-317d8ddb8552.png" width="170px"> </div><br>
<div align="center"> <img src="pics/f48883c8-9d8a-494e-99a4-317d8ddb8552.png" width="170px"> </div><br>
```java
public class Heap<T extends Comparable<T>> {
@ -414,7 +414,7 @@ public class Heap<T extends Comparable<T>> {
在堆中当一个节点比父节点大那么需要交换这个两个节点交换后还可能比它新的父节点大因此需要不断地进行比较和交换操作把这种操作称为上浮
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/99d5e84e-fc2a-49a3-8259-8de274617756.gif" width="270px"> </div><br>
<div align="center"> <img src="pics/99d5e84e-fc2a-49a3-8259-8de274617756.gif" width="270px"> </div><br>
```java
private void swim(int k) {
@ -427,7 +427,7 @@ private void swim(int k) {
类似地当一个节点比子节点来得小也需要不断地向下进行比较和交换操作把这种操作称为下沉一个节点如果有两个子节点应当与两个子节点中最大那个节点进行交换
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4bf5e3fb-a285-4138-b3b6-780956eb1df1.gif" width="270px"> </div><br>
<div align="center"> <img src="pics/4bf5e3fb-a285-4138-b3b6-780956eb1df1.gif" width="270px"> </div><br>
```java
private void sink(int k) {
@ -476,13 +476,13 @@ public T delMax() {
无序数组建立堆最直接的方法是从左到右遍历数组进行上浮操作一个更高效的方法是从右至左进行下沉操作如果一个节点的两个节点都已经是堆有序那么进行下沉操作可以使得这个节点为根节点的堆有序叶子节点不需要进行下沉操作可以忽略叶子节点的元素因此只需要遍历一半的元素即可
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c2ca8dd2-8d00-4a3e-bece-db7849ac9cfd.gif" width="210px"> </div><br>
<div align="center"> <img src="pics/c2ca8dd2-8d00-4a3e-bece-db7849ac9cfd.gif" width="210px"> </div><br>
#### 5.2 交换堆顶元素与最后一个元素
交换之后需要进行下沉操作维持堆的有序状态
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d156bcda-ac8d-4324-95e0-0c8df41567c9.gif" width="250px"> </div><br>
<div align="center"> <img src="pics/d156bcda-ac8d-4324-95e0-0c8df41567c9.gif" width="250px"> </div><br>
```java
public class HeapSort<T extends Comparable<T>> extends Sort<T> {

View File

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

View File

@ -211,7 +211,7 @@ CDN 主要有以下优点:
- 通过部署多台服务器从而提高系统整体的带宽性能
- 多台服务器可以看成是一种冗余机制从而具有高可用性
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/15313ed8-a520-4799-a300-2b6b36be314f.jpg"/> </div><br>
<div align="center"> <img src="pics/15313ed8-a520-4799-a300-2b6b36be314f.jpg"/> </div><br>
# 缓存问题
@ -285,11 +285,11 @@ Distributed Hash TableDHT 是一种哈希分布方式,其目的是为了
将哈希空间 [0, 2<sup>n</sup>-1] 看成一个哈希环每个服务器节点都配置到哈希环上每个数据对象通过哈希取模得到哈希值之后存放到哈希环中顺时针方向第一个大于等于该哈希值的节点上
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/68b110b9-76c6-4ee2-b541-4145e65adb3e.jpg"/> </div><br>
<div align="center"> <img src="pics/68b110b9-76c6-4ee2-b541-4145e65adb3e.jpg"/> </div><br>
一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点例如下图中新增节点 X只需要将它前一个节点 C 上的数据重新进行分布即可对于节点 ABD 都没有影响
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/66402828-fb2b-418f-83f6-82153491bcfe.jpg"/> </div><br>
<div align="center"> <img src="pics/66402828-fb2b-418f-83f6-82153491bcfe.jpg"/> </div><br>
## 虚拟节点

View File

@ -22,7 +22,7 @@
从上面的描述中可以看出虚拟内存允许程序不用将地址空间中的每一页都映射到物理内存也就是说一个程序不需要全部调入内存就可以运行这使得有限的内存运行大程序成为可能例如有一台计算机可以产生 16 位地址那么一个程序的地址空间范围是 0\~64K该计算机只有 32KB 的物理内存虚拟内存技术允许该计算机运行一个 64K 大小的程序
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7b281b1e-0595-402b-ae35-8c91084c33c1.png"/> </div><br>
<div align="center"> <img src="pics/7b281b1e-0595-402b-ae35-8c91084c33c1.png"/> </div><br>
# 分页系统地址映射
@ -32,7 +32,7 @@
下图的页表存放着 16 个页 16 个页需要用 4 个比特位来进行索引定位例如对于虚拟地址0010 000000000100 4 位是存储页面号 2读取表项内容为110 1页表项最后一位表示是否存在于内存中1 表示存在 12 位存储偏移量这个页对应的页框的地址为 110 000000000100
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/cf4386a1-58c9-4eca-a17f-e12b1e9770eb.png" width="500"/> </div><br>
<div align="center"> <img src="pics/cf4386a1-58c9-4eca-a17f-e12b1e9770eb.png" width="500"/> </div><br>
# 页面置换算法
@ -72,7 +72,7 @@
47071012126
```
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/eb859228-c0f2-4bce-910d-d9f76929352b.png"/> </div><br>
<div align="center"> <img src="pics/eb859228-c0f2-4bce-910d-d9f76929352b.png"/> </div><br>
## 3. 最近未使用
> NRU, Not Recently Used
@ -102,7 +102,7 @@ FIFO 算法可能会把经常使用的页面置换出去,为了避免这一问
当页面被访问 (读或写) 时设置该页面的 R 位为 1需要替换的时候检查最老页面的 R 如果 R 位是 0那么这个页面既老又没有被使用可以立刻置换掉如果是 1就将 R 位清 0并把该页面放到链表的尾端修改它的装入时间使它就像刚装入的一样然后继续从链表的头部开始搜索
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ecf8ad5d-5403-48b9-b6e7-f2e20ffe8fca.png"/> </div><br>
<div align="center"> <img src="pics/ecf8ad5d-5403-48b9-b6e7-f2e20ffe8fca.png"/> </div><br>
## 6. 时钟
@ -110,7 +110,7 @@ FIFO 算法可能会把经常使用的页面置换出去,为了避免这一问
第二次机会算法需要在链表中移动页面降低了效率时钟算法使用环形链表将页面连接起来再使用一个指针指向最老的页面
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/5f5ef0b6-98ea-497c-a007-f6c55288eab1.png"/> </div><br>
<div align="center"> <img src="pics/5f5ef0b6-98ea-497c-a007-f6c55288eab1.png"/> </div><br>
# 分段
@ -118,11 +118,11 @@ FIFO 算法可能会把经常使用的页面置换出去,为了避免这一问
下图为一个编译器在编译过程中建立的多个表 4 个表是动态增长的如果使用分页系统的一维地址空间动态增长的特点会导致覆盖问题的出现
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/22de0538-7c6e-4365-bd3b-8ce3c5900216.png"/> </div><br>
<div align="center"> <img src="pics/22de0538-7c6e-4365-bd3b-8ce3c5900216.png"/> </div><br>
分段的做法是把每个表分成段一个段构成一个独立的地址空间每个段的长度可以不同并且可以动态增长
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e0900bb2-220a-43b7-9aa9-1d5cd55ff56e.png"/> </div><br>
<div align="center"> <img src="pics/e0900bb2-220a-43b7-9aa9-1d5cd55ff56e.png"/> </div><br>
# 段页式

View File

@ -76,7 +76,7 @@
如果一个进程在用户态需要使用内核态的功能就进行系统调用从而陷入内核由操作系统代为完成
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/tGPV0.png" width="600"/> </div><br>
<div align="center"> <img src="pics/tGPV0.png" width="600"/> </div><br>
Linux 的系统调用主要有以下这些
@ -105,7 +105,7 @@ Linux 的系统调用主要有以下这些:
因为需要频繁地在用户态和核心态之间进行切换所以会有一定的性能损失
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2_14_microkernelArchitecture.jpg"/> </div><br>
<div align="center"> <img src="pics/2_14_microkernelArchitecture.jpg"/> </div><br>
# 中断分类

View File

@ -20,7 +20,7 @@
# 必要条件
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c037c901-7eae-4e31-a1e4-9d41329e5c3e.png"/> </div><br>
<div align="center"> <img src="pics/c037c901-7eae-4e31-a1e4-9d41329e5c3e.png"/> </div><br>
- 互斥每个资源要么已经分配给了一个进程要么就是可用的
- 占有和等待已经得到了某个资源的进程可以再请求新的资源
@ -52,7 +52,7 @@
## 1. 每种类型一个资源的死锁检测
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b1fa0453-a4b0-4eae-a352-48acca8fff74.png"/> </div><br>
<div align="center"> <img src="pics/b1fa0453-a4b0-4eae-a352-48acca8fff74.png"/> </div><br>
上图为资源分配图其中方框表示资源圆圈表示进程资源指向进程表示该资源已经分配给该进程进程指向资源表示进程请求获取该资源
@ -62,7 +62,7 @@
## 2. 每种类型多个资源的死锁检测
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e1eda3d5-5ec8-4708-8e25-1a04c5e11f48.png"/> </div><br>
<div align="center"> <img src="pics/e1eda3d5-5ec8-4708-8e25-1a04c5e11f48.png"/> </div><br>
上图中有三个进程四个资源每个数据代表的含义如下
@ -111,7 +111,7 @@
## 1. 安全状态
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ed523051-608f-4c3f-b343-383e2d194470.png"/> </div><br>
<div align="center"> <img src="pics/ed523051-608f-4c3f-b343-383e2d194470.png"/> </div><br>
a 的第二列 Has 表示已拥有的资源数第三列 Max 表示总共需要的资源数Free 表示还有可以使用的资源数从图 a 开始出发先让 B 拥有所需的所有资源 b运行结束后释放 B此时 Free 变为 5 c接着以同样的方式运行 C A使得所有进程都能成功运行因此可以称图 a 所示的状态时安全的
@ -123,13 +123,13 @@
一个小城镇的银行家他向一群客户分别承诺了一定的贷款额度算法要做的是判断对请求的满足是否会进入不安全状态如果是就拒绝请求否则予以分配
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d160ec2e-cfe2-4640-bda7-62f53e58b8c0.png"/> </div><br>
<div align="center"> <img src="pics/d160ec2e-cfe2-4640-bda7-62f53e58b8c0.png"/> </div><br>
上图 c 为不安全状态因此算法会拒绝之前的请求从而避免进入图 c 中的状态
## 3. 多个资源的银行家算法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/62e0dd4f-44c3-43ee-bb6e-fedb9e068519.png"/> </div><br>
<div align="center"> <img src="pics/62e0dd4f-44c3-43ee-bb6e-fedb9e068519.png"/> </div><br>
上图中有五个进程四个资源左边的图表示已经分配的资源右边的图表示还需要分配的资源最右边的 EP 以及 A 分别表示总资源已分配资源以及可用资源注意这三个为向量而不是具体数值例如 A=(1020)表示 4 个资源分别还剩下 1/0/2/0

View File

@ -16,7 +16,7 @@
- 制动手臂Actuator arm用于在磁道之间移动磁头
- 主轴Spindle使整个盘面转动
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/014fbc4d-d873-4a12-b160-867ddaed9807.jpg"/> </div><br>
<div align="center"> <img src="pics/014fbc4d-d873-4a12-b160-867ddaed9807.jpg"/> </div><br>
# 磁盘调度算法
@ -44,7 +44,7 @@
虽然平均寻道时间比较低但是不够公平如果新到达的磁道请求总是比一个在等待的磁道请求近那么在等待的磁道请求会一直等待下去也就是出现饥饿现象具体来说两端的磁道请求更容易出现饥饿现象
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4e2485e4-34bd-4967-9f02-0c093b797aaa.png"/> </div><br>
<div align="center"> <img src="pics/4e2485e4-34bd-4967-9f02-0c093b797aaa.png"/> </div><br>
## 3. 电梯算法
@ -56,7 +56,7 @@
因为考虑了移动方向因此所有的磁盘请求都会被满足解决了 SSTF 的饥饿问题
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/271ce08f-c124-475f-b490-be44fedc6d2e.png"/> </div><br>
<div align="center"> <img src="pics/271ce08f-c124-475f-b490-be44fedc6d2e.png"/> </div><br>

View File

@ -36,7 +36,7 @@
下图显示了 4 个程序创建了 4 个进程 4 个进程可以并发地执行
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a6ac2b08-3861-4e85-baa8-382287bfee9f.png"/> </div><br>
<div align="center"> <img src="pics/a6ac2b08-3861-4e85-baa8-382287bfee9f.png"/> </div><br>
## 2. 线程
@ -46,7 +46,7 @@
QQ 和浏览器是两个进程浏览器进程里面有很多线程例如 HTTP 请求线程事件响应线程渲染线程等等线程的并发执行使得在浏览器中点击一个新链接从而发起 HTTP 请求时浏览器还可以响应用户的其它事件
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/3cd630ea-017c-488d-ad1d-732b4efeddf5.png"/> </div><br>
<div align="center"> <img src="pics/3cd630ea-017c-488d-ad1d-732b4efeddf5.png"/> </div><br>
## 3. 区别
@ -68,7 +68,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H
# 进程状态的切换
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ProcessState.png" width="500"/> </div><br>
<div align="center"> <img src="pics/ProcessState.png" width="500"/> </div><br>
- 就绪状态ready等待被调度
- 运行状态running
@ -116,7 +116,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H
- 因为进程切换都要保存进程的信息并且载入新进程的信息如果时间片太小会导致进程切换得太频繁在进程切换上就会花过多时间
- 而如果时间片过长那么实时性就不能得到保证
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/8c662999-c16c-481c-9f40-1fdba5bc9167.png"/> </div><br>
<div align="center"> <img src="pics/8c662999-c16c-481c-9f40-1fdba5bc9167.png"/> </div><br>
**2.2 优先级调度**
@ -134,7 +134,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H
可以将这种调度算法看成是时间片轮转调度算法和优先级调度算法的结合
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/042cf928-3c8e-4815-ae9c-f2780202c68f.png"/> </div><br>
<div align="center"> <img src="pics/042cf928-3c8e-4815-ae9c-f2780202c68f.png"/> </div><br>
## 3. 实时系统
@ -308,7 +308,7 @@ end;
## 1. 哲学家进餐问题
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a9077f06-7584-4f2b-8c20-3a8e46928820.jpg"/> </div><br>
<div align="center"> <img src="pics/a9077f06-7584-4f2b-8c20-3a8e46928820.jpg"/> </div><br>
五个哲学家围着一张圆桌每个哲学家面前放着食物哲学家的生活有两种交替活动吃饭以及思考当一个哲学家吃饭时需要先拿起自己左右两边的两根筷子并且一次只能拿起一根筷子
@ -553,7 +553,7 @@ int pipe(int fd[2]);
- 只支持半双工通信单向交替传输
- 只能在父子进程或者兄弟进程中使用
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/53cd9ade-b0a6-4399-b4de-7f1fbd06cdfb.png"/> </div><br>
<div align="center"> <img src="pics/53cd9ade-b0a6-4399-b4de-7f1fbd06cdfb.png"/> </div><br>
## 2. FIFO
@ -567,7 +567,7 @@ int mkfifoat(int fd, const char *path, mode_t mode);
FIFO 常用于客户-服务器应用程序中FIFO 用作汇聚点在客户进程和服务器进程之间传递数据
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2ac50b81-d92a-4401-b9ec-f2113ecc3076.png"/> </div><br>
<div align="center"> <img src="pics/2ac50b81-d92a-4401-b9ec-f2113ecc3076.png"/> </div><br>
## 3. 消息队列

View File

@ -29,7 +29,7 @@ gcc -o hello hello.c
这个过程大致如下
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b396d726-b75f-4a32-89a2-03a7b6e19f6f.jpg" width="800"/> </div><br>
<div align="center"> <img src="pics/b396d726-b75f-4a32-89a2-03a7b6e19f6f.jpg" width="800"/> </div><br>
- 预处理阶段处理以 # 开头的预处理命令
- 编译阶段翻译成汇编文件
@ -43,7 +43,7 @@ gcc -o hello hello.c
- 符号解析每个符号对应于一个函数一个全局变量或一个静态变量符号解析的目的是将每个符号引用与一个符号定义关联起来
- 重定位链接器通过把每个符号定义与一个内存位置关联起来然后修改所有对这些符号的引用使得它们指向这个内存位置
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/47d98583-8bb0-45cc-812d-47eefa0a4a40.jpg"/> </div><br>
<div align="center"> <img src="pics/47d98583-8bb0-45cc-812d-47eefa0a4a40.jpg"/> </div><br>
# 目标文件
@ -63,7 +63,7 @@ gcc -o hello hello.c
- 在给定的文件系统中一个库只有一个文件所有引用该库的可执行目标文件都共享这个文件它不会被复制到引用它的可执行文件中
- 在内存中一个共享库的 .text 已编译程序的机器代码的一个副本可以被不同的正在运行的进程共享
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/76dc7769-1aac-4888-9bea-064f1caa8e77.jpg"/> </div><br>
<div align="center"> <img src="pics/76dc7769-1aac-4888-9bea-064f1caa8e77.jpg"/> </div><br>

View File

@ -23,13 +23,13 @@
# UDP 首部格式
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d4c3a4a1-0846-46ec-9cc3-eaddfca71254.jpg" width="600"/> </div><br>
<div align="center"> <img src="pics/d4c3a4a1-0846-46ec-9cc3-eaddfca71254.jpg" width="600"/> </div><br>
首部字段只有 8 个字节包括源端口目的端口长度检验和12 字节的伪首部是为了计算检验和临时添加的
# TCP 首部格式
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/55dc4e84-573d-4c13-a765-52ed1dd251f9.png" width="700"/> </div><br>
<div align="center"> <img src="pics/55dc4e84-573d-4c13-a765-52ed1dd251f9.png" width="700"/> </div><br>
- **序号** 用于对字节流进行编号例如序号为 301表示第一个字节的编号为 301如果携带的数据长度为 100 字节那么下一个报文段的序号应为 401
@ -47,7 +47,7 @@
# TCP 的三次握手
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e92d0ebc-7d46-413b-aec1-34a39602f787.png" width="600"/> </div><br>
<div align="center"> <img src="pics/e92d0ebc-7d46-413b-aec1-34a39602f787.png" width="600"/> </div><br>
假设 A 为客户端B 为服务器端
@ -69,7 +69,7 @@
# TCP 的四次挥手
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f87afe72-c2df-4c12-ac03-9b8d581a8af8.jpg" width="600"/> </div><br>
<div align="center"> <img src="pics/f87afe72-c2df-4c12-ac03-9b8d581a8af8.jpg" width="600"/> </div><br>
以下描述不讨论序号和确认号因为序号和确认号的规则比较简单并且不讨论 ACK因为 ACK 在连接建立之后都为 1
@ -117,7 +117,7 @@ TCP 使用超时重传来实现可靠传输:如果一个已经发送的报文
接收窗口只会对窗口内最后一个按序到达的字节进行确认例如接收窗口已经收到的字节为 {31, 34, 35}其中 {31} 按序到达 {34, 35} 就不是因此只对字节 31 进行确认发送方得到一个字节的确认之后就知道这个字节之前的所有字节都已经被接收
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a3253deb-8d21-40a1-aae4-7d178e4aa319.jpg" width="800"/> </div><br>
<div align="center"> <img src="pics/a3253deb-8d21-40a1-aae4-7d178e4aa319.jpg" width="800"/> </div><br>
# TCP 流量控制
@ -129,7 +129,7 @@ TCP 使用超时重传来实现可靠传输:如果一个已经发送的报文
如果网络出现拥塞分组将会丢失此时发送方会继续重传从而导致网络拥塞程度更高因此当出现拥塞时应当控制发送方的速率这一点和流量控制很像但是出发点不同流量控制是为了让接收方能来得及接收而拥塞控制是为了降低整个网络的拥塞程度
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/51e2ed95-65b8-4ae9-8af3-65602d452a25.jpg" width="500"/> </div><br>
<div align="center"> <img src="pics/51e2ed95-65b8-4ae9-8af3-65602d452a25.jpg" width="500"/> </div><br>
TCP 主要通过四个算法来进行拥塞控制慢开始拥塞避免快重传快恢复
@ -140,7 +140,7 @@ TCP 主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、
- 接收方有足够大的接收缓存因此不会发生流量控制
- 虽然 TCP 的窗口基于字节但是这里设窗口的大小单位为报文段
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/910f613f-514f-4534-87dd-9b4699d59d31.png" width="800"/> </div><br>
<div align="center"> <img src="pics/910f613f-514f-4534-87dd-9b4699d59d31.png" width="800"/> </div><br>
## 1. 慢开始与拥塞避免
@ -160,7 +160,7 @@ TCP 主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、
慢开始和快恢复的快慢指的是 cwnd 的设定值而不是 cwnd 的增长速率慢开始 cwnd 设定为 1而快恢复 cwnd 设定为 ssthresh
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f61b5419-c94a-4df1-8d4d-aed9ae8cc6d5.png" width="600"/> </div><br>
<div align="center"> <img src="pics/f61b5419-c94a-4df1-8d4d-aed9ae8cc6d5.png" width="600"/> </div><br>

View File

@ -22,7 +22,7 @@ DNS 是一个分布式数据库,提供了主机名和 IP 地址之间相互转
域名具有层次结构从上到下依次为根域名顶级域名二级域名
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b54eeb16-0b0e-484c-be62-306f57c40d77.jpg"/> </div><br>
<div align="center"> <img src="pics/b54eeb16-0b0e-484c-be62-306f57c40d77.jpg"/> </div><br>
DNS 可以使用 UDP 或者 TCP 进行传输使用的端口号都为 53大多数情况下 DNS 使用 UDP 进行传输这就要求域名解析器和域名服务器都必须自己处理超时和重传从而保证可靠性在两种情况下会使用 TCP 进行传输
@ -40,11 +40,11 @@ FTP 使用 TCP 进行连接,它需要两个连接来传送一个文件:
- 主动模式服务器端主动建立数据连接其中服务器端的端口号为 20客户端的端口号随机但是必须大于 1024因为 0\~1023 是熟知端口号
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/03f47940-3843-4b51-9e42-5dcaff44858b.jpg"/> </div><br>
<div align="center"> <img src="pics/03f47940-3843-4b51-9e42-5dcaff44858b.jpg"/> </div><br>
- 被动模式客户端主动建立数据连接其中客户端的端口号由客户端自己指定服务器端的端口号随机
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/be5c2c61-86d2-4dba-a289-b48ea23219de.jpg"/> </div><br>
<div align="center"> <img src="pics/be5c2c61-86d2-4dba-a289-b48ea23219de.jpg"/> </div><br>
主动模式要求客户端开放端口号给服务器端需要去配置客户端的防火墙被动模式只需要服务器端开放端口号即可无需客户端配置防火墙但是被动模式会导致服务器端的安全性减弱因为开放了过多的端口号
@ -61,7 +61,7 @@ DHCP 工作过程如下:
3. 如果客户端选择了某个 DHCP 服务器提供的信息那么就发送 Request 报文给该 DHCP 服务器
4. DHCP 服务器发送 Ack 报文表示客户端此时可以使用提供给它的信息
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/23219e4c-9fc0-4051-b33a-2bd95bf054ab.jpg"/> </div><br>
<div align="center"> <img src="pics/23219e4c-9fc0-4051-b33a-2bd95bf054ab.jpg"/> </div><br>
# 远程登录协议
@ -75,13 +75,13 @@ TELNET 可以适应许多计算机和操作系统的差异,例如不同操作
邮件协议包含发送协议和读取协议发送协议常用 SMTP读取协议常用 POP3 IMAP
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7b3efa99-d306-4982-8cfb-e7153c33aab4.png" width="700"/> </div><br>
<div align="center"> <img src="pics/7b3efa99-d306-4982-8cfb-e7153c33aab4.png" width="700"/> </div><br>
## 1. SMTP
SMTP 只能发送 ASCII 而互联网邮件扩充 MIME 可以发送二进制文件MIME 并没有改动或者取代 SMTP而是增加邮件主体的结构定义了非 ASCII 码的编码规则
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ed5522bb-3a60-481c-8654-43e7195a48fe.png" width=""/> </div><br>
<div align="center"> <img src="pics/ed5522bb-3a60-481c-8654-43e7195a48fe.png" width=""/> </div><br>
## 2. POP3

View File

@ -22,27 +22,27 @@
网络把主机连接起来而互连网internet是把多种不同的网络连接起来因此互连网是网络的网络而互联网Internet是全球范围的互连网
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/network-of-networks.gif" width="450"/> </div><br>
<div align="center"> <img src="pics/network-of-networks.gif" width="450"/> </div><br>
# ISP
互联网服务提供商 ISP 可以从互联网管理机构获得许多 IP 地址同时拥有通信线路以及路由器等联网设备个人或机构向 ISP 缴纳一定的费用就可以接入互联网
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/72be01cd-41ae-45f7-99b9-a8d284e44dd4.png" width="500"/> </div><br>
<div align="center"> <img src="pics/72be01cd-41ae-45f7-99b9-a8d284e44dd4.png" width="500"/> </div><br>
目前的互联网是一种多层次 ISP 结构ISP 根据覆盖面积的大小分为第一层 ISP区域 ISP 和接入 ISP互联网交换点 IXP 允许两个 ISP 直接相连而不用经过第三个 ISP
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/3be42601-9d33-4d29-8358-a9d16453af93.png" width="500"/> </div><br>
<div align="center"> <img src="pics/3be42601-9d33-4d29-8358-a9d16453af93.png" width="500"/> </div><br>
# 主机之间的通信方式
- 客户-服务器C/S客户是服务的请求方服务器是服务的提供方
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/914894c2-0bc4-46b5-bef9-0316a69ef521.jpg" width="240px"> </div><br>
<div align="center"> <img src="pics/914894c2-0bc4-46b5-bef9-0316a69ef521.jpg" width="240px"> </div><br>
- 对等P2P不区分客户和服务器
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/42430e94-3137-48c0-bdb6-3cebaf9102e3.jpg" width="200px"> </div><br>
<div align="center"> <img src="pics/42430e94-3137-48c0-bdb6-3cebaf9102e3.jpg" width="200px"> </div><br>
# 电路交换与分组交换
@ -60,7 +60,7 @@
总时延 = 排队时延 + 处理时延 + 传输时延 + 传播时延
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4b2ae78c-e254-44df-9e37-578e2f2bef52.jpg" width="380"/> </div><br>
<div align="center"> <img src="pics/4b2ae78c-e254-44df-9e37-578e2f2bef52.jpg" width="380"/> </div><br>
## 1. 排队时延
@ -76,7 +76,7 @@
<!-- <div align="center"><img src="https://latex.codecogs.com/gif.latex?delay=\frac{l(bit)}{v(bit/s)}" class="mathjax-pic"/></div> <br> -->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/dcdbb96c-9077-4121-aeb8-743e54ac02a4.png" width="150px"> </div><br>
<div align="center"> <img src="pics/dcdbb96c-9077-4121-aeb8-743e54ac02a4.png" width="150px"> </div><br>
其中 l 表示数据帧的长度v 表示传输速率
@ -87,13 +87,13 @@
<!-- <div align="center"><img src="https://latex.codecogs.com/gif.latex?delay=\frac{l(m)}{v(m/s)}" class="mathjax-pic"/></div> <br> -->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a1616dac-0e12-40b2-827d-9e3f7f0b940d.png" width="150"> </div><br>
<div align="center"> <img src="pics/a1616dac-0e12-40b2-827d-9e3f7f0b940d.png" width="150"> </div><br>
其中 l 表示信道长度v 表示电磁波在信道上的传播速度
# 计算机网络体系结构
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/0fa6c237-a909-4e2a-a771-2c5485cd8ce0.png" width="450"/> </div><br>
<div align="center"> <img src="pics/0fa6c237-a909-4e2a-a771-2c5485cd8ce0.png" width="450"/> </div><br>
## 1. 五层协议
@ -123,7 +123,7 @@
TCP/IP 体系结构不严格遵循 OSI 分层概念应用层可能会直接使用 IP 层或者网络接口层
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/48d79be8-085b-4862-8a9d-18402eb93b31.png" width="250"/> </div><br>
<div align="center"> <img src="pics/48d79be8-085b-4862-8a9d-18402eb93b31.png" width="250"/> </div><br>
## 4. 数据在各层之间的传递过程

View File

@ -16,7 +16,7 @@
模拟信号是连续的信号数字信号是离散的信号带通调制把数字信号转换为模拟信号
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c34f4503-f62c-4043-9dc6-3e03288657df.jpg" width="500"/> </div><br>
<div align="center"> <img src="pics/c34f4503-f62c-4043-9dc6-3e03288657df.jpg" width="500"/> </div><br>

View File

@ -26,7 +26,7 @@
使用 IP 协议可以把异构的物理网络连接起来使得在网络层看起来好像是一个统一的网络
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/8d779ab7-ffcc-47c6-90ec-ede8260b2368.png" width="800"/> </div><br>
<div align="center"> <img src="pics/8d779ab7-ffcc-47c6-90ec-ede8260b2368.png" width="800"/> </div><br>
IP 协议配套使用的还有三个协议
@ -36,7 +36,7 @@
# IP 数据报格式
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/85c05fb1-5546-4c50-9221-21f231cdc8c5.jpg" width="700"/> </div><br>
<div align="center"> <img src="pics/85c05fb1-5546-4c50-9221-21f231cdc8c5.jpg" width="700"/> </div><br>
- **版本** : 4IPv4 6IPv6两个值
@ -56,7 +56,7 @@
- **片偏移** : 和标识符一起用于发生分片的情况片偏移的单位为 8 字节
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/23ba890e-e11c-45e2-a20c-64d217f83430.png" width="700"/> </div><br>
<div align="center"> <img src="pics/23ba890e-e11c-45e2-a20c-64d217f83430.png" width="700"/> </div><br>
# IP 地址编址方式
@ -72,7 +72,7 @@ IP 地址的编址方式经历了三个历史阶段:
IP 地址 ::= {< 网络号 >, < 主机号 >}
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/cbf50eb8-22b4-4528-a2e7-d187143d57f7.png" width="500"/> </div><br>
<div align="center"> <img src="pics/cbf50eb8-22b4-4528-a2e7-d187143d57f7.png" width="500"/> </div><br>
## 2. 子网划分
@ -102,27 +102,27 @@ CIDR 的地址掩码可以继续称为子网掩码,子网掩码首 1 长度为
网络层实现主机之间的通信而链路层实现具体每段链路之间的通信因此在通信过程中IP 数据报的源地址和目的地址始终不变 MAC 地址随着链路的改变而改变
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/66192382-558b-4b05-a35d-ac4a2b1a9811.jpg" width="700"/> </div><br>
<div align="center"> <img src="pics/66192382-558b-4b05-a35d-ac4a2b1a9811.jpg" width="700"/> </div><br>
ARP 实现由 IP 地址得到 MAC 地址
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b9d79a5a-e7af-499b-b989-f10483e71b8b.jpg" width="500"/> </div><br>
<div align="center"> <img src="pics/b9d79a5a-e7af-499b-b989-f10483e71b8b.jpg" width="500"/> </div><br>
每个主机都有一个 ARP 高速缓存里面有本局域网上的各主机和路由器的 IP 地址到 MAC 地址的映射表
如果主机 A 知道主机 B IP 地址但是 ARP 高速缓存中没有该 IP 地址到 MAC 地址的映射此时主机 A 通过广播的方式发送 ARP 请求分组主机 B 收到该请求后会发送 ARP 响应分组给主机 A 告知其 MAC 地址随后主机 A 向其高速缓存中写入主机 B IP 地址到 MAC 地址的映射
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/8006a450-6c2f-498c-a928-c927f758b1d0.png" width="700"/> </div><br>
<div align="center"> <img src="pics/8006a450-6c2f-498c-a928-c927f758b1d0.png" width="700"/> </div><br>
# 网际控制报文协议 ICMP
ICMP 是为了更有效地转发 IP 数据报和提高交付成功的机会它封装在 IP 数据报中但是不属于高层协议
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e3124763-f75e-46c3-ba82-341e6c98d862.jpg" width="500"/> </div><br>
<div align="center"> <img src="pics/e3124763-f75e-46c3-ba82-341e6c98d862.jpg" width="500"/> </div><br>
ICMP 报文分为差错报告报文和询问报文
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/aa29cc88-7256-4399-8c7f-3cf4a6489559.png" width="600"/> </div><br>
<div align="center"> <img src="pics/aa29cc88-7256-4399-8c7f-3cf4a6489559.png" width="600"/> </div><br>
## 1. Ping
@ -155,7 +155,7 @@ VPN 使用公用的互联网作为本机构各专用网之间的通信载体。
下图中场所 A B 的通信经过互联网如果场所 A 的主机 X 要和另一个场所 B 的主机 Y 通信IP 数据报的源地址是 10.1.0.1目的地址是 10.2.0.3数据报先发送到与互联网相连的路由器 R1R1 对内部数据进行加密然后重新加上数据报的首部源地址是路由器 R1 的全球地址 125.1.2.3目的地址是路由器 R2 的全球地址 194.4.5.6路由器 R2 收到数据报后将数据部分进行解密恢复原来的数据报此时目的地址为 10.2.0.3就交付给 Y
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1556770b-8c01-4681-af10-46f1df69202c.jpg" width="800"/> </div><br>
<div align="center"> <img src="pics/1556770b-8c01-4681-af10-46f1df69202c.jpg" width="800"/> </div><br>
# 网络地址转换 NAT
@ -163,7 +163,7 @@ VPN 使用公用的互联网作为本机构各专用网之间的通信载体。
在以前NAT 将本地 IP 和全球 IP 一一对应这种方式下拥有 n 个全球 IP 地址的专用网内最多只可以同时有 n 台主机接入互联网为了更有效地利用全球 IP 地址现在常用的 NAT 转换表把传输层的端口号也用上了使得多个专用网内部的主机共用一个全球 IP 地址使用端口号的 NAT 也叫做网络地址与端口转换 NAPT
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2719067e-b299-4639-9065-bed6729dbf0b.png" width=""/> </div><br>
<div align="center"> <img src="pics/2719067e-b299-4639-9065-bed6729dbf0b.png" width=""/> </div><br>
# 路由器的结构
@ -171,7 +171,7 @@ VPN 使用公用的互联网作为本机构各专用网之间的通信载体。
分组转发结构由三个部分组成交换结构一组输入端口和一组输出端口
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c3369072-c740-43b0-b276-202bd1d3960d.jpg" width="600"/> </div><br>
<div align="center"> <img src="pics/c3369072-c740-43b0-b276-202bd1d3960d.jpg" width="600"/> </div><br>
# 路由器分组转发流程
@ -182,7 +182,7 @@ VPN 使用公用的互联网作为本机构各专用网之间的通信载体。
- 若路由表中有一个默认路由则把数据报传送给路由表中所指明的默认路由器
- 报告转发分组出错
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1ab49e39-012b-4383-8284-26570987e3c4.jpg" width="800"/> </div><br>
<div align="center"> <img src="pics/1ab49e39-012b-4383-8284-26570987e3c4.jpg" width="800"/> </div><br>
# 路由选择协议
@ -239,7 +239,7 @@ BGP 只能寻找一条比较好的路由,而不是最佳路由。
每个 AS 都必须配置 BGP 发言人通过在两个相邻 BGP 发言人之间建立 TCP 连接来交换路由信息
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9cd0ae20-4fb5-4017-a000-f7d3a0eb3529.png" width="600"/> </div><br>
<div align="center"> <img src="pics/9cd0ae20-4fb5-4017-a000-f7d3a0eb3529.png" width="600"/> </div><br>

View File

@ -28,7 +28,7 @@
将网络层传下来的分组添加首部和尾部用于标记帧的开始和结束
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/29a14735-e154-4f60-9a04-c9628e5d09f4.png" width="300"/> </div><br>
<div align="center"> <img src="pics/29a14735-e154-4f60-9a04-c9628e5d09f4.png" width="300"/> </div><br>
## 2. 透明传输
@ -36,7 +36,7 @@
帧使用首部和尾部进行定界如果帧的数据部分含有和首部尾部相同的内容那么帧的开始和结束位置就会被错误的判定需要在数据部分出现首部尾部相同的内容前面插入转义字符如果数据部分出现转义字符那么就在转义字符前面再加个转义字符在接收端进行处理之后可以还原出原始数据这个过程透明传输的内容是转义字符用户察觉不到转义字符的存在
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e738a3d2-f42e-4755-ae13-ca23497e7a97.png" width="500"/> </div><br>
<div align="center"> <img src="pics/e738a3d2-f42e-4755-ae13-ca23497e7a97.png" width="500"/> </div><br>
## 3. 差错检测
@ -64,13 +64,13 @@
频分复用的所有主机在相同的时间占用不同的频率带宽资源
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4aa5e057-bc57-4719-ab57-c6fbc861c505.png" width="350"/> </div><br>
<div align="center"> <img src="pics/4aa5e057-bc57-4719-ab57-c6fbc861c505.png" width="350"/> </div><br>
## 2. 时分复用
时分复用的所有主机在不同的时间占用相同的频率带宽资源
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/67582ade-d44a-46a6-8757-3c1296cc1ef9.png" width="350"/> </div><br>
<div align="center"> <img src="pics/67582ade-d44a-46a6-8757-3c1296cc1ef9.png" width="350"/> </div><br>
使用频分复用和时分复用进行通信在通信的过程中主机会一直占用一部分信道资源但是由于计算机数据的突发性质通信过程没必要一直占用信道资源而不让出给其它用户使用因此这两种方式对信道的利用率都不高
@ -78,7 +78,7 @@
是对时分复用的一种改进不固定每个用户在时分复用帧中的位置只要有数据就集中起来组成统计时分复用帧然后发送
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6283be2a-814a-4a10-84bf-9592533fe6bc.png" width="350"/> </div><br>
<div align="center"> <img src="pics/6283be2a-814a-4a10-84bf-9592533fe6bc.png" width="350"/> </div><br>
## 4. 波分复用
@ -90,7 +90,7 @@
<!-- <div align="center"><img src="https://latex.codecogs.com/gif.latex?\frac{1}{m}\vec{S}\cdot\vec{T}=0" class="mathjax-pic"/></div> <br> -->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/308a02e9-3346-4251-8c41-bd5536dab491.png" width="100px"> </div><br>
<div align="center"> <img src="pics/308a02e9-3346-4251-8c41-bd5536dab491.png" width="100px"> </div><br>
为了讨论方便 m=8设码片 <img src="https://latex.codecogs.com/gif.latex?\vec{S}" class="mathjax-pic"/> 为 00011011。在拥有该码片的用户发送比特 1 时就发送该码片,发送比特 0 时就发送该码片的反码 11100100。
@ -100,9 +100,9 @@
<!-- <div align="center"><img src="https://latex.codecogs.com/gif.latex?\frac{1}{m}\vec{S}\cdot\vec{S'}=-1" class="mathjax-pic"/></div> <br> -->
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6fda1dc7-5c74-49c1-bb79-237a77e43a43.png" width="100px"> </div><br>
<div align="center"> <img src="pics/6fda1dc7-5c74-49c1-bb79-237a77e43a43.png" width="100px"> </div><br>
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e325a903-f0b1-4fbd-82bf-88913dc2f290.png" width="125px"> </div><br>
<div align="center"> <img src="pics/e325a903-f0b1-4fbd-82bf-88913dc2f290.png" width="125px"> </div><br>
其中 <img src="https://latex.codecogs.com/gif.latex?\vec{S'}" class="mathjax-pic"/> 为 <img src="https://latex.codecogs.com/gif.latex?\vec{S}" class="mathjax-pic"/> 的反码。
@ -110,7 +110,7 @@
码分复用需要发送的数据量为原先的 m
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/99b6060e-099d-4201-8e86-f8ab3768a7cf.png" width="500px"> </div><br>
<div align="center"> <img src="pics/99b6060e-099d-4201-8e86-f8ab3768a7cf.png" width="500px"> </div><br>
# CSMA/CD 协议
@ -125,13 +125,13 @@ CSMA/CD 表示载波监听多点接入 / 碰撞检测。
当发生碰撞时站点要停止发送等待一段时间再发送这个时间采用 **截断二进制指数退避算法** 来确定从离散的整数集合 {0, 1, .., (2<sup>k</sup>-1)} 中随机取出一个数记作 r然后取 r 倍的争用期作为重传等待时间
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/19d423e9-74f7-4c2b-9b97-55890e0d5193.png" width="400"/> </div><br>
<div align="center"> <img src="pics/19d423e9-74f7-4c2b-9b97-55890e0d5193.png" width="400"/> </div><br>
# PPP 协议
互联网用户通常需要连接到某个 ISP 之后才能接入到互联网PPP 协议是用户计算机和 ISP 进行通信时所使用的数据链路层协议
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e1ab9f28-cb15-4178-84b2-98aad87f9bc8.jpg" width="300"/> </div><br>
<div align="center"> <img src="pics/e1ab9f28-cb15-4178-84b2-98aad87f9bc8.jpg" width="300"/> </div><br>
PPP 的帧格式
@ -140,7 +140,7 @@ PPP 的帧格式:
- FCS 字段是使用 CRC 的检验序列
- 信息部分的长度不超过 1500
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/759013d7-61d8-4509-897a-d75af598a236.png" width="400"/> </div><br>
<div align="center"> <img src="pics/759013d7-61d8-4509-897a-d75af598a236.png" width="400"/> </div><br>
# MAC 地址
@ -156,7 +156,7 @@ MAC 地址是链路层地址,长度为 6 字节48 位),用于唯一标
可以按照网络拓扑结构对局域网进行分类
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/807f4258-dba8-4c54-9c3c-a707c7ccffa2.jpg" width="800"/> </div><br>
<div align="center"> <img src="pics/807f4258-dba8-4c54-9c3c-a707c7ccffa2.jpg" width="800"/> </div><br>
# 以太网
@ -172,7 +172,7 @@ MAC 地址是链路层地址,长度为 6 字节48 位),用于唯一标
- **数据** 长度在 46-1500 之间如果太小则需要填充
- **FCS** 帧检验序列使用的是 CRC 检验方法
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/164944d3-bbd2-4bb2-924b-e62199c51b90.png" width="500"/> </div><br>
<div align="center"> <img src="pics/164944d3-bbd2-4bb2-924b-e62199c51b90.png" width="500"/> </div><br>
# 交换机
@ -182,7 +182,7 @@ MAC 地址是链路层地址,长度为 6 字节48 位),用于唯一标
下图中交换机有 4 个接口主机 A 向主机 B 发送数据帧时交换机把主机 A 到接口 1 的映射写入交换表中为了发送数据帧到 B先查交换表此时没有主机 B 的表项那么主机 A 就发送广播帧主机 C 和主机 D 会丢弃该帧主机 B 回应该帧向主机 A 发送数据包时交换机查找交换表得到主机 A 映射的接口为 1就发送数据帧到接口 1同时交换机添加主机 B 到接口 2 的映射
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a4444545-0d68-4015-9a3d-19209dc436b3.png" width="800"/> </div><br>
<div align="center"> <img src="pics/a4444545-0d68-4015-9a3d-19209dc436b3.png" width="800"/> </div><br>
# 虚拟局域网
@ -192,7 +192,7 @@ MAC 地址是链路层地址,长度为 6 字节48 位),用于唯一标
使用 VLAN 干线连接来建立虚拟局域网每台交换机上的一个特殊接口被设置为干线接口以互连 VLAN 交换机IEEE 定义了一种扩展的以太网帧格式 802.1Q它在标准以太网帧上加进了 4 字节首部 VLAN 标签用于表示该帧属于哪一个虚拟局域网
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e98e9d20-206b-4533-bacf-3448d0096f38.png" width="500"/> </div><br>
<div align="center"> <img src="pics/e98e9d20-206b-4533-bacf-3448d0096f38.png" width="500"/> </div><br>

View File

@ -10,7 +10,7 @@
私有构造函数保证了不能通过构造函数来创建对象实例只能通过公有静态函数返回唯一的私有静态变量
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/eca1f422-8381-409b-ad04-98ef39ae38ba.png"/> </div><br>
<div align="center"> <img src="pics/eca1f422-8381-409b-ad04-98ef39ae38ba.png"/> </div><br>
### Implementation

View File

@ -11,17 +11,17 @@
- Mediator中介者定义一个接口用于与各同事Colleague对象通信
- Colleague同事相关对象
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/30d6e95c-2e3c-4d32-bf4f-68128a70bc05.png"/> </div><br>
<div align="center"> <img src="pics/30d6e95c-2e3c-4d32-bf4f-68128a70bc05.png"/> </div><br>
### Implementation
Alarm闹钟CoffeePot咖啡壶Calendar日历Sprinkler喷头是一组相关的对象在某个对象的事件产生时需要去操作其它对象形成了下面这种依赖结构
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/82cfda3b-b53b-4c89-9fdb-26dd2db0cd02.jpg"/> </div><br>
<div align="center"> <img src="pics/82cfda3b-b53b-4c89-9fdb-26dd2db0cd02.jpg"/> </div><br>
使用中介者模式可以将复杂的依赖结构变成星形结构
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/5359cbf5-5a79-4874-9b17-f23c53c2cb80.jpg"/> </div><br>
<div align="center"> <img src="pics/5359cbf5-5a79-4874-9b17-f23c53c2cb80.jpg"/> </div><br>
```java
public abstract class Colleague {

View File

@ -12,7 +12,7 @@
- IntrinsicState内部状态享元对象共享内部状态
- ExtrinsicState外部状态每个享元对象的外部状态不同
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/5f5c22d5-9c0e-49e1-b5b0-6cc7032724d4.png"/> </div><br>
<div align="center"> <img src="pics/5f5c22d5-9c0e-49e1-b5b0-6cc7032724d4.png"/> </div><br>
### Implementation

View File

@ -13,7 +13,7 @@
- 保护代理Protection Proxy按权限控制对象的访问它负责检查调用者是否具有实现一个请求所必须的访问权限
- 智能代理Smart Reference取代了简单的指针它在访问对象时执行一些附加操作记录对象的引用次数当第一次引用一个对象时将它装入内存在访问一个实际对象前检查是否已经锁定了它以确保其它对象不能改变它
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9b679ff5-94c6-48a7-b9b7-2ea868e828ed.png"/> </div><br>
<div align="center"> <img src="pics/9b679ff5-94c6-48a7-b9b7-2ea868e828ed.png"/> </div><br>
### Implementation

View File

@ -6,7 +6,7 @@
### Class Diagram
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b8922f8c-95e6-4187-be85-572a509afb71.png"/> </div><br>
<div align="center"> <img src="pics/b8922f8c-95e6-4187-be85-572a509afb71.png"/> </div><br>
### Implementation

View File

@ -16,13 +16,13 @@
- Invoker通过它来调用命令
- Client可以设置命令与命令的接收者
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c44a0342-f405-4f17-b750-e27cf4aadde2.png"/> </div><br>
<div align="center"> <img src="pics/c44a0342-f405-4f17-b750-e27cf4aadde2.png"/> </div><br>
### Implementation
设计一个遥控器可以控制电灯开关
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e6bded8e-41a0-489a-88a6-638e88ab7666.jpg"/> </div><br>
<div align="center"> <img src="pics/e6bded8e-41a0-489a-88a6-638e88ab7666.jpg"/> </div><br>
```java
public interface Command {

View File

@ -10,7 +10,7 @@
- Caretaker负责保存好备忘录
- Memento备忘录存储原始对象的的状态备忘录实际上有两个接口一个是提供给 Caretaker 的窄接口它只能将备忘录传递给其它对象一个是提供给 Originator 的宽接口允许它访问到先前状态所需的所有数据理想情况是只允许 Originator 访问本备忘录的内部状态
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/50678f34-694f-45a4-91c6-34d985c83fee.png"/> </div><br>
<div align="center"> <img src="pics/50678f34-694f-45a4-91c6-34d985c83fee.png"/> </div><br>
### Implementation

View File

@ -6,7 +6,7 @@
### Class Diagram
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f9978fa6-9f49-4a0f-8540-02d269ac448f.png"/> </div><br>
<div align="center"> <img src="pics/f9978fa6-9f49-4a0f-8540-02d269ac448f.png"/> </div><br>
### Implementation

View File

@ -10,7 +10,7 @@
下图中Factory 有一个 doSomething() 方法这个方法需要用到一个产品对象这个产品对象由 factoryMethod() 方法创建该方法是抽象的需要由子类去实现
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/f4d0afd0-8e78-4914-9e60-4366eaf065b5.png"/> </div><br>
<div align="center"> <img src="pics/f4d0afd0-8e78-4914-9e60-4366eaf065b5.png"/> </div><br>
### Implementation

View File

@ -14,7 +14,7 @@
从高层次来看抽象工厂使用了组合 Cilent 组合了 AbstractFactory而工厂方法模式使用了继承
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e2190c36-8b27-4690-bde5-9911020a1294.png"/> </div><br>
<div align="center"> <img src="pics/e2190c36-8b27-4690-bde5-9911020a1294.png"/> </div><br>
### Implementation

View File

@ -11,7 +11,7 @@
- Abstraction定义抽象类的接口
- Implementor定义实现类接口
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2a1f8b0f-1dd7-4409-b177-a381c58066ad.png"/> </div><br>
<div align="center"> <img src="pics/2a1f8b0f-1dd7-4409-b177-a381c58066ad.png"/> </div><br>
### Implementation

View File

@ -8,13 +8,13 @@
### Class Diagram
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ac6a794b-68c0-486c-902f-8d988eee5766.png"/> </div><br>
<div align="center"> <img src="pics/ac6a794b-68c0-486c-902f-8d988eee5766.png"/> </div><br>
### Implementation
冲咖啡和冲茶都有类似的流程但是某些步骤会有点不一样要求复用那些相同步骤的代码
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/11236498-1417-46ce-a1b0-e10054256955.png"/> </div><br>
<div align="center"> <img src="pics/11236498-1417-46ce-a1b0-e10054256955.png"/> </div><br>
```java
public abstract class CaffeineBeverage {

View File

@ -6,13 +6,13 @@
### Class Diagram
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/79df886f-fdc3-4020-a07f-c991bb58e0d8.png"/> </div><br>
<div align="center"> <img src="pics/79df886f-fdc3-4020-a07f-c991bb58e0d8.png"/> </div><br>
### Implementation
糖果销售机有多种状态每种状态下销售机有不同的行为状态可以发生转移使得销售机的行为也发生改变
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/396be981-3f2c-4fd9-8101-dbf9c841504b.jpg" width="600"/> </div><br>
<div align="center"> <img src="pics/396be981-3f2c-4fd9-8101-dbf9c841504b.jpg" width="600"/> </div><br>
```java
public interface State {

Some files were not shown because too many files have changed in this diff Show More