From 6cb517e4a51352bc13d616b594a6ea35f0169376 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 17 Mar 2018 22:48:41 +0800 Subject: [PATCH] auto commit --- notes/算法.md | 114 ++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 65 deletions(-) diff --git a/notes/算法.md b/notes/算法.md index d7e8babe..c27b6841 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -16,44 +16,17 @@ * [各种 union-find 算法的比较](#各种-union-find-算法的比较) * [四、排序](#四排序) * [初级排序算法](#初级排序算法) - * [1. 选择排序](#1-选择排序) - * [2. 插入排序](#2-插入排序) - * [3. 希尔排序](#3-希尔排序) * [归并排序](#归并排序) - * [1. 归并方法](#1-归并方法) - * [2. 自顶向下归并排序](#2-自顶向下归并排序) - * [3. 自底向上归并排序](#3-自底向上归并排序) * [快速排序](#快速排序) - * [1. 基本算法](#1-基本算法) - * [2. 切分](#2-切分) - * [3. 性能分析](#3-性能分析) - * [4. 算法改进](#4-算法改进) * [优先队列](#优先队列) - * [1. 堆](#1-堆) - * [2. 上浮和下沉](#2-上浮和下沉) - * [3. 插入元素](#3-插入元素) - * [4. 删除最大元素](#4-删除最大元素) - * [5. 堆排序](#5-堆排序) - * [6. 分析](#6-分析) * [应用](#应用) - * [1. 排序算法的比较](#1-排序算法的比较) - * [2. Java 的排序算法实现](#2-java-的排序算法实现) - * [3. 基于切分的快速选择算法](#3-基于切分的快速选择算法) * [五、查找](#五查找) * [符号表](#符号表) * [二叉查找树](#二叉查找树) - * [平衡查找树](#平衡查找树) - * [1. 2-3 查找树](#1-2-3-查找树) - * [2. 红黑二叉查找树](#2-红黑二叉查找树) + * [2-3 查找树](#2-3-查找树) + * [红黑二叉查找树](#红黑二叉查找树) * [散列表](#散列表) - * [1. 散列函数](#1-散列函数) - * [2. 基于拉链法的散列表](#2-基于拉链法的散列表) - * [3. 基于线性探测法的散列表](#3-基于线性探测法的散列表) * [应用](#应用) - * [1. 各种符号表实现的比较](#1-各种符号表实现的比较) - * [2. Java 的符号表实现](#2-java-的符号表实现) - * [3. 集合类型](#3-集合类型) - * [4. 稀疏向量乘法](#4-稀疏向量乘法) @@ -73,23 +46,23 @@ ## 数学模型 -#### 1. 近似 + **1. 近似**
使用 \~f(N) 来表示所有随着 N 的增大除以 f(N) 的结果趋近于 1 的函数 , 例如 N3/6-N2/2+N/3 \~ N3/6。

-#### 2. 增长数量级 + **2. 增长数量级**
增长数量级将算法与它的实现隔离开来,一个算法的增长数量级为 N3 与它是否用 Java 实现,是否运行于特定计算机上无关。

-#### 3. 内循环 + **3. 内循环**
执行最频繁的指令决定了程序执行的总时间,把这些指令称为程序的内循环。 -#### 4. 成本模型 + **4. 成本模型**
使用成本模型来评估算法,例如数组的访问次数就是一种成本模型。 @@ -156,23 +129,31 @@ public class ThreeSumFast { ## 注意事项 -#### 1. 大常数 + **1. 大常数**
+ 在求近似时,如果低级项的常数系数很大,那么近似的结果就是错误的。 -#### 2. 缓存 + **2. 缓存**
+ + 计算机系统会使用缓存技术来组织内存,访问数组相邻的元素会比访问不相邻的元素快很多。 -#### 3. 对最坏情况下的性能的保证 + **3. 对最坏情况下的性能的保证**
+ + 在核反应堆、心脏起搏器或者刹车控制器中的软件,最坏情况下的性能是十分重要的。 -#### 4. 随机化算法 + **4. 随机化算法**
+ + 通过打乱输入,去除算法对输入的依赖。 -#### 5. 均摊分析 + **5. 均摊分析**
+ 将所有操作的总成本除于操作总数来将成本均摊。例如对一个空栈进行 N 次连续的 push() 调用需要访问数组的元素为 N+4+8+16+...+2N=5N-4(N 是向数组写入元素,其余的都是调整数组大小时进行复制需要的访问数组操作),均摊后每次操作访问数组的平均次数为常数。 @@ -184,7 +165,8 @@ first-in-last-out(FILO)

-#### 1. 数组实现 + **1. 数组实现**
+ ```java public class ResizeArrayStack implements Iterable { @@ -251,7 +233,7 @@ public class ResizeArrayStack implements Iterable { Item[] arr = (Item[]) new Object[N]; ``` -#### 2. 链表实现 + **2. 链表实现**
需要使用链表的头插法来实现,因为头插法中最后压入栈的元素在链表的开头,它的 next 指针指向前一个压入栈的元素,在弹出元素使就可以让前一个压入栈的元素称为栈顶元素。 @@ -910,11 +892,13 @@ public static Comparable select(Comparable[] a, int k) { ## 符号表 -#### 1. 无序符号表 + **1. 无序符号表**

-#### 2. 有序符号表 + + **2. 有序符号表**
+

@@ -922,7 +906,9 @@ public static Comparable select(Comparable[] a, int k) { 查找的成本模型:键的比较次数,在不进行比较时使用数组的访问次数。 -#### 3. 二分查找实现有序符号表 + **3. 二分查找实现有序符号表**
+ + 使用一对平行数组,一个存储键一个存储值。 @@ -1028,7 +1014,7 @@ public class BST, Value> { } ``` -#### 1. get() +### 1. get() 如果树是空的,则查找未命中;如果被查找的键和根节点的键相等,查找命中,否则递归地在子树中查找:如果被查找的键较小就在左子树中查找,较大就在右子树中查找。 @@ -1045,7 +1031,7 @@ private Value get(Node x, Key key) { } ``` -#### 2. put() +### 2. put() 当插入的键不存在于树中,需要创建一个新节点,并且更新上层节点的链接使得该节点正确链接到树中。 @@ -1064,7 +1050,7 @@ private Node put(Node x, Key key, Value val) { } ``` -#### 3. 分析 +### 3. 分析 二叉查找树的算法运行时间取决于树的形状,而树的形状又取决于键被插入的先后顺序。最好的情况下树是完全平衡的,每条空链接和根节点的距离都为 logN。在最坏的情况下,树的高度为 N。 @@ -1072,7 +1058,7 @@ private Node put(Node x, Key key, Value val) { 复杂度:查找和插入操作都为对数级别。 -#### 4. floor() +### 4. floor() 如果 key 小于根节点的 key,那么小于等于 key 的最大键节点一定在左子树中;如果 key 大于根节点的 key,只有当根节点右子树中存在小于等于 key 的节点,小于等于 key 的最大键节点才在右子树中,否则根节点就是小于等于 key 的最大键节点。 @@ -1096,7 +1082,7 @@ private Node floor(Node x, Key key) { } ``` -#### 5. rank() +### 5. rank() ```java public int rank(Key key) { @@ -1111,7 +1097,7 @@ private int rank(Key key, Node x) { } ``` -#### 6. min() +### 6. min() ```java private Node min(Node x) { @@ -1120,7 +1106,7 @@ private Node min(Node x) { } ``` -#### 7. deleteMin() +### 7. deleteMin() 令指向最小节点的链接指向最小节点的右子树。 @@ -1138,7 +1124,7 @@ public Node deleteMin(Node x) { } ``` -#### 8. delete() +### 8. delete() 如果待删除的节点只有一个子树,那么只需要让指向待删除节点的链接指向唯一的子树即可;否则,让右子树的最小节点替换该节点。 @@ -1166,7 +1152,7 @@ private Node delete(Node x, Key key) { } ``` -#### 9. keys() +### 9. keys() 利用二叉查找树中序遍历的结果为有序序列的特点。 @@ -1186,31 +1172,29 @@ private void keys(Node x, Queue queue, Key lo, Key hi) { } ``` -#### 10. 性能分析 +### 10. 性能分析 复杂度:二叉查找树所有操作在最坏的情况下所需要的时间都和树的高度成正比。 -## 平衡查找树 - -### 1. 2-3 查找树 +## 2-3 查找树

一颗完美平衡的 2-3 查找树的所有空链接到根节点的距离应该是相同的。 -#### 1.1 插入操作 +### 1. 插入操作 当插入之后产生一个临时 4- 节点时,需要将 4- 节点分裂成 3 个 2- 节点,并将中间的 2- 节点移到上层节点中。如果上移操作继续产生临时 4- 节点则一直进行分裂上移,直到不存在临时 4- 节点。

-#### 1.2 性质 +### 2. 性质 2-3 查找树插入操作的变换都是局部的,除了相关的节点和链接之外不必修改或者检查树的其它部分,而这些局部变换不会影响树的全局有序性和平衡性。 2-3 查找树的查找和插入操作复杂度和插入顺序 **无关** ,在最坏的情况下查找和插入操作访问的节点必然不超过 logN 个,含有 10 亿个节点的 2-3 查找树最多只需要访问 30 个节点就能进行任意的查找和插入操作。 -### 2. 红黑二叉查找树 +## 红黑二叉查找树 2-3 查找树需要用到 2- 节点和 3- 节点,红黑树使用红链接来实现 3- 节点。指向一个节点的链接颜色如果为红色,那么这个节点和上层节点表示的是一个 3- 节点,而黑色则是普通链接。 @@ -1253,7 +1237,7 @@ public class RedBlackBST, Value> { } ``` -#### 2.1 左旋转 +### 1. 左旋转 因为合法的红链接都为左链接,如果出现右链接为红链接,那么就需要进行左旋转操作。 @@ -1274,7 +1258,7 @@ public Node rotateLeft(Node h) { } ``` -#### 2.2 右旋转 +### 2. 右旋转 进行右旋转是为了转换两个连续的左红链接,这会在之后的插入过程中探讨。 @@ -1294,7 +1278,7 @@ public Node rotateRight(Node h) { } ``` -#### 2.3 颜色转换 +### 3. 颜色转换 一个 4- 节点在红黑树中表现为一个节点的左右子节点都是红色的。分裂 4- 节点除了需要将子节点的颜色由红变黑之外,同时需要将父节点的颜色由黑变红,从 2-3 树的角度看就是将中间节点移到上层节点。 @@ -1310,7 +1294,7 @@ void flipColors(Node h){ } ``` -#### 2.4 插入 +### 4. 插入 先将一个节点按二叉查找树的方法插入到正确位置,然后再进行如下颜色操作: @@ -1346,7 +1330,7 @@ private Node put(Node x, Key key, Value val) { 根节点一定为黑色,因为根节点没有上层节点,也就没有上层节点的左链接指向根节点。flipColors() 有可能会使得根节点的颜色变为红色,每当根节点由红色变成黑色时树的黑链接高度加 1. -#### 2.5 删除最小键 +### 5. 删除最小键 如果最小键在一个 2- 节点中,那么删除该键会留下一个空链接,就破坏了平衡性,因此要确保最小键不在 2- 节点中。将 2- 节点转换成 3- 节点或者 4- 节点有两种方法,一种是向上层节点拿一个 key,一种是向兄弟节点拿一个 key。如果上层节点是 2- 节点,那么就没办法从上层节点拿 key 了,因此要保证删除路径上的所有节点都不是 2- 节点。在向下删除的过程中,保证以下情况之一发生: @@ -1360,7 +1344,7 @@ private Node put(Node x, Key key, Value val) {

-#### 2.6 分析 +### 6. 分析 一颗大小为 N 的红黑树的高度不会超过 2logN。最坏的情况下是它所对应的 2-3 树中构成最左边的路径节点全部都是 3- 节点而其余都是 2- 节点。