Improve language
This commit is contained in:
parent
d4b4bb6708
commit
c8ed23c39e
107
chapter18.tex
107
chapter18.tex
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue