没有合适的资源?快使用搜索试试~ 我知道了~
首页C++算法入门:实践与分析(第1-4部分)
C++算法入门:实践与分析(第1-4部分)
5星 · 超过95%的资源 需积分: 50 12 下载量 8 浏览量
更新于2024-07-24
收藏 11.45MB PDF 举报
《C++算法入门:基础篇1-4》是一本实用的教材,由知名作者编著,适合于学习算法的学生,特别是工程类专业的学生。不同于经典的《算法导论》,这本书更注重算法在C++语言中的实现,而非纯粹的理论讲解。作者利用普林斯顿大学在线课程的方式授课,强调算法的实际应用。 在本书的Part One: Fundamentals部分,首先介绍了算法的基本概念(Chapter One),包括什么是算法、一个示例问题——连通性分析,以及Union-Find算法。作者通过实际问题引导读者理解算法的工作原理,并从不同角度审视算法设计(1.4 Perspective)。 Chapter Two探讨了算法分析原则。这部分内容涵盖了实施和经验性分析(2.1),如如何衡量算法效率,以及对算法性能增长的理解。作者引入了函数增长的概念和Big-O符号(2.4),这是评估算法复杂度的标准工具。通过解决具体的递归问题,如数据的一半处理(Formula 2.2 和 2.5),读者能掌握如何处理线性搜索和递归分割的情况。 在每个章节末尾,都提供了详细的解决方案和练习题注解(Notes on Exercises),帮助读者巩固所学知识并提升实践能力。作者还提醒读者,对于图论相关的Part Five,如果有人手头有资料,可以联系分享。对于积分较低的读者,也表达了愿意提供帮助的态度,表明这是一本互动性和实用性都很强的学习资源。 总体来说,《C++算法入门》是学习C++编程与算法结合的实用教程,尤其适合那些希望将理论知识转化为代码实现的工程背景学生。通过阅读这本书,读者不仅能深入理解算法的核心思想,还能掌握在实际项目中如何运用这些算法来优化代码性能。
资源详情
资源推荐
Figure 1.6. Example of quick union (not-too-quick find)
This sequence depicts the contents of the id array after each of the pairs at left
are processed by the quick-find algorithm (Program 1.1). Shaded entries are those
that change for the union operation (just one per operation). When we process the
pair p q, we follow pointers from p to get an entry i with id[i] == i; then,
we follow pointers from q to get an entry j with id[j] == j; then, if i and j
differ, we set id[i] = id[j]. For the find operation for the pair 5-8 (final
line), i takes on the values 5 6 9 0 1, and j takes on the values 8 0 1.
Part One: Fundamentals 11
Part One: Fundamentals 11
The connected components depicted in Figure 1.5 are called trees; they are
fundamental combinatorial structures that we shall encounter on numerous
occasions throughout the book. We shall consider the properties of trees in detail
in Chapter 5. For the union and find operations, the trees in Figure 1.5 are useful
because they are quick to build and have the property that two objects are
connected in the tree if and only if the objects are connected in the input. By
moving up the tree, we can easily find the root of the tree containing each object,
so we have a way to find whether or not they are connected. Each tree has
precisely one object that points to itself, which is called the root of the tree. The
self-pointer is not shown in the diagrams. When we start at any object in the tree,
move to the object to which it points, then move to the object to which that object
points, and so forth, we eventually end up at the root, always. We can prove this
property to be true by induction: It is true after the array is initialized to have
every object point to itself, and if it is true before a given union operation, it is
certainly true afterward.
The diagrams in Figure 1.4 for the quick-find algorithm have the same properties
as those described in the previous paragraph. The difference between the two is
that we reach the root from all the nodes in the quick-find trees after following
just one link, whereas we might need to follow several links to get to the root in a
quick-union tree.
Program 1.2. Quick-union solution to connectivity problem
If we replace the body of the while loop in Program 1.1 by this code,
we have a program that meets the same specifications as Program 1.1,
but does less computation for the union operation at the expense of
more computation for the find operation. The for loops and
subsequent if statement in this code specify the necessary and
sufficient conditions on the id array for p and q to be connected. The
assignment statement id[i] = j implements the union operation.
for (i = p; i != id[i]; i = id[i]) ;
for (j = q; j != id[j]; j = id[j]) ;
12 Part One: Fundamentals
12 Part One: Fundamentals
if (i == j) continue;
id[i] = j;
cout << " " << p << " " << q << endl;
Program 1.2 is an implementation of the union and find operations that comprise
the quick-union algorithm to solve the connectivity problem. The quick-union
algorithm would seem to be faster than the quick-find algorithm, because it does
not have to go through the entire array for each input pair; but how much faster is
it? This question is more difficult to answer here than it was for quick find,
because the running time is much more dependent on the nature of the input. By
running empirical studies or doing mathematical analysis (see Chapter 2), we can
convince ourselves that Program 1.2 is far more efficient than Program 1.1, and
that it is feasible to consider using Program 1.2 for huge practical problems. We
shall discuss one such empirical study at the end of this section. For the moment,
we can regard quick union as an improvement because it removes quick find's
main liability (that the program requires at least NM instructions to process M
union operations among N objects).
This difference between quick union and quick find certainly represents an
improvement, but quick union still has the liability that we cannot guarantee it to
be substantially faster than quick find in every case, because the input data could
conspire to make the find operation slow.
Property 1.2. For M > N, the quick-union algorithm could take more than MN/2
instructions to solve a connectivity problem with M pairs of N objects
Suppose that the input pairs come in the order 1-2, then 2-3, then
3-4, and so forth. After N – 1 such pairs, we have N objects all in the
same set, and the tree that is formed by the quick-union algorithm is a
straight line, with N pointing to N – 1, which points to N – 2, which
points to N – 3, and so forth. To execute the find operation for object
N, the program has to follow N – 1 pointers. Thus, the average number
of pointers followed for the first N pairs is
(0 + 1 + ... + (N – 1))/N = (N – 1)/2.
Now suppose that the remainder of the pairs all connect N to some
other object. The find operation for each of these pairs involves at least
(N – 1) pointers. The grand total for the M find operations for this
sequence of input pairs is certainly greater than MN/2.
Fortunately, there is an easy modification to the algorithm that allows us to
guarantee that bad cases such as this one do not occur. Rather than arbitrarily
connecting the second tree to the first for union, we keep track of the number of
nodes in each tree and always connect the smaller tree to the larger. This change
requires slightly more code and another array to hold the node counts, as shown
in Program 1.3, but it leads to substantial improvements in efficiency. We refer to
this algorithm as the weighted quick-union algorithm.
Figure 1.7 shows the forest of trees constructed by the weighted union–find
algorithm for the example input in Figure 1.1. Even for this small example, the
Part One: Fundamentals 13
Part One: Fundamentals 13
paths in the trees are substantially shorter than for the unweighted version in
Figure 1.5. Figure 1.8 illustrates what happens in the worst case, when the sizes
of the sets to be merged in the union operation are always equal (and a power of
2). These tree structures look complex, but they have the simple property that the
maximum number of pointers that we need to follow to get to the root in a tree of
2
n
nodes is n. Furthermore, when we merge two trees of 2
n
nodes, we get a tree of
2
n+1
nodes, and we increase the maximum distance to the root to n+1. This
observation generalizes to provide a proof that the weighted algorithm is
substantially more efficient than the unweighted algorithm.
Figure 1.7. Tree representation of weighted quick union
This sequence depicts the result of changing the quick-union algorithm to link the
root of the smaller of the two trees to the root of the larger of the two trees. The
distance from each node to the root of its tree is small, so the find operation is
efficient.
Figure 1.8. Weighted quick union (worst case)
The worst scenario for the weighted quick-union algorithm is that each union
operation links trees of equal size. If the number of objects is less than 2
n
, the
distance from any node to the root of its tree is less than n.
14 Part One: Fundamentals
14 Part One: Fundamentals
Program 1.3. Weighted version of quick union
This program is a modification to the quick-union algorithm (see
Program 1.2) that keeps an additional array sz for the purpose of
maintaining, for each object with id[i] == i, the number of nodes
in the associated tree, so that the union operation can link the smaller of
the two specified trees to the larger, thus preventing the growth of long
paths in the trees.
#include <iostream.h>
static const int N = 10000;
int main()
{ int i, j, p, q, id[N], sz[N];
for (i = 0; i < N; i++)
{ id[i] = i; sz[i] = 1; }
while (cin >> p >> q)
{
for (i = p; i != id[i]; i = id[i]) ;
for (j = q; j != id[j]; j = id[j]) ;
if (i == j) continue;
if (sz[i] < sz[j])
{ id[i] = j; sz[j] += sz[i]; }
else { id[j] = i; sz[i] += sz[j]; }
Part One: Fundamentals 15
Part One: Fundamentals 15
剩余652页未读,继续阅读
lym1108csu
- 粉丝: 10
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 计算机人脸表情动画技术发展综述
- 关系数据库的关键字搜索技术综述:模型、架构与未来趋势
- 迭代自适应逆滤波在语音情感识别中的应用
- 概念知识树在旅游领域智能分析中的应用
- 构建is-a层次与OWL本体集成:理论与算法
- 基于语义元的相似度计算方法研究:改进与有效性验证
- 网格梯度多密度聚类算法:去噪与高效聚类
- 网格服务工作流动态调度算法PGSWA研究
- 突发事件连锁反应网络模型与应急预警分析
- BA网络上的病毒营销与网站推广仿真研究
- 离散HSMM故障预测模型:有效提升系统状态预测
- 煤矿安全评价:信息融合与可拓理论的应用
- 多维度Petri网工作流模型MD_WFN:统一建模与应用研究
- 面向过程追踪的知识安全描述方法
- 基于收益的软件过程资源调度优化策略
- 多核环境下基于数据流Java的Web服务器优化实现提升性能
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功