Statistics
376
Views
68
Downloads
0
Donations
Uploader

高宏飞

Shared on 2025-07-17
Support
Share
Support Statistics
¥.00 · 0times
Text Preview (First 20 pages)
Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

(This page has no text content)
(This page has no text content)
图灵社区的电子书没有采用专有客 户端,您可以在任意设备上,用自 己喜欢的浏览器和PDF阅读器进行 阅读。 但您购买的电子书仅供您个人使用, 未经授权,不得进行传播。 我们愿意相信读者具有这样的良知 和觉悟,与我们共同保护知识产权。 如果购买者有侵权行为,我们可能 对该用户实施包括但不限于关闭该 帐号等维权措施,并可能追究法律 责任。
表 1.2.14 一种能够累加数据的抽象数据类型(可视版本) API public class VisualAccumulator VisualAccumulator(int trials, double max) void addDataValue(double val) 添加一个新的数据值 double mean() 所有数据的平均值 String toString() 对象的字符串表示 public class TestVisualAccumulator { public static void main(String[] args) { int T = Integer.parseInt(args[0]); VisualAccumulator a = new VisualAccumulator(T, 1.0); for (int t = 0; t < T; t++) a.addDataValue(StdRandom.random()); StdOut.println(a); } } public class VisualAccumulator { private double total; private int N; public VisualAccumulator(int trials, double max) { StdDraw.setXscale(0, trials); StdDraw.setYscale(0, max); StdDraw.setPenRadius(.005); } public void addDataValue(double val) { N++; total += val; StdDraw.setPenColor(StdDraw.DARK_GRAY); StdDraw.point(N, val); StdDraw.setPenColor(StdDraw.RED); StdDraw.point(N, total/N); } public double mean() public String toString() // 和 Accumulator 相同 } 典型的用例 数据类型的实现
一个装有 弹子球的 背包 处理任意弹子球 m(任意顺序) add( ) for (Marble m : bag) add( ) 图 1.3.1 背包的操作 灰点的高度 即数据点的值 左起第N个红点的高度为最 靠左的N个灰点的平均高度   % java TestVisualAccumulator 2000 Mean (2000 values): 0.509789 图 1.2.8 可视化累加器图像 0 0 128 256 成 本 ( 数 组 引 用 ) add()操作的数量 每个灰点表 示一次操作 红点表示的是累计平均 5 128 64 图 1.4.7 向一个 RandomBag对象中添加元素时的 均摊成本
0 1 2 3 4 5 6 7 8 9 4 3 3 8 6 5 9 4 2 1 8 9 5 0 7 2 6 1 1 0 6 7 2个连通分量 不用打印 出已知相 连的整数对 图 1.5.1 动态连通性问题 黑色的元素 参与了比较 灰色的元素 没有被移动 插入排序 选择排序 图 2.1.1 初级排序算法的可视轨迹图 quick-union算法 加权quick-union算法 0 0 900 1300 458 访 问 数 组 的 次 数 连接总数 0 100 0 20 每个灰点都表 示用例处理过 的一条连接 每个红点都表 示一个累计平均 union()操作至 少访问数组625次 connected()操作 只会访问数组2次 find()操作变 得越来越昂贵 没有任何昂贵的操作 20 8 quick-find算法 图 1.5.10 所有操作的总成本
切分元素 输入 结果 第一次切 分的结果 左子数组 部分有序 两个子数组 都已部分有序 图 2.3.3 使用了三取样切分和插入排序转换的快速排序 和切分元素相等的元素 图 2.3.5 三向切分的快速排序的可视轨迹
输入 排序 结果 堆有序 红色的条目 是下沉的元素 灰色的元 素不会移动 黑色的元素 正在进行交换 图 2.4.8 堆排序的可视轨迹 中位数 lo i hi 图 2.5.2 用切分找出中位数 红色为新 加入的结点 黑色是在查找 中被遍历的结点 首结点 S 0 S 0E 1 S 0E 1A 2 S 0E 1A 2R 3 S 0E 1A 2R 3C 4 S 0E 1A 2R 3C 4H 5 S 0E 6A 2R 3C 4H 5 S 0E 6A 2R 3C 4H 5 S 0E 6A 8R 3C 4H 5 X 7 X 7 M 9 P 10 L 11 L 11 圈中是被 修改过的值 灰色结点没 有被访问过 S 0E 6A 8R 3C 4H 5X 7 M 9 S 0E 6A 8R 3C 4H 5X 7 P 10 M 9 S 0E 6A 8R 3C 4H 5X 7 P 10 M 9 S 0E 12A 8R 3C 4H 5X 7 键 值 S 0 E 1 A 2 R 3 C 4 H 5 E 6 X 7 A 8 M 9 P 10 L 11 E 12 图 3.1.2 使用基于链表的符号表的索引用例的轨迹
1.39 lgN −1.85 20 0 10 000节点数量N 平 均 路 径 长 度 16 100 图 3.2.14 一棵随机构造的二叉查找树中由根到达任意结点的平均路径长度 图 3.3.13 将红链接画平时,一棵红黑树就是一棵 2-3 树 ... ... ... ... ... ... a b3-结点 a b 介于a 和b之间 介于a 和b之间 小于a 小于a 大于b 大于b 图 3.3.12 由一条红色左链接相连的两个 2- 结点表示一个 3- 结点
X SH P J R E A M C L XSH P J RE A M C L 红黑树 将红链接画平 2-3树 E J H L M R P S XA C private static final boolean RED = true; private static final boolean BLACK = false; private class Node { Key key; // 键 Value val; // 相关联的值 Node left, right; // 左右子树 int N; // 这棵子树中的结点总数 boolean color; // 由其父结点指向它的链接的颜色 Node(Key key, Value val, int N, boolean color) { this.key = key; this.val = val; this.N = N; this.color = color; } } private boolean isRed(Node x) { if (x == null) return false; return x.color == RED; } J G E A D C hh.left.color 的值是RED h.right.color 的值是BLACK 图 3.3.14 红黑树和 2-3 树的一一对应关系 图 3.3.15 红黑树的结点表示 Node rotateLeft(Node h) { Node x = h.right; h.right = x.left; x.left = h; x.color = h.color; h.color = RED; x.N = h.N; h.N = 1 + size(h.left) + size(h.right); return x; } h x x h E S E S 介于E 和S之间 可能是左链接也可能是 右链接,颜色可红可黑 小于E 大于S 介于E 和S之间小于E 大于S Node rotateRight(Node h) { Node x = h.left; h.left = x.right; x.right = h; x.color = h.color; h.color = RED; x.N = h.N; h.N = 1 + size(h.left) + size(h.right); return x; } x h h x E S 介于E 和S之间小于E 大于S E S 介于E 和S之间 小于E 大于S 图 3.3.16 左旋转 h的右链接 图 3.3.17 右旋转 h的左链接
指向含有a的 新结点的红链 接将这个2-结点 变为一个3-结点 查找结束 于该空链接 查找结束 于该空链接 用红链接和 新结点相连 左旋转得到一 个正常的3-结点 a b a a b b a b 根结点 根结点 根结点 根结点 向左插入 向右插入 E A E R S R S A C E R S C A 在此处插 入新结点 出现红色右链接, 进行左旋转 插入C 图 3.3.18 向单个 2- 结点中插入一个新键 图 3.3.19 向树底部的 2- 结点插入一个新键 a c b 旋转后变为红色左链接 旋转后变为 红色右链接 旋转后变为 红色右链接 查找结束 于该空链接 查找结束 于该空链接 查找结束 于该空链接 用红链接和 新结点相连 用红链接和 新结点相连 用红链接和 新结点相连 将链接颜 色变为黑 将链接颜 色变为黑 将链接颜 色变为黑 a c b b c a b c a b c a b c a b c a c a c b 新键最小 新键介于两者之间 a b a b c a b c 新键最大 图 3.3.20 向一棵双键树(即一个 3- 结点)中插入一个新键的三种情况
void flipColors(Node h) { h.color = RED; h.left.color = BLACK; h.right.color = BLACK; } h A E 介于A 和E之间小于A S 可能是左链接, 也可能是右链接 用红链接将中间 结点和父结点相连 黑色链接分 别指向两个 2-结点 大于S A E S 介于E 和S之间 介于A 和E之间小于A 大于S 介于E 和S之间 图 3.3.21 通过转换链接的颜色来分解 4- 结点 H E R S A C S S R E H 在此插 入新结点 E R S A C 出现红色右链 接,需要左旋转 出现两条连续的左 链接,需要右旋转 E H R A C 拥有两个红色子链接, 需要进行颜色转换 S E H R A C A C 插入H E R SA C E H R SA C SH E R A C 图 3.3.22 向树底部的 3- 结点插入一个新键 颜色转换 右旋转 左旋转 h h h 图 3.3.23 红黑树中红链接向上传递
S E A S E A PA H C M E L A H C M E L E A R C H X M P L C S A E H L M P R S X E R S L M P R S X A H C E R S C A E H A C E S A C A E A C S X M R E A H C S X R E A C H P R S X M E A C H P R SH X M E A C L S R E A C H L H C A E S R M L P A H C E R M L P H C A E 标准索引测试用例 用同一组键按照升序插入来构造一棵红黑树 插入 插入 图 3.3.24 红黑树的构造轨迹 图 3.3.27 使用随机键构造的典型红黑树,没有画出空链接
图 3.3.28 使用升序键列构造的一棵红黑树,没有画出空链接 lgN − 0.5 20 0 10 000 操作 成 本 13 100 图 3.3.30 随机构造的红黑树中到达一个随机结点的平均路径长度 0 96 频 率 键值 110 10679/97 图 3.4.2 《双城记》中每个单词的散列值的出现频率(10 679 个键,即单词,M=97) 125 0 0 10 20 30 α =10.711... αke-α k ! 链表的长度(10 679个键, M = 997) 频 率 图 3.4.4  使用 SeparateChainingHashST,运行 java FrequencyCounter 8 < tale.txt时所有链表 的长度
0 1 2 3 4 5 6 7 8 9 S 0 S E 0 1 A S E 2 0 1 A S E R 2 0 1 3 A C S E R 2 4 0 1 3 A C S H E R 2 4 0 5 1 3 A C S H E R 2 4 0 5 6 3 A C S H E R X 2 4 0 5 6 3 7 A C S H E R X 8 4 0 5 6 3 7 M A C S H E R X 9 8 4 0 5 6 3 7 P M A C S H E R X 9 8 4 0 5 6 3 7 P M A C S H L E R X 9 8 4 0 5 6 3 7 P M A C S H L E R X 9 8 4 0 5 3 7 10 11 12 13 14 15 11 12 1110 10 10 灰色的键 未被访问 探测序列 折回到0 红色的是 新插入的键 黑色的 是探针键 S 6 0 E 10 1 A 4 2 R 14 3 C 5 4 H 4 5 E 10 6 X 15 7 A 4 8 M 1 9 P 14 10 L 6 11 E 10 12 keys[] vals[] 键散列值 值 图 3.4.6 标准索引用例使用的基于线性探测的符号表的轨迹 13 13 0 5 4 3 0 1 9 12 6 4 5 4 0 2 11 12 9 10 0 6 7 8 9 11 5 3 % java Graph tinyG.txt 13 vertices, 13 edges 0: 6 2 1 5 1: 0 2: 0 3: 5 4 4: 5 6 3 5: 3 4 0 6: 0 4 7: 8 8: 7 9: 11 10 12 10: 9 11: 9 12 12: 11 9 tinyG.txt V E 输入的第一个 相邻顶点在链表 中排在最后 每条边在第 二次出现时 都被标记为红色 图 4.1.10 由边得到的邻接表 图 4.1.12 Tremaux 搜索 0 3 4 7 10 11 图 4.1.7 二分图
marked[] 0 T 1 2 3 4 5 0 T 1 2 T 3 4 5 0 T 1 T 2 T 3 4 5 0 T 1 T 2 T 3 T 4 5 0 T 1 T 2 T 3 T 4 5 T 0 T 1 T 2 T 3 T 4 T 5 T dfs(0) dfs(2) 检查 0 dfs(1) 检查 0 检查 2 1 完成 dfs(3) dfs(5) 检查 3 检查 0 5 完成 dfs(4) 检查 3 检查 2 4 完成 检查 2 3 完成 检查 4 2 完成 检查 1 检查 5 0 完成 0 2 1 5 1 0 2 2 0 1 3 4 3 5 4 2 4 3 2 5 3 0 0 2 1 5 1 0 2 2 0 1 3 4 3 5 4 2 4 3 2 5 3 0 0 2 1 5 1 0 2 2 0 1 3 4 3 5 4 2 4 3 2 5 3 0 0 2 1 5 1 0 2 2 0 1 3 4 3 5 4 2 4 3 2 5 3 0 0 2 1 5 1 0 2 2 0 1 3 4 3 5 4 2 4 3 2 5 3 0 adj[] 0 2 1 5 1 0 2 2 0 1 3 4 3 5 4 2 4 3 2 5 3 0 图 4.1.14  使用深度优先搜索的轨迹,寻找所有和顶点 0 连通的顶点 edgeTo[] 0 1 2 3 4 5 0 1 2 0 3 4 5 0 1 2 2 0 3 4 5 0 1 2 2 0 3 2 4 5 0 1 2 2 0 3 2 4 5 3 0 1 2 2 0 3 2 4 3 5 3 dfs(0) dfs(2) 检查 0 dfs(1) 检查 0 检查 2 1 完成 dfs(3) dfs(5) 检查 3 检查 0 5 完成 dfs(4) 检查 3 检查 2 4 完成 检查 2 3 完成 检查 4 2 完成 检查 1 检查 5 0 完成 0 1 2 2 0 3 2 4 3 5 3 图 4.1.15  使用深度优先搜索的轨迹,寻找所有 起点为 0 的路径
marked[] 0 T 1 2 3 4 5 0 T 1 T 2 T 3 4 5 T 0 T 1 T 2 T 3 T 4 T 5 T 0 1 5 3 4 2 1 5 5 3 4 3 4 4 edgeTo[] 0 1 2 3 4 5 0 1 0 2 0 3 4 5 0 0 1 0 2 0 3 2 4 2 5 0 0 2 1 5 1 0 2 2 0 1 3 4 3 5 4 2 4 3 2 5 3 0 0 2 1 5 1 0 2 2 0 1 3 4 3 5 4 2 4 3 2 5 3 0 0 T 1 T 2 T 3 T 4 T 5 T 0 1 0 2 0 3 2 4 2 5 0 0 2 1 5 1 0 2 2 0 1 3 4 3 5 4 2 4 3 2 5 3 0 adj[] 0 2 1 5 1 0 2 2 0 1 3 4 3 5 4 2 4 3 2 5 3 0 0 T 1 T 2 T 3 T 4 T 5 T 0 1 0 2 0 3 2 4 2 5 0 0 2 1 5 1 0 2 2 0 1 3 4 3 5 4 2 4 3 2 5 3 0 0 T 1 T 2 T 3 T 4 T 5 T 0 1 0 2 0 3 2 4 2 5 0 0 2 1 5 1 0 2 2 0 1 3 4 3 5 4 2 4 3 2 5 3 0 queue 图 4.1.18  使用广度优先搜索的轨迹,寻找所有起点为 0的路径 0 1 2 3 4 5 6 7 8 9 10 11 12 0 T T T T T T 1 T 2 T T T T T T 3 T T T T T T 4 T T T T T T 5 T T T T T T 6 T T T T T T T T T T T 7 T T T T T T T T T T T T T 8 T T T T T T T T T T T T T 9 T T T T T T T T T T 10 T T T T T T T T T T 11 T T T T T T T T T T 12 T T T T T T T T T T 自环(灰色) 顶点12是从 顶点6可达的 原始有向图 中的边(红色) 图 4.2.18 传递闭包 最小生成树中的边 切分生成的权 重最小的边 图 4.3.6 贪心最小生成树算法 权重最小的横切边肯 定属于最小生成树 将灰色和白色顶点区别 开来的横切边为红色 e f 图 4.3.4 切分定理
将要添加到最 小生成树中的 权重最小的横 切边 树中的边 (黑色加粗) 横切边 (红色) 失效的边 (灰色) 图 4.3.9 最小生成树的 Prim 算法 3-6 0.52 6-0 0.58 6-4 0.93 * 0-7 0.16 * 0-2 0.26 * 0-4 0.38 * 6-0 0.58 * 1-7 0.19 0-2 0.26 * 5-7 0.28 * 2-7 0.34 * 4-7 0.37 0-4 0.38 6-0 0.58 0-2 0.26 5-7 0.28 * 1-3 0.29 * 1-5 0.32 2-7 0.34 * 1-2 0.36 4-7 0.37 0-4 0.38 6-0 0.58 * 2-3 0.17 5-7 0.28 1-3 0.29 1-5 0.32 2-7 0.34 1-2 0.36 4-7 0.37 0-4 0.38 * 6-2 0.40 6-0 0.58 5-7 0.28 1-3 0.29 1-5 0.32 2-7 0.34 1-2 0.36 4-7 0.37 0-4 0.38 6-2 0.40 * 3-6 0.52 6-0 0.58 1-3 0.29 1-5 0.32 2-7 0.34 * 4-5 0.35 1-2 0.36 4-7 0.37 0-4 0.38 6-2 0.40 3-6 0.52 6-0 0.58 1-2 0.36 4-7 0.37 0-4 0.38 6-2 0.40 3-6 0.52 6-0 0.58 * 6-4 0.93 失效的边 (灰色) 所有横切边 (按照权重排序) * 表示新 加入的边 图 4.3.10 Prim 算法的轨迹
红色:优先队 列(pq)中的边 红色加粗:优先 队列(pq)中的最 小边,即将被加 入最小生成树 黑色:最小 生成树中的边 灰色:非最小 生成树中的边 0 1 2 0-2 0.26 3 4 0-4 0.38 5 6 6-0 0.58 7 0-7 0.16 0 1 1-7 0.19 2 0-2 0.26 3 4 4-7 0.37 5 5-7 0.28 6 6-0 0.58 7 0-7 0.16 0 1 1-7 0.19 2 0-2 0.26 3 1-3 0.29 4 4-7 0.37 5 5-7 0.28 6 6-0 0.58 7 0-7 0.16 0 1 1-7 0.19 2 0-2 0.26 3 2-3 0.17 4 4-7 0.37 5 5-7 0.28 6 6-2 0.40 7 0-7 0.16 0 1 1-7 0.19 2 0-2 0.26 3 2-3 0.17 4 4-7 0.37 5 5-7 0.28 6 6-2 0.40 7 0-7 0.16 0 1 1-7 0.19 2 0-2 0.26 3 2-3 0.17 4 4-5 0.35 5 5-7 0.28 6 6-2 0.40 7 0-7 0.16 0 1 1-7 0.19 2 0-2 0.26 3 2-3 0.17 4 4-5 0.35 5 5-7 0.28 6 6-2 0.40 7 0-7 0.16 0 1 1-7 0.19 2 0-2 0.26 3 2-3 0.17 4 4-5 0.35 5 5-7 0.28 6 6-2 0.40 7 0-7 0.16 edgeTo[] distTo[] 4.3.12  Prim 算法的轨迹图
0-7 0.16 2-3 0.17 1-7 0.19 0-2 0.26 5-7 0.28 1-3 0.29 1-5 0.32 2-7 0.34 4-5 0.35 1-2 0.36 4-7 0.37 0-4 0.38 6-2 0.40 3-6 0.52 6-0 0.58 6-4 0.93 无用的 边(灰色) 灰色的顶点是由和所 有红色边的顶点相邻 的顶点所构成的一个切分 下一条将要被加入最 小生成树中的边为红色 最小生成树 的边(黑色) 按权重排 序的所有边 图 4.3.14 Kruskal 算法的轨迹 0 6->0 1 null 2 6->2 3 1->3 4 6->4 5 7->5 6 3->6 7 2->7 0 6->0 1 5->1 2 null 3 7->3 4 5->4 5 7->5 6 3->6 7 2->7 0 null 1 5->1 2 0->2 3 7->3 4 0->4 5 4->5 6 3->6 7 2->7 0 6->0 1 5->1 2 6->2 3 null 4 6->4 5 7->5 6 3->6 7 2->7 0 6->0 1 5->1 2 6->2 3 7->3 4 null 5 4->5 6 3->6 7 4->70 6->1 1 5->1 2 6->2 3 1->3 4 5->4 5 null 6 3->6 7 5->7 0 6->0 1 5->1 2 6->2 3 7->3 4 6->4 5 7->5 6 null 7 2->70 6->0 1 5->1 2 6->2 3 7->3 4 5->4 5 7->5 6 3->6 7 null 父链接数组 起点 0 1 2 3 4 5 6 7 图 4.4.2 最短路径树
The above is a preview of the first 20 pages. Register to read the complete e-book.