I1M2011: Ejercicios sobre árboles binarios en Haskell
En la clase de hoy de Informática de 1º del Grado en Matemáticas se han explicado las soluciones de los ejercicios de la 19ª relación.
En esta relación se plantean ejercicios sobre árboles binarios. En concreto, se definen funciones para calcular:
- el número de hojas de un árbol,
- el número de nodos de un árbol,
- la profundidad de un árbol,
- el recorrido preorden de un árbol,
- el recorrido postorden de un árbol,
- el recorrido preorden de forma iterativa,
- la imagen especular de un árbol,
- el subárbol de profundidad dada,
- el árbol infinito generado con un elemento y
- el árbol de profundidad dada cuyos nodos son iguales a un elemento.
Los ejercicios, y sus soluciones, se muestran a continuación.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
-- --------------------------------------------------------------------- -- Importación de librerías auxiliares -- --------------------------------------------------------------------- import Data.List -- --------------------------------------------------------------------- -- Nota. En los siguientes ejercicios se trabajará con los árboles -- binarios definidos como sigue -- data Arbol a = Hoja -- | Nodo a (Arbol a) (Arbol a) -- deriving (Show, Eq) -- En los ejemplos se usará el siguiente árbol -- arbol = Nodo 9 -- (Nodo 3 -- (Nodo 2 Hoja Hoja) -- (Nodo 4 Hoja Hoja)) -- (Nodo 7 Hoja Hoja) -- --------------------------------------------------------------------- data Arbol a = Hoja | Nodo a (Arbol a) (Arbol a) deriving (Show, Eq) arbol = Nodo 9 (Nodo 3 (Nodo 2 Hoja Hoja) (Nodo 4 Hoja Hoja)) (Nodo 7 Hoja Hoja) -- --------------------------------------------------------------------- -- Ejercicio 1. Definir la función -- nHojas :: Arbol a -> Int -- tal que (nHojas x) es el número de hojas del árbol x. Por ejemplo, -- ghci> arbol -- Nodo 9 (Nodo 3 (Nodo 2 Hoja Hoja) (Nodo 4 Hoja Hoja)) (Nodo 7 Hoja Hoja) -- ghci> nHojas arbol -- 6 -- --------------------------------------------------------------------- nHojas :: Arbol a -> Int nHojas Hoja = 1 nHojas (Nodo x i d) = nHojas i + nHojas d -- --------------------------------------------------------------------- -- Ejercicio 2. Definir la función -- nNodos :: Arbol a -> Int -- tal que (nNodos x) es el número de nodos del árbol x. Por ejemplo, -- ghci> arbol -- Nodo 9 (Nodo 3 (Nodo 2 Hoja Hoja) (Nodo 4 Hoja Hoja)) (Nodo 7 Hoja Hoja) -- ghci> nNodos arbol -- 5 -- --------------------------------------------------------------------- nNodos :: Arbol a -> Int nNodos Hoja = 0 nNodos (Nodo x i d) = 1 + nNodos i + nNodos d -- --------------------------------------------------------------------- -- Ejercicio 3. Definir la función -- profundidad :: Arbol a -> Int -- tal que (profundidad x) es la profundidad del árbol x. Por ejemplo, -- ghci> arbol -- Nodo 9 (Nodo 3 (Nodo 2 Hoja Hoja) (Nodo 4 Hoja Hoja)) (Nodo 7 Hoja Hoja) -- ghci> profundidad arbol -- 3 -- --------------------------------------------------------------------- profundidad :: Arbol a -> Int profundidad Hoja = 0 profundidad (Nodo x i d) = 1 + max (profundidad i) (profundidad d) -- --------------------------------------------------------------------- -- Ejercicio 4. Definir la función -- preorden :: Arbol a -> [a] -- tal que (preorden x) es la lista correspondiente al recorrido -- preorden del árbol x; es decir, primero visita la raíz del árbol, a -- continuación recorre el subárbol izquierdo y, finalmente, recorre el -- subárbol derecho. Por ejemplo, -- ghci> arbol -- Nodo 9 (Nodo 3 (Nodo 2 Hoja Hoja) (Nodo 4 Hoja Hoja)) (Nodo 7 Hoja Hoja) -- ghci> preorden arbol -- [9,3,2,4,7] -- --------------------------------------------------------------------- preorden :: Arbol a -> [a] preorden Hoja = [] preorden (Nodo x i d) = x : (preorden i ++ preorden d) -- --------------------------------------------------------------------- -- Ejercicio 5. Definir la función -- postorden :: Arbol a -> [a] -- tal que (postorden x) es la lista correspondiente al recorrido -- postorden del árbol x; es decir, primero recorre el subárbol -- izquierdo, a continuación el subárbol derecho y, finalmente, la raíz -- del árbol. Por ejemplo, -- ghci> arbol -- Nodo 9 (Nodo 3 (Nodo 2 Hoja Hoja) (Nodo 4 Hoja Hoja)) (Nodo 7 Hoja Hoja) -- ghci> postorden arbol -- [2,4,3,7,9] -- --------------------------------------------------------------------- postorden :: Arbol a -> [a] postorden Hoja = [] postorden (Nodo x i d) = postorden i ++ postorden d ++ [x] -- --------------------------------------------------------------------- -- Ejercicio 6. Definir, usando un acumulador, la función -- preordenIt :: Arbol a -> [a] -- tal que (preordenIt x) es la lista correspondiente al recorrido -- preorden del árbol x; es decir, primero visita la raíz del árbol, a -- continuación recorre el subárbol izquierdo y, finalmente, recorre el -- subárbol derecho. Por ejemplo, -- ghci> arbol -- Nodo 9 (Nodo 3 (Nodo 2 Hoja Hoja) (Nodo 4 Hoja Hoja)) (Nodo 7 Hoja Hoja) -- ghci> preordenIt arbol -- [9,3,2,4,7] -- Nota: No usar (++) en la definición -- --------------------------------------------------------------------- preordenIt :: Arbol a -> [a] preordenIt x = preordenItAux x [] where preordenItAux Hoja xs = xs preordenItAux (Nodo x i d) xs = x : preordenItAux i (preordenItAux d xs) -- --------------------------------------------------------------------- -- Ejercicio 7. Definir la función -- espejo :: Arbol a -> Arbol a -- tal que (espejo x) es la imagen especular del árbol x. Por ejemplo, -- ghci> espejo arbol -- Nodo 9 -- (Nodo 7 Hoja Hoja) -- (Nodo 3 -- (Nodo 4 Hoja Hoja) -- (Nodo 2 Hoja Hoja)) -- --------------------------------------------------------------------- espejo :: Arbol a -> Arbol a espejo Hoja = Hoja espejo (Nodo x i d) = Nodo x (espejo d) (espejo i) -- --------------------------------------------------------------------- -- Ejercicio 8. La función take está definida por -- take :: Int -> [a] -> [a] -- take 0 = [] -- take (n+1) [] = [] -- take (n+1) (x:xs) = x : take n xs -- Definir la función -- takeArbol :: Int -> Arbol a -> Arbol a -- tal que (takeArbol n t) es el subárbol de t de profundidad n. Por -- ejemplo, -- ghci> takeArbol 0 (Nodo 6 Hoja (Nodo 7 (Nodo 5 Hoja Hoja) Hoja)) -- Hoja -- ghci> takeArbol 1 (Nodo 6 Hoja (Nodo 7 (Nodo 5 Hoja Hoja) Hoja)) -- Nodo 6 Hoja Hoja -- ghci> takeArbol 2 (Nodo 6 Hoja (Nodo 7 (Nodo 5 Hoja Hoja) Hoja)) -- Nodo 6 Hoja (Nodo 7 Hoja Hoja) -- ghci> takeArbol 3 (Nodo 6 Hoja (Nodo 7 (Nodo 5 Hoja Hoja) Hoja)) -- Nodo 6 Hoja (Nodo 7 (Nodo 5 Hoja Hoja) Hoja) -- ghci> takeArbol 4 (Nodo 6 Hoja (Nodo 7 (Nodo 5 Hoja Hoja) Hoja)) -- Nodo 6 Hoja (Nodo 7 (Nodo 5 Hoja Hoja) Hoja) -- --------------------------------------------------------------------- takeArbol :: Int -> Arbol a -> Arbol a takeArbol 0 _ = Hoja takeArbol _ Hoja = Hoja takeArbol n (Nodo x i d) = Nodo x (takeArbol (n-1) i) (takeArbol (n-1) d) -- --------------------------------------------------------------------- -- Ejercicio 9. La función -- repeat :: a -> [a] -- está definida de forma que (repeat x) es la lista formada por -- infinitos elementos x. Por ejemplo, -- repeat 3 == [3,3,3,3,3,3,3,3,3,3,3,3,3,... -- La definición de repeat es -- repeat x = xs where xs = x:xs -- Definir la función -- repeatArbol :: a -> Arbol a -- tal que (repeatArbol x) es es árbol con infinitos nodos x. Por -- ejemplo, -- ghci> takeArbol 0 (repeatArbol 3) -- Hoja -- ghci> takeArbol 1 (repeatArbol 3) -- Nodo 3 Hoja Hoja -- ghci> takeArbol 2 (repeatArbol 3) -- Nodo 3 (Nodo 3 Hoja Hoja) (Nodo 3 Hoja Hoja) -- --------------------------------------------------------------------- repeatArbol :: a -> Arbol a repeatArbol x = Nodo x t t where t = repeatArbol x -- --------------------------------------------------------------------- -- Ejercicio 10. La función -- replicate :: Int -> a -> [a] -- está definida por -- replicate n = take n . repeat -- es tal que (replicate n x) es la lista de longitud n cuyos elementos -- son x. Por ejemplo, -- replicate 3 5 == [5,5,5] -- Definir la función -- replicateArbol :: Int -> a -> Arbol a -- tal que (replicate n x) es el árbol de profundidad n cuyos nodos son -- x. Por ejemplo, -- ghci> replicateArbol 0 5 -- Hoja -- ghci> replicateArbol 1 5 -- Nodo 5 Hoja Hoja -- ghci> replicateArbol 2 5 -- Nodo 5 (Nodo 5 Hoja Hoja) (Nodo 5 Hoja Hoja) -- --------------------------------------------------------------------- replicateArbol :: Int -> a -> Arbol a replicateArbol n = takeArbol n . repeatArbol |