Haskell Hero
Haskell Hero es un manual interactivo del lenguaje Haskell para principiantes.
|
Plantamos árbolesSobre árboles binariosUn árbol binario Un árbol binario es una estructura de datos. Puede estar vacío o no vacío. Un árbol no vacío consta de
En Haskell definimos árboles de manera siguiente:
data BinTree a = Empty | Node a (BinTree a) (BinTree a) donde Empty indica un árbol vacío. Un árbol no vacío se define como
Node a (BinTree a) (BinTree a) En la expresión Node x l r el valor x indica el valor del raíz, l el subárbol izquierdo y r el subárbol derecho.
Ejemplos de árboles binarios de tipo BinTree Int
Funciones aplicadas a árboles binariosEjemplo
Definid la función ¿Cómo empezar? La mayoría de las funciones aplicadas a árboles binarios se define de manera siguiente:
Podemos entonces escribir la definición:
size :: BinTree a -> Int size Empty = size (Node x l r) =
¿Cuántos nodos hay en un árbol vacío? Exactamente cero. Podemos entonces completar la primera ecuación.
size Empty = 0 ¿Cuántos nodos hay en un árbol no vacío? Esta pregunta no es tan fácil contestar. Miremos de que disponemos. Tenemos el valor del raíz, el subárbol izquierdo y el subárbol derecho. Nada más.
¿Cuántos nodos hay en tal árbol? Exactamente tantos cuantos están en el raíz, en el subárbol izquierdo y en el derecho en total. Entonces vamos a contar los nodos en el subárbol izquierdo de manera recursiva, lo mismo con el subárbol derecho y después añadimos uno por el raíz. Y de esta manera lo también vamos a escribir.
size (Node x l r) = size l + size r + 1 Podemos ver que el valor del raíz no importa, por eso podemos sustituir x por un guión bajo. Toda la definición es entonces la siguiente:
size :: BinTree a -> Int size Empty = 0 size (Node _ l r) = size l + size r + 1 La evaluación modelo
Vamos a mostrar ahora como se cuentan nodos en un árbol de tres nodos.
size (Node 5 -- x (Node 2 Empty Empty) -- l (Node 4 Empty Empty) -- r ) ~> size (Node 2 Empty Empty) + size (Node 4 Empty Empty) + 1 ~> size Empty + size Empty + 1 + size (Node 4 Empty Empty) + 1 ~> 0 + size Empty + 1 + size (Node 4 Empty Empty) + 1 ~> 0 + 0 + 1 + size (Node 4 Empty Empty) + 1 ~> 0 + 0 + 1 + size Empty + size Empty + 1 + 1 ~> 0 + 0 + 1 + 0 + size Empty + 1 + 1 ~> 0 + 0 + 1 + 0 + 0 + 1 + 1 ~>* 3 Árboles n-ariosAdemás de árboles binarios podemos también definir árboles n-arios. Difieren de árboles binarios en el hecho de que todos los nodos pueden tener un cualquier número de hijos/descendientes. Por ejemplo la estructura de directorios típica está en forma de un árbol n-ario. Un ejemplo de un árbol n-ario de tipo NTree Char
En Haskell definimos árboles n-arios de manera siguiente:
data NTree a = Nnode a [ NTree a ] En la expresión Nnode x s el valor x es el valor del raíz y s es una lista de descendientes.
Ejemplos de árboles n-arios
Fijémonos en el hecho que el árbol vacío no está definido. Si estara definido, la notación de árboles sería ambiguo. Por ejemplo un árbol de un nodo se podría definir de manera siguiente:
data NTree a = Empty | Nnode a [ NTree a ] Nnode 3 [] Nnode 3 [Empty] Nnode 3 [Empty, Empty] Nnode 3 [Empty, Empty, Empty] Nnode 3 [Empty, Empty, Empty, Empty] ... Funciones aplicadas a árboles n-ariosEjemplo
Definid la función Mirando la estructura de un árbol n-ario podemos proceder de manera siguiente:
Para la suma recursiva de todos árboles en la lista de subárboles utilizamos la función treeSum :: NTree Integer -> Integer treeSum (Nnode x s) = sum (map treeSum s) + x La evaluación modelo
treeSum (Nnode 5 [ Nnode 4 [], Nnode 6 [], Nnode 8 [] ]) ~> sum (map treeSum [ Nnode 4 [], Nnode 6 [], Nnode 8 [] ]) + 5 ~>* sum [ 4 , 6 , 8 ] + 5 ~>* 18 + 5 ~> 23 |