Add reference etc.

This commit is contained in:
Antti H S Laaksonen 2017-02-24 20:07:25 +02:00
parent a4d12103be
commit 92ad87112b
1 changed files with 39 additions and 28 deletions

View File

@ -555,69 +555,6 @@ common ancestor of given two nodes.
For example, in the following tree, For example, in the following tree,
the lowest common ancestor of nodes 5 and 8 the lowest common ancestor of nodes 5 and 8
is node 2: is node 2:
\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] (5) at (2,-1) {$7$};
\node[draw, circle] (6) at (-3,-1) {$5$};
\node[draw, circle] (7) at (-1,-1) {$6$};
\node[draw, circle] (8) at (-1,-3) {$8$};
\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,-] (7) -- (8);
\end{tikzpicture}
\end{center}
Next we will discuss two efficient techniques for
finding the lowest common ancestor of two nodes.
\subsubsection{Method 1}
One way to solve the problem is to use the fact
that we can efficiently find the $k$th
ancestor of any node in the tree.
Thus, we can first make sure that
both nodes are at the same level in the tree,
and then find the smallest value of $k$
such that the $k$th ancestor of both nodes is the same.
As an example, let us find the lowest common
ancestor of nodes $5$ and $8$:
\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] (5) at (2,-1) {$7$};
\node[draw, circle,fill=lightgray] (6) at (-3,-1) {$5$};
\node[draw, circle] (7) at (-1,-1) {$6$};
\node[draw, circle,fill=lightgray] (8) at (-1,-3) {$8$};
\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,-] (7) -- (8);
\end{tikzpicture}
\end{center}
Node $5$ is at level $3$, while node $8$ is at level $4$.
Thus, we first move one step upwards from node $8$ to node $6$.
After this, it turns out that the parent of both nodes $5$
and $6$ is node $2$, so we have found the lowest common ancestor.
The following picture shows how we move in the tree:
\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$};
@ -637,15 +574,88 @@ The following picture shows how we move in the tree:
\path[draw,thick,-] (7) -- (8); \path[draw,thick,-] (7) -- (8);
\path[draw=red,thick,->,line width=2pt] (6) edge [bend left] (3); \path[draw=red,thick,->,line width=2pt] (6) edge [bend left] (3);
\path[draw=red,thick,->,line width=2pt] (8) edge [bend right=40] (3);
\end{tikzpicture}
\end{center}
Next we will discuss two efficient techniques for
finding the lowest common ancestor of two nodes.
\subsubsection{Method 1}
One way to solve the problem is to use the fact
that we can efficiently find the $k$th
ancestor of any node in the tree.
Using this, we can divide the problem of
finding the lowest common ancestor into two parts.
We use two pointers that initially point to the
two nodes for which we should find the
lowest common ancestor.
First, we move one of the pointers upwards
so that both nodes are at the same level in the tree.
In the example case, we move from node 8 to node 6,
after which both nodes are at the same level:
\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] (5) at (2,-1) {$7$};
\node[draw, circle,fill=lightgray] (6) at (-3,-1) {$5$};
\node[draw, circle,fill=lightgray] (7) at (-1,-1) {$6$};
\node[draw, circle] (8) at (-1,-3) {$8$};
\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,-] (7) -- (8);
\path[draw=red,thick,->,line width=2pt] (8) edge [bend right] (7); \path[draw=red,thick,->,line width=2pt] (8) edge [bend right] (7);
\end{tikzpicture}
\end{center}
After this, we determine the minimum number of steps
needed to move both pointers upwards so that
they will point to the same node.
This node is the lowest common ancestor of the nodes.
In the example case, it suffices to move both pointers
one step upwards to node 2,
which is the lowest common ancestor:
\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,fill=lightgray] (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$};
\node[draw, circle] (8) at (-1,-3) {$8$};
\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,-] (7) -- (8);
\path[draw=red,thick,->,line width=2pt] (6) edge [bend left] (3);
\path[draw=red,thick,->,line width=2pt] (7) edge [bend right] (3); \path[draw=red,thick,->,line width=2pt] (7) edge [bend right] (3);
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Using this method, we can find the lowest common ancestor Since both parts of the algorithm can be performed in
of any two nodes in $O(\log n)$ time after an $O(n \log n)$ time $O(\log n)$ time using precomputed information,
preprocessing, because both steps can be we can find the lowest common ancestor of any two
performed in $O(\log n)$ time. nodes in $O(\log n)$ time using this technique.
\subsubsection{Method 2} \subsubsection{Method 2}
@ -689,13 +699,14 @@ using a depth-first search:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
However, we use a bit different variant of However, we use a bit different tree
the tree traversal array where traversal array than before:
we add each node to the array \emph{always} we add each node to the array \emph{always}
when the depth-first search visits the node, when the depth-first search walks through the node,
and not only at the first visit. and not only at the first visit\footnote{A similar technique is sometimes called the
\key{Euler tour technique} \cite{tar84}.}.
Hence, a node that has $k$ children appears $k+1$ times Hence, a node that has $k$ children appears $k+1$ times
in the array, and there are a total of $2n-1$ in the array and there are a total of $2n-1$
nodes in the array. nodes in the array.
We store two values in the array: We store two values in the array: