Generar un árbol a partir de sus recorridos en inorden y postorden

Preliminares

Recordad que el recorrido en inorden de un árbol es la lista de los
nodos del árbol ordenada como sigue: en primer lugar, el recorrido en
inorden del hijo izquierdo del árbol, después la raíz del árbol, y
después el recorrido en inorden del hijo derecho del árbol. En otras
palabras:
$$\begin{align*}
inorden(x(t_1,t_2)) &= inorden(t_1)\;\cdot{}\;x\;\cdot{}\;inorden(t_2) \\
inorden(()) &= ()
\end{align*}$$
es decir, el inorden del árbol vacío es el árbol vacío.

Recordad también que el recorrido en postorden de un árbol es la lista
de los nodos del árbol ordenada como sigue: en primer lugar, el
recorrido en postorden del hijo izquierdo del árbol, después el
recorrido en postorden del hijo derecho del árbol, y finalmente la raíz
del árbol. En otras palabras:
$$\begin{align*}
postorden(x(t_1,t_2)) &= postorden(t_1)\cdot{}postorden(t_2)\cdot{}x \\
postorden(()) &= ()
\end{align*}$$
es decir, el postorden del árbol vacío es el árbol vacío.

Por ejemplo, considerad el siguiente árbol, que tiene 12 nodos con
valores 1, 2, …, 12:

                      9
                      |
                  ---- ----
                 |         |
                 2         6
                 |
          ------- -------
         |               |
         12              10
         |               |
     ---- ----       ---- ----
    |         |     |         |
    3         7     4         11
              |               |
          ---- ----       ----
         |         |     |
         1         8     5

Su recorrido en inorden es: 3, 12, 1, 7, 8, 2, 4, 10, 5, 11, 9, 6.
Su recorrido en postorden es: 3, 1, 8, 7, 12, 4, 5, 11, 10, 2, 6, 9.

Ahora bien, sería posible, si sólo conociéramos los recorridos en
inorden y postorden, reconstruir el árbol original?

Ejercicio:

Hay que implementar un programa que lea varios casos de entrada. Cada
caso empieza con el tamaño n de un árbol binario de enteros desconocido,
y viene seguido de los recorridos en inorden y postorden de este árbol
desconocido, donde cada uno de estos recorridos consiste en una lista
con todos los valores posibles entre 1 y n. Con esta información,
tendréis que construir el árbol y escribirlo por la salida.

Fijaos que el enunciado de este ejercicio ya ofrece el fichero
BinTree.hh, que tendréis que utilizar para compilar. Sólo hace falta que
creéis main.cc, poniendo los includes que hagan falta e implementando el
programa y las funciones que hagan falta para solucionar el ejercicio.
Sólo hace falta que subáis main.cc al Jutge.

Entrada

La primera línea de la entrada describe el formato en el que se
describen los árboles de salida, o bien INLINEFORMAT o bien
VISUALFORMAT. Después viene una línea en blanco. Después vienen un
número arbitrario de casos. Cada caso consiste en una primera línea con
un número n, una segunda línea con los nodos 1 y n en inorden y
separados por espacios en blanco, y una tercera línea con los nodos 1 y
n en postorden y separados por espacios en blanco. Después de cada caso
hay una línea en blanco.

Salida

Para cada caso, hay que escribir el árbol binario con n nodos que
contienen todos los valores entre 1 y n, y tal que su recorrido en
inorden es la primera lista de valores, y su recorrido en postorden es
la segunda lista de valores.

Observación

AVISO: Este problema requiere un análisis a fondo antes de empezar a
programar, porque hay que pensar detenidamente la estrategia y sobre
todo los detalles. La solución no es larga pero no llegaréis por "ensayo
y error", es imperativo usar papel y lápiz primero. Los conceptos que
hay que tener muy presentes mentalmente para poder llegar a la solución
son:

- la definición recursiva del inorden y el postorden, y la posición de
  la raíz en los dos casos,

- cómo hacer una inmersión, es decir, utilizar parámetros en las
  llamadas recursivas para establecer el contexto en el que se ejecuta
  cada llamada.

En particular, hay que notar que si tanto inorden I como postorden P se
almacenan en vectores, los inordenes y postordenes de los subárboles son
subsecuencias de los vectores I y P, con posiciones iniciales y finales
que son índices en I y P.

Vuestra solución ha de trabajar con BinTree, aunque podéis utilizar
otras estructuras de datos presentadas en el curso como elemento de
soporte.

Para tratar la entrada y la salida, podéis utilizar este esquema:

    #include <iostream>
    using namespace std;
    #include "BinTree.hh"
    /* Puedes añadir más includes */

    typedef BinTree<int> BT;

    /* Las funciones que quieras */

    int main() {
        string format;
        cin >> format;
        int n;
        while (cin >> n) {
            /* Leer dos secuencias de n enteros cada una. */

            BinTree t;
            /* Calcular t a partir de las dos secuencias. */

            t.setOutputFormat(format=="INLINEFORMAT"?  BT::INLINEFORMAT : BT::VISUALFORMAT);
            cout << t << endl;
      	}
    }

Evalución sobre 10 puntos:

- Solución lenta: 5 puntos.

- Solución rápida: 10 puntos.

Entendemos como solución rápida una que es correcta, de coste lineal y
capaz de superar los juegos de pruebas públicos y privados. Entendemos
como solución lenta una que no es rápida, pero es correcta y capaz de
superar los juegos de pruebas públicos.

Información del problema

Autoría: PRO2

Generación: 2026-01-25T14:49:24.479Z

© Jutge.org, 2006–2026.
https://jutge.org
