Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wushizhenking
CS-Notes
提交
d8c6cfb8
C
CS-Notes
项目概览
wushizhenking
/
CS-Notes
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
CS-Notes
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
d8c6cfb8
编写于
6月 06, 2018
作者:
C
CyC2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
auto commit
上级
775902ad
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
183 addition
and
162 deletion
+183
-162
notes/算法.md
notes/算法.md
+181
-157
notes/设计模式.md
notes/设计模式.md
+2
-5
未找到文件。
notes/算法.md
浏览文件 @
d8c6cfb8
<!-- GFM-TOC -->
*
[
一、算法分析
](
#一算法分析
)
*
[
一、前言
](
#一前言
)
*
[
二、算法分析
](
#二算法分析
)
*
[
数学模型
](
#数学模型
)
*
[
ThreeSum
](
#threesum
)
*
[
倍率实验
](
#倍率实验
)
*
[
注意事项
](
#注意事项
)
*
[
二、栈和队列
](
#二
栈和队列
)
*
[
三、栈和队列
](
#三
栈和队列
)
*
[
栈
](
#栈
)
*
[
队列
](
#队列
)
*
[
三、排序
](
#三排序
)
*
[
四、并查集
](
#四并查集
)
*
[
quick-find
](
#quick-find
)
*
[
quick-union
](
#quick-union
)
*
[
加权 quick-union
](
#加权-quick-union
)
*
[
路径压缩的加权 quick-union
](
#路径压缩的加权-quick-union
)
*
[
各种 union-find 算法的比较
](
#各种-union-find-算法的比较
)
*
[
五、排序
](
#五排序
)
*
[
选择排序
](
#选择排序
)
*
[
冒泡排序
](
#冒泡排序
)
*
[
插入排序
](
#插入排序
)
...
...
@@ -20,24 +27,22 @@
*
[
外部排序
](
#外部排序
)
*
[
排序算法的比较
](
#排序算法的比较
)
*
[
Java 的排序算法实现
](
#java-的排序算法实现
)
*
[
四、查找
](
#四
查找
)
*
[
六、查找
](
#六
查找
)
*
[
二分查找实现有序符号表
](
#二分查找实现有序符号表
)
*
[
二叉查找树
](
#二叉查找树
)
*
[
2-3 查找树
](
#2-3-查找树
)
*
[
红黑二叉查找树
](
#红黑二叉查找树
)
*
[
散列表
](
#散列表
)
*
[
应用
](
#应用
)
*
[
五、union-find
](
#五union-find
)
*
[
quick-find
](
#quick-find
)
*
[
quick-union
](
#quick-union
)
*
[
加权 quick-union
](
#加权-quick-union
)
*
[
路径压缩的加权 quick-union
](
#路径压缩的加权-quick-union
)
*
[
各种 union-find 算法的比较
](
#各种-union-find-算法的比较
)
*
[
参考资料
](
#参考资料
)
<!-- GFM-TOC -->
# 一、算法分析
# 一、前言
本文实现代码以及测试代码放在
[
Algorithm
](
https://github.com/CyC2018/Algorithm
)
# 二、算法分析
## 数学模型
...
...
@@ -199,7 +204,7 @@ public class StopWatch {
将所有操作的总成本除于操作总数来将成本均摊。例如对一个空栈进行 N 次连续的 push() 调用需要访问数组的元素为 N+4+8+16+...+2N=5N-4(N 是向数组写入元素,其余的都是调整数组大小时进行复制需要的访问数组操作),均摊后每次操作访问数组的平均次数为常数。
#
二
、栈和队列
#
三
、栈和队列
## 栈
...
...
@@ -446,7 +451,169 @@ public class ListQueue<Item> implements MyQueue<Item> {
}
```
# 三、排序
# 四、并查集
用于解决动态连通性问题,能动态连接两个点,并且判断两个点是否连通。
<div
align=
"center"
>
<img
src=
"../pics//9d0a637c-6a8f-4f5a-99b9-fdcfa26793ff.png"
width=
"400"
/>
</div><br>
| 方法 | 描述 |
| :---: | :---: |
| UF(int N) | 构造一个大小为 N 的并查集 |
| void union(int p, int q) | 连接 p 和 q 节点 |
| int find(int p) | 查找 p 所在的连通分量 |
| boolean connected(int p, int q) | 判断 p 和 q 节点是否连通 |
```
java
public
abstract
class
UF
{
protected
int
[]
id
;
public
UF
(
int
N
)
{
id
=
new
int
[
N
];
for
(
int
i
=
0
;
i
<
N
;
i
++)
id
[
i
]
=
i
;
}
public
boolean
connected
(
int
p
,
int
q
)
{
return
find
(
p
)
==
find
(
q
);
}
public
abstract
int
find
(
int
p
);
public
abstract
void
union
(
int
p
,
int
q
);
}
```
## quick-find
可以快速进行 find 操作,即可以快速判断两个节点是否连通。
同一连通分量的所有节点的 id 值相等。
但是 union 操作代价却很高,需要将其中一个连通分量中的所有节点 id 值都修改为另一个节点的 id 值。
<div
align=
"center"
>
<img
src=
"../pics//8f0cc500-5994-4c7a-91a9-62885d658662.png"
width=
"350"
/>
</div><br>
```
java
public
class
QuickFindUF
extends
UF
{
public
QuickFindUF
(
int
N
)
{
super
(
N
);
}
@Override
public
int
find
(
int
p
)
{
return
id
[
p
];
}
@Override
public
void
union
(
int
p
,
int
q
)
{
int
pID
=
find
(
p
);
int
qID
=
find
(
q
);
if
(
pID
==
qID
)
return
;
for
(
int
i
=
0
;
i
<
id
.
length
;
i
++)
if
(
id
[
i
]
==
pID
)
id
[
i
]
=
qID
;
}
}
```
## quick-union
可以快速进行 union 操作,只需要修改一个节点的 id 值即可。
但是 find 操作开销很大,因为同一个连通分量的节点 id 值不同,id 值只是用来指向另一个节点。因此需要一直向上查找操作,直到找到最上层的节点。
<div
align=
"center"
>
<img
src=
"../pics//5d4a5181-65fb-4bf2-a9c6-899cab534b44.png"
width=
"350"
/>
</div><br>
```
java
public
class
QuickUnionUF
extends
UF
{
public
QuickUnionUF
(
int
N
)
{
super
(
N
);
}
@Override
public
int
find
(
int
p
)
{
while
(
p
!=
id
[
p
])
p
=
id
[
p
];
return
p
;
}
@Override
public
void
union
(
int
p
,
int
q
)
{
int
pRoot
=
find
(
p
);
int
qRoot
=
find
(
q
);
if
(
pRoot
!=
qRoot
)
id
[
pRoot
]
=
qRoot
;
}
}
```
这种方法可以快速进行 union 操作,但是 find 操作和树高成正比,最坏的情况下树的高度为触点的数目。
<div
align=
"center"
>
<img
src=
"../pics//bfbb11e2-d208-4efa-b97b-24cd40467cd8.png"
width=
"150"
/>
</div><br>
## 加权 quick-union
为了解决 quick-union 的树通常会很高的问题,加权 quick-union 在 union 操作时会让较小的树连接较大的树上面。
理论研究证明,加权 quick-union 算法构造的树深度最多不超过 logN。
<div
align=
"center"
>
<img
src=
"../pics//a4c17d43-fa5e-4935-b74e-147e7f7e782c.png"
width=
"200"
/>
</div><br>
```
java
public
class
WeightedQuickUnionUF
extends
UF
{
// 保存节点的数量信息
private
int
[]
sz
;
public
WeightedQuickUnionUF
(
int
N
)
{
super
(
N
);
this
.
sz
=
new
int
[
N
];
for
(
int
i
=
0
;
i
<
N
;
i
++)
this
.
sz
[
i
]
=
1
;
}
@Override
public
int
find
(
int
p
)
{
while
(
p
!=
id
[
p
])
p
=
id
[
p
];
return
p
;
}
@Override
public
void
union
(
int
p
,
int
q
)
{
int
i
=
find
(
p
);
int
j
=
find
(
q
);
if
(
i
==
j
)
return
;
if
(
sz
[
i
]
<
sz
[
j
])
{
id
[
i
]
=
j
;
sz
[
j
]
+=
sz
[
i
];
}
else
{
id
[
j
]
=
i
;
sz
[
i
]
+=
sz
[
j
];
}
}
}
```
## 路径压缩的加权 quick-union
在检查节点的同时将它们直接链接到根节点,只需要在 find 中添加一个循环即可。
## 各种 union-find 算法的比较
| 算法 | union | find |
| :---: | :---: | :---: |
| quick-find | N | 1 |
| quick-union | 树高 | 树高 |
| 加权 quick-union | logN | logN |
| 路径压缩的加权 quick-union | 非常接近 1 | 非常接近 1 |
# 五、排序
待排序的元素需要实现 Java 的 Comparable 接口,该接口有 compareTo() 方法,可以用它来判断两个元素的大小关系。
...
...
@@ -949,7 +1116,7 @@ public class HeapSort {
Java 主要排序方法为 java.util.Arrays.sort(),对于原始数据类型使用三向切分的快速排序,对于引用类型使用归并排序。
#
四
、查找
#
六
、查找
符号表是一种存储键值对的数据结构,主要支持两种操作:插入一个新的键值对、根据给定键得到值。
...
...
@@ -1659,149 +1826,6 @@ public class SparseVector {
}
```
# 五、union-find
用于解决动态连通性问题,能动态连接两个点,并且判断两个点是否连通。
<div
align=
"center"
>
<img
src=
"../pics//9d0a637c-6a8f-4f5a-99b9-fdcfa26793ff.png"
width=
"400"
/>
</div><br>
| 方法 | 描述 |
| :---: | :---: |
| UF(int N) | 构造一个大小为 N 的并查集 |
| void union(int p, int q) | 连接 p 和 q 节点 |
| int find(int p) | 查找 p 所在的连通分量 |
| boolean connected(int p, int q) | 判断 p 和 q 节点是否连通 |
```
java
public
class
UF
{
private
int
[]
id
;
public
UF
(
int
N
)
{
id
=
new
int
[
N
];
for
(
int
i
=
0
;
i
<
N
;
i
++)
{
id
[
i
]
=
i
;
}
}
public
boolean
connected
(
int
p
,
int
q
)
{
return
find
(
p
)
==
find
(
q
);
}
}
```
## quick-find
可以快速进行 find 操作,即可以快速判断两个节点是否连通。
同一连通分量的所有节点的 id 值相等。
但是 union 操作代价却很高,需要将其中一个连通分量中的所有节点 id 值都修改为另一个节点的 id 值。
<div
align=
"center"
>
<img
src=
"../pics//8f0cc500-5994-4c7a-91a9-62885d658662.png"
width=
"350"
/>
</div><br>
```
java
public
int
find
(
int
p
)
{
return
id
[
p
];
}
public
void
union
(
int
p
,
int
q
)
{
int
pID
=
find
(
p
);
int
qID
=
find
(
q
);
if
(
pID
==
qID
)
return
;
for
(
int
i
=
0
;
i
<
id
.
length
;
i
++)
{
if
(
id
[
i
]
==
pID
)
id
[
i
]
=
qID
;
}
}
```
## quick-union
可以快速进行 union 操作,只需要修改一个节点的 id 值即可。
但是 find 操作开销很大,因为同一个连通分量的节点 id 值不同,id 值只是用来指向另一个节点。因此需要一直向上查找操作,直到找到最上层的节点。
<div
align=
"center"
>
<img
src=
"../pics//5d4a5181-65fb-4bf2-a9c6-899cab534b44.png"
width=
"350"
/>
</div><br>
```
java
public
int
find
(
int
p
)
{
while
(
p
!=
id
[
p
])
p
=
id
[
p
];
return
p
;
}
public
void
union
(
int
p
,
int
q
)
{
int
pRoot
=
find
(
p
);
int
qRoot
=
find
(
q
);
if
(
pRoot
==
qRoot
)
return
;
id
[
pRoot
]
=
qRoot
;
}
```
这种方法可以快速进行 union 操作,但是 find 操作和树高成正比,最坏的情况下树的高度为触点的数目。
<div
align=
"center"
>
<img
src=
"../pics//bfbb11e2-d208-4efa-b97b-24cd40467cd8.png"
width=
"150"
/>
</div><br>
## 加权 quick-union
为了解决 quick-union 的树通常会很高的问题,加权 quick-union 在 union 操作时会让较小的树连接较大的树上面。
理论研究证明,加权 quick-union 算法构造的树深度最多不超过 logN。
<div
align=
"center"
>
<img
src=
"../pics//a4c17d43-fa5e-4935-b74e-147e7f7e782c.png"
width=
"200"
/>
</div><br>
```
java
public
class
WeightedQuickUnionUF
{
private
int
[]
id
;
// 保存节点的数量信息
private
int
[]
sz
;
public
WeightedQuickUnionUF
(
int
N
)
{
id
=
new
int
[
N
];
sz
=
new
int
[
N
];
for
(
int
i
=
0
;
i
<
N
;
i
++)
{
id
[
i
]
=
i
;
sz
[
i
]
=
1
;
}
}
public
boolean
connected
(
int
p
,
int
q
)
{
return
find
(
p
)
==
find
(
q
);
}
public
int
find
(
int
p
)
{
while
(
p
!=
id
[
p
])
p
=
id
[
p
];
return
p
;
}
public
void
union
(
int
p
,
int
q
)
{
int
i
=
find
(
p
);
int
j
=
find
(
q
);
if
(
i
==
j
)
return
;
if
(
sz
[
i
]
<
sz
[
j
])
{
id
[
i
]
=
j
;
sz
[
j
]
+=
sz
[
i
];
}
else
{
id
[
j
]
=
i
;
sz
[
i
]
+=
sz
[
j
];
}
}
}
```
## 路径压缩的加权 quick-union
在检查节点的同时将它们直接链接到根节点,只需要在 find 中添加一个循环即可。
## 各种 union-find 算法的比较
| 算法 | union | find |
| :---: | :---: | :---: |
| quick-find | N | 1 |
| quick-union | 树高 | 树高 |
| 加权 quick-union | logN | logN |
| 路径压缩的加权 quick-union | 非常接近 1 | 非常接近 1 |
# 参考资料
-
Sedgewick, Robert, and Kevin Wayne. _Algorithms_. Addison-Wesley Professional, 2011.
...
...
notes/设计模式.md
浏览文件 @
d8c6cfb8
...
...
@@ -1280,7 +1280,7 @@ public class CalculatorImp implements Calculator {
```
java
/**
* Memento Interface to Originator
*
*
* This interface allows the originator to restore its state
*/
public
interface
PreviousCalculationToOriginator
{
...
...
@@ -1359,7 +1359,7 @@ public class Client {
// user hits CTRL + Z to undo last operation and see last result
calculator
.
restorePreviousCalculation
(
memento
);
// result restored
// result restored
System
.
out
.
println
(
calculator
.
getCalculationResult
());
}
}
...
...
@@ -2269,7 +2269,6 @@ public class Client {
}
```
# 四、结构型
## 1. 适配器(Adapter)
...
...
@@ -2582,7 +2581,6 @@ public class Leaf extends Component {
System
.
out
.
println
(
"left:"
+
name
);
}
@Override
public
void
add
(
Component
component
)
{
throw
new
UnsupportedOperationException
();
// 牺牲透明性换取单一职责原则,这样就不用考虑是叶子节点还是组合节点
...
...
@@ -2887,7 +2885,6 @@ Java 利用缓存来加速大量小对象的访问时间。
控制对其它对象的方法。
### 类图
代理有以下四类:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录