546 lines
17 KiB
TeX
546 lines
17 KiB
TeX
\chapter{Tree algorithms}
|
|
|
|
\index{tree}
|
|
|
|
A \key{tree} is a connected, acyclic graph
|
|
that contains $n$ nodes and $n-1$ edges.
|
|
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
|
|
two nodes in a tree.
|
|
|
|
For example, the following tree contains 7 nodes and 6 edges:
|
|
\begin{center}
|
|
\begin{tikzpicture}[scale=0.9]
|
|
\node[draw, circle] (1) at (0,3) {$1$};
|
|
\node[draw, circle] (2) at (2,3) {$2$};
|
|
\node[draw, circle] (3) at (0,1) {$4$};
|
|
\node[draw, circle] (4) at (2,1) {$5$};
|
|
\node[draw, circle] (5) at (4,1) {$6$};
|
|
\node[draw, circle] (6) at (-2,3) {$7$};
|
|
\node[draw, circle] (7) at (-2,1) {$3$};
|
|
\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}
|
|
|
|
\index{leaf}
|
|
|
|
The \key{leaves} of a tree are nodes
|
|
with degree 1, i.e., with only one neighbor.
|
|
For example, the leaves in the above tree
|
|
are nodes 3, 5, 6 and 7.
|
|
|
|
\index{root}
|
|
\index{rooted tree}
|
|
|
|
In a \key{rooted} tree, one of the nodes
|
|
is chosen to be a \key{root}, and all other nodes are
|
|
placed underneath the root.
|
|
For example, in the following tree,
|
|
node 1 is the root of the tree.
|
|
|
|
\begin{center}
|
|
\begin{tikzpicture}[scale=0.9]
|
|
\node[draw, circle] (1) at (0,3) {$1$};
|
|
\node[draw, circle] (2) at (2,1) {$2$};
|
|
\node[draw, circle] (3) at (-2,1) {$4$};
|
|
\node[draw, circle] (4) at (0,1) {$5$};
|
|
\node[draw, circle] (5) at (2,-1) {$6$};
|
|
\node[draw, circle] (6) at (-3,-1) {$3$};
|
|
\node[draw, circle] (7) at (-1,-1) {$7$};
|
|
\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}
|
|
|
|
\index{child}
|
|
\index{parent}
|
|
|
|
In a rooted tree, the \key{childern} of a node
|
|
are its lower neighbors, and the \key{parent} of a node
|
|
is its upper neighbor.
|
|
Each node has exactly one parent,
|
|
except that the root doesn't have a parent.
|
|
For example, in the above tree,
|
|
the childern of node 4 are nodes 3 and 7,
|
|
and the parent is node 1.
|
|
|
|
\index{subtree}
|
|
|
|
The structure of a rooted tree is \emph{recursive}:
|
|
each node in the tree is the root of a \key{subtree}
|
|
that contains the node itself and all other nodes
|
|
that can be reached by travelling downwards in the tree.
|
|
For example, in the above tree, the subtree of node 4
|
|
contains nodes 4, 3 and 7.
|
|
|
|
\section{Tree search}
|
|
|
|
Depth-first search and breadth-first search
|
|
can be used for going through the nodes in a tree.
|
|
However, the search is easier to implement than
|
|
for a general graph, because
|
|
there are no cycles in the tree, and it is not
|
|
possible that the search would visit a node several times.
|
|
|
|
Often, we start a depth-first search from a chosen
|
|
root node.
|
|
The following recursive function implements it:
|
|
|
|
\begin{lstlisting}
|
|
void dfs(int s, int e) {
|
|
// process node s
|
|
for (auto u : v[s]) {
|
|
if (u != e) dfs(u, s);
|
|
}
|
|
}
|
|
\end{lstlisting}
|
|
|
|
The function parameters are the current node $s$
|
|
and the previous node $e$.
|
|
The idea of the parameter $e$ is to ensure
|
|
that the search only proceeds downwards in the tree
|
|
towards nodes that have not been visited yet.
|
|
|
|
The following function call starts the search
|
|
at node $x$:
|
|
|
|
\begin{lstlisting}
|
|
dfs(x, 0);
|
|
\end{lstlisting}
|
|
|
|
In the first call $e=0$ because there is no
|
|
previous node, and it is allowed
|
|
to proceed to any direction in the tree.
|
|
|
|
\subsubsection{Dynamic programming}
|
|
|
|
We can also use dynamic programming to calculate
|
|
some information from the tree during the search.
|
|
Using dynamic programming, we can, for example,
|
|
calculate in $O(n)$ time for each node the
|
|
number of nodes in its subtree,
|
|
or the length of the longest path downwards
|
|
that begins at the node.
|
|
|
|
As an example, let's calculate for each node $s$
|
|
a value $\texttt{c}[s]$: the number of nodes in its subtree.
|
|
The subtree contains the node itself and
|
|
all nodes in the subtrees of its children.
|
|
Thus, we can calculate the number of nodes
|
|
recursively using the following code:
|
|
|
|
\begin{lstlisting}
|
|
void haku(int s, int e) {
|
|
c[s] = 1;
|
|
for (auto u : v[s]) {
|
|
if (u == e) continue;
|
|
haku(u, s);
|
|
c[s] += c[u];
|
|
}
|
|
}
|
|
\end{lstlisting}
|
|
|
|
\section{Diameter}
|
|
|
|
\index{diameter}
|
|
|
|
The \key{diameter} of a tree
|
|
is the length of the longest path
|
|
between two nodes in the tree.
|
|
For example, in the tree
|
|
\begin{center}
|
|
\begin{tikzpicture}[scale=0.9]
|
|
\node[draw, circle] (1) at (0,3) {$1$};
|
|
\node[draw, circle] (2) at (2,3) {$2$};
|
|
\node[draw, circle] (3) at (0,1) {$4$};
|
|
\node[draw, circle] (4) at (2,1) {$5$};
|
|
\node[draw, circle] (5) at (4,1) {$6$};
|
|
\node[draw, circle] (6) at (-2,3) {$7$};
|
|
\node[draw, circle] (7) at (-2,1) {$3$};
|
|
\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 is 4, and it corresponds to two paths:
|
|
the path between nodes 3 and 6,
|
|
and the path between nodes 7 and 6.
|
|
|
|
Next we will learn two efficient algorithms
|
|
for calculating the diameter of a tree.
|
|
Both algorithms calculate the diameter in $O(n)$ time.
|
|
The first algorithm is based on dynamic programming,
|
|
and the second algorithm uses two depth-first searches
|
|
to calculate the diameter.
|
|
|
|
\subsubsection{Algorithm 1}
|
|
|
|
First, one of the nodes is chosen to be the root.
|
|
After this, the algorithm calculates for each node
|
|
the length of the longest path that begins at some leaf,
|
|
ascends to the node and then descends to another leaf.
|
|
The length of the
|
|
longest such path equals the diameter of the tree.
|
|
|
|
In the example case, the longest path begins at node 7,
|
|
ascends to node 1, and then descends to node 6:
|
|
\begin{center}
|
|
\begin{tikzpicture}[scale=0.9]
|
|
\node[draw, circle] (1) at (0,3) {$1$};
|
|
\node[draw, circle] (2) at (2,1) {$2$};
|
|
\node[draw, circle] (3) at (-2,1) {$4$};
|
|
\node[draw, circle] (4) at (0,1) {$5$};
|
|
\node[draw, circle] (5) at (2,-1) {$6$};
|
|
\node[draw, circle] (6) at (-3,-1) {$3$};
|
|
\node[draw, circle] (7) at (-1,-1) {$7$};
|
|
\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}
|
|
|
|
The algorithm first calculates using dynamic programming
|
|
for each node the length of the longest path
|
|
that goes downwards from the node.
|
|
For example, in the above tree,
|
|
the longest path from node 1 downwards has length 2
|
|
(the path can be $1 \rightarrow 4 \rightarrow 3$,
|
|
$1 \rightarrow 4 \rightarrow 7$ or $1 \rightarrow 2 \rightarrow 6$).
|
|
|
|
After this, the algorithm calculates for each node
|
|
the length of the longest path where the node
|
|
is the turning point of the path.
|
|
The longest such path can be found by selecting
|
|
two children with longest paths downwards.
|
|
For example, in the above graph,
|
|
nodes 2 and 4 are chosen for node 1.
|
|
|
|
\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
|
|
and find a node $b$ with maximum distance to $a$.
|
|
Then, we find a node $c$ with maximum distance to $b$.
|
|
The diameter is the distance between nodes $b$ and $c$.
|
|
|
|
In the example case, $a$, $b$ and $c$ could be:
|
|
\begin{center}
|
|
\begin{tikzpicture}[scale=0.9]
|
|
\node[draw, circle] (1) at (0,3) {$1$};
|
|
\node[draw, circle] (2) at (2,3) {$2$};
|
|
\node[draw, circle] (3) at (0,1) {$4$};
|
|
\node[draw, circle] (4) at (2,1) {$5$};
|
|
\node[draw, circle] (5) at (4,1) {$6$};
|
|
\node[draw, circle] (6) at (-2,3) {$7$};
|
|
\node[draw, circle] (7) at (-2,1) {$3$};
|
|
\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 (-1.4,3) {$b$};
|
|
\node[color=red] at (4,1.6) {$c$};
|
|
|
|
\path[draw,thick,-,color=red,line width=2pt] (6) -- (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}
|
|
|
|
This is an elegant method, but why does it work?
|
|
|
|
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:
|
|
\begin{center}
|
|
\begin{tikzpicture}[scale=0.9]
|
|
\node[draw, circle] (1) at (2,1) {$1$};
|
|
\node[draw, circle] (2) at (4,1) {$2$};
|
|
\node[draw, circle] (3) at (0,1) {$4$};
|
|
\node[draw, circle] (4) at (2,-1) {$5$};
|
|
\node[draw, circle] (5) at (6,1) {$6$};
|
|
\node[draw, circle] (6) at (0,-1) {$3$};
|
|
\node[draw, circle] (7) at (-2,1) {$7$};
|
|
\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}
|
|
|
|
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$.
|
|
Thus, this node can always be chosen for
|
|
a starting node of a path that corresponds to the diameter.
|
|
|
|
\section{Distances between nodes}
|
|
|
|
A more difficult problem is to calculate
|
|
for each node in the tree and for each direction,
|
|
the maximum distance to a node in that direction.
|
|
It turns out that this can be calculated in
|
|
$O(n)$ time as well using dynamic programming.
|
|
|
|
\begin{samepage}
|
|
In the example case, the distances are as follows:
|
|
\begin{center}
|
|
\begin{tikzpicture}[scale=0.9]
|
|
\node[draw, circle] (1) at (0,3) {$1$};
|
|
\node[draw, circle] (2) at (2,3) {$2$};
|
|
\node[draw, circle] (3) at (0,1) {$4$};
|
|
\node[draw, circle] (4) at (2,1) {$5$};
|
|
\node[draw, circle] (5) at (4,1) {$6$};
|
|
\node[draw, circle] (6) at (-2,3) {$7$};
|
|
\node[draw, circle] (7) at (-2,1) {$3$};
|
|
\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 (0.5,3.2) {$2$};
|
|
\node[color=red] at (0.3,2.4) {$1$};
|
|
\node[color=red] at (-0.2,2.4) {$2$};
|
|
\node[color=red] at (-0.2,1.5) {$3$};
|
|
\node[color=red] at (-0.5,1.2) {$1$};
|
|
\node[color=red] at (-1.7,2.4) {$4$};
|
|
\node[color=red] at (-0.5,0.8) {$1$};
|
|
\node[color=red] at (-1.5,0.8) {$4$};
|
|
\node[color=red] at (1.5,3.2) {$3$};
|
|
\node[color=red] at (1.5,1.2) {$3$};
|
|
\node[color=red] at (3.5,1.2) {$4$};
|
|
\node[color=red] at (2.2,2.4) {$1$};
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
\end{samepage}
|
|
For example, the furthest node from node 4
|
|
upwards is node 6, and the distance to this
|
|
node is 3 using the path
|
|
$4 \rightarrow 1 \rightarrow 2 \rightarrow 6$.
|
|
|
|
\begin{samepage}
|
|
Also in this problem, a good starting point
|
|
is to root the tree.
|
|
After this, all distances downwards can
|
|
be calculated using dynamic programming:
|
|
\begin{center}
|
|
\begin{tikzpicture}[scale=0.9]
|
|
\node[draw, circle] (1) at (0,3) {$1$};
|
|
\node[draw, circle] (2) at (2,1) {$2$};
|
|
\node[draw, circle] (3) at (-2,1) {$4$};
|
|
\node[draw, circle] (4) at (0,1) {$5$};
|
|
\node[draw, circle] (5) at (2,-1) {$6$};
|
|
\node[draw, circle] (6) at (-3,-1) {$3$};
|
|
\node[draw, circle] (7) at (-1,-1) {$7$};
|
|
\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.5,0.7) {$1$};
|
|
\node[color=red] at (-1.5,0.7) {$1$};
|
|
|
|
\node[color=red] at (2.2,0.5) {$1$};
|
|
|
|
\node[color=red] at (-0.5,2.8) {$2$};
|
|
\node[color=red] at (0.2,2.5) {$1$};
|
|
\node[color=red] at (0.5,2.8) {$2$};
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
\end{samepage}
|
|
|
|
The remaining task is to calculate the distances upwards.
|
|
This can be done by going through the nodes once again
|
|
and keeping track of the largest distance from the parent
|
|
of the current node to some other node in another direction.
|
|
|
|
For example, the distance from node 2 upwards
|
|
is one larger than the distance from node 1
|
|
downwards in some other direction than node 2:
|
|
\begin{center}
|
|
\begin{tikzpicture}[scale=0.9]
|
|
\node[draw, circle] (1) at (0,3) {$1$};
|
|
\node[draw, circle] (2) at (2,1) {$2$};
|
|
\node[draw, circle] (3) at (-2,1) {$4$};
|
|
\node[draw, circle] (4) at (0,1) {$5$};
|
|
\node[draw, circle] (5) at (2,-1) {$6$};
|
|
\node[draw, circle] (6) at (-3,-1) {$3$};
|
|
\node[draw, circle] (7) at (-1,-1) {$7$};
|
|
\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] (1) -- (2);
|
|
\path[draw,thick,-,color=red,line width=2pt] (1) -- (3);
|
|
\path[draw,thick,-,color=red,line width=2pt] (3) -- (7);
|
|
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
Finally, we can calculate the distances for all nodes
|
|
and all directions:
|
|
\begin{center}
|
|
\begin{tikzpicture}[scale=0.9]
|
|
\node[draw, circle] (1) at (0,3) {$1$};
|
|
\node[draw, circle] (2) at (2,1) {$2$};
|
|
\node[draw, circle] (3) at (-2,1) {$4$};
|
|
\node[draw, circle] (4) at (0,1) {$5$};
|
|
\node[draw, circle] (5) at (2,-1) {$6$};
|
|
\node[draw, circle] (6) at (-3,-1) {$3$};
|
|
\node[draw, circle] (7) at (-1,-1) {$7$};
|
|
\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.5,0.7) {$1$};
|
|
\node[color=red] at (-1.5,0.7) {$1$};
|
|
|
|
\node[color=red] at (2.2,0.5) {$1$};
|
|
|
|
\node[color=red] at (-0.5,2.8) {$2$};
|
|
\node[color=red] at (0.2,2.5) {$1$};
|
|
\node[color=red] at (0.5,2.8) {$2$};
|
|
|
|
\node[color=red] at (-3,-0.4) {$4$};
|
|
\node[color=red] at (-1,-0.4) {$4$};
|
|
\node[color=red] at (-2,1.6) {$3$};
|
|
\node[color=red] at (2,1.6) {$3$};
|
|
|
|
\node[color=red] at (2.2,-0.4) {$4$};
|
|
\node[color=red] at (0.2,1.6) {$3$};
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
\section{Binary trees}
|
|
|
|
\index{binary tree}
|
|
|
|
\begin{samepage}
|
|
A \key{binary tree} is a rooted tree
|
|
where each node has a left subtree
|
|
and a right subtree.
|
|
It is possible that a subtree of a node is empty.
|
|
Thus, every node in a binary tree has
|
|
0, 1 or 2 children.
|
|
|
|
For example, the following tree is a binary tree:
|
|
\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}
|
|
|
|
\index{pre-order}
|
|
\index{in-order}
|
|
\index{post-order}
|
|
|
|
The nodes in a binary tree have three natural
|
|
orders that correspond to different ways to
|
|
recursively traverse the nodes:
|
|
|
|
\begin{itemize}
|
|
\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
|
|
\end{itemize}
|
|
|
|
For the above tree, the nodes in
|
|
pre-order are
|
|
$[1,2,4,5,6,3,7]$,
|
|
in in-order $[4,2,6,5,1,3,7]$
|
|
and in post-order $[4,6,5,2,7,3,1]$.
|
|
|
|
If we know the pre-order and the in-order
|
|
of a tree, we can find out the exact structure of the tree.
|
|
For example, the tree above is the only possible tree
|
|
with pre-order $[1,2,4,5,6,3,7]$ and
|
|
in-order $[4,2,6,5,1,3,7]$.
|
|
Correspondingly, the post-order and the in-order
|
|
also determine the structure of a tree.
|
|
|
|
However, the situation is different if we only know
|
|
the pre-order and the post-order of a tree.
|
|
In this case, there may be more than one tree
|
|
that match the orders.
|
|
For example, in both of the trees
|
|
\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}
|
|
the pre-order is $[1,2]$ and the post-order is $[2,1]$
|
|
but the trees have different structures.
|
|
|