Add reference etc.
This commit is contained in:
parent
a4d12103be
commit
92ad87112b
155
chapter18.tex
155
chapter18.tex
|
@ -555,69 +555,6 @@ common ancestor of given two nodes.
|
|||
For example, in the following tree,
|
||||
the lowest common ancestor of nodes 5 and 8
|
||||
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{tikzpicture}[scale=0.9]
|
||||
\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=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);
|
||||
\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);
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
|
||||
Using this method, we can find the lowest common ancestor
|
||||
of any two nodes in $O(\log n)$ time after an $O(n \log n)$ time
|
||||
preprocessing, because both steps can be
|
||||
performed in $O(\log n)$ time.
|
||||
Since both parts of the algorithm can be performed in
|
||||
$O(\log n)$ time using precomputed information,
|
||||
we can find the lowest common ancestor of any two
|
||||
nodes in $O(\log n)$ time using this technique.
|
||||
|
||||
\subsubsection{Method 2}
|
||||
|
||||
|
@ -689,13 +699,14 @@ using a depth-first search:
|
|||
\end{tikzpicture}
|
||||
\end{center}
|
||||
|
||||
However, we use a bit different variant of
|
||||
the tree traversal array where
|
||||
However, we use a bit different tree
|
||||
traversal array than before:
|
||||
we add each node to the array \emph{always}
|
||||
when the depth-first search visits the node,
|
||||
and not only at the first visit.
|
||||
when the depth-first search walks through the node,
|
||||
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
|
||||
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.
|
||||
|
||||
We store two values in the array:
|
||||
|
|
Loading…
Reference in New Issue