Corrections

This commit is contained in:
Antti H S Laaksonen 2017-02-05 13:40:54 +02:00
parent 0d71484380
commit 215ea748b6
1 changed files with 66 additions and 65 deletions

View File

@ -3,14 +3,14 @@
\index{tree} \index{tree}
A \key{tree} is a connected, acyclic graph A \key{tree} is a connected, acyclic graph
that contains $n$ nodes and $n-1$ edges. that consists of $n$ nodes and $n-1$ edges.
Removing any edge from a tree divides it Removing any edge from a tree divides it
into two components, into two components,
and adding any edge to a tree creates a cycle. and adding any edge to a tree creates a cycle.
Moreover, there is always a unique path between any Moreover, there is always a unique path between any
two nodes in a tree. two nodes in a tree.
For example, the following tree contains 7 nodes and 6 edges: For example, the following tree consists of 7 nodes and 6 edges:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$}; \node[draw, circle] (1) at (0,3) {$1$};
@ -31,7 +31,7 @@ For example, the following tree contains 7 nodes and 6 edges:
\index{leaf} \index{leaf}
The \key{leaves} of a tree are nodes The \key{leaves} of a tree are the nodes
with degree 1, i.e., with only one neighbor. with degree 1, i.e., with only one neighbor.
For example, the leaves in the above tree For example, the leaves in the above tree
are nodes 3, 5, 6 and 7. are nodes 3, 5, 6 and 7.
@ -40,7 +40,8 @@ are nodes 3, 5, 6 and 7.
\index{rooted tree} \index{rooted tree}
In a \key{rooted} tree, one of the nodes In a \key{rooted} tree, one of the nodes
is chosen to be a \key{root}, and all other nodes are is appointed the \key{root} of the tree,
and all other nodes are
placed underneath the root. placed underneath the root.
For example, in the following tree, For example, in the following tree,
node 1 is the root of the tree. node 1 is the root of the tree.
@ -66,11 +67,11 @@ node 1 is the root of the tree.
\index{child} \index{child}
\index{parent} \index{parent}
In a rooted tree, the \key{childern} of a node In a rooted tree, the \key{children} of a node
are its lower neighbors, and the \key{parent} of a node are its lower neighbors, and the \key{parent} of a node
is its upper neighbor. is its upper neighbor.
Each node has exactly one parent, Each node has exactly one parent,
except that the root doesn't have a parent. except for the root that does not have a parent.
For example, in the above tree, For example, in the above tree,
the childern of node 4 are nodes 3 and 7, the childern of node 4 are nodes 3 and 7,
and the parent is node 1. and the parent is node 1.
@ -80,22 +81,22 @@ and the parent is node 1.
The structure of a rooted tree is \emph{recursive}: The structure of a rooted tree is \emph{recursive}:
each node in the tree is the root of a \key{subtree} each node in the tree is the root of a \key{subtree}
that contains the node itself and all other nodes that contains the node itself and all other nodes
that can be reached by travelling downwards in the tree. that can be reached by traversing down the tree.
For example, in the above tree, the subtree of node 4 For example, in the above tree, the subtree of node 4
contains nodes 4, 3 and 7. consists of nodes 4, 3 and 7.
\section{Tree search} \section{Tree traversal}
Depth-first search and breadth-first search Depth-first search and breadth-first search
can be used for going through the nodes in a tree. can be used for traversing the nodes in a tree.
However, the search is easier to implement than However, the traversal is easier to implement than
for a general graph, because in a general graph because
there are no cycles in the tree, and it is not there are no cycles in the tree, and it is not
possible that the search would visit a node several times. possible to reach a node from multiple directions.
Often, we start a depth-first search from a chosen The typical way to traverse a tree is to start
root node. a depth-first search at an arbitrary node.
The following recursive function implements it: The following recursive function can be used:
\begin{lstlisting} \begin{lstlisting}
void dfs(int s, int e) { void dfs(int s, int e) {
@ -108,9 +109,9 @@ void dfs(int s, int e) {
The function parameters are the current node $s$ The function parameters are the current node $s$
and the previous node $e$. and the previous node $e$.
The idea of the parameter $e$ is to ensure The purpose of the parameter $e$ is to make sure
that the search only proceeds downwards in the tree that the search only moves to nodes
towards nodes that have not been visited yet. that have not been visited yet.
The following function call starts the search The following function call starts the search
at node $x$: at node $x$:
@ -119,21 +120,22 @@ at node $x$:
dfs(x, 0); dfs(x, 0);
\end{lstlisting} \end{lstlisting}
In the first call $e=0$ because there is no In the first call $e=0$, because there is no
previous node, and it is allowed previous node, and it is allowed
to proceed to any direction in the tree. to proceed to any direction in the tree.
\subsubsection{Dynamic programming} \subsubsection{Dynamic programming}
We can also use dynamic programming to calculate Dynamic programming can be used to calculate
some information from the tree during the search. some information during a tree traversal.
Using dynamic programming, we can, for example, Using dynamic programming, we can, for example,
calculate in $O(n)$ time for each node the calculate in $O(n)$ time for each node
number of nodes in its subtree, in a rooted tree the
or the length of the longest path downwards number of nodes in its subtree
that begins at the node. or the length of the longest path from the node
to a leaf.
As an example, let's calculate for each node $s$ As an example, let us calculate for each node $s$
a value $\texttt{c}[s]$: the number of nodes in its subtree. a value $\texttt{c}[s]$: the number of nodes in its subtree.
The subtree contains the node itself and The subtree contains the node itself and
all nodes in the subtrees of its children. all nodes in the subtrees of its children.
@ -141,11 +143,11 @@ Thus, we can calculate the number of nodes
recursively using the following code: recursively using the following code:
\begin{lstlisting} \begin{lstlisting}
void haku(int s, int e) { void dfs(int s, int e) {
c[s] = 1; c[s] = 1;
for (auto u : v[s]) { for (auto u : v[s]) {
if (u == e) continue; if (u == e) continue;
haku(u, s); dfs(u, s);
c[s] += c[u]; c[s] += c[u];
} }
} }
@ -189,14 +191,15 @@ to calculate the diameter.
\subsubsection{Algorithm 1} \subsubsection{Algorithm 1}
First, one of the nodes is chosen to be the root. First, we root the tree arbitrarily.
After this, the algorithm calculates for each node After this, we use dynamic programming
to calculate for each node $x$
the length of the longest path that begins at some leaf, the length of the longest path that begins at some leaf,
ascends to the node and then descends to another leaf. ascends to $x$ and then descends to another leaf.
The length of the The length of the
longest such path equals the diameter of the tree. longest such path equals the diameter of the tree.
In the example case, the longest path begins at node 7, In the example graph, the longest path begins at node 7,
ascends to node 1, and then descends to node 6: ascends to node 1, and then descends to node 6:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -221,32 +224,30 @@ ascends to node 1, and then descends to node 6:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
The algorithm first calculates using dynamic programming The algorithm first calculates for each node $x$
for each node the length of the longest path the length of the longest path from $x$ to a leaf.
that goes downwards from the node.
For example, in the above tree, For example, in the above tree,
the longest path from node 1 downwards has length 2 the longest path from node 1 to a leaf has length 2
(the path can be $1 \rightarrow 4 \rightarrow 3$, (the path can be $1 \rightarrow 4 \rightarrow 3$,
$1 \rightarrow 4 \rightarrow 7$ or $1 \rightarrow 2 \rightarrow 6$). $1 \rightarrow 4 \rightarrow 7$ or $1 \rightarrow 2 \rightarrow 6$).
After this, the algorithm calculates for each node After this, the algorithm calculates for each node
the length of the longest path where the node $x$ the length of the longest path where $x$
is the turning point of the path. is the turning point of the path.
The longest such path can be found by selecting The longest such path can be found by choosing
two children with longest paths downwards. two children with longest paths two leaves.
For example, in the above graph, For example, in the above graph,
nodes 2 and 4 are chosen for node 1. nodes 2 and 4 yield the longest path for node 1.
\subsubsection{Algorithm 2} \subsubsection{Algorithm 2}
Another efficient way to calculate the diameter Another efficient way to calculate the diameter
of a tree is based on two depth-first searches. of a tree is based on two depth-first searches.
First, we choose an arbitrary node $a$ in the tree First, we choose an arbitrary node $a$ in the tree
and find a node $b$ with maximum distance to $a$. and find the farthest node $b$ from $a$.
Then, we find a node $c$ with maximum distance to $b$. Then, we find the farthest node $c$ from $b$.
The diameter is the distance between nodes $b$ and $c$. The diameter of the tree is the distance between $b$ and $c$.
In the example case, $a$, $b$ and $c$ could be: In the example graph, $a$, $b$ and $c$ could be:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$}; \node[draw, circle] (1) at (0,3) {$1$};
@ -312,7 +313,7 @@ to the diameter.
The farthest node from $a$ The farthest node from $a$
is node $b$, node $c$ or some other node is node $b$, node $c$ or some other node
that is at least as far from node $x$. that is at least as far from node $x$.
Thus, this node can always be chosen for Thus, this node is always a valid choice for
a starting node of a path that corresponds to the diameter. a starting node of a path that corresponds to the diameter.
\section{Distances between nodes} \section{Distances between nodes}
@ -321,10 +322,10 @@ A more difficult problem is to calculate
for each node in the tree and for each direction, for each node in the tree and for each direction,
the maximum distance to a node in that direction. the maximum distance to a node in that direction.
It turns out that this can be calculated in It turns out that this can be calculated in
$O(n)$ time as well using dynamic programming. $O(n)$ time using dynamic programming.
\begin{samepage} \begin{samepage}
In the example case, the distances are as follows: In the example graph, the distances are as follows:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$}; \node[draw, circle] (1) at (0,3) {$1$};
@ -355,15 +356,15 @@ In the example case, the distances are as follows:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
\end{samepage} \end{samepage}
For example, the furthest node from node 4 For example, the farthest node from node 4
upwards is node 6, and the distance to this in the direction of node 1 is node 6, and the distance to this
node is 3 using the path node is 3 using the path
$4 \rightarrow 1 \rightarrow 2 \rightarrow 6$. $4 \rightarrow 1 \rightarrow 2 \rightarrow 6$.
\begin{samepage} \begin{samepage}
Also in this problem, a good starting point Also in this problem, a good starting point
is to root the tree. is to root the tree.
After this, all distances downwards can After this, all distances to leaves can
be calculated using dynamic programming: be calculated using dynamic programming:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -393,8 +394,9 @@ be calculated using dynamic programming:
\end{center} \end{center}
\end{samepage} \end{samepage}
The remaining task is to calculate the distances upwards. The remaining task is to calculate
This can be done by going through the nodes once again the distances through parents.
This can be done by traversing the tree once again
and keeping track of the largest distance from the parent and keeping track of the largest distance from the parent
of the current node to some other node in another direction. of the current node to some other node in another direction.
@ -466,11 +468,10 @@ and all directions:
\begin{samepage} \begin{samepage}
A \key{binary tree} is a rooted tree A \key{binary tree} is a rooted tree
where each node has a left subtree where each node has a left and right subtree.
and a right subtree.
It is possible that a subtree of a node is empty. It is possible that a subtree of a node is empty.
Thus, every node in a binary tree has Thus, every node in a binary tree has
0, 1 or 2 children. zero, one or two children.
For example, the following tree is a binary tree: For example, the following tree is a binary tree:
\begin{center} \begin{center}
@ -498,7 +499,7 @@ For example, the following tree is a binary tree:
\index{post-order} \index{post-order}
The nodes in a binary tree have three natural The nodes in a binary tree have three natural
orders that correspond to different ways to orderings that correspond to different ways to
recursively traverse the nodes: recursively traverse the nodes:
\begin{itemize} \begin{itemize}
@ -516,18 +517,18 @@ $[1,2,4,5,6,3,7]$,
in in-order $[4,2,6,5,1,3,7]$ in in-order $[4,2,6,5,1,3,7]$
and in post-order $[4,6,5,2,7,3,1]$. and in post-order $[4,6,5,2,7,3,1]$.
If we know the pre-order and the in-order If we know the pre-order and in-order
of a tree, we can find out the exact structure of the tree. of a tree, we can reconstruct the exact structure of the tree.
For example, the tree above is the only possible tree For example, the tree above is the only possible tree
with pre-order $[1,2,4,5,6,3,7]$ and with pre-order $[1,2,4,5,6,3,7]$ and
in-order $[4,2,6,5,1,3,7]$. in-order $[4,2,6,5,1,3,7]$.
Correspondingly, the post-order and the in-order In a similar way, the post-order and in-order
also determine the structure of a tree. also determine the structure of a tree.
However, the situation is different if we only know However, the situation is different if we only know
the pre-order and the post-order of a tree. the pre-order and post-order of a tree.
In this case, there may be more than one tree In this case, there may be more than one tree
that match the orders. that match the orderings.
For example, in both of the trees For example, in both of the trees
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -540,6 +541,6 @@ For example, in both of the trees
\path[draw,thick,-] (1b) -- (2b); \path[draw,thick,-] (1b) -- (2b);
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
the pre-order is $[1,2]$ and the post-order is $[2,1]$ the pre-order is $[1,2]$ and the post-order is $[2,1]$,
but the trees have different structures. but the structures of the trees are different.