cphb/chapter14.tex

608 lines
19 KiB
TeX
Raw Permalink Normal View History

2017-01-07 22:31:41 +01:00
\chapter{Tree algorithms}
2016-12-28 23:54:51 +01:00
2017-01-07 22:31:41 +01:00
\index{tree}
2016-12-28 23:54:51 +01:00
2017-01-07 22:31:41 +01:00
A \key{tree} is a connected, acyclic graph
2017-02-05 12:40:54 +01:00
that consists of $n$ nodes and $n-1$ edges.
2017-01-07 22:31:41 +01:00
Removing any edge from a tree divides it
into two components,
and adding any edge to a tree creates a cycle.
Moreover, there is always a unique path between any
2017-02-17 21:13:30 +01:00
two nodes of a tree.
2016-12-28 23:54:51 +01:00
2017-05-28 12:22:15 +02:00
For example, the following tree consists of 8 nodes and 7 edges:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$};
2017-05-28 12:22:15 +02:00
\node[draw, circle] (2) at (2,3) {$4$};
\node[draw, circle] (3) at (0,1) {$2$};
\node[draw, circle] (4) at (2,1) {$3$};
\node[draw, circle] (5) at (4,1) {$7$};
\node[draw, circle] (6) at (-2,3) {$5$};
\node[draw, circle] (7) at (-2,1) {$6$};
\node[draw, circle] (8) at (-4,1) {$8$};
2016-12-28 23:54:51 +01:00
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (3) -- (7);
2017-05-28 12:22:15 +02:00
\path[draw,thick,-] (7) -- (8);
2016-12-28 23:54:51 +01:00
\end{tikzpicture}
\end{center}
2017-01-07 22:31:41 +01:00
\index{leaf}
2016-12-28 23:54:51 +01:00
2017-02-05 12:40:54 +01:00
The \key{leaves} of a tree are the nodes
2017-01-07 22:31:41 +01:00
with degree 1, i.e., with only one neighbor.
2017-02-17 21:13:30 +01:00
For example, the leaves of the above tree
2017-05-28 12:22:15 +02:00
are nodes 3, 5, 7 and 8.
2016-12-28 23:54:51 +01:00
2017-01-07 22:31:41 +01:00
\index{root}
\index{rooted tree}
2016-12-28 23:54:51 +01:00
2017-01-07 22:31:41 +01:00
In a \key{rooted} tree, one of the nodes
2017-02-05 12:40:54 +01:00
is appointed the \key{root} of the tree,
and all other nodes are
2017-01-07 22:31:41 +01:00
placed underneath the root.
For example, in the following tree,
2017-05-28 12:22:15 +02:00
node 1 is the root node.
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$};
2017-05-28 12:22:15 +02:00
\node[draw, circle] (4) at (2,1) {$4$};
\node[draw, circle] (2) at (-2,1) {$2$};
\node[draw, circle] (3) at (0,1) {$3$};
\node[draw, circle] (7) at (2,-1) {$7$};
\node[draw, circle] (5) at (-3,-1) {$5$};
\node[draw, circle] (6) at (-1,-1) {$6$};
\node[draw, circle] (8) at (-1,-3) {$8$};
2016-12-28 23:54:51 +01:00
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (2) -- (5);
2017-05-28 12:22:15 +02:00
\path[draw,thick,-] (2) -- (6);
\path[draw,thick,-] (4) -- (7);
\path[draw,thick,-] (6) -- (8);
2016-12-28 23:54:51 +01:00
\end{tikzpicture}
\end{center}
2017-01-07 22:31:41 +01:00
\index{child}
\index{parent}
2017-02-05 12:40:54 +01:00
In a rooted tree, the \key{children} of a node
2017-01-07 22:31:41 +01:00
are its lower neighbors, and the \key{parent} of a node
is its upper neighbor.
Each node has exactly one parent,
2017-02-05 12:40:54 +01:00
except for the root that does not have a parent.
2017-01-07 22:31:41 +01:00
For example, in the above tree,
2017-05-28 12:22:15 +02:00
the children of node 2 are nodes 5 and 6,
and its parent is node 1.
2017-01-07 22:31:41 +01:00
\index{subtree}
The structure of a rooted tree is \emph{recursive}:
2017-05-07 20:18:56 +02:00
each node of the tree acts as the root of a \key{subtree}
2017-05-28 12:22:15 +02:00
that contains the node itself and all nodes
that are in the subtrees of its children.
For example, in the above tree, the subtree of node 2
consists of nodes 2, 5, 6 and 8:
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (2) at (-2,1) {$2$};
\node[draw, circle] (5) at (-3,-1) {$5$};
\node[draw, circle] (6) at (-1,-1) {$6$};
\node[draw, circle] (8) at (-1,-3) {$8$};
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (2) -- (6);
\path[draw,thick,-] (6) -- (8);
\end{tikzpicture}
\end{center}
2017-01-07 22:31:41 +01:00
2017-02-05 12:40:54 +01:00
\section{Tree traversal}
2017-01-07 22:31:41 +01:00
2017-05-28 12:22:15 +02:00
General graph traversal algorithms
can be used to traverse the nodes of a tree.
However, the traversal of a tree is easier to implement than
2017-02-17 21:13:30 +01:00
that of a general graph, because
there are no cycles in the tree and it is not
2017-02-05 12:40:54 +01:00
possible to reach a node from multiple directions.
2017-01-07 22:31:41 +01:00
2017-02-05 12:40:54 +01:00
The typical way to traverse a tree is to start
a depth-first search at an arbitrary node.
The following recursive function can be used:
2016-12-28 23:54:51 +01:00
\begin{lstlisting}
2021-02-08 23:10:42 +01:00
void dfs(int v, int p) {
for (auto w : g[v])
if (w != p)
dfs(w, v);
2016-12-28 23:54:51 +01:00
}
\end{lstlisting}
2021-02-08 23:10:42 +01:00
The function is given two parameters: the current node $v$
and the previous node $p$.
The purpose of the parameter $p$ is to make sure
2017-02-05 12:40:54 +01:00
that the search only moves to nodes
that have not been visited yet.
2016-12-28 23:54:51 +01:00
2017-01-07 22:31:41 +01:00
The following function call starts the search
at node $x$:
2016-12-28 23:54:51 +01:00
\begin{lstlisting}
2021-02-08 23:10:42 +01:00
dfs(x, -1);
2016-12-28 23:54:51 +01:00
\end{lstlisting}
2021-02-08 23:10:42 +01:00
In the first call $p=-1$, because there is no
2017-01-07 22:31:41 +01:00
previous node, and it is allowed
to proceed to any direction in the tree.
2016-12-28 23:54:51 +01:00
2021-02-08 23:10:42 +01:00
\subsubsection{Storing Information}
We can calculate
some information during a tree traversal and store that for later use.
We can, for example,
2017-05-07 20:18:56 +02:00
calculate in $O(n)$ time for each node of a rooted tree the
2017-02-05 12:40:54 +01:00
number of nodes in its subtree
or the length of the longest path from the node
to a leaf.
2016-12-28 23:54:51 +01:00
2021-02-08 23:10:42 +01:00
As an example, let us calculate for each node $v$
a value $\texttt{subtreesize}[v]$: the number of nodes in its subtree.
2017-01-07 22:31:41 +01:00
The subtree contains the node itself and
2017-05-28 12:22:15 +02:00
all nodes in the subtrees of its children,
so we can calculate the number of nodes
2017-01-07 22:31:41 +01:00
recursively using the following code:
2016-12-28 23:54:51 +01:00
\begin{lstlisting}
2021-02-08 23:10:42 +01:00
void dfs(int v, int p) {
subtreesize[s] = 1;
for (auto w : g[v]) {
if (w == p) continue;
dfs(w, v);
subtreesize[s] += subtreesize[u];
2016-12-28 23:54:51 +01:00
}
}
\end{lstlisting}
2017-01-07 22:31:41 +01:00
\section{Diameter}
2016-12-28 23:54:51 +01:00
2017-01-07 22:31:41 +01:00
\index{diameter}
2016-12-28 23:54:51 +01:00
2017-01-07 22:31:41 +01:00
The \key{diameter} of a tree
2017-05-28 12:22:15 +02:00
is the maximum length of a path between two nodes.
For example, consider the following tree:
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$};
\node[draw, circle] (2) at (2,3) {$4$};
\node[draw, circle] (3) at (0,1) {$2$};
\node[draw, circle] (4) at (2,1) {$3$};
\node[draw, circle] (5) at (4,1) {$7$};
\node[draw, circle] (6) at (-2,3) {$5$};
\node[draw, circle] (7) at (-2,1) {$6$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (3) -- (7);
\end{tikzpicture}
\end{center}
The diameter of this tree is 4,
which corresponds to the following path:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$};
2017-05-28 12:22:15 +02:00
\node[draw, circle] (2) at (2,3) {$4$};
\node[draw, circle] (3) at (0,1) {$2$};
\node[draw, circle] (4) at (2,1) {$3$};
\node[draw, circle] (5) at (4,1) {$7$};
\node[draw, circle] (6) at (-2,3) {$5$};
\node[draw, circle] (7) at (-2,1) {$6$};
2016-12-28 23:54:51 +01:00
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (3) -- (7);
2017-05-28 12:22:15 +02:00
\path[draw,thick,-,color=red,line width=2pt] (7) -- (3);
\path[draw,thick,-,color=red,line width=2pt] (3) -- (1);
\path[draw,thick,-,color=red,line width=2pt] (1) -- (2);
\path[draw,thick,-,color=red,line width=2pt] (2) -- (5);
2016-12-28 23:54:51 +01:00
\end{tikzpicture}
\end{center}
2017-05-28 12:22:15 +02:00
Note that there may be several maximum-length paths.
In the above path, we could replace node 6 with node 5
to obtain another path with length 4.
2017-01-07 22:31:41 +01:00
2017-05-28 12:22:15 +02:00
Next we will discuss two $O(n)$ time algorithms
2017-01-07 22:31:41 +01:00
for calculating the diameter of a tree.
2021-02-08 23:10:42 +01:00
The first algorithm is based on the previous idea of storing information,
2017-05-28 12:22:15 +02:00
and the second algorithm uses two depth-first searches.
2017-01-07 22:31:41 +01:00
\subsubsection{Algorithm 1}
2017-05-28 12:22:15 +02:00
A general way to approach many tree problems
is to first root the tree arbitrarily.
After this, we can try to solve the problem
separately for each subtree.
Our first algorithm for calculating the diameter
is based on this idea.
An important observation is that every path
in a rooted tree has a \emph{highest point}:
the highest node that belongs to the path.
Thus, we can calculate for each node the length
of the longest path whose highest point is the node.
One of those paths corresponds to the diameter of the tree.
2017-01-07 22:31:41 +01:00
2017-05-28 12:22:15 +02:00
For example, in the following tree,
node 1 is the highest point on the path
that corresponds to the diameter:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$};
2017-05-28 12:22:15 +02:00
\node[draw, circle] (2) at (2,1) {$4$};
\node[draw, circle] (3) at (-2,1) {$2$};
\node[draw, circle] (4) at (0,1) {$3$};
\node[draw, circle] (5) at (2,-1) {$7$};
\node[draw, circle] (6) at (-3,-1) {$5$};
\node[draw, circle] (7) at (-1,-1) {$6$};
2016-12-28 23:54:51 +01:00
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (3) -- (7);
\path[draw,thick,-,color=red,line width=2pt] (7) -- (3);
\path[draw,thick,-,color=red,line width=2pt] (3) -- (1);
\path[draw,thick,-,color=red,line width=2pt] (1) -- (2);
\path[draw,thick,-,color=red,line width=2pt] (2) -- (5);
\end{tikzpicture}
\end{center}
2017-05-28 12:22:15 +02:00
We calculate for each node $x$ two values:
\begin{itemize}
\item $\texttt{toLeaf}(x)$: the maximum length of a path from $x$ to any leaf
\item $\texttt{maxLength}(x)$: the maximum length of a path
whose highest point is $x$
\end{itemize}
2017-01-07 22:31:41 +01:00
For example, in the above tree,
2017-05-28 12:22:15 +02:00
$\texttt{toLeaf}(1)=2$, because there is a path
$1 \rightarrow 2 \rightarrow 6$,
and $\texttt{maxLength}(1)=4$,
because there is a path
$6 \rightarrow 2 \rightarrow 1 \rightarrow 4 \rightarrow 7$.
In this case, $\texttt{maxLength}(1)$ equals the diameter.
2021-02-08 23:10:42 +01:00
We can calculate the above
2017-05-28 12:22:15 +02:00
values for all nodes in $O(n)$ time.
First, to calculate $\texttt{toLeaf}(x)$,
we go through the children of $x$,
choose a child $c$ with maximum $\texttt{toLeaf}(c)$
and add one to this value.
Then, to calculate $\texttt{maxLength}(x)$,
we choose two distinct children $a$ and $b$
such that the sum $\texttt{toLeaf}(a)+\texttt{toLeaf}(b)$
is maximum and add two to this sum.
2017-01-07 22:31:41 +01:00
\subsubsection{Algorithm 2}
Another efficient way to calculate the diameter
of a tree is based on two depth-first searches.
First, we choose an arbitrary node $a$ in the tree
2017-02-05 12:40:54 +01:00
and find the farthest node $b$ from $a$.
Then, we find the farthest node $c$ from $b$.
The diameter of the tree is the distance between $b$ and $c$.
2017-01-07 22:31:41 +01:00
2017-05-28 12:22:15 +02:00
In the following graph, $a$, $b$ and $c$ could be:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$};
2017-05-28 12:22:15 +02:00
\node[draw, circle] (2) at (2,3) {$4$};
\node[draw, circle] (3) at (0,1) {$2$};
\node[draw, circle] (4) at (2,1) {$3$};
\node[draw, circle] (5) at (4,1) {$7$};
\node[draw, circle] (6) at (-2,3) {$5$};
\node[draw, circle] (7) at (-2,1) {$6$};
2016-12-28 23:54:51 +01:00
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (3) -- (7);
\node[color=red] at (2,1.6) {$a$};
2017-05-28 12:22:15 +02:00
\node[color=red] at (-2,1.6) {$b$};
2016-12-28 23:54:51 +01:00
\node[color=red] at (4,1.6) {$c$};
2017-05-28 12:22:15 +02:00
\path[draw,thick,-,color=red,line width=2pt] (7) -- (3);
2016-12-28 23:54:51 +01:00
\path[draw,thick,-,color=red,line width=2pt] (3) -- (1);
\path[draw,thick,-,color=red,line width=2pt] (1) -- (2);
\path[draw,thick,-,color=red,line width=2pt] (2) -- (5);
\end{tikzpicture}
\end{center}
2017-01-07 22:31:41 +01:00
This is an elegant method, but why does it work?
2016-12-28 23:54:51 +01:00
2017-01-07 22:31:41 +01:00
It helps to draw the tree differently so that
the path that corresponds to the diameter
is horizontal, and all other
nodes hang from it:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (2,1) {$1$};
2017-05-28 12:22:15 +02:00
\node[draw, circle] (2) at (4,1) {$4$};
\node[draw, circle] (3) at (0,1) {$2$};
\node[draw, circle] (4) at (2,-1) {$3$};
\node[draw, circle] (5) at (6,1) {$7$};
\node[draw, circle] (6) at (0,-1) {$5$};
\node[draw, circle] (7) at (-2,1) {$6$};
2016-12-28 23:54:51 +01:00
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (3) -- (7);
\node[color=red] at (2,-1.6) {$a$};
\node[color=red] at (-2,1.6) {$b$};
\node[color=red] at (6,1.6) {$c$};
\node[color=red] at (2,1.6) {$x$};
\path[draw,thick,-,color=red,line width=2pt] (7) -- (3);
\path[draw,thick,-,color=red,line width=2pt] (3) -- (1);
\path[draw,thick,-,color=red,line width=2pt] (1) -- (2);
\path[draw,thick,-,color=red,line width=2pt] (2) -- (5);
\end{tikzpicture}
\end{center}
2017-01-07 22:31:41 +01:00
Node $x$ indicates the place where the path
from node $a$ joins the path that corresponds
to the diameter.
The farthest node from $a$
is node $b$, node $c$ or some other node
that is at least as far from node $x$.
2017-02-05 12:40:54 +01:00
Thus, this node is always a valid choice for
2017-05-28 12:22:15 +02:00
an endpoint of a path that corresponds to the diameter.
2017-01-07 22:31:41 +01:00
2017-05-28 23:54:46 +02:00
\section{All longest paths}
2017-01-07 22:31:41 +01:00
2017-05-28 23:54:46 +02:00
Our next problem is to calculate for every node
in the tree the maximum length of a path
that begins at the node.
This can be seen as a generalization of the
tree diameter problem, because the largest of those
lengths equals the diameter of the tree.
Also this problem can be solved in $O(n)$ time.
2016-12-28 23:54:51 +01:00
2017-05-28 23:54:46 +02:00
As an example, consider the following tree:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
2017-05-28 23:54:46 +02:00
\node[draw, circle] (1) at (0,0) {$1$};
\node[draw, circle] (2) at (-1.5,-1) {$4$};
\node[draw, circle] (3) at (2,0) {$2$};
\node[draw, circle] (4) at (-1.5,1) {$3$};
\node[draw, circle] (6) at (3.5,-1) {$6$};
\node[draw, circle] (7) at (3.5,1) {$5$};
2016-12-28 23:54:51 +01:00
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (3) -- (7);
\end{tikzpicture}
\end{center}
2017-05-28 23:54:46 +02:00
Let $\texttt{maxLength}(x)$ denote the maximum length
of a path that begins at node $x$.
For example, in the above tree,
$\texttt{maxLength}(4)=3$, because there
is a path $4 \rightarrow 1 \rightarrow 2 \rightarrow 6$.
Here is a complete table of the values:
\begin{center}
\begin{tabular}{l|lllllll}
node $x$ & 1 & 2 & 3 & 4 & 5 & 6 \\
$\texttt{maxLength}(x)$ & 2 & 2 & 3 & 3 & 3 & 3 \\
\end{tabular}
\end{center}
2017-01-07 22:31:41 +01:00
Also in this problem, a good starting point
2017-05-28 23:54:46 +02:00
for solving the problem is to root the tree arbitrarily:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$};
2017-05-28 23:54:46 +02:00
\node[draw, circle] (2) at (2,1) {$4$};
\node[draw, circle] (3) at (-2,1) {$2$};
\node[draw, circle] (4) at (0,1) {$3$};
\node[draw, circle] (6) at (-3,-1) {$5$};
\node[draw, circle] (7) at (-1,-1) {$6$};
2016-12-28 23:54:51 +01:00
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (3) -- (7);
\end{tikzpicture}
\end{center}
2017-05-28 23:54:46 +02:00
The first part of the problem is to calculate for every node $x$
the maximum length of a path that goes through a child of $x$.
For example, the longest path from node 1
goes through its child 2:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$};
2017-05-28 23:54:46 +02:00
\node[draw, circle] (2) at (2,1) {$4$};
\node[draw, circle] (3) at (-2,1) {$2$};
\node[draw, circle] (4) at (0,1) {$3$};
\node[draw, circle] (6) at (-3,-1) {$5$};
\node[draw, circle] (7) at (-1,-1) {$6$};
2016-12-28 23:54:51 +01:00
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (3) -- (7);
2017-05-28 23:54:46 +02:00
\path[draw,thick,->,color=red,line width=2pt] (1) -- (3);
\path[draw,thick,->,color=red,line width=2pt] (3) -- (6);
2016-12-28 23:54:51 +01:00
\end{tikzpicture}
\end{center}
2021-02-08 23:10:42 +01:00
This part is easy to solve in $O(n)$ time, because we can use a
similar technique to what we have done previously.
2017-05-28 23:54:46 +02:00
Then, the second part of the problem is to calculate
for every node $x$ the maximum length of a path
through its parent $p$.
For example, the longest path
from node 3 goes through its parent 1:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$};
2017-05-28 23:54:46 +02:00
\node[draw, circle] (2) at (2,1) {$4$};
\node[draw, circle] (3) at (-2,1) {$2$};
\node[draw, circle] (4) at (0,1) {$3$};
\node[draw, circle] (6) at (-3,-1) {$5$};
\node[draw, circle] (7) at (-1,-1) {$6$};
2016-12-28 23:54:51 +01:00
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (3) -- (7);
2017-05-28 23:54:46 +02:00
\path[draw,thick,->,color=red,line width=2pt] (4) -- (1);
\path[draw,thick,->,color=red,line width=2pt] (1) -- (3);
\path[draw,thick,->,color=red,line width=2pt] (3) -- (6);
\end{tikzpicture}
\end{center}
2016-12-28 23:54:51 +01:00
2017-05-28 23:54:46 +02:00
At first glance, it seems that we should choose
the longest path from $p$.
However, this \emph{does not} always work,
because the longest path from $p$
may go through $x$.
Here is an example of this situation:
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,3) {$1$};
\node[draw, circle] (2) at (2,1) {$4$};
\node[draw, circle] (3) at (-2,1) {$2$};
\node[draw, circle] (4) at (0,1) {$3$};
\node[draw, circle] (6) at (-3,-1) {$5$};
\node[draw, circle] (7) at (-1,-1) {$6$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (3) -- (7);
2016-12-28 23:54:51 +01:00
2017-05-28 23:54:46 +02:00
\path[draw,thick,->,color=red,line width=2pt] (3) -- (1);
\path[draw,thick,->,color=red,line width=2pt] (1) -- (2);
2016-12-28 23:54:51 +01:00
\end{tikzpicture}
\end{center}
2017-05-28 23:54:46 +02:00
Still, we can solve the second part in
$O(n)$ time by storing \emph{two} maximum lengths
for each node $x$:
\begin{itemize}
\item $\texttt{maxLength}_1(x)$:
the maximum length of a path from $x$
\item $\texttt{maxLength}_2(x)$
the maximum length of a path from $x$
in another direction than the first path
\end{itemize}
For example, in the above graph,
$\texttt{maxLength}_1(1)=2$
using the path $1 \rightarrow 2 \rightarrow 5$,
and $\texttt{maxLength}_2(1)=1$
using the path $1 \rightarrow 3$.
Finally, if the path that corresponds to
$\texttt{maxLength}_1(p)$ goes through $x$,
we conclude that the maximum length is
$\texttt{maxLength}_2(p)+1$,
and otherwise the maximum length is
$\texttt{maxLength}_1(p)+1$.
2017-01-07 22:31:41 +01:00
\section{Binary trees}
2016-12-28 23:54:51 +01:00
2017-01-07 22:31:41 +01:00
\index{binary tree}
2016-12-28 23:54:51 +01:00
\begin{samepage}
2017-01-07 22:31:41 +01:00
A \key{binary tree} is a rooted tree
2017-02-05 12:40:54 +01:00
where each node has a left and right subtree.
2017-01-07 22:31:41 +01:00
It is possible that a subtree of a node is empty.
Thus, every node in a binary tree has
2017-02-05 12:40:54 +01:00
zero, one or two children.
2017-01-07 22:31:41 +01:00
For example, the following tree is a binary tree:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,0) {$1$};
\node[draw, circle] (2) at (-1.5,-1.5) {$2$};
\node[draw, circle] (3) at (1.5,-1.5) {$3$};
\node[draw, circle] (4) at (-3,-3) {$4$};
\node[draw, circle] (5) at (0,-3) {$5$};
\node[draw, circle] (6) at (-1.5,-4.5) {$6$};
\node[draw, circle] (7) at (3,-3) {$7$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (2) -- (4);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (5) -- (6);
\path[draw,thick,-] (3) -- (7);
\end{tikzpicture}
\end{center}
\end{samepage}
2017-01-07 22:31:41 +01:00
\index{pre-order}
\index{in-order}
\index{post-order}
2016-12-28 23:54:51 +01:00
2017-05-07 20:18:56 +02:00
The nodes of a binary tree have three natural
2017-02-05 12:40:54 +01:00
orderings that correspond to different ways to
2017-02-17 21:13:30 +01:00
recursively traverse the tree:
2016-12-28 23:54:51 +01:00
\begin{itemize}
2017-01-07 22:31:41 +01:00
\item \key{pre-order}: first process the root,
then traverse the left subtree, then traverse the right subtree
\item \key{in-order}: first traverse the left subtree,
then process the root, then traverse the right subtree
\item \key{post-order}: first traverse the left subtree,
then traverse the right subtree, then process the root
2016-12-28 23:54:51 +01:00
\end{itemize}
2017-01-07 22:31:41 +01:00
For the above tree, the nodes in
pre-order are
2016-12-28 23:54:51 +01:00
$[1,2,4,5,6,3,7]$,
2017-01-07 22:31:41 +01:00
in in-order $[4,2,6,5,1,3,7]$
and in post-order $[4,6,5,2,7,3,1]$.
2017-02-05 12:40:54 +01:00
If we know the pre-order and in-order
of a tree, we can reconstruct the exact structure of the tree.
2017-02-17 21:13:30 +01:00
For example, the above tree is the only possible tree
2017-01-07 22:31:41 +01:00
with pre-order $[1,2,4,5,6,3,7]$ and
in-order $[4,2,6,5,1,3,7]$.
2017-02-05 12:40:54 +01:00
In a similar way, the post-order and in-order
2017-01-07 22:31:41 +01:00
also determine the structure of a tree.
However, the situation is different if we only know
2017-02-05 12:40:54 +01:00
the pre-order and post-order of a tree.
2017-01-07 22:31:41 +01:00
In this case, there may be more than one tree
2017-02-05 12:40:54 +01:00
that match the orderings.
2017-01-07 22:31:41 +01:00
For example, in both of the trees
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (0,0) {$1$};
\node[draw, circle] (2) at (-1.5,-1.5) {$2$};
\path[draw,thick,-] (1) -- (2);
\node[draw, circle] (1b) at (0+4,0) {$1$};
\node[draw, circle] (2b) at (1.5+4,-1.5) {$2$};
\path[draw,thick,-] (1b) -- (2b);
\end{tikzpicture}
\end{center}
2017-02-05 12:40:54 +01:00
the pre-order is $[1,2]$ and the post-order is $[2,1]$,
but the structures of the trees are different.
2016-12-28 23:54:51 +01:00