Improve language

This commit is contained in:
Antti H S Laaksonen 2017-05-29 21:23:47 +03:00
parent d4b4bb6708
commit c8ed23c39e
1 changed files with 38 additions and 69 deletions

View File

@ -3,14 +3,14 @@
\index{tree query} \index{tree query}
This chapter discusses techniques for This chapter discusses techniques for
processing queries related processing queries on
to subtrees and paths of a rooted tree. subtrees and paths of a rooted tree.
For example, such queries are: For example, such queries are:
\begin{itemize} \begin{itemize}
\item what is the $k$th ancestor of a node? \item what is the $k$th ancestor of a node?
\item what is the sum of values in the subtree of a node? \item what is the sum of values in the subtree of a node?
\item what is the sum of values in a path between two nodes? \item what is the sum of values on a path between two nodes?
\item what is the lowest common ancestor of two nodes? \item what is the lowest common ancestor of two nodes?
\end{itemize} \end{itemize}
@ -21,11 +21,10 @@ For example, such queries are:
The $k$th \key{ancestor} of a node $x$ in a rooted tree The $k$th \key{ancestor} of a node $x$ in a rooted tree
is the node that we will reach if we move $k$ is the node that we will reach if we move $k$
levels up from $x$. levels up from $x$.
Let $f(x,k)$ denote the $k$th ancestor of a node $x$ Let $\texttt{ancestor}(x,k)$ denote the $k$th ancestor of a node $x$
(or $0$ if there is no such an ancestor). (or $0$ if there is no such an ancestor).
For example, in the following tree, $f(2,1)=1$, $f(8,2)=4$ For example, in the following tree,
and $f(5,2)=0$. $\texttt{ancestor}(2,1)=1$ and $\texttt{ancestor}(8,2)=4$.
\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$};
@ -49,17 +48,17 @@ and $f(5,2)=0$.
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
An easy way to calculate the value of $f(x,k)$ An easy way to calculate any value of $\texttt{ancestor}(x,k)$
is to perform a sequence of $k$ moves in the tree. is to perform a sequence of $k$ moves in the tree.
However, the time complexity of this method However, the time complexity of this method
is $O(k)$, which may be slow, because a tree of $n$ is $O(k)$, which may be slow, because a tree of $n$
nodes may have a chain of $n$ nodes. nodes may have a chain of $n$ nodes.
Fortunately, using a technique similar to that Fortunately, using a technique similar to that
used in Chapter 16.3, any value of $f(x,k)$ used in Chapter 16.3, any value of $\texttt{ancestor}(x,k)$
can be efficiently calculated in $O(\log k)$ time can be efficiently calculated in $O(\log k)$ time
after preprocessing. after preprocessing.
The idea is to precalculate all values $f(x,k)$ The idea is to precalculate all values $\texttt{ancestor}(x,k)$
where $k \le n$ is a power of two. where $k \le n$ is a power of two.
For example, the values for the above tree For example, the values for the above tree
are as follows: are as follows:
@ -68,16 +67,16 @@ are as follows:
\begin{tabular}{r|rrrrrrrrr} \begin{tabular}{r|rrrrrrrrr}
$x$ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 \\ $x$ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 \\
\hline \hline
$f(x,1)$ & 0 & 1 & 4 & 1 & 1 & 2 & 4 & 7 \\ $\texttt{ancestor}(x,1)$ & 0 & 1 & 4 & 1 & 1 & 2 & 4 & 7 \\
$f(x,2)$ & 0 & 0 & 1 & 0 & 0 & 1 & 1 & 4 \\ $\texttt{ancestor}(x,2)$ & 0 & 0 & 1 & 0 & 0 & 1 & 1 & 4 \\
$f(x,4)$ & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ $\texttt{ancestor}(x,4)$ & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
$\cdots$ \\ $\cdots$ \\
\end{tabular} \end{tabular}
\end{center} \end{center}
The preprocessing takes $O(n \log n)$ time, The preprocessing takes $O(n \log n)$ time,
because $O(\log n)$ values are calculated for each node. because $O(\log n)$ values are calculated for each node.
After this, any value of $f(x,k)$ can be calculated After this, any value of $\texttt{ancestor}(x,k)$ can be calculated
in $O(\log k)$ time by representing $k$ in $O(\log k)$ time by representing $k$
as a sum where each term is a power of two. as a sum where each term is a power of two.
@ -391,7 +390,7 @@ Using a tree traversal array, we can also efficiently
calculate sums of values on calculate sums of values on
paths from the root node to any paths from the root node to any
node of the tree. node of the tree.
Let us consider a problem where our task Consider a problem where our task
is to support the following queries: is to support the following queries:
\begin{itemize} \begin{itemize}
\item change the value of a node \item change the value of a node
@ -436,7 +435,7 @@ $4+5+5=14$:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
We can solve this problem in a similar way as before, We can solve this problem like before,
but now each value in the last row of the array is the sum of values but now each value in the last row of the array is the sum of values
on a path from the root to the node. on a path from the root to the node.
For example, the following array corresponds to the above tree: For example, the following array corresponds to the above tree:
@ -477,17 +476,6 @@ For example, the following array corresponds to the above tree:
\node at (6.5,-1.5) {$12$}; \node at (6.5,-1.5) {$12$};
\node at (7.5,-1.5) {$10$}; \node at (7.5,-1.5) {$10$};
\node at (8.5,-1.5) {$6$}; \node at (8.5,-1.5) {$6$};
%
% \footnotesize
% \node at (0.5,1.4) {$1$};
% \node at (1.5,1.4) {$2$};
% \node at (2.5,1.4) {$3$};
% \node at (3.5,1.4) {$4$};
% \node at (4.5,1.4) {$5$};
% \node at (5.5,1.4) {$6$};
% \node at (6.5,1.4) {$7$};
% \node at (7.5,1.4) {$8$};
% \node at (8.5,1.4) {$9$};
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
@ -534,17 +522,6 @@ the array changes as follows:
\node at (6.5,-1.5) {$13$}; \node at (6.5,-1.5) {$13$};
\node at (7.5,-1.5) {$11$}; \node at (7.5,-1.5) {$11$};
\node at (8.5,-1.5) {$6$}; \node at (8.5,-1.5) {$6$};
%
% \footnotesize
% \node at (0.5,1.4) {$1$};
% \node at (1.5,1.4) {$2$};
% \node at (2.5,1.4) {$3$};
% \node at (3.5,1.4) {$4$};
% \node at (4.5,1.4) {$5$};
% \node at (5.5,1.4) {$6$};
% \node at (6.5,1.4) {$7$};
% \node at (7.5,1.4) {$8$};
% \node at (8.5,1.4) {$9$};
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
@ -608,7 +585,7 @@ two nodes whose lowest common ancestor we should find.
First, we move one of the pointers upwards First, we move one of the pointers upwards
so that both pointers point to nodes at the same level. so that both pointers point to nodes at the same level.
In the example case, we move the second pointer one In the example scenario, we move the second pointer one
level up so that it points to node 6 level up so that it points to node 6
which is at the same level with node 5: which is at the same level with node 5:
@ -640,7 +617,7 @@ they will point to the same node.
The node to which the pointers point after this The node to which the pointers point after this
is the lowest common ancestor. is the lowest common ancestor.
In the example case, it suffices to move both pointers In the example scenario, it suffices to move both pointers
one step upwards to node 2, one step upwards to node 2,
which is the lowest common ancestor: which is the lowest common ancestor:
@ -726,7 +703,7 @@ 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:
the identifier of the node and the level of the the identifier of the node and the depth of the
node in the tree. node in the tree.
The following array corresponds to the above tree: The following array corresponds to the above tree:
@ -734,10 +711,9 @@ The following array corresponds to the above tree:
\begin{tikzpicture}[scale=0.7] \begin{tikzpicture}[scale=0.7]
\node[left] at (-1,1.5) {node id}; \node[left] at (-1,1.5) {node id};
\node[left] at (-1,0.5) {level}; \node[left] at (-1,0.5) {depth};
\draw (0,1) grid (15,2); \draw (0,1) grid (15,2);
%\node at (-1.1,1.5) {\texttt{node}};
\node at (0.5,1.5) {$1$}; \node at (0.5,1.5) {$1$};
\node at (1.5,1.5) {$2$}; \node at (1.5,1.5) {$2$};
\node at (2.5,1.5) {$5$}; \node at (2.5,1.5) {$5$};
@ -754,9 +730,7 @@ The following array corresponds to the above tree:
\node at (13.5,1.5) {$4$}; \node at (13.5,1.5) {$4$};
\node at (14.5,1.5) {$1$}; \node at (14.5,1.5) {$1$};
\draw (0,0) grid (15,1); \draw (0,0) grid (15,1);
%\node at (-1.1,0.5) {\texttt{depth}};
\node at (0.5,0.5) {$1$}; \node at (0.5,0.5) {$1$};
\node at (1.5,0.5) {$2$}; \node at (1.5,0.5) {$2$};
\node at (2.5,0.5) {$3$}; \node at (2.5,0.5) {$3$};
@ -793,7 +767,7 @@ The following array corresponds to the above tree:
\end{center} \end{center}
Now we can find the lowest common ancestor Now we can find the lowest common ancestor
of nodes $a$ and $b$ by finding the node with the \emph{lowest} level of nodes $a$ and $b$ by finding the node with the \emph{minimum} depth
between nodes $a$ and $b$ in the array. between nodes $a$ and $b$ in the array.
For example, the lowest common ancestor of nodes $5$ and $8$ For example, the lowest common ancestor of nodes $5$ and $8$
can be found as follows: can be found as follows:
@ -802,7 +776,7 @@ can be found as follows:
\begin{tikzpicture}[scale=0.7] \begin{tikzpicture}[scale=0.7]
\node[left] at (-1,1.5) {node id}; \node[left] at (-1,1.5) {node id};
\node[left] at (-1,0.5) {level}; \node[left] at (-1,0.5) {depth};
\fill[color=lightgray] (2,1) rectangle (3,2); \fill[color=lightgray] (2,1) rectangle (3,2);
\fill[color=lightgray] (5,1) rectangle (6,2); \fill[color=lightgray] (5,1) rectangle (6,2);
@ -865,9 +839,9 @@ can be found as follows:
\end{center} \end{center}
Node 5 is at position 2, node 8 is at position 5, Node 5 is at position 2, node 8 is at position 5,
and the node with lowest level between and the node with minimum depth between
positions $2 \ldots 5$ is node 2 at position 3 positions $2 \ldots 5$ is node 2 at position 3
whose level is 2. whose depth is 2.
Thus, the lowest common ancestor of Thus, the lowest common ancestor of
nodes 5 and 8 is node 2. nodes 5 and 8 is node 2.
@ -880,22 +854,19 @@ after an $O(n \log n)$ time preprocessing.
\subsubsection{Distances of nodes} \subsubsection{Distances of nodes}
Finally, let us consider the problem of The distance between nodes $a$ and $b$
calculating the distance between equals the length of the path from $a$ to $b$.
two nodes of a tree, which equals It turns out that the problem of calculating
the length of the path between them. the distance between nodes reduces to
It turns out that this problem reduces to finding their lowest common ancestor.
finding the lowest common ancestor of the nodes.
First, we root the tree arbitrarily. First, we root the tree arbitrarily.
After this, the distance between nodes $a$ and $b$ After this, the distance of nodes $a$ and $b$
can be calculated using the formula can be calculated using the formula
\[d(a)+d(b)-2 \cdot d(c),\] \[\texttt{depth}(a)+\texttt{depth}(b)-2 \cdot \texttt{depth}(c),\]
where $c$ is the lowest common ancestor of $a$ and $b$ where $c$ is the lowest common ancestor of $a$ and $b$
and $d(s)$ denotes the distance from the root and $\texttt{depth}(s)$ denotes the depth of node $s$.
to node $s$. For example, consider the distance of nodes 5 and 8:
For example, 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$};
@ -919,12 +890,10 @@ For example, in the tree
\path[draw=red,thick,-,line width=2pt] (6) -- node[font=\small] {} (3); \path[draw=red,thick,-,line width=2pt] (6) -- node[font=\small] {} (3);
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
the lowest common ancestor of nodes 5 and 8 is node 2.
A path from node 5 to node 8 The lowest common ancestor of nodes 5 and 8 is node 2.
first ascends from node 5 to node 2 The depths of the nodes are
and then descends from node 2 to node 8. $\texttt{depth}(5)=3$, $\texttt{depth}(8)=4$ and $\texttt{depth}(2)=2$,
The distances of the nodes from the root are
$d(5)=3$, $d(8)=4$ and $d(2)=2$,
so the distance between nodes 5 and 8 is so the distance between nodes 5 and 8 is
$3+4-2\cdot2=3$. $3+4-2\cdot2=3$.
@ -1167,7 +1136,7 @@ is the highest node in the set of $y$.
Then, after processing node $x$, Then, after processing node $x$,
the algorithm joins the sets of $x$ and its parent. the algorithm joins the sets of $x$ and its parent.
For example, assume that we wish to find the lowest For example, suppose that we want to find the lowest
common ancestors of node pairs $(5,8)$ common ancestors of node pairs $(5,8)$
and $(2,7)$ in the following tree: and $(2,7)$ in the following tree:
\begin{center} \begin{center}
@ -1190,7 +1159,7 @@ and $(2,7)$ in the following tree:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
In the following pictures, gray nodes denote visited nodes In the following trees, gray nodes denote visited nodes
and dashed groups of nodes belong to the same set. and dashed groups of nodes belong to the same set.
When the algorithm visits node 8, it notices that When the algorithm visits node 8, it notices that
node 5 has been visited and the highest node node 5 has been visited and the highest node