Beruflich Dokumente
Kultur Dokumente
www3.cs.stonybrook.edu/~skiena/algorist/book/errata
Errata List for "The Algorithm Design Manual (2nd Edition)" by Steven Skiena
Last addition: September 28, 2015
Non-trivial errata are denoted with a (*). I include a separate section
at the end for commentaries -- additional suggestions / clarifications
suggested by readers which are not really errata.
============================================================================
Fresh Errata (now with Section descriptions for e-Book readers):
Page 6, paragraph 3, line 9 (Section 1.1) "...before returning at the rightmost
point." should be
"...before returning at the leftmost point."
(*) Page 18, line 5 (Section 1.3) -- The "..." is misleading. Replace
with "in the Harmonic numbers, $H(n) = \sum_{i=1}^n 1/i \approx \ln n$.
Page 24, Figure 24 (Section 1.6) Adding commas between the digits would make
it clearer
Page 26, line 5 (Section 1.6) -- Replacing {2,3,4} by {2,4,5} might offer
a more direct connection to the reasoning underlying the caption of
figure 1.10. (which is updated in figure 1.11)
(*) Page 36, fifth and sixth expressions (Section 2.2) can be clarified
3n^2 - 100n + 6 is not \Omega(n^3) because because for any [positive] c I choose
3n^2 - 100n + 6 < cn^3 for any n > 3/c+3;
3n^2 - 100n + 6 = \Omega(n) because I choose c = 1 and n < 3n^2 - 100n + 6 when n >
34;
Page 44, line 3 (Section 2.5.3) for p="Skiena." the period should be moved outside
the quotes.
Page 46, line -17 (Section 2.6): "this definition is the same" could be "this
equivalence is the same"
(*) Page 53, all mentions of 1,818 (Section 2.8): If, as I claim earlier that m>=2
in defining the pyramidal numbers, then there are in fact only 1,816 such numbers
under a billion. I included in my count the values for m=0 and m=1, both of which
are zero by the defining formula n = (m^3 - m)/6.
(*) Page 55, line -10 (Section 2.9.1) "a d-dimensional hypercube of length n^(1/d)
on each side has volume d." should be
"a d-dimensional hypercube of length n^(1/d) on each side has volume n."
Page 62, problem 2-36 (Section 2.10) - the output statement is improperly indented.
Page 67, line -18 (Section 3.1) The $\lg n$s in the formula should be written
as $\lceil \lg n \rceil$.
(*) Page 67, line -18 (Section 3.1) This analysis can be looked at in a different
way, which yields a simpler and more precise (though asymptotically identical)
answer. If we sum the number of copy operations as they are made, we get:
Sum from (i=1) to (log n) of n/(2^i)
instead of
Sum from (i=1) to (log n)-1 of [i*n/(2^(i-1))]
which is counting the number of elements which get copied i times, times i.
When n=2^j implied in the analysis, both summations are asymptotically the
same, approaching 2n.
http://www3.cs.stonybrook.edu/~skiena/algorist/book/errata
1/11
10/18/2015
www3.cs.stonybrook.edu/~skiena/algorist/book/errata
2/11
10/18/2015
www3.cs.stonybrook.edu/~skiena/algorist/book/errata
Page 164, line 8 (Section 5.6) - there is a right parenthesis missing at the end of
this line.
Page 170, in the second bulleted paragraph (Section 5.8), the spelling
"descendents," which appears twice, should be "descendants."
Page 170-171 (Section 5.8) - there is an inconsistency between how the exit time is
incremented between the psuedocode and the real code. I don't think it matters for
the correctness of algorithms using it, since the time just has to inrease with each
operation, but I think I like the code better.
(*) Page 177, line 3 (Section 5.9) - comment should be "is the parent of the vertex
the root of the DFS tree?".
(*) Page 180, second and third bullet points (Section 5.10) - the word "completed"
in both paragraphs should be "processed".
Page 183, line 3 (Section 5.10) - "edges that point vertices" should be "edges that
point to vertices".
(*) Page 188, line 4 of problem 5-20 (Section 5.11) - "is a subset of U" should be
"is a subset U".
Page 195, line -5 (Section 6.1) - "out of new tree vertex" should be "out of each
new tree vertex".
Page 197, last line, last word (Section 6.1.2) - "psuedocode" -> "pseudocode"
Page 199, line -3 (Section 6.1.3) - "The height ... stay the same" should be "The
heights ... stay the same"
Page 200, line 1 of unions_sets (Section 6.1.3) - the return type should not be int,
because the function returns nothing.
Page 201, line 3, 6 (first occurence) and 7 (Section 6.1.3) - "height-2" and
"height-3" should be "height 2" and "height 3" respectively.
Page 202, line 14 (Section 6.1.4) - "the highest degree node ... is small" should be
"the highest degree of a node ... is small".
Page 204, line 8 (Section 6.2) - "the right arm to visits" should be "the right arm
visits".
(*) Page 216, Figure 6.13 (Section 6.5.2): The graph showing the residual flow
R(G) has a directed edge from the center node to the top center node (with
weight 3), which should be undirected.
Page 231, line -7 (Section 7.1): "$S_k = S_k - a_k$ " ==> $S_k = S_k - \{a_k\}$
Page 231, section 7.1, second paragraph: "each one possible configuration" ==> "each
possible configuration"
(*) Page 232, backtrack code (Section 7.1) - the call to unmake_move() should be
before the if (finished) check, otherwise the finished solution will be unmade.
Page 232, line -6 (Section 7.1) : "elements of vector a from a complete solution" ->
"elements of vector a form a complete solution".
(*) Page 235: construct_candidates (Section 7.1.2) : The line:
for (i=0; i<k; i++) in_perm[ a[i] ] = TRUE;
should be
for (i=1; i<k; i++) in_perm[ a[i] ] = TRUE;
(*) Page 237, line 8 of construct_candidates (Section 7.1.3) should be "for (i=0;
http://www3.cs.stonybrook.edu/~skiena/algorist/book/errata
3/11
10/18/2015
www3.cs.stonybrook.edu/~skiena/algorist/book/errata
4/11
10/18/2015
www3.cs.stonybrook.edu/~skiena/algorist/book/errata
5/11
10/18/2015
www3.cs.stonybrook.edu/~skiena/algorist/book/errata
6/11
10/18/2015
www3.cs.stonybrook.edu/~skiena/algorist/book/errata
7/11
10/18/2015
www3.cs.stonybrook.edu/~skiena/algorist/book/errata
the "entry[u] = time" one (as it is the case in the corresponding C code)
(*) Page 171, line -2 -- The dfs code has a bug, where each tree edge is
processed twice in undirected graphs. The test needs to be strengthed
to be:
else if (((!processed[y]) && (parent[v]!=y)) || (g->directed))
(*) Page 173, line 2 -- Delete the word "not", ie. "The issue is also easy
if y has *not* been completely processed" should be "The issue is also easy
if y has been completely processed".
(*) Page 173, process_edge procedure -- the correct test should be
if (discovered[y] && (parent[x] != y)) { /* found back edge */
Page 174, second to last line -- "vertices 2 and 6" should read "vertices 5 and 6"
(*) Page 175, line 13 -- it is clearer to say:
"denote the earliest reachable ancestor of vertex v, meaning the
oldest ancestor of v that we can reach from a descendant of $v$.
by using a back edge."
(*) Page 177, process-vertex-late code -- There is a problem with published
code when the root is of degree one, as in node 6 of Figure 5.12, because
no root testing is applied in the bridge cutnode case. A fix is:
root = (parent[parent[v]] < 1); /* test if parent[v] is root */
if (!root) {
if (reachable_ancestor[v] == parent[v]) {
printf("parent articulation vertex: %d \n",parent[v]);
}
if (reachable_ancestor[v] == v) {
printf("bridge articulation vertex: %d \n",parent[v]);
if (tree_out_degree[v] > 0) /* test if v is not a leaf */
printf("bridge articulation vertex: %d \n",v);
}
}
Page 177, last line -- "minor" should be "appropriate" and
"the reachable_ancestor function" should be "process_late_vertex".
Page 178, Figure 5.14 -- the upgoing cross edge on right cannot appear in
a DFS, but can in a BFS.
(*) Pg 179, line 4 of the DFS-Graph(G) algorithm:
The line "for each vertex $u \in V[G]$ do" should be indented left (to
align with the first for-loop line).
Page 182, line 6 -- "peal" should be "peel".
(*) Page 184, process-vertex-late code -- There is a problem with published
code when the component has to be popped at the root node, such as when
the root is of degree one. A fix is:
process_vertex_late(int v) {
/*printf("exit vertex %d at time %d\n",v, exit_time[v]);*/
if (low[v] == v) { /* edge (parent[v],v) cuts off scc */
/*printf("strong commonent started backtracking from %d\n",v);*/
pop_component(v);
http://www3.cs.stonybrook.edu/~skiena/algorist/book/errata
8/11
10/18/2015
www3.cs.stonybrook.edu/~skiena/algorist/book/errata
}
if (parent[v] > 0) { /* only if v is not the root */
if (entry_time[low[v]] < entry_time[low[parent[v]]]) {
low[parent[v]] = low[v];
}
}
}
9/11
10/18/2015
www3.cs.stonybrook.edu/~skiena/algorist/book/errata
10/11
10/18/2015
www3.cs.stonybrook.edu/~skiena/algorist/book/errata
container
variables? Currently stacks and queues are lower-case, but dictionaries are uppercase.
And to always put the container parameter first and the item/key parameter second?
Currently stacks and queues are second in Push and Enqueue, while dictionaries are
first
in all their operations.
Page 76, last paragraph: There's really no need for an extra sweep over the list to
maintain
the pointer to the last item, as the deletion already requires that we get a pointer
to the
second to last item in order to un-link the last item.
Pg 111, the two C function definitions:
It might be nice to specify the function definitions that these
functions return 'int'.
Pg 199, figure 6.5 right:
Root nodes in this figure are indicated via "0", but in the algorithm
on the next page, the representation parent[x] = x is used. Perhaps
this figure could be changes to match up with that representation.
- p 397, line 10: an equally good reason to avoid inv(A) is that it
is less numerically stable. See Sec 14.1 of
http://www.maths.manchester.ac.uk/~higham/asna
@Book{Higham:2002:ASN,
author =
"Nicholas J. Higham",
title =
"Accuracy and Stability of Numerical Algorithms",
publisher =
"Society for Industrial and Applied Mathematics",
address =
"Philadelphia, PA, USA",
edition =
"Second",
year =
"2002",
pages =
"xxx+680",
ISBN =
"0-89871-521-0"
}
- p 397, line 15: you can delete "apparently". It's indubitably true.
- p 402, third para from bottom. You should really refer to the
level 3 BLAS here, not LAPACK. I'm not sure that Alg 601 is used
nowadays. More recent is
http://www-users.cs.umn.edu/~saad/software/SPARSKIT/sparskit.html
- p 433: I'd suggest citing the classic book by Van Loan
@book{vanl92a,
author = "Van Loan, Charles F.",
title = "Computational Frameworks for the Fast {Fourier} Transform",
publisher = pub-SIAM,
address = pub-SIAM:adr,
year = 1992,
pages = "xiii+273",
isbn = "0-89871-285-8",
}
@String{pub-SIAM
= "Society for Industrial and Applied
Mathematics"}
@String{pub-SIAM:adr
= "Philadelphia, PA, USA"}
http://www3.cs.stonybrook.edu/~skiena/algorist/book/errata
11/11